source: branches/samba-3.0/source/nmbd/nmbd.c@ 422

Last change on this file since 422 was 158, checked in by Paul Smedley, 17 years ago

Update source to 3.0.32

File size: 21.7 KB
Line 
1/*
2 Unix SMB/CIFS implementation.
3 NBT netbios routines and daemon - version 2
4 Copyright (C) Andrew Tridgell 1994-1998
5 Copyright (C) Jeremy Allison 1997-2002
6 Copyright (C) Jelmer Vernooij 2002,2003 (Conversion to popt)
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#include "includes.h"
25
26int ClientNMB = -1;
27int ClientDGRAM = -1;
28int global_nmb_port = -1;
29
30extern BOOL rescan_listen_set;
31extern struct in_addr loopback_ip;
32extern BOOL global_in_nmbd;
33
34extern BOOL override_logfile;
35
36/* are we running as a daemon ? */
37static BOOL is_daemon;
38
39/* fork or run in foreground ? */
40static BOOL Fork = True;
41
42/* log to standard output ? */
43static BOOL log_stdout;
44
45/* have we found LanMan clients yet? */
46BOOL found_lm_clients = False;
47
48/* what server type are we currently */
49
50time_t StartupTime = 0;
51
52/**************************************************************************** **
53 Handle a SIGTERM in band.
54 **************************************************************************** */
55
56static void terminate(void)
57{
58 DEBUG(0,("Got SIGTERM: going down...\n"));
59
60 /* Write out wins.dat file if samba is a WINS server */
61 wins_write_database(0,False);
62
63 /* Remove all SELF registered names from WINS */
64 release_wins_names();
65
66 /* Announce all server entries as 0 time-to-live, 0 type. */
67 announce_my_servers_removed();
68
69 /* If there was an async dns child - kill it. */
70 kill_async_dns_child();
71
72 exit(0);
73}
74
75/**************************************************************************** **
76 Handle a SHUTDOWN message from smbcontrol.
77 **************************************************************************** */
78
79static void nmbd_terminate(int msg_type, struct process_id src,
80 void *buf, size_t len, void *private_data)
81{
82 terminate();
83}
84
85/**************************************************************************** **
86 Catch a SIGTERM signal.
87 **************************************************************************** */
88
89static SIG_ATOMIC_T got_sig_term;
90
91static void sig_term(int sig)
92{
93 got_sig_term = 1;
94 sys_select_signal(SIGTERM);
95}
96
97/**************************************************************************** **
98 Catch a SIGHUP signal.
99 **************************************************************************** */
100
101static SIG_ATOMIC_T reload_after_sighup;
102
103static void sig_hup(int sig)
104{
105 reload_after_sighup = 1;
106 sys_select_signal(SIGHUP);
107}
108
109/**************************************************************************** **
110 Possibly continue after a fault.
111 **************************************************************************** */
112
113static void fault_continue(void)
114{
115 dump_core();
116}
117
118/**************************************************************************** **
119 Expire old names from the namelist and server list.
120 **************************************************************************** */
121
122static void expire_names_and_servers(time_t t)
123{
124 static time_t lastrun = 0;
125
126 if ( !lastrun )
127 lastrun = t;
128 if ( t < (lastrun + 5) )
129 return;
130 lastrun = t;
131
132 /*
133 * Expire any timed out names on all the broadcast
134 * subnets and those registered with the WINS server.
135 * (nmbd_namelistdb.c)
136 */
137
138 expire_names(t);
139
140 /*
141 * Go through all the broadcast subnets and for each
142 * workgroup known on that subnet remove any expired
143 * server names. If a workgroup has an empty serverlist
144 * and has itself timed out then remove the workgroup.
145 * (nmbd_workgroupdb.c)
146 */
147
148 expire_workgroups_and_servers(t);
149}
150
151/************************************************************************** **
152 Reload the list of network interfaces.
153 Doesn't return until a network interface is up.
154 ************************************************************************** */
155
156static void reload_interfaces(time_t t)
157{
158 static time_t lastt;
159 int n;
160 bool print_waiting_msg = true;
161 struct subnet_record *subrec;
162
163 if (t && ((t - lastt) < NMBD_INTERFACES_RELOAD)) {
164 return;
165 }
166 lastt = t;
167
168 if (!interfaces_changed()) {
169 return;
170 }
171
172 try_again:
173
174 /* the list of probed interfaces has changed, we may need to add/remove
175 some subnets */
176 load_interfaces();
177
178 /* find any interfaces that need adding */
179 for (n=iface_count() - 1; n >= 0; n--) {
180 struct interface *iface = get_interface(n);
181
182 if (!iface) {
183 DEBUG(2,("reload_interfaces: failed to get interface %d\n", n));
184 continue;
185 }
186
187 /*
188 * We don't want to add a loopback interface, in case
189 * someone has added 127.0.0.1 for smbd, nmbd needs to
190 * ignore it here. JRA.
191 */
192
193 if (ip_equal(iface->ip, loopback_ip)) {
194 DEBUG(2,("reload_interfaces: Ignoring loopback interface %s\n", inet_ntoa(iface->ip)));
195 continue;
196 }
197
198 for (subrec=subnetlist; subrec; subrec=subrec->next) {
199 if (ip_equal(iface->ip, subrec->myip) &&
200 ip_equal(iface->nmask, subrec->mask_ip)) break;
201 }
202
203 if (!subrec) {
204 /* it wasn't found! add it */
205 DEBUG(2,("Found new interface %s\n",
206 inet_ntoa(iface->ip)));
207 subrec = make_normal_subnet(iface);
208 if (subrec)
209 register_my_workgroup_one_subnet(subrec);
210 }
211 }
212
213 /* find any interfaces that need deleting */
214 for (subrec=subnetlist; subrec; subrec=subrec->next) {
215 for (n=iface_count() - 1; n >= 0; n--) {
216 struct interface *iface = get_interface(n);
217 if (ip_equal(iface->ip, subrec->myip) &&
218 ip_equal(iface->nmask, subrec->mask_ip)) break;
219 }
220 if (n == -1) {
221 /* oops, an interface has disapeared. This is
222 tricky, we don't dare actually free the
223 interface as it could be being used, so
224 instead we just wear the memory leak and
225 remove it from the list of interfaces without
226 freeing it */
227 DEBUG(2,("Deleting dead interface %s\n",
228 inet_ntoa(subrec->myip)));
229 close_subnet(subrec);
230 }
231 }
232
233 rescan_listen_set = True;
234
235 /* We need to wait if there are no subnets... */
236 if (FIRST_SUBNET == NULL) {
237
238 if (print_waiting_msg) {
239 DEBUG(0,("reload_interfaces: "
240 "No subnets to listen to. Waiting..\n"));
241 print_waiting_msg = false;
242 }
243
244 /*
245 * Whilst we're waiting for an interface, allow SIGTERM to
246 * cause us to exit.
247 */
248
249 BlockSignals(false, SIGTERM);
250
251 while (iface_count_nl() == 0 && !got_sig_term) {
252 sleep(5);
253 load_interfaces();
254 }
255
256 /*
257 * Handle termination inband.
258 */
259
260 if (got_sig_term) {
261 got_sig_term = 0;
262 terminate();
263 }
264
265 /*
266 * We got an interface, go back to blocking term.
267 */
268
269 BlockSignals(true, SIGTERM);
270 goto try_again;
271 }
272}
273
274/**************************************************************************** **
275 Reload the services file.
276 **************************************************************************** */
277
278static BOOL reload_nmbd_services(BOOL test)
279{
280 BOOL ret;
281
282 set_remote_machine_name("nmbd", False);
283
284 if ( lp_loaded() ) {
285 pstring fname;
286 pstrcpy( fname,lp_configfile());
287 if (file_exist(fname,NULL) && !strcsequal(fname,dyn_CONFIGFILE)) {
288 pstrcpy(dyn_CONFIGFILE,fname);
289 test = False;
290 }
291 }
292
293 if ( test && !lp_file_list_changed() )
294 return(True);
295
296 ret = lp_load( dyn_CONFIGFILE, True , False, False, True);
297
298 /* perhaps the config filename is now set */
299 if ( !test ) {
300 DEBUG( 3, ( "services not loaded\n" ) );
301 reload_nmbd_services( True );
302 }
303
304 return(ret);
305}
306
307/**************************************************************************** **
308 * React on 'smbcontrol nmbd reload-config' in the same way as to SIGHUP
309 **************************************************************************** */
310
311static void msg_reload_nmbd_services(int msg_type, struct process_id src,
312 void *buf, size_t len, void *private_data)
313{
314 write_browse_list( 0, True );
315 dump_all_namelists();
316 reload_nmbd_services( True );
317 reopen_logs();
318 reload_interfaces(0);
319}
320
321static void msg_nmbd_send_packet(int msg_type, struct process_id src,
322 void *buf, size_t len, void *private_data)
323{
324 struct packet_struct *p = (struct packet_struct *)buf;
325 struct subnet_record *subrec;
326 struct in_addr *local_ip;
327
328 DEBUG(10, ("Received send_packet from %d\n", procid_to_pid(&src)));
329
330 if (len != sizeof(struct packet_struct)) {
331 DEBUG(2, ("Discarding invalid packet length from %d\n",
332 procid_to_pid(&src)));
333 return;
334 }
335
336 if ((p->packet_type != NMB_PACKET) &&
337 (p->packet_type != DGRAM_PACKET)) {
338 DEBUG(2, ("Discarding invalid packet type from %d: %d\n",
339 procid_to_pid(&src), p->packet_type));
340 return;
341 }
342
343 local_ip = iface_ip(p->ip);
344
345 if (local_ip == NULL) {
346 DEBUG(2, ("Could not find ip for packet from %d\n",
347 procid_to_pid(&src)));
348 return;
349 }
350
351 subrec = FIRST_SUBNET;
352
353 p->fd = (p->packet_type == NMB_PACKET) ?
354 subrec->nmb_sock : subrec->dgram_sock;
355
356 for (subrec = FIRST_SUBNET; subrec != NULL;
357 subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) {
358 if (ip_equal(*local_ip, subrec->myip)) {
359 p->fd = (p->packet_type == NMB_PACKET) ?
360 subrec->nmb_sock : subrec->dgram_sock;
361 break;
362 }
363 }
364
365 if (p->packet_type == DGRAM_PACKET) {
366 p->port = 138;
367 p->packet.dgram.header.source_ip.s_addr = local_ip->s_addr;
368 p->packet.dgram.header.source_port = 138;
369 }
370
371 send_packet(p);
372}
373
374/**************************************************************************** **
375 The main select loop.
376 **************************************************************************** */
377
378static void process(void)
379{
380 BOOL run_election;
381
382 while( True ) {
383 time_t t = time(NULL);
384
385 /* Check for internal messages */
386
387 message_dispatch();
388
389 /*
390 * Check all broadcast subnets to see if
391 * we need to run an election on any of them.
392 * (nmbd_elections.c)
393 */
394
395 run_election = check_elections();
396
397 /*
398 * Read incoming UDP packets.
399 * (nmbd_packets.c)
400 */
401
402 if(listen_for_packets(run_election))
403 return;
404
405 /*
406 * Handle termination inband.
407 */
408
409 if (got_sig_term) {
410 got_sig_term = 0;
411 terminate();
412 }
413
414 /*
415 * Process all incoming packets
416 * read above. This calls the success and
417 * failure functions registered when response
418 * packets arrrive, and also deals with request
419 * packets from other sources.
420 * (nmbd_packets.c)
421 */
422
423 run_packet_queue();
424
425 /*
426 * Run any elections - initiate becoming
427 * a local master browser if we have won.
428 * (nmbd_elections.c)
429 */
430
431 run_elections(t);
432
433 /*
434 * Send out any broadcast announcements
435 * of our server names. This also announces
436 * the workgroup name if we are a local
437 * master browser.
438 * (nmbd_sendannounce.c)
439 */
440
441 announce_my_server_names(t);
442
443 /*
444 * Send out any LanMan broadcast announcements
445 * of our server names.
446 * (nmbd_sendannounce.c)
447 */
448
449 announce_my_lm_server_names(t);
450
451 /*
452 * If we are a local master browser, periodically
453 * announce ourselves to the domain master browser.
454 * This also deals with syncronising the domain master
455 * browser server lists with ourselves as a local
456 * master browser.
457 * (nmbd_sendannounce.c)
458 */
459
460 announce_myself_to_domain_master_browser(t);
461
462 /*
463 * Fullfill any remote announce requests.
464 * (nmbd_sendannounce.c)
465 */
466
467 announce_remote(t);
468
469 /*
470 * Fullfill any remote browse sync announce requests.
471 * (nmbd_sendannounce.c)
472 */
473
474 browse_sync_remote(t);
475
476 /*
477 * Scan the broadcast subnets, and WINS client
478 * namelists and refresh any that need refreshing.
479 * (nmbd_mynames.c)
480 */
481
482 refresh_my_names(t);
483
484 /*
485 * Scan the subnet namelists and server lists and
486 * expire thos that have timed out.
487 * (nmbd.c)
488 */
489
490 expire_names_and_servers(t);
491
492 /*
493 * Write out a snapshot of our current browse list into
494 * the browse.dat file. This is used by smbd to service
495 * incoming NetServerEnum calls - used to synchronise
496 * browse lists over subnets.
497 * (nmbd_serverlistdb.c)
498 */
499
500 write_browse_list(t, False);
501
502 /*
503 * If we are a domain master browser, we have a list of
504 * local master browsers we should synchronise browse
505 * lists with (these are added by an incoming local
506 * master browser announcement packet). Expire any of
507 * these that are no longer current, and pull the server
508 * lists from each of these known local master browsers.
509 * (nmbd_browsesync.c)
510 */
511
512 dmb_expire_and_sync_browser_lists(t);
513
514 /*
515 * Check that there is a local master browser for our
516 * workgroup for all our broadcast subnets. If one
517 * is not found, start an election (which we ourselves
518 * may or may not participate in, depending on the
519 * setting of the 'local master' parameter.
520 * (nmbd_elections.c)
521 */
522
523 check_master_browser_exists(t);
524
525 /*
526 * If we are configured as a logon server, attempt to
527 * register the special NetBIOS names to become such
528 * (WORKGROUP<1c> name) on all broadcast subnets and
529 * with the WINS server (if used). If we are configured
530 * to become a domain master browser, attempt to register
531 * the special NetBIOS name (WORKGROUP<1b> name) to
532 * become such.
533 * (nmbd_become_dmb.c)
534 */
535
536 add_domain_names(t);
537
538 /*
539 * If we are a WINS server, do any timer dependent
540 * processing required.
541 * (nmbd_winsserver.c)
542 */
543
544 initiate_wins_processing(t);
545
546 /*
547 * If we are a domain master browser, attempt to contact the
548 * WINS server to get a list of all known WORKGROUPS/DOMAINS.
549 * This will only work to a Samba WINS server.
550 * (nmbd_browsesync.c)
551 */
552
553 if (lp_enhanced_browsing())
554 collect_all_workgroup_names_from_wins_server(t);
555
556 /*
557 * Go through the response record queue and time out or re-transmit
558 * and expired entries.
559 * (nmbd_packets.c)
560 */
561
562 retransmit_or_expire_response_records(t);
563
564 /*
565 * check to see if any remote browse sync child processes have completed
566 */
567
568 sync_check_completion();
569
570 /*
571 * regularly sync with any other DMBs we know about
572 */
573
574 if (lp_enhanced_browsing())
575 sync_all_dmbs(t);
576
577 /*
578 * clear the unexpected packet queue
579 */
580
581 clear_unexpected(t);
582
583 /*
584 * Reload the services file if we got a sighup.
585 */
586
587 if(reload_after_sighup) {
588 DEBUG( 0, ( "Got SIGHUP dumping debug info.\n" ) );
589 msg_reload_nmbd_services(MSG_SMB_CONF_UPDATED,
590 pid_to_procid(0), NULL, 0, NULL);
591 reload_after_sighup = 0;
592 }
593
594 /* check for new network interfaces */
595
596 reload_interfaces(t);
597
598 /* free up temp memory */
599 lp_TALLOC_FREE();
600 }
601}
602
603/**************************************************************************** **
604 Open the socket communication.
605 **************************************************************************** */
606
607static BOOL open_sockets(BOOL isdaemon, int port)
608{
609 /*
610 * The sockets opened here will be used to receive broadcast
611 * packets *only*. Interface specific sockets are opened in
612 * make_subnet() in namedbsubnet.c. Thus we bind to the
613 * address "0.0.0.0". The parameter 'socket address' is
614 * now deprecated.
615 */
616
617 if ( isdaemon )
618 ClientNMB = open_socket_in(SOCK_DGRAM, port,
619 0, interpret_addr(lp_socket_address()),
620 True);
621 else
622 ClientNMB = 0;
623
624 ClientDGRAM = open_socket_in(SOCK_DGRAM, DGRAM_PORT,
625 3, interpret_addr(lp_socket_address()),
626 True);
627
628 if ( ClientNMB == -1 )
629 return( False );
630
631 /* we are never interested in SIGPIPE */
632 BlockSignals(True,SIGPIPE);
633
634 set_socket_options( ClientNMB, "SO_BROADCAST" );
635 set_socket_options( ClientDGRAM, "SO_BROADCAST" );
636
637 /* Ensure we're non-blocking. */
638 set_blocking( ClientNMB, False);
639 set_blocking( ClientDGRAM, False);
640
641 DEBUG( 3, ( "open_sockets: Broadcast sockets opened.\n" ) );
642 return( True );
643}
644
645/**************************************************************************** **
646 main program
647 **************************************************************************** */
648 int main(int argc, const char *argv[])
649{
650 pstring logfile;
651 static BOOL opt_interactive;
652 poptContext pc;
653#ifndef __OS2__
654 static char *p_lmhosts = dyn_LMHOSTSFILE;
655#else
656 char *p_lmhosts = dyn_LMHOSTSFILE;
657#endif /* __OS2__ */
658 static BOOL no_process_group = False;
659 struct poptOption long_options[] = {
660 POPT_AUTOHELP
661 {"daemon", 'D', POPT_ARG_VAL, &is_daemon, True, "Become a daemon(default)" },
662 {"interactive", 'i', POPT_ARG_VAL, &opt_interactive, True, "Run interactive (not a daemon)" },
663 {"foreground", 'F', POPT_ARG_VAL, &Fork, False, "Run daemon in foreground (for daemontools & etc)" },
664 {"no-process-group", 0, POPT_ARG_VAL, &no_process_group, True, "Don't create a new process group" },
665 {"log-stdout", 'S', POPT_ARG_VAL, &log_stdout, True, "Log to stdout" },
666 {"hosts", 'H', POPT_ARG_STRING, &p_lmhosts, 'H', "Load a netbios hosts file"},
667 {"port", 'p', POPT_ARG_INT, &global_nmb_port, NMB_PORT, "Listen on the specified port" },
668 POPT_COMMON_SAMBA
669 { NULL }
670 };
671
672 load_case_tables();
673
674 global_nmb_port = NMB_PORT;
675
676 pc = poptGetContext("nmbd", argc, argv, long_options, 0);
677 while (poptGetNextOpt(pc) != -1) {};
678 poptFreeContext(pc);
679
680 global_in_nmbd = True;
681
682 StartupTime = time(NULL);
683
684 sys_srandom(time(NULL) ^ sys_getpid());
685
686 if (!override_logfile) {
687 slprintf(logfile, sizeof(logfile)-1, "%s/log.nmbd", dyn_LOGFILEBASE);
688 lp_set_logfile(logfile);
689 }
690
691 fault_setup((void (*)(void *))fault_continue );
692 dump_core_setup("nmbd");
693
694 /* POSIX demands that signals are inherited. If the invoking process has
695 * these signals masked, we will have problems, as we won't receive them. */
696 BlockSignals(False, SIGHUP);
697 BlockSignals(False, SIGUSR1);
698 BlockSignals(False, SIGTERM);
699
700 CatchSignal( SIGHUP, SIGNAL_CAST sig_hup );
701 CatchSignal( SIGTERM, SIGNAL_CAST sig_term );
702
703#if defined(SIGFPE)
704 /* we are never interested in SIGFPE */
705 BlockSignals(True,SIGFPE);
706#endif
707
708 /* We no longer use USR2... */
709#if defined(SIGUSR2)
710 BlockSignals(True, SIGUSR2);
711#endif
712
713 if ( opt_interactive ) {
714 Fork = False;
715 log_stdout = True;
716 }
717
718 if ( log_stdout && Fork ) {
719 DEBUG(0,("ERROR: Can't log to stdout (-S) unless daemon is in foreground (-F) or interactive (-i)\n"));
720 exit(1);
721 }
722
723 setup_logging( argv[0], log_stdout );
724
725 reopen_logs();
726
727 DEBUG( 0, ( "Netbios nameserver version %s started.\n", SAMBA_VERSION_STRING) );
728 DEBUGADD( 0, ( "%s\n", COPYRIGHT_STARTUP_MESSAGE ) );
729
730 if ( !reload_nmbd_services(False) )
731 return(-1);
732
733 if(!init_names())
734 return -1;
735
736 reload_nmbd_services( True );
737
738 if (strequal(lp_workgroup(),"*")) {
739 DEBUG(0,("ERROR: a workgroup name of * is no longer supported\n"));
740 exit(1);
741 }
742
743 set_samba_nb_type();
744
745 if (!is_daemon && !is_a_socket(0)) {
746 DEBUG(0,("standard input is not a socket, assuming -D option\n"));
747 is_daemon = True;
748 }
749
750 if (is_daemon && !opt_interactive) {
751 DEBUG( 2, ( "Becoming a daemon.\n" ) );
752 become_daemon(Fork, no_process_group);
753 }
754
755#if HAVE_SETPGID
756 /*
757 * If we're interactive we want to set our own process group for
758 * signal management.
759 */
760 if (opt_interactive && !no_process_group)
761 setpgid( (pid_t)0, (pid_t)0 );
762#endif
763
764#ifndef SYNC_DNS
765 /* Setup the async dns. We do it here so it doesn't have all the other
766 stuff initialised and thus chewing memory and sockets */
767 if(lp_we_are_a_wins_server() && lp_dns_proxy()) {
768 start_async_dns();
769 }
770#endif
771
772 if (!directory_exist(lp_lockdir(), NULL)) {
773 mkdir(lp_lockdir(), 0755);
774 }
775
776 pidfile_create("nmbd");
777 message_init();
778 message_register(MSG_FORCE_ELECTION, nmbd_message_election, NULL);
779#if 0
780 /* Until winsrepl is done. */
781 message_register(MSG_WINS_NEW_ENTRY, nmbd_wins_new_entry, NULL);
782#endif
783 message_register(MSG_SHUTDOWN, nmbd_terminate, NULL);
784 message_register(MSG_SMB_CONF_UPDATED, msg_reload_nmbd_services, NULL);
785 message_register(MSG_SEND_PACKET, msg_nmbd_send_packet, NULL);
786
787 TimeInit();
788
789 DEBUG( 3, ( "Opening sockets %d\n", global_nmb_port ) );
790
791 if ( !open_sockets( is_daemon, global_nmb_port ) ) {
792 kill_async_dns_child();
793 return 1;
794 }
795
796 /* Determine all the IP addresses we have. */
797 load_interfaces();
798
799 /* Create an nmbd subnet record for each of the above. */
800 if( False == create_subnets() ) {
801 DEBUG(0,("ERROR: Failed when creating subnet lists. Exiting.\n"));
802 kill_async_dns_child();
803 exit(1);
804 }
805
806 /* Load in any static local names. */
807 load_lmhosts_file(p_lmhosts);
808 DEBUG(3,("Loaded hosts file %s\n", p_lmhosts));
809
810 /* If we are acting as a WINS server, initialise data structures. */
811 if( !initialise_wins() ) {
812 DEBUG( 0, ( "nmbd: Failed when initialising WINS server.\n" ) );
813 kill_async_dns_child();
814 exit(1);
815 }
816
817 /*
818 * Register nmbd primary workgroup and nmbd names on all
819 * the broadcast subnets, and on the WINS server (if specified).
820 * Also initiate the startup of our primary workgroup (start
821 * elections if we are setup as being able to be a local
822 * master browser.
823 */
824
825 if( False == register_my_workgroup_and_names() ) {
826 DEBUG(0,("ERROR: Failed when creating my my workgroup. Exiting.\n"));
827 kill_async_dns_child();
828 exit(1);
829 }
830
831 /* We can only take signals in the select. */
832 BlockSignals( True, SIGTERM );
833
834 process();
835
836 if (dbf)
837 x_fclose(dbf);
838 kill_async_dns_child();
839 return(0);
840}
Note: See TracBrowser for help on using the repository browser.