summaryrefslogtreecommitdiff
path: root/source3/nsswitch/winbindd.c
diff options
context:
space:
mode:
authorTim Potter <tpot@samba.org>2001-05-07 04:32:40 +0000
committerTim Potter <tpot@samba.org>2001-05-07 04:32:40 +0000
commita36f9250e7c9446f3eece6d8db29fcbde99256fb (patch)
tree5b981dc1171e92f4a28232c3cc7b6d619054ea75 /source3/nsswitch/winbindd.c
parentc2887d57b5ff6da52aefac4657c23c142977ee2e (diff)
downloadsamba-a36f9250e7c9446f3eece6d8db29fcbde99256fb.tar.gz
samba-a36f9250e7c9446f3eece6d8db29fcbde99256fb.tar.bz2
samba-a36f9250e7c9446f3eece6d8db29fcbde99256fb.zip
Preliminary merge of winbind into HEAD. Note that this compiles and links
but I haven't actually run it yet so it probably doesn't work. (-: (This used to be commit 59f95416b66db6df05289bde224de29c721978e5)
Diffstat (limited to 'source3/nsswitch/winbindd.c')
-rw-r--r--source3/nsswitch/winbindd.c849
1 files changed, 478 insertions, 371 deletions
diff --git a/source3/nsswitch/winbindd.c b/source3/nsswitch/winbindd.c
index b0e35f3cd6..9d315a0811 100644
--- a/source3/nsswitch/winbindd.c
+++ b/source3/nsswitch/winbindd.c
@@ -23,17 +23,29 @@
#include "winbindd.h"
+pstring servicesf = CONFIGFILE;
+
/* List of all connected clients */
-static struct winbindd_cli_state *client_list;
+struct winbindd_cli_state *client_list;
+static int num_clients;
/* Reload configuration */
-static BOOL reload_services_file(void)
+static BOOL reload_services_file(BOOL test)
{
- pstring servicesf = CONFIGFILE;
BOOL ret;
+ if (lp_loaded()) {
+ pstring fname;
+
+ pstrcpy(fname,lp_configfile());
+ if (file_exist(fname,NULL) && !strcsequal(fname,servicesf)) {
+ pstrcpy(servicesf,fname);
+ test = False;
+ }
+ }
+
reopen_logs();
ret = lp_load(servicesf,False,False,True);
@@ -43,61 +55,75 @@ static BOOL reload_services_file(void)
return(ret);
}
-/* Print client information */
-
-static void do_print_client_info(void)
+void winbindd_dump_status(void)
{
- struct winbindd_cli_state *client;
- int i;
-
- if (client_list == NULL) {
- DEBUG(0, ("no clients in list\n"));
- return;
- }
+ struct winbindd_cli_state *tmp;
+
+ DEBUG(0, ("Global status for winbindd:\n"));
+
+ /* Print client state information */
+
+ DEBUG(0, ("\t%d clients currently active\n", num_clients));
+
+ if (DEBUGLEVEL >= 2) {
+ DEBUG(2, ("\tclient list:\n"));
+ for(tmp = client_list; tmp; tmp = tmp->next) {
+ DEBUG(2, ("\t\tpid %d, sock %d, rbl %d, wbl %d\n",
+ tmp->pid, tmp->sock, tmp->read_buf_len,
+ tmp->write_buf_len));
+ }
+ }
+}
- DEBUG(0, ("client list is:\n"));
+/* Print winbindd status to log file */
- for (client = client_list, i = 0; client; client = client->next) {
- DEBUG(0, ("client %3d: pid = %5d fd = %d read = %4d write = %4d\n",
- i, client->pid, client->sock, client->read_buf_len,
- client->write_buf_len));
- i++;
- }
+static void do_print_winbindd_status(void)
+{
+ winbindd_dump_status();
+ winbindd_idmap_dump_status();
+ winbindd_cache_dump_status();
}
/* Flush client cache */
static void do_flush_caches(void)
{
- /* Clear cached user and group enumation info */
-
- winbindd_flush_cache();
+ /* Clear cached user and group enumation info */
+
+ winbindd_flush_cache();
}
/* Handle the signal by unlinking socket and exiting */
static void termination_handler(int signum)
{
- pstring path;
+ pstring path;
+
+ /* Remove socket file */
+
+ snprintf(path, sizeof(path), "%s/%s",
+ WINBINDD_SOCKET_DIR, WINBINDD_SOCKET_NAME);
+ unlink(path);
+
+ exit(0);
+}
- /* Remove socket file */
+static BOOL print_winbindd_status;
- slprintf(path, sizeof(path)-1, "%s/%s",
- WINBINDD_SOCKET_DIR, WINBINDD_SOCKET_NAME);
- unlink(path);
-
- exit(0);
+static void sigusr1_handler(int signum)
+{
+ BlockSignals(True, SIGUSR1);
+ print_winbindd_status = True;
+ BlockSignals(False, SIGUSR1);
}
-static BOOL print_client_info;
-
-static BOOL flush_cache;
+static BOOL do_sighup;
static void sighup_handler(int signum)
{
- BlockSignals(True, SIGHUP);
- flush_cache = True;
- BlockSignals(False, SIGHUP);
+ BlockSignals(True, SIGHUP);
+ do_sighup = True;
+ BlockSignals(False, SIGHUP);
}
/* Create winbindd socket */
@@ -120,14 +146,14 @@ static int create_sock(void)
if (mkdir(WINBINDD_SOCKET_DIR, 0755) == -1) {
DEBUG(0, ("error creating socket directory %s: %s\n",
- WINBINDD_SOCKET_DIR, sys_errlist[errno]));
+ WINBINDD_SOCKET_DIR, strerror(errno)));
return -1;
}
} else {
DEBUG(0, ("lstat failed on socket directory %s: %s\n",
- WINBINDD_SOCKET_DIR, sys_errlist[errno]));
+ WINBINDD_SOCKET_DIR, strerror(errno)));
return -1;
}
@@ -159,7 +185,7 @@ static int create_sock(void)
return -1;
}
- slprintf(path, sizeof(path)-1, "%s/%s",
+ snprintf(path, sizeof(path), "%s/%s",
WINBINDD_SOCKET_DIR, WINBINDD_SOCKET_NAME);
unlink(path);
@@ -170,7 +196,7 @@ static int create_sock(void)
if (bind(sock, (struct sockaddr *)&sunaddr, sizeof(sunaddr)) == -1) {
DEBUG(0, ("bind failed on winbind socket %s: %s\n",
path,
- sys_errlist[errno]));
+ strerror(errno)));
close(sock);
return -1;
}
@@ -178,7 +204,7 @@ static int create_sock(void)
if (listen(sock, 5) == -1) {
DEBUG(0, ("listen failed on winbind socket %s: %s\n",
path,
- sys_errlist[errno]));
+ strerror(errno)));
close(sock);
return -1;
}
@@ -190,377 +216,420 @@ static int create_sock(void)
return sock;
}
-static void process_request(struct winbindd_cli_state *state)
-{
- /* Process command */
+struct dispatch_table {
+ enum winbindd_cmd cmd;
+ enum winbindd_result (*fn)(struct winbindd_cli_state *state);
+};
- state->response.result = WINBINDD_ERROR;
- state->response.length = sizeof(struct winbindd_response);
+static struct dispatch_table dispatch_table[] = {
+
+ /* User functions */
- DEBUG(3,("processing command %s from pid %d\n",
- winbindd_cmd_to_string(state->request.cmd), state->pid));
+ { WINBINDD_GETPWNAM_FROM_USER, winbindd_getpwnam_from_user },
+ { WINBINDD_GETPWNAM_FROM_UID, winbindd_getpwnam_from_uid },
+ { WINBINDD_SETPWENT, winbindd_setpwent },
+ { WINBINDD_ENDPWENT, winbindd_endpwent },
+ { WINBINDD_GETPWENT, winbindd_getpwent },
+ { WINBINDD_GETGROUPS, winbindd_getgroups },
- if (!server_state.lsa_handle_open) return;
+ /* Group functions */
- switch(state->request.cmd) {
-
- /* User functions */
-
- case WINBINDD_GETPWNAM_FROM_USER:
- state->response.result = winbindd_getpwnam_from_user(state);
- break;
-
- case WINBINDD_GETPWNAM_FROM_UID:
- state->response.result = winbindd_getpwnam_from_uid(state);
- break;
-
- case WINBINDD_SETPWENT:
- state->response.result = winbindd_setpwent(state);
- break;
-
- case WINBINDD_ENDPWENT:
- state->response.result = winbindd_endpwent(state);
- break;
-
- case WINBINDD_GETPWENT:
- state->response.result = winbindd_getpwent(state);
- break;
+ { WINBINDD_GETGRNAM_FROM_GROUP, winbindd_getgrnam_from_group },
+ { WINBINDD_GETGRNAM_FROM_GID, winbindd_getgrnam_from_gid },
+ { WINBINDD_SETGRENT, winbindd_setgrent },
+ { WINBINDD_ENDGRENT, winbindd_endgrent },
+ { WINBINDD_GETGRENT, winbindd_getgrent },
- /* Group functions */
-
- case WINBINDD_GETGRNAM_FROM_GROUP:
- state->response.result = winbindd_getgrnam_from_group(state);
- break;
-
- case WINBINDD_GETGRNAM_FROM_GID:
- state->response.result = winbindd_getgrnam_from_gid(state);
- break;
-
- case WINBINDD_SETGRENT:
- state->response.result = winbindd_setgrent(state);
- break;
-
- case WINBINDD_ENDGRENT:
- state->response.result = winbindd_endgrent(state);
- break;
-
- case WINBINDD_GETGRENT:
- state->response.result = winbindd_getgrent(state);
- break;
+ /* PAM auth functions */
- /* pam auth functions */
- case WINBINDD_PAM_AUTH:
- state->response.result = winbindd_pam_auth(state);
- break;
+ { WINBINDD_PAM_AUTH, winbindd_pam_auth },
+ { WINBINDD_PAM_CHAUTHTOK, winbindd_pam_chauthtok },
- /* Oops */
-
- default:
- DEBUG(0, ("oops - unknown winbindd command %d\n", state->request.cmd));
- break;
- }
-}
-
-/* Process a new connection by adding it to the client connection list */
+ /* Enumeration functions */
-static void new_connection(int accept_sock)
-{
- struct sockaddr_un sunaddr;
- struct winbindd_cli_state *state;
- int len, sock;
-
- /* Accept connection */
-
- len = sizeof(sunaddr);
- if ((sock = accept(accept_sock, (struct sockaddr *)&sunaddr, &len))
- == -1) {
-
- return;
- }
+ { WINBINDD_LIST_USERS, winbindd_list_users },
+ { WINBINDD_LIST_GROUPS, winbindd_list_groups },
+ { WINBINDD_LIST_TRUSTDOM, winbindd_list_trusted_domains },
- DEBUG(6,("accepted socket %d\n", sock));
+ /* SID related functions */
- /* Create new connection structure */
+ { WINBINDD_LOOKUPSID, winbindd_lookupsid },
+ { WINBINDD_LOOKUPNAME, winbindd_lookupname },
- if ((state = (struct winbindd_cli_state *)
- malloc(sizeof(*state))) == NULL) {
+ /* S*RS related functions */
- return;
- }
+ { WINBINDD_SID_TO_UID, winbindd_sid_to_uid },
+ { WINBINDD_SID_TO_GID, winbindd_sid_to_gid },
+ { WINBINDD_GID_TO_SID, winbindd_gid_to_sid },
+ { WINBINDD_UID_TO_SID, winbindd_uid_to_sid },
- ZERO_STRUCTP(state);
- state->sock = sock;
+ /* Miscellaneous */
- /* Add to connection list */
+ { WINBINDD_CHECK_MACHACC, winbindd_check_machine_acct },
- DLIST_ADD(client_list, state);
-}
+ /* End of list */
-/* Remove a client connection from client connection list */
+ { WINBINDD_NUM_CMDS, NULL }
+};
-static void remove_client(struct winbindd_cli_state *state)
+static void process_request(struct winbindd_cli_state *state)
{
- /* It's a dead client - hold a funeral */
+ struct dispatch_table *table = dispatch_table;
- if (state != NULL) {
+ /* Free response data - we may be interrupted and receive another
+ command before being able to send this data off. */
- /* Close socket */
+ safe_free(state->response.extra_data);
- close(state->sock);
+ ZERO_STRUCT(state->response);
- /* Free any getent state */
+ state->response.result = WINBINDD_ERROR;
+ state->response.length = sizeof(struct winbindd_response);
- free_getent_state(state->getpwent_state);
- free_getent_state(state->getgrent_state);
+ /* Process command */
- /* Free any extra data */
+ if (!server_state.lsa_handle_open) return;
- safe_free(state->response.extra_data);
+ for (table = dispatch_table; table->fn; table++) {
+ if (state->request.cmd == table->cmd) {
+ state->response.result = table->fn(state);
+ break;
+ }
+ }
- /* Remove from list and free */
+ /* In case extra data pointer is NULL */
- DLIST_REMOVE(client_list, state);
- free(state);
- }
+ if (!state->response.extra_data) {
+ state->response.length = sizeof(struct winbindd_response);
+ }
}
-/* Process a complete received packet from a client */
+/* Process a new connection by adding it to the client connection list */
-static void process_packet(struct winbindd_cli_state *state)
+static void new_connection(int accept_sock)
{
- /* Process request */
+ struct sockaddr_un sunaddr;
+ struct winbindd_cli_state *state;
+ int len, sock;
+
+ /* Accept connection */
+
+ len = sizeof(sunaddr);
+ if ((sock = accept(accept_sock, (struct sockaddr *)&sunaddr, &len))
+ == -1) {
+
+ return;
+ }
+
+ DEBUG(6,("accepted socket %d\n", sock));
+
+ /* Create new connection structure */
+
+ if ((state = (struct winbindd_cli_state *)
+ malloc(sizeof(*state))) == NULL) {
+
+ return;
+ }
+
+ ZERO_STRUCTP(state);
+ state->sock = sock;
+
+ /* Add to connection list */
+
+ DLIST_ADD(client_list, state);
+ num_clients++;
+}
- state->pid = state->request.pid;
+/* Remove a client connection from client connection list */
- process_request(state);
+static void remove_client(struct winbindd_cli_state *state)
+{
+ /* It's a dead client - hold a funeral */
+
+ if (state != NULL) {
+
+ /* Close socket */
+
+ close(state->sock);
+
+ /* Free any getent state */
+
+ free_getent_state(state->getpwent_state);
+ free_getent_state(state->getgrent_state);
+
+ /* We may have some extra data that was not freed if the
+ client was killed unexpectedly */
+
+ safe_free(state->response.extra_data);
+
+ /* Remove from list and free */
+
+ DLIST_REMOVE(client_list, state);
+ free(state);
+ num_clients--;
+ }
+}
- /* Update client state */
+/* Process a complete received packet from a client */
- state->read_buf_len = 0;
- state->write_buf_len = sizeof(state->response);
+static void process_packet(struct winbindd_cli_state *state)
+{
+ /* Process request */
+
+ state->pid = state->request.pid;
+
+ process_request(state);
+
+ /* Update client state */
+
+ state->read_buf_len = 0;
+ state->write_buf_len = sizeof(struct winbindd_response);
}
/* Read some data from a client connection */
static void client_read(struct winbindd_cli_state *state)
{
- int n;
+ int n;
- /* Read data */
-
- n = read(state->sock, state->read_buf_len + (char *)&state->request,
- sizeof(state->request) - state->read_buf_len);
-
- /* Read failed, kill client */
-
- if (n == -1 || n == 0) {
- DEBUG(5,("read failed on sock %d, pid %d: %s\n",
- state->sock, state->pid,
- (n == -1) ? sys_errlist[errno] : "EOF"));
-
- state->finished = True;
- return;
- }
-
- /* Update client state */
-
- state->read_buf_len += n;
+ /* Read data */
+
+ n = read(state->sock, state->read_buf_len + (char *)&state->request,
+ sizeof(state->request) - state->read_buf_len);
+
+ /* Read failed, kill client */
+
+ if (n == -1 || n == 0) {
+ DEBUG(5,("read failed on sock %d, pid %d: %s\n",
+ state->sock, state->pid,
+ (n == -1) ? strerror(errno) : "EOF"));
+
+ state->finished = True;
+ return;
+ }
+
+ /* Update client state */
+
+ state->read_buf_len += n;
}
/* Write some data to a client connection */
static void client_write(struct winbindd_cli_state *state)
{
- char *data;
- int n;
-
- /* Write data */
-
- if (state->write_extra_data) {
-
- /* Write extra data */
-
- data = (char *)state->response.extra_data +
- state->response.length - sizeof(struct winbindd_response) -
- state->write_buf_len;
-
- } else {
-
- /* Write response structure */
-
- data = (char *)&state->response + sizeof(state->response) -
- state->write_buf_len;
- }
-
- n = write(state->sock, data, state->write_buf_len);
-
- /* Write failed, kill cilent */
-
- if (n == -1 || n == 0) {
-
- DEBUG(3,("write failed on sock %d, pid %d: %s\n",
- state->sock, state->pid,
- (n == -1) ? sys_errlist[errno] : "EOF"));
-
- state->finished = True;
- return;
- }
-
- /* Update client state */
-
- state->write_buf_len -= n;
-
- /* Have we written all data? */
+ char *data;
+ int num_written;
+
+ /* Write some data */
+
+ if (!state->write_extra_data) {
+
+ /* Write response structure */
+
+ data = (char *)&state->response + sizeof(state->response) -
+ state->write_buf_len;
+
+ } else {
+
+ /* Write extra data */
+
+ data = (char *)state->response.extra_data +
+ state->response.length -
+ sizeof(struct winbindd_response) -
+ state->write_buf_len;
+ }
+
+ num_written = write(state->sock, data, state->write_buf_len);
+
+ /* Write failed, kill cilent */
+
+ if (num_written == -1 || num_written == 0) {
+
+ DEBUG(3,("write failed on sock %d, pid %d: %s\n",
+ state->sock, state->pid,
+ (num_written == -1) ? strerror(errno) : "EOF"));
+
+ state->finished = True;
+
+ safe_free(state->response.extra_data);
+ state->response.extra_data = NULL;
+
+ return;
+ }
+
+ /* Update client state */
+
+ state->write_buf_len -= num_written;
+
+ /* Have we written all data? */
+
+ if (state->write_buf_len == 0) {
+
+ /* Take care of extra data */
+
+ if (state->write_extra_data) {
+
+ safe_free(state->response.extra_data);
+ state->response.extra_data = NULL;
+
+ state->write_extra_data = False;
+
+ } else if (state->response.length >
+ sizeof(struct winbindd_response)) {
+
+ /* Start writing extra data */
+
+ state->write_buf_len =
+ state->response.length -
+ sizeof(struct winbindd_response);
+
+ state->write_extra_data = True;
+ }
+ }
+}
- if (state->write_buf_len == 0) {
+/* Process incoming clients on accept_sock. We use a tricky non-blocking,
+ non-forking, non-threaded model which allows us to handle many
+ simultaneous connections while remaining impervious to many denial of
+ service attacks. */
- /* Take care of extra data */
+static void process_loop(int accept_sock)
+{
+ /* We'll be doing this a lot */
- if (state->response.length > sizeof(struct winbindd_response)) {
+ while (1) {
+ struct winbindd_cli_state *state;
+ fd_set r_fds, w_fds;
+ int maxfd = accept_sock, selret;
+ struct timeval timeout;
- if (state->write_extra_data) {
+ /* Free up temporary memory */
- /* Already written extra data - free it */
+ lp_talloc_free();
- safe_free(state->response.extra_data);
- state->response.extra_data = NULL;
- state->write_extra_data = False;
+ /* Do any connection establishment that is needed */
- } else {
+ establish_connections(False); /* Honour timeout */
- /* Start writing extra data */
+ /* Initialise fd lists for select() */
- state->write_buf_len = state->response.length -
- sizeof(struct winbindd_response);
- state->write_extra_data = True;
- }
- }
- }
-}
+ FD_ZERO(&r_fds);
+ FD_ZERO(&w_fds);
+ FD_SET(accept_sock, &r_fds);
-/* Process incoming clients on accept_sock. We use a tricky non-blocking,
- non-forking, non-threaded model which allows us to handle many
- simultaneous connections while remaining impervious to many denial of
- service attacks. */
+ timeout.tv_sec = WINBINDD_ESTABLISH_LOOP;
+ timeout.tv_usec = 0;
-static void process_loop(int accept_sock)
-{
- /* We'll be doing this a lot */
+ /* Set up client readers and writers */
- while (1) {
- struct winbindd_cli_state *state;
- fd_set r_fds, w_fds;
- int maxfd = accept_sock, selret;
- struct timeval timeout;
+ state = client_list;
- /* do any connection establishment that is needed */
- establish_connections();
+ while (state) {
- /* Initialise fd lists for select() */
+ /* Dispose of client connection if it is marked as
+ finished */
- FD_ZERO(&r_fds);
- FD_ZERO(&w_fds);
- FD_SET(accept_sock, &r_fds);
+ if (state->finished) {
+ struct winbindd_cli_state *next = state->next;
- timeout.tv_sec = WINBINDD_ESTABLISH_LOOP;
- timeout.tv_usec = 0;
+ remove_client(state);
+ state = next;
+ continue;
+ }
- /* Set up client readers and writers */
+ /* Select requires we know the highest fd used */
- state = client_list;
+ if (state->sock > maxfd) maxfd = state->sock;
- while (state) {
- /* Dispose of client connection if it is marked as finished */
+ /* Add fd for reading */
- if (state->finished) {
- struct winbindd_cli_state *next = state->next;
+ if (state->read_buf_len != sizeof(state->request)) {
+ FD_SET(state->sock, &r_fds);
+ }
- remove_client(state);
- state = next;
- continue;
- }
+ /* Add fd for writing */
- /* Select requires we know the highest fd used */
+ if (state->write_buf_len) {
+ FD_SET(state->sock, &w_fds);
+ }
- if (state->sock > maxfd) maxfd = state->sock;
+ state = state->next;
+ }
- /* Add fd for reading */
+ /* Check signal handling things */
- if (state->read_buf_len != sizeof(state->request)) {
- FD_SET(state->sock, &r_fds);
- }
+ if (do_sighup) {
- /* Add fd for writing */
+ /* Flush winbindd cache */
- if (state->write_buf_len) {
- FD_SET(state->sock, &w_fds);
- }
+ do_flush_caches();
+ reload_services_file(True);
- state = state->next;
- }
+ /* Close and re-open all connections. This will also
+ refresh the trusted domains list */
- /* Check signal handling things */
+ winbindd_kill_all_connections();
+ establish_connections(True); /* Force re-establish */
- if (flush_cache) {
- do_flush_caches();
- reload_services_file();
- flush_cache = False;
- }
+ do_sighup = False;
+ }
- if (print_client_info) {
- do_print_client_info();
- print_client_info = False;
- }
+ if (print_winbindd_status) {
+ do_print_winbindd_status();
+ print_winbindd_status = False;
+ }
- /* Call select */
+ /* Call select */
- selret = select(maxfd + 1, &r_fds, &w_fds, NULL, &timeout);
+ selret = select(maxfd + 1, &r_fds, &w_fds, NULL, &timeout);
- if (selret == 0) continue;
+ if (selret == 0) continue;
- if ((selret == -1 && errno != EINTR) || selret == 0) {
+ if ((selret == -1 && errno != EINTR) || selret == 0) {
- /* Select error, something is badly wrong */
+ /* Select error, something is badly wrong */
- perror("select");
- exit(1);
- }
+ perror("select");
+ exit(1);
+ }
- /* Create a new connection if accept_sock readable */
+ /* Create a new connection if accept_sock readable */
- if (selret > 0) {
+ if (selret > 0) {
- if (FD_ISSET(accept_sock, &r_fds)) {
- new_connection(accept_sock);
- }
+ if (FD_ISSET(accept_sock, &r_fds)) {
+ new_connection(accept_sock);
+ }
- /* Process activity on client connections */
+ /* Process activity on client connections */
- for (state = client_list; state ; state = state->next) {
+ for (state = client_list; state; state = state->next) {
- /* Data available for reading */
+ /* Data available for reading */
- if (FD_ISSET(state->sock, &r_fds)) {
+ if (FD_ISSET(state->sock, &r_fds)) {
- /* Read data */
+ /* Read data */
- client_read(state);
+ client_read(state);
- /* A request packet might be complete */
+ /* A request packet might be
+ complete */
- if (state->read_buf_len == sizeof(state->request)) {
- process_packet(state);
- }
- }
+ if (state->read_buf_len ==
+ sizeof(state->request)) {
+ process_packet(state);
+ }
+ }
- /* Data available for writing */
+ /* Data available for writing */
- if (FD_ISSET(state->sock, &w_fds)) {
- client_write(state);
- }
- }
- }
- }
+ if (FD_ISSET(state->sock, &w_fds)) {
+ client_write(state);
+ }
+ }
+ }
+ }
}
/* Main function */
@@ -569,87 +638,125 @@ struct winbindd_state server_state; /* Server state information */
int main(int argc, char **argv)
{
- extern pstring global_myname;
- extern pstring debugf;
- int accept_sock;
- BOOL interactive = False;
- int opt;
-
- while ((opt = getopt(argc, argv, "i")) != EOF) {
- switch (opt) {
+ extern pstring global_myname;
+ extern pstring debugf;
+ int accept_sock;
+ BOOL interactive = False;
+ int opt, new_debuglevel = -1;
+
+ /* Set environment variable so we don't recursively call ourselves.
+ This may also be useful interactively. */
+ SETENV(WINBINDD_DONT_ENV, "1", 1);
+
+ /* Initialise samba/rpc client stuff */
+
+ while ((opt = getopt(argc, argv, "id:s:")) != EOF) {
+ switch (opt) {
+
+ /* Don't become a daemon */
+
case 'i':
interactive = True;
break;
+
+ /* Run with specified debug level */
+
+ case 'd':
+ new_debuglevel = atoi(optarg);
+ break;
+
+ /* Load a different smb.conf file */
+
+ case 's':
+ pstrcpy(servicesf,optarg);
+ break;
+
default:
- printf("Unknown option %c (%d)\n", (char)opt, opt);
+ printf("Unknown option %c\n", (char)opt);
exit(1);
}
- }
+ }
- /* Initialise samba/rpc client stuff */
- slprintf(debugf, sizeof(debugf)-1, "%s/log.winbindd", LOGFILEBASE);
- setup_logging("winbindd", interactive);
- reopen_logs();
+ snprintf(debugf, sizeof(debugf), "%s/log.winbindd", LOGFILEBASE);
+ setup_logging("winbindd", interactive);
+ reopen_logs();
- if (!*global_myname) {
- char *p;
+ if (!*global_myname) {
+ char *p;
- fstrcpy(global_myname, myhostname());
- p = strchr(global_myname, '.');
- if (p) {
- *p = 0;
- }
- }
+ fstrcpy(global_myname, myhostname());
+ p = strchr(global_myname, '.');
+ if (p) {
+ *p = 0;
+ }
+ }
- TimeInit();
- charset_initialise();
- codepage_initialise(lp_client_code_page());
+ TimeInit();
+ charset_initialise();
- if (!lp_load(CONFIGFILE, True, False, False)) {
- DEBUG(0, ("error opening config file\n"));
- exit(1);
- }
+ if (!reload_services_file(False)) {
+ DEBUG(0, ("error opening config file\n"));
+ exit(1);
+ }
- if (!interactive) {
- become_daemon();
- }
- load_interfaces();
+ if (new_debuglevel != -1) {
+ DEBUGLEVEL = new_debuglevel;
+ }
- secrets_init();
+ codepage_initialise(lp_client_code_page());
- ZERO_STRUCT(server_state);
+ if (!interactive) {
+ become_daemon();
+ }
- /* Winbind daemon initialisation */
- if (!winbindd_param_init()) {
- return 1;
- }
+ load_interfaces();
- if (!winbindd_idmap_init()) {
- return 1;
- }
+ secrets_init();
- winbindd_cache_init();
+ ZERO_STRUCT(server_state);
- /* Setup signal handlers */
+ /* Winbind daemon initialisation */
- CatchSignal(SIGINT, termination_handler); /* Exit on these sigs */
- CatchSignal(SIGQUIT, termination_handler);
- CatchSignal(SIGTERM, termination_handler);
+ if (!winbindd_param_init()) {
+ return 1;
+ }
- CatchSignal(SIGPIPE, SIG_IGN); /* Ignore sigpipe */
+ if (!winbindd_idmap_init()) {
+ return 1;
+ }
- CatchSignal(SIGHUP, sighup_handler);
+ winbindd_cache_init();
- /* Create UNIX domain socket */
+ /* Unblock all signals we are interested in as they may have been
+ blocked by the parent process. */
- if ((accept_sock = create_sock()) == -1) {
- DEBUG(0, ("failed to create socket\n"));
- return 1;
- }
+ BlockSignals(False, SIGINT);
+ BlockSignals(False, SIGQUIT);
+ BlockSignals(False, SIGTERM);
+ BlockSignals(False, SIGUSR1);
+ BlockSignals(False, SIGHUP);
+
+ /* Setup signal handlers */
+
+ CatchSignal(SIGINT, termination_handler); /* Exit on these sigs */
+ CatchSignal(SIGQUIT, termination_handler);
+ CatchSignal(SIGTERM, termination_handler);
+
+ CatchSignal(SIGPIPE, SIG_IGN); /* Ignore sigpipe */
+
+ CatchSignal(SIGUSR1, sigusr1_handler); /* Debugging sigs */
+ CatchSignal(SIGHUP, sighup_handler);
+
+ /* Create UNIX domain socket */
+
+ if ((accept_sock = create_sock()) == -1) {
+ DEBUG(0, ("failed to create socket\n"));
+ return 1;
+ }
- /* Loop waiting for requests */
+ /* Loop waiting for requests */
- process_loop(accept_sock);
+ process_loop(accept_sock);
- return 0;
+ return 0;
}