r12542: Move some more prototypes out to seperate headers
[kai/samba-autobuild/.git] / source4 / smbd / server.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    Main SMB server routines
5
6    Copyright (C) Andrew Tridgell                1992-2005
7    Copyright (C) Martin Pool                    2002
8    Copyright (C) Jelmer Vernooij                2002
9    Copyright (C) James J Myers                  2003 <myersjj@samba.org>
10    
11    This program is free software; you can redistribute it and/or modify
12    it under the terms of the GNU General Public License as published by
13    the Free Software Foundation; either version 2 of the License, or
14    (at your option) any later version.
15    
16    This program is distributed in the hope that it will be useful,
17    but WITHOUT ANY WARRANTY; without even the implied warranty of
18    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19    GNU General Public License for more details.
20    
21    You should have received a copy of the GNU General Public License
22    along with this program; if not, write to the Free Software
23    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 */
25
26 #include "includes.h"
27 #include "lib/events/events.h"
28 #include "version.h"
29 #include "lib/cmdline/popt_common.h"
30 #include "system/dir.h"
31 #include "system/filesys.h"
32 #include "system/kerberos.h"
33 #include "smb_build.h"
34 #include "registry/registry.h"
35 #include "ntvfs/ntvfs.h"
36 #include "ntptr/ntptr.h"
37
38 /*
39   recursively delete a directory tree
40 */
41 static void recursive_delete(const char *path)
42 {
43         DIR *dir;
44         struct dirent *de;
45
46         dir = opendir(path);
47         if (!dir) {
48                 return;
49         }
50
51         for (de=readdir(dir);de;de=readdir(dir)) {
52                 char *fname;
53                 struct stat st;
54
55                 if (strcmp(de->d_name, ".") == 0 ||
56                     strcmp(de->d_name, "..") == 0) {
57                         continue;
58                 }
59
60                 fname = talloc_asprintf(path, "%s/%s", path, de->d_name);
61                 if (stat(fname, &st) != 0) {
62                         continue;
63                 }
64                 if (S_ISDIR(st.st_mode)) {
65                         recursive_delete(fname);
66                         talloc_free(fname);
67                         continue;
68                 }
69                 if (unlink(fname) != 0) {
70                         DEBUG(0,("Unabled to delete '%s' - %s\n", 
71                                  fname, strerror(errno)));
72                         smb_panic("unable to cleanup tmp files");
73                 }
74                 talloc_free(fname);
75         }
76         closedir(dir);
77 }
78
79 /*
80   cleanup temporary files. This is the new alternative to
81   TDB_CLEAR_IF_FIRST. Unfortunately TDB_CLEAR_IF_FIRST is not
82   efficient on unix systems due to the lack of scaling of the byte
83   range locking system. So instead of putting the burden on tdb to
84   cleanup tmp files, this function deletes them. 
85 */
86 static void cleanup_tmp_files(void)
87 {
88         char *path;
89         TALLOC_CTX *mem_ctx = talloc_new(NULL);
90
91         path = smbd_tmp_path(mem_ctx, NULL);
92
93         recursive_delete(path);
94         talloc_free(mem_ctx);
95 }
96
97 /*
98   setup signal masks
99 */
100 static void setup_signals(void)
101 {
102         /* we are never interested in SIGPIPE */
103         BlockSignals(True,SIGPIPE);
104
105 #if defined(SIGFPE)
106         /* we are never interested in SIGFPE */
107         BlockSignals(True,SIGFPE);
108 #endif
109
110         /* We are no longer interested in USR1 */
111         BlockSignals(True, SIGUSR1);
112
113 #if defined(SIGUSR2)
114         /* We are no longer interested in USR2 */
115         BlockSignals(True,SIGUSR2);
116 #endif
117
118         /* POSIX demands that signals are inherited. If the invoking process has
119          * these signals masked, we will have problems, as we won't recieve them. */
120         BlockSignals(False, SIGHUP);
121         BlockSignals(False, SIGTERM);
122
123         /* as we don't handle on this signals yet, we need to ignore them,
124          * instead of terminating */
125         CatchSignal(SIGHUP, SIG_IGN);
126 }
127
128 /*
129   handle io on stdin
130 */
131 static void server_stdin_handler(struct event_context *event_ctx, struct fd_event *fde, 
132                                  uint16_t flags, void *private)
133 {
134         const char *binary_name = private;
135         uint8_t c;
136         if (read(0, &c, 1) == 0) {
137                 DEBUG(0,("%s: EOF on stdin - terminating\n", binary_name));
138                 exit(0);
139         }
140 }
141
142 /*
143   die if the user selected maximum runtime is exceeded
144 */
145 static void max_runtime_handler(struct event_context *ev, struct timed_event *te, 
146                                 struct timeval t, void *private)
147 {
148         const char *binary_name = private;
149         DEBUG(0,("%s: maximum runtime exceeded - terminating\n", binary_name));
150         exit(0);
151 }
152
153 /*
154  main server.
155 */
156 static int binary_smbd_main(const char *binary_name, int argc, const char *argv[])
157 {
158         BOOL interactive = False;
159         int opt;
160         poptContext pc;
161         init_module_fn static_init[] = STATIC_SERVER_SERVICE_MODULES;
162         init_module_fn *shared_init;
163         struct event_context *event_ctx;
164         NTSTATUS status;
165         const char *model = "standard";
166         int max_runtime = 0;
167         struct poptOption long_options[] = {
168                 POPT_AUTOHELP
169                 {"interactive", 'i', POPT_ARG_VAL, &interactive, True, 
170                  "Run interactive (not a daemon)", NULL},
171                 {"model", 'M', POPT_ARG_STRING, &model, True, 
172                  "Select process model", "MODEL"},
173                 {"maximum-runtime", 0, POPT_ARG_INT, &max_runtime, True, 
174                  "set maximum runtime of the server process, till autotermination", "seconds"},
175                 POPT_COMMON_SAMBA
176                 POPT_COMMON_VERSION
177                 POPT_TABLEEND
178         };
179
180         pc = poptGetContext(binary_name, argc, argv, long_options, 0);
181         
182         while((opt = poptGetNextOpt(pc)) != -1) /* noop */ ;
183
184         poptFreeContext(pc);
185
186         setup_logging(binary_name, interactive?DEBUG_STDOUT:DEBUG_FILE);
187         setup_signals();
188
189         /* we want total control over the permissions on created files,
190            so set our umask to 0 */
191         umask(0);
192
193         DEBUG(0,("%s version %s started.\n", binary_name, SAMBA_VERSION_STRING));
194         DEBUGADD(0,("Copyright Andrew Tridgell and the Samba Team 1992-2005\n"));
195
196         if (sizeof(uint16_t) < 2 || sizeof(uint32_t) < 4 || sizeof(uint64_t) < 8) {
197                 DEBUG(0,("ERROR: Samba is not configured correctly for the word size on your machine\n"));
198                 exit(1);
199         }
200
201         if (!interactive) {
202                 DEBUG(3,("Becoming a daemon.\n"));
203                 become_daemon(True);
204         }
205
206         cleanup_tmp_files();
207
208         if (!directory_exist(lp_lockdir())) {
209                 mkdir(lp_lockdir(), 0755);
210         }
211
212         pidfile_create(binary_name);
213
214         /* Do *not* remove this, until you have removed
215          * passdb/secrets.c, and proved that Samba still builds... */
216         /* Setup the SECRETS subsystem */
217         if (!secrets_init()) {
218                 exit(1);
219         }
220
221         smbd_init_subsystems;
222
223         registry_init(); /* FIXME: maybe run this in the initialization function 
224                                                 of the winreg RPC server instead? */
225
226         ntptr_init();   /* FIXME: maybe run this in the initialization function 
227                                                 of the spoolss RPC server instead? */
228
229         ntvfs_init();   /* FIXME: maybe run this in the initialization functions 
230                                                 of the SMB[,2] server instead? */
231
232         process_model_init(); 
233
234         shared_init = load_samba_modules(NULL, "service");
235
236         run_init_functions(static_init);
237         run_init_functions(shared_init);
238
239         talloc_free(shared_init);
240         
241         /* the event context is the top level structure in smbd. Everything else
242            should hang off that */
243         event_ctx = event_context_init(NULL);
244
245         if (interactive) {
246                 /* catch EOF on stdin */
247 #ifdef SIGTTIN
248                 signal(SIGTTIN, SIG_IGN);
249 #endif
250                 event_add_fd(event_ctx, event_ctx, 0, EVENT_FD_READ, 
251                              server_stdin_handler,
252                              discard_const(binary_name));
253         }
254
255
256         if (max_runtime) {
257                 event_add_timed(event_ctx, event_ctx, 
258                                 timeval_current_ofs(max_runtime, 0), 
259                                 max_runtime_handler,
260                                 discard_const(binary_name));
261         }
262
263         DEBUG(0,("%s: using '%s' process model\n", binary_name, model));
264         status = server_service_startup(event_ctx, model, lp_server_services());
265         if (!NT_STATUS_IS_OK(status)) {
266                 DEBUG(0,("Starting Services failed - %s\n", nt_errstr(status)));
267                 return 1;
268         }
269
270         /* wait for events - this is where smbd sits for most of its
271            life */
272         event_loop_wait(event_ctx);
273
274         /* as everything hangs off this event context, freeing it
275            should initiate a clean shutdown of all services */
276         talloc_free(event_ctx);
277
278         return 0;
279 }
280
281  int main(int argc, const char *argv[])
282 {
283         return binary_smbd_main("smbd", argc, argv);
284 }