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

Last change on this file since 131 was 124, checked in by Paul Smedley, 18 years ago

Update source to 3.0.28a

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