remove accidental debug code..
[kai/samba.git] / source3 / nsswitch / winbindd_dual.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    Winbind background daemon
5
6    Copyright (C) Andrew Tridgell 2002
7    
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.
12    
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.
17    
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.
21 */
22
23 /*
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
29
30  */
31
32 #include "winbindd.h"
33
34 #undef DBGC_CLASS
35 #define DBGC_CLASS DBGC_WINBIND
36
37 extern BOOL opt_dual_daemon;
38 BOOL background_process = False;
39 int dual_daemon_pipe = -1;
40
41
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;
48 };
49
50 static struct dual_list *dual_list;
51 static struct dual_list *dual_list_end;
52
53 /*
54   setup a select() including the dual daemon pipe
55  */
56 int dual_select_setup(fd_set *fds, int maxfd)
57 {
58         if (dual_daemon_pipe == -1 ||
59             !dual_list) {
60                 return maxfd;
61         }
62
63         FD_SET(dual_daemon_pipe, fds);
64         if (dual_daemon_pipe > maxfd) {
65                 maxfd = dual_daemon_pipe;
66         }
67         return maxfd;
68 }
69
70
71 /*
72   a hook called from the main winbindd select() loop to handle writes
73   to the dual daemon pipe 
74 */
75 void dual_select(fd_set *fds)
76 {
77         int n;
78
79         if (dual_daemon_pipe == -1 ||
80             !dual_list ||
81             !FD_ISSET(dual_daemon_pipe, fds)) {
82                 return;
83         }
84
85         n = sys_write(dual_daemon_pipe, 
86                   &dual_list->data[dual_list->offset],
87                   dual_list->length - dual_list->offset);
88
89         if (n <= 0) {
90                 /* the pipe is dead! fall back to normal operation */
91                 dual_daemon_pipe = -1;
92                 return;
93         }
94
95         dual_list->offset += n;
96
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;
105                 }
106         }
107 }
108
109 /* 
110    send a request to the background daemon 
111    this is called for stale cached entries
112 */
113 void dual_send_request(struct winbindd_cli_state *state)
114 {
115         struct dual_list *list;
116
117         if (!background_process) return;
118
119         list = malloc(sizeof(*list));
120         if (!list) return;
121
122         list->next = NULL;
123         list->data = memdup(&state->request, sizeof(state->request));
124         list->length = sizeof(state->request);
125         list->offset = 0;
126         
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;
133         }
134
135         background_process = False;
136 }
137
138
139 /* 
140 the main dual daemon 
141 */
142 void do_dual_daemon(void)
143 {
144         int fdpair[2];
145         struct winbindd_cli_state state;
146         
147         if (pipe(fdpair) != 0) {
148                 return;
149         }
150
151         ZERO_STRUCT(state);
152         state.pid = getpid();
153
154         dual_daemon_pipe = fdpair[1];
155         state.sock = fdpair[0];
156
157         if (fork() != 0) {
158                 close(fdpair[0]);
159                 return;
160         }
161         close(fdpair[1]);
162         
163         if (!winbind_setup_common()) 
164                 _exit(0);
165
166         dual_daemon_pipe = -1;
167         opt_dual_daemon = False;
168
169         while (1) {
170                 /* free up any talloc memory */
171                 lp_talloc_free();
172                 main_loop_talloc_free();
173
174                 /* fetch a request from the main daemon */
175                 winbind_client_read(&state);
176
177                 if (state.finished) {
178                         /* we lost contact with our parent */
179                         exit(0);
180                 }
181
182                 /* process full rquests */
183                 if (state.read_buf_len == sizeof(state.request)) {
184                         DEBUG(4,("dual daemon request %d\n", (int)state.request.cmd));
185
186                         /* special handling for the stateful requests */
187                         switch (state.request.cmd) {
188                         case WINBINDD_GETPWENT:
189                                 winbindd_setpwent(&state);
190                                 break;
191                                 
192                         case WINBINDD_GETGRENT:
193                         case WINBINDD_GETGRLST:
194                                 winbindd_setgrent(&state);
195                                 break;
196                         default:
197                                 break;
198                         }
199
200                         winbind_process_packet(&state);
201                         SAFE_FREE(state.response.extra_data);
202
203                         free_getent_state(state.getpwent_state);
204                         free_getent_state(state.getgrent_state);
205                         state.getpwent_state = NULL;
206                         state.getgrent_state = NULL;
207                 }
208         }
209 }
210