Finish conversion of Locking options
[Samba/gebeck_regimport.git] / source3 / nsswitch / winbindd_dual.c
blob3597171005cfd5090d26af519c08e5e03a2be911
1 /*
2 Unix SMB/CIFS implementation.
4 Winbind background daemon
6 Copyright (C) Andrew Tridgell 2002
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 the idea of the optional dual daemon mode is ot prevent slow domain
25 responses from clagging up the rest of the system. When in dual
26 daemon mode winbindd always responds to requests from cache if the
27 request is in cache, and if the cached answer is stale then it asks
28 the "dual daemon" to update the cache for that request
32 #include "winbindd.h"
34 #undef DBGC_CLASS
35 #define DBGC_CLASS DBGC_WINBIND
37 extern BOOL opt_dual_daemon;
38 BOOL background_process = False;
39 int dual_daemon_pipe = -1;
42 /* a list of requests ready to be sent to the dual daemon */
43 struct dual_list {
44 struct dual_list *next;
45 char *data;
46 int length;
47 int offset;
50 static struct dual_list *dual_list;
51 static struct dual_list *dual_list_end;
54 setup a select() including the dual daemon pipe
56 int dual_select_setup(fd_set *fds, int maxfd)
58 if (dual_daemon_pipe == -1 ||
59 !dual_list) {
60 return maxfd;
63 FD_SET(dual_daemon_pipe, fds);
64 if (dual_daemon_pipe > maxfd) {
65 maxfd = dual_daemon_pipe;
67 return maxfd;
72 a hook called from the main winbindd select() loop to handle writes
73 to the dual daemon pipe
75 void dual_select(fd_set *fds)
77 int n;
79 if (dual_daemon_pipe == -1 ||
80 !dual_list ||
81 !FD_ISSET(dual_daemon_pipe, fds)) {
82 return;
85 n = sys_write(dual_daemon_pipe,
86 &dual_list->data[dual_list->offset],
87 dual_list->length - dual_list->offset);
89 if (n <= 0) {
90 /* the pipe is dead! fall back to normal operation */
91 dual_daemon_pipe = -1;
92 return;
95 dual_list->offset += n;
97 if (dual_list->offset == dual_list->length) {
98 struct dual_list *next;
99 next = dual_list->next;
100 free(dual_list->data);
101 free(dual_list);
102 dual_list = next;
103 if (!dual_list) {
104 dual_list_end = NULL;
110 send a request to the background daemon
111 this is called for stale cached entries
113 void dual_send_request(struct winbindd_cli_state *state)
115 struct dual_list *list;
117 if (!background_process) return;
119 list = malloc(sizeof(*list));
120 if (!list) return;
122 list->next = NULL;
123 list->data = memdup(&state->request, sizeof(state->request));
124 list->length = sizeof(state->request);
125 list->offset = 0;
127 if (!dual_list_end) {
128 dual_list = list;
129 dual_list_end = list;
130 } else {
131 dual_list_end->next = list;
132 dual_list_end = list;
135 background_process = False;
140 the main dual daemon
142 void do_dual_daemon(void)
144 int fdpair[2];
145 struct winbindd_cli_state state;
147 if (pipe(fdpair) != 0) {
148 return;
151 ZERO_STRUCT(state);
152 state.pid = getpid();
154 dual_daemon_pipe = fdpair[1];
155 state.sock = fdpair[0];
157 if (fork() != 0) {
158 close(fdpair[0]);
159 return;
161 close(fdpair[1]);
163 /* tdb needs special fork handling */
164 if (tdb_reopen_all() == -1) {
165 DEBUG(0,("tdb_reopen_all failed.\n"));
166 _exit(0);
169 if (!winbind_setup_common())
170 _exit(0);
172 dual_daemon_pipe = -1;
173 opt_dual_daemon = False;
175 while (1) {
176 /* free up any talloc memory */
177 lp_talloc_free();
178 main_loop_talloc_free();
180 /* fetch a request from the main daemon */
181 winbind_client_read(&state);
183 if (state.finished) {
184 /* we lost contact with our parent */
185 exit(0);
188 /* process full rquests */
189 if (state.read_buf_len == sizeof(state.request)) {
190 DEBUG(4,("dual daemon request %d\n", (int)state.request.cmd));
192 /* special handling for the stateful requests */
193 switch (state.request.cmd) {
194 case WINBINDD_GETPWENT:
195 winbindd_setpwent(&state);
196 break;
198 case WINBINDD_GETGRENT:
199 case WINBINDD_GETGRLST:
200 winbindd_setgrent(&state);
201 break;
202 default:
203 break;
206 winbind_process_packet(&state);
207 SAFE_FREE(state.response.extra_data);
209 free_getent_state(state.getpwent_state);
210 free_getent_state(state.getgrent_state);
211 state.getpwent_state = NULL;
212 state.getgrent_state = NULL;