I've decided to move the auth code around a bit more...
[ira/wip.git] / source3 / smbd / server.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 1.9.
4    Main SMB server routines
5    Copyright (C) Andrew Tridgell 1992-1998
6    
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11    
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16    
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22 #include "includes.h"
23
24 extern fstring global_myworkgroup;
25 extern pstring global_myname;
26
27 int am_parent = 1;
28
29 /* the last message the was processed */
30 int last_message = -1;
31
32 /* a useful macro to debug the last message processed */
33 #define LAST_MESSAGE() smb_fn_name(last_message)
34
35 extern pstring user_socket_options;
36
37 #ifdef WITH_DFS
38 extern int dcelogin_atmost_once;
39 #endif /* WITH_DFS */
40
41 extern fstring remote_machine;
42
43 /* really we should have a top level context structure that has the
44    client file descriptor as an element. That would require a major rewrite :(
45
46    the following 2 functions are an alternative - they make the file
47    descriptor private to smbd
48  */
49 static int server_fd = -1;
50
51 int smbd_server_fd(void)
52 {
53         return server_fd;
54 }
55
56 void smbd_set_server_fd(int fd)
57 {
58         server_fd = fd;
59         client_setfd(fd);
60 }
61
62 /****************************************************************************
63   when exiting, take the whole family
64 ****************************************************************************/
65 static void *dflt_sig(void)
66 {
67         exit_server("caught signal");
68         return NULL;
69 }
70
71 /****************************************************************************
72   Send a SIGTERM to our process group.
73 *****************************************************************************/
74 static void  killkids(void)
75 {
76         if(am_parent) kill(0,SIGTERM);
77 }
78
79 /****************************************************************************
80   process a sam sync message - not sure whether to do this here or
81   somewhere else
82 ****************************************************************************/
83 static void msg_sam_sync(int msg_type, pid_t pid, void *buf, size_t len)
84 {
85         DEBUG(10, ("** sam sync message received, ignoring\n"));
86 }
87
88 /****************************************************************************
89   process a sam sync replicate message - not sure whether to do this here or
90   somewhere else
91 ****************************************************************************/
92 static void msg_sam_repl(int msg_type, pid_t pid, void *buf, size_t len)
93 {
94         uint32 low_serial;
95
96         if (len != sizeof(uint32))
97                 return;
98
99         low_serial = *((uint32 *)buf);
100
101         DEBUG(3, ("received sam replication message, serial = 0x%04x\n",
102                   low_serial));
103 }
104
105 /****************************************************************************
106   open the socket communication
107 ****************************************************************************/
108 static BOOL open_sockets_inetd(void)
109 {
110         /* Started from inetd. fd 0 is the socket. */
111         /* We will abort gracefully when the client or remote system 
112            goes away */
113         smbd_set_server_fd(dup(0));
114         
115         /* close our standard file descriptors */
116         close_low_fds();
117         
118         set_socket_options(smbd_server_fd(),"SO_KEEPALIVE");
119         set_socket_options(smbd_server_fd(),user_socket_options);
120
121         return True;
122 }
123
124
125 /****************************************************************************
126   open the socket communication
127 ****************************************************************************/
128 static BOOL open_sockets(BOOL is_daemon,int port)
129 {
130         int num_interfaces = iface_count();
131         int fd_listenset[FD_SETSIZE];
132         fd_set listen_set;
133         int s;
134         int i;
135
136         if (!is_daemon) {
137                 return open_sockets_inetd();
138         }
139
140                 
141 #ifdef HAVE_ATEXIT
142         {
143                 static int atexit_set;
144                 if(atexit_set == 0) {
145                         atexit_set=1;
146                         atexit(killkids);
147                 }
148         }
149 #endif
150
151         /* Stop zombies */
152         CatchChild();
153                 
154                 
155         FD_ZERO(&listen_set);
156
157         if(lp_interfaces() && lp_bind_interfaces_only()) {
158                 /* We have been given an interfaces line, and been 
159                    told to only bind to those interfaces. Create a
160                    socket per interface and bind to only these.
161                 */
162                 
163                 if(num_interfaces > FD_SETSIZE) {
164                         DEBUG(0,("open_sockets: Too many interfaces specified to bind to. Number was %d \
165 max can be %d\n", 
166                                  num_interfaces, FD_SETSIZE));
167                         return False;
168                 }
169                 
170                 /* Now open a listen socket for each of the
171                    interfaces. */
172                 for(i = 0; i < num_interfaces; i++) {
173                         struct in_addr *ifip = iface_n_ip(i);
174                         
175                         if(ifip == NULL) {
176                                 DEBUG(0,("open_sockets: interface %d has NULL IP address !\n", i));
177                                 continue;
178                         }
179                         s = fd_listenset[i] = open_socket_in(SOCK_STREAM, port, 0, ifip->s_addr, True);
180                         if(s == -1)
181                                 return False;
182
183                         /* ready to listen */
184                         set_socket_options(s,"SO_KEEPALIVE"); 
185                         set_socket_options(s,user_socket_options);
186       
187                         if (listen(s, 5) == -1) {
188                                 DEBUG(0,("listen: %s\n",strerror(errno)));
189                                 close(s);
190                                 return False;
191                         }
192                         FD_SET(s,&listen_set);
193                 }
194         } else {
195                 /* Just bind to 0.0.0.0 - accept connections
196                    from anywhere. */
197                 num_interfaces = 1;
198                 
199                 /* open an incoming socket */
200                 s = open_socket_in(SOCK_STREAM, port, 0,
201                                    interpret_addr(lp_socket_address()),True);
202                 if (s == -1)
203                         return(False);
204                 
205                 /* ready to listen */
206                 set_socket_options(s,"SO_KEEPALIVE"); 
207                 set_socket_options(s,user_socket_options);
208
209                 if (listen(s, 5) == -1) {
210                         DEBUG(0,("open_sockets: listen: %s\n",
211                                  strerror(errno)));
212                         close(s);
213                         return False;
214                 }
215                 
216                 fd_listenset[0] = s;
217                 FD_SET(s,&listen_set);
218         } 
219
220         /* Listen to messages */
221
222         message_register(MSG_SMB_SAM_SYNC, msg_sam_sync);
223         message_register(MSG_SMB_SAM_REPL, msg_sam_repl);
224
225         /* now accept incoming connections - forking a new process
226            for each incoming connection */
227         DEBUG(2,("waiting for a connection\n"));
228         while (1) {
229                 fd_set lfds;
230                 int num;
231                 
232                 /* Free up temporary memory from the main smbd. */
233                 lp_talloc_free();
234
235                 /* Ensure we respond to PING and DEBUG messages from the main smbd. */
236                 message_dispatch();
237
238                 memcpy((char *)&lfds, (char *)&listen_set, 
239                        sizeof(listen_set));
240                 
241                 num = sys_select(FD_SETSIZE,&lfds,NULL);
242                 
243                 if (num == -1 && errno == EINTR) {
244                         extern VOLATILE sig_atomic_t reload_after_sighup;
245
246                         /* check for sighup processing */
247                         if (reload_after_sighup) {
248                                 change_to_root_user();
249                                 DEBUG(1,("Reloading services after SIGHUP\n"));
250                                 reload_services(False);
251                                 reload_after_sighup = False;
252                         }
253
254                         continue;
255                 }
256                 
257                 /* check if we need to reload services */
258                 check_reload(time(NULL));
259
260                 /* Find the sockets that are read-ready -
261                    accept on these. */
262                 for( ; num > 0; num--) {
263                         struct sockaddr addr;
264                         socklen_t in_addrlen = sizeof(addr);
265                         
266                         s = -1;
267                         for(i = 0; i < num_interfaces; i++) {
268                                 if(FD_ISSET(fd_listenset[i],&lfds)) {
269                                         s = fd_listenset[i];
270                                         /* Clear this so we don't look
271                                            at it again. */
272                                         FD_CLR(fd_listenset[i],&lfds);
273                                         break;
274                                 }
275                         }
276
277                         smbd_set_server_fd(accept(s,&addr,&in_addrlen));
278                         
279                         if (smbd_server_fd() == -1 && errno == EINTR)
280                                 continue;
281                         
282                         if (smbd_server_fd() == -1) {
283                                 DEBUG(0,("open_sockets: accept: %s\n",
284                                          strerror(errno)));
285                                 continue;
286                         }
287                         
288                         if (smbd_server_fd() != -1 && sys_fork()==0) {
289                                 /* Child code ... */
290                                 
291                                 /* close the listening socket(s) */
292                                 for(i = 0; i < num_interfaces; i++)
293                                         close(fd_listenset[i]);
294                                 
295                                 /* close our standard file
296                                    descriptors */
297                                 close_low_fds();
298                                 am_parent = 0;
299                                 
300                                 set_socket_options(smbd_server_fd(),"SO_KEEPALIVE");
301                                 set_socket_options(smbd_server_fd(),user_socket_options);
302                                 
303                                 /* Reset global variables in util.c so
304                                    that client substitutions will be
305                                    done correctly in the process.  */
306                                 reset_globals_after_fork();
307
308                                 /* tdb needs special fork handling */
309                                 tdb_reopen_all();
310
311                                 return True; 
312                         }
313                         /* The parent doesn't need this socket */
314                         close(smbd_server_fd()); 
315
316                         /* Sun May 6 18:56:14 2001 ackley@cs.unm.edu:
317                                 Clear the closed fd info out of server_fd --
318                                 and more importantly, out of client_fd in
319                                 util_sock.c, to avoid a possible
320                                 getpeername failure if we reopen the logs
321                                 and use %I in the filename.
322                         */
323
324                         smbd_set_server_fd(-1);
325
326                         /* Force parent to check log size after
327                          * spawning child.  Fix from
328                          * klausr@ITAP.Physik.Uni-Stuttgart.De.  The
329                          * parent smbd will log to logserver.smb.  It
330                          * writes only two messages for each child
331                          * started/finished. But each child writes,
332                          * say, 50 messages also in logserver.smb,
333                          * begining with the debug_count of the
334                          * parent, before the child opens its own log
335                          * file logserver.client. In a worst case
336                          * scenario the size of logserver.smb would be
337                          * checked after about 50*50=2500 messages
338                          * (ca. 100kb).
339                          * */
340                         force_check_log_size();
341  
342                 } /* end for num */
343         } /* end while 1 */
344
345 /* NOTREACHED   return True; */
346 }
347
348 /****************************************************************************
349   reload the services file
350   **************************************************************************/
351 BOOL reload_services(BOOL test)
352 {
353         BOOL ret;
354         
355         if (lp_loaded()) {
356                 pstring fname;
357                 pstrcpy(fname,lp_configfile());
358                 if (file_exist(fname,NULL) && !strcsequal(fname,dyn_CONFIGFILE)) {
359                         pstrcpy(dyn_CONFIGFILE,fname);
360                         test = False;
361                 }
362         }
363
364         reopen_logs();
365
366         if (test && !lp_file_list_changed())
367                 return(True);
368
369         lp_killunused(conn_snum_used);
370         
371         ret = lp_load(dyn_CONFIGFILE,False,False,True);
372
373         load_printers();
374
375         /* perhaps the config filename is now set */
376         if (!test)
377                 reload_services(True);
378
379         reopen_logs();
380
381         load_interfaces();
382
383         {
384                 if (smbd_server_fd() != -1) {      
385                         set_socket_options(smbd_server_fd(),"SO_KEEPALIVE");
386                         set_socket_options(smbd_server_fd(),user_socket_options);
387                 }
388         }
389
390         reset_mangled_cache();
391         reset_stat_cache();
392
393         /* this forces service parameters to be flushed */
394         set_current_service(NULL,True);
395
396         return(ret);
397 }
398
399
400
401 /****************************************************************************
402  Catch a sighup.
403 ****************************************************************************/
404
405 VOLATILE sig_atomic_t reload_after_sighup = False;
406
407 static void sig_hup(int sig)
408 {
409         BlockSignals(True,SIGHUP);
410         DEBUG(0,("Got SIGHUP\n"));
411
412         sys_select_signal();
413         reload_after_sighup = True;
414         BlockSignals(False,SIGHUP);
415 }
416
417
418
419 #if DUMP_CORE
420 /*******************************************************************
421 prepare to dump a core file - carefully!
422 ********************************************************************/
423 static BOOL dump_core(void)
424 {
425         char *p;
426         pstring dname;
427         pstrcpy(dname,lp_logfile());
428         if ((p=strrchr_m(dname,'/'))) *p=0;
429         pstrcat(dname,"/corefiles");
430         mkdir(dname,0700);
431         sys_chown(dname,getuid(),getgid());
432         chmod(dname,0700);
433         if (chdir(dname)) return(False);
434         umask(~(0700));
435
436 #ifdef HAVE_GETRLIMIT
437 #ifdef RLIMIT_CORE
438         {
439                 struct rlimit rlp;
440                 getrlimit(RLIMIT_CORE, &rlp);
441                 rlp.rlim_cur = MAX(4*1024*1024,rlp.rlim_cur);
442                 setrlimit(RLIMIT_CORE, &rlp);
443                 getrlimit(RLIMIT_CORE, &rlp);
444                 DEBUG(3,("Core limits now %d %d\n",
445                          (int)rlp.rlim_cur,(int)rlp.rlim_max));
446         }
447 #endif
448 #endif
449
450
451         DEBUG(0,("Dumping core in %s\n",dname));
452         abort();
453         return(True);
454 }
455 #endif
456
457 /****************************************************************************
458 update the current smbd process count
459 ****************************************************************************/
460
461 static void decrement_smbd_process_count(void)
462 {
463         int total_smbds;
464
465         if (lp_max_smbd_processes()) {
466                 total_smbds = 0;
467                 tdb_change_int_atomic(conn_tdb_ctx(), "INFO/total_smbds", &total_smbds, -1);
468         }
469 }
470
471 /****************************************************************************
472 exit the server
473 ****************************************************************************/
474 void exit_server(char *reason)
475 {
476         static int firsttime=1;
477         extern char *last_inbuf;
478         extern struct auth_context *negprot_global_auth_context;
479
480         if (!firsttime)
481                 exit(0);
482         firsttime = 0;
483
484         change_to_root_user();
485         DEBUG(2,("Closing connections\n"));
486
487         if (negprot_global_auth_context) {
488                 negprot_global_auth_context->free(&negprot_global_auth_context);
489         }
490
491         conn_close_all();
492
493         invalidate_all_vuids();
494
495         /* delete our entry in the connections database. */
496         yield_connection(NULL,"",MAXSTATUS);
497
498         respond_to_all_remaining_local_messages();
499         decrement_smbd_process_count();
500
501 #ifdef WITH_DFS
502         if (dcelogin_atmost_once) {
503                 dfs_unlogin();
504         }
505 #endif
506
507         if (!reason) {   
508                 int oldlevel = DEBUGLEVEL;
509                 DEBUGLEVEL = 10;
510                 DEBUG(0,("Last message was %s\n",smb_fn_name(last_message)));
511                 if (last_inbuf)
512                         show_msg(last_inbuf);
513                 DEBUGLEVEL = oldlevel;
514                 DEBUG(0,("===============================================================\n"));
515 #if DUMP_CORE
516                 if (dump_core()) return;
517 #endif
518         }    
519
520         locking_end();
521
522         DEBUG(3,("Server exit (%s)\n", (reason ? reason : "")));
523         exit(0);
524 }
525
526 /****************************************************************************
527   initialise connect, service and file structs
528 ****************************************************************************/
529 static void init_structs(void )
530 {
531         /*
532          * Set the machine NETBIOS name if not already
533          * set from the config file.
534          */
535
536         if (!*global_myname) {
537                 char *p;
538                 fstrcpy( global_myname, myhostname() );
539                 p = strchr_m( global_myname, '.' );
540                 if (p) 
541                         *p = 0;
542         }
543
544         strupper( global_myname );
545
546         conn_init();
547
548         file_init();
549
550         /* for RPC pipes */
551         init_rpc_pipe_hnd();
552
553         init_dptrs();
554
555         secrets_init();
556 }
557
558 /****************************************************************************
559 usage on the program
560 ****************************************************************************/
561 static void usage(char *pname)
562 {
563
564         d_printf("Usage: %s [-DaioPh?Vb] [-d debuglevel] [-l log basename] [-p port]\n", pname);
565         d_printf("       [-O socket options] [-s services file]\n");
566         d_printf("\t-D                    Become a daemon (default)\n");
567         d_printf("\t-a                    Append to log file (default)\n");
568         d_printf("\t-i                    Run interactive (not a daemon)\n" );
569         d_printf("\t-o                    Overwrite log file, don't append\n");
570         d_printf("\t-h                    Print usage\n");
571         d_printf("\t-?                    Print usage\n");
572         d_printf("\t-V                    Print version\n");
573         d_printf("\t-b                    Print build options\n");
574         d_printf("\t-d debuglevel         Set the debuglevel\n");
575         d_printf("\t-l log basename.      Basename for log/debug files\n");
576         d_printf("\t-p port               Listen on the specified port\n");
577         d_printf("\t-O socket options     Socket options\n");
578         d_printf("\t-s services file.     Filename of services file\n");
579         d_printf("\n");
580 }
581
582 /****************************************************************************
583   main program
584 ****************************************************************************/
585  int main(int argc,char *argv[])
586 {
587         extern BOOL append_log;
588         extern char *optarg;
589         /* shall I run as a daemon */
590         BOOL is_daemon = False;
591         BOOL interactive = False;
592         BOOL specified_logfile = False;
593         int port = SMB_PORT;
594         int opt;
595         pstring logfile;
596
597 #ifdef HAVE_SET_AUTH_PARAMETERS
598         set_auth_parameters(argc,argv);
599 #endif
600
601         /* this is for people who can't start the program correctly */
602         while (argc > 1 && (*argv[1] != '-')) {
603                 argv++;
604                 argc--;
605         }
606
607         while ( EOF != (opt = getopt(argc, argv, "O:l:s:d:Dp:h?bVaiof:")) )
608                 switch (opt)  {
609                 case 'O':
610                         pstrcpy(user_socket_options,optarg);
611                         break;
612
613                 case 's':
614                         pstrcpy(dyn_CONFIGFILE,optarg);
615                         break;
616
617                 case 'l':
618                         specified_logfile = True;
619                         slprintf(logfile, sizeof(logfile)-1, "%s/log.smbd", optarg);
620                         lp_set_logfile(logfile);
621                         break;
622
623                 case 'a':
624                         append_log = True;
625                         break;
626
627                 case 'i':
628                         interactive = True;
629                         break;
630
631                 case 'o':
632                         append_log = False;
633                         break;
634
635                 case 'D':
636                         is_daemon = True;
637                         break;
638
639                 case 'd':
640                         if (*optarg == 'A')
641                                 DEBUGLEVEL = 10000;
642                         else
643                                 DEBUGLEVEL = atoi(optarg);
644                         break;
645
646                 case 'p':
647                         port = atoi(optarg);
648                         break;
649
650                 case 'h':
651                 case '?':
652                         usage(argv[0]);
653                         exit(0);
654                         break;
655
656                 case 'V':
657                         d_printf("Version %s\n",VERSION);
658                         exit(0);
659                         break;
660                 case 'b':
661                         build_options(True); /* Display output to screen as well as debug */ 
662                         exit(0);
663                         break;
664                 default:
665                         DEBUG(0,("Incorrect program usage - are you sure the command line is correct?\n"));
666                         usage(argv[0]);
667                         exit(1);
668                 }
669
670 #ifdef HAVE_SETLUID
671         /* needed for SecureWare on SCO */
672         setluid(0);
673 #endif
674
675         sec_init();
676
677         load_case_tables();
678
679         append_log = True;
680
681         if(!specified_logfile) {
682                 slprintf(logfile, sizeof(logfile)-1, "%s/log.smbd",
683                          dyn_LOGFILEBASE);
684                 lp_set_logfile(logfile);
685         }
686
687         pstrcpy(remote_machine, "smbd");
688
689         setup_logging(argv[0],interactive);
690
691         /* we want to re-seed early to prevent time delays causing
692            client problems at a later date. (tridge) */
693         generate_random_buffer(NULL, 0, False);
694
695         /* make absolutely sure we run as root - to handle cases where people
696            are crazy enough to have it setuid */
697
698         gain_root_privilege();
699         gain_root_group_privilege();
700
701         fault_setup((void (*)(void *))exit_server);
702         CatchSignal(SIGTERM , SIGNAL_CAST dflt_sig);
703
704         /* we are never interested in SIGPIPE */
705         BlockSignals(True,SIGPIPE);
706
707 #if defined(SIGFPE)
708         /* we are never interested in SIGFPE */
709         BlockSignals(True,SIGFPE);
710 #endif
711
712 #if defined(SIGUSR2)
713         /* We are no longer interested in USR2 */
714         BlockSignals(True,SIGUSR2);
715 #endif
716
717         /* POSIX demands that signals are inherited. If the invoking process has
718          * these signals masked, we will have problems, as we won't recieve them. */
719         BlockSignals(False, SIGHUP);
720         BlockSignals(False, SIGUSR1);
721
722         /* we want total control over the permissions on created files,
723            so set our umask to 0 */
724         umask(0);
725
726         init_sec_ctx();
727
728         reopen_logs();
729
730         DEBUG(1,( "smbd version %s started.\n", VERSION));
731         DEBUGADD(1,( "Copyright Andrew Tridgell 1992-2002\n"));
732
733         DEBUG(2,("uid=%d gid=%d euid=%d egid=%d\n",
734                  (int)getuid(),(int)getgid(),(int)geteuid(),(int)getegid()));
735
736         /* Output the build options to the debug log */ 
737         build_options(False);
738
739         if (sizeof(uint16) < 2 || sizeof(uint32) < 4) {
740                 DEBUG(0,("ERROR: Samba is not configured correctly for the word size on your machine\n"));
741                 exit(1);
742         }
743
744         /*
745          * Do this before reload_services.
746          */
747
748         if (!reload_services(False))
749                 return(-1);     
750
751         init_structs();
752
753         /* don't call winbind for our domain if we are the DC */
754         if (lp_domain_logons()) {
755                 winbind_exclude_domain(lp_workgroup());
756         }
757         
758 #ifdef WITH_PROFILE
759         if (!profile_setup(False)) {
760                 DEBUG(0,("ERROR: failed to setup profiling\n"));
761                 return -1;
762         }
763 #endif
764
765 #ifdef WITH_SSL
766         {
767                 extern BOOL sslEnabled;
768                 sslEnabled = lp_ssl_enabled();
769                 if(sslEnabled)
770                         sslutil_init(True);
771         }
772 #endif        /* WITH_SSL */
773
774         fstrcpy(global_myworkgroup, lp_workgroup());
775
776         CatchSignal(SIGHUP,SIGNAL_CAST sig_hup);
777         
778         DEBUG(3,( "loaded services\n"));
779
780         if (!is_daemon && !is_a_socket(0)) {
781                 DEBUG(0,("standard input is not a socket, assuming -D option\n"));
782                 is_daemon = True;
783         }
784
785         if (is_daemon && !interactive) {
786                 DEBUG( 3, ( "Becoming a daemon.\n" ) );
787                 become_daemon();
788         }
789
790 #if HAVE_SETPGID
791         /*
792          * If we're interactive we want to set our own process group for
793          * signal management.
794          */
795         if (interactive)
796                 setpgid( (pid_t)0, (pid_t)0);
797 #endif
798
799         if (!directory_exist(lp_lockdir(), NULL)) {
800                 mkdir(lp_lockdir(), 0755);
801         }
802
803         if (is_daemon) {
804                 pidfile_create("smbd");
805         }
806
807         if (!message_init()) {
808                 exit(1);
809         }
810         register_msg_pool_usage();
811
812         /* Setup the main smbd so that we can get messages. */
813         claim_connection(NULL,"",MAXSTATUS,True);
814
815         /* 
816            DO NOT ENABLE THIS TILL YOU COPE WITH KILLING THESE TASKS AND INETD
817            THIS *killed* LOTS OF BUILD FARM MACHINES. IT CREATED HUNDREDS OF 
818            smbd PROCESSES THAT NEVER DIE
819            start_background_queue(); 
820         */
821
822         if (!open_sockets(is_daemon,port))
823                 exit(1);
824
825         /*
826          * everything after this point is run after the fork()
827          */ 
828
829         if (!locking_init(0)) {
830                 exit(1);
831         }
832
833         if (!print_backend_init()) {
834                 exit(1);
835         }
836
837         if (!share_info_db_init()) {
838                 exit(1);
839         }
840
841         if(!initialize_password_db(False)) {
842                 exit(1);
843         }
844
845         /* possibly reload the services file. */
846         reload_services(True);
847
848         if(!pdb_generate_sam_sid()) {
849                 DEBUG(0,("ERROR: Samba cannot create a SAM SID.\n"));
850                 exit(1);
851         }
852
853         if (!init_group_mapping()) {
854                 DEBUG(0,("Could not open tdb mapping file.\n"));
855                 return 0;
856         }
857
858         if (!init_account_policy()) {
859                 DEBUG(0,("Could not open account policy tdb.\n"));
860                 exit(1);
861         }
862
863         if (*lp_rootdir()) {
864                 if (sys_chroot(lp_rootdir()) == 0)
865                         DEBUG(2,("Changed root to %s\n", lp_rootdir()));
866         }
867
868         /* Setup oplocks */
869         if (!init_oplocks()) {
870                 exit(1);
871         }
872         
873         /* Setup mangle */
874         if (!init_mangle_tdb()) {
875                 exit(1);
876         }
877
878         /* Setup change notify */
879         if (!init_change_notify()) {
880                 exit(1);
881         }
882
883         smbd_process();
884         
885         exit_server("normal exit");
886         return(0);
887 }