xref: /dragonfly/usr.sbin/dntpd/main.c (revision 2408d859)
1e0163549SMatthew Dillon /*
2e0163549SMatthew Dillon  * Copyright (c) 2005 The DragonFly Project.  All rights reserved.
3e0163549SMatthew Dillon  *
4e0163549SMatthew Dillon  * This code is derived from software contributed to The DragonFly Project
5e0163549SMatthew Dillon  * by Matthew Dillon <dillon@backplane.com>
6e0163549SMatthew Dillon  *
7e0163549SMatthew Dillon  * Redistribution and use in source and binary forms, with or without
8e0163549SMatthew Dillon  * modification, are permitted provided that the following conditions
9e0163549SMatthew Dillon  * are met:
10e0163549SMatthew Dillon  *
11e0163549SMatthew Dillon  * 1. Redistributions of source code must retain the above copyright
12e0163549SMatthew Dillon  *    notice, this list of conditions and the following disclaimer.
13e0163549SMatthew Dillon  * 2. Redistributions in binary form must reproduce the above copyright
14e0163549SMatthew Dillon  *    notice, this list of conditions and the following disclaimer in
15e0163549SMatthew Dillon  *    the documentation and/or other materials provided with the
16e0163549SMatthew Dillon  *    distribution.
17e0163549SMatthew Dillon  * 3. Neither the name of The DragonFly Project nor the names of its
18e0163549SMatthew Dillon  *    contributors may be used to endorse or promote products derived
19e0163549SMatthew Dillon  *    from this software without specific, prior written permission.
20e0163549SMatthew Dillon  *
21e0163549SMatthew Dillon  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22e0163549SMatthew Dillon  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23e0163549SMatthew Dillon  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24e0163549SMatthew Dillon  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
25e0163549SMatthew Dillon  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26e0163549SMatthew Dillon  * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
27e0163549SMatthew Dillon  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28e0163549SMatthew Dillon  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29e0163549SMatthew Dillon  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30e0163549SMatthew Dillon  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
31e0163549SMatthew Dillon  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32e0163549SMatthew Dillon  * SUCH DAMAGE.
33e0163549SMatthew Dillon  *
34*2408d859SMatthew Dillon  * $DragonFly: src/usr.sbin/dntpd/main.c,v 1.10 2007/06/25 21:33:36 dillon Exp $
35e0163549SMatthew Dillon  */
36e0163549SMatthew Dillon 
37e0163549SMatthew Dillon #include "defs.h"
38e0163549SMatthew Dillon 
39e0163549SMatthew Dillon static void usage(const char *av0);
40e0163549SMatthew Dillon static void dotest(const char *target);
41e0163549SMatthew Dillon static void add_server(const char *target);
4297c30a15SMatthew Dillon static void process_config_file(const char *path);
4397c30a15SMatthew Dillon static pid_t check_pid(void);
4497c30a15SMatthew Dillon static void set_pid(const char *av0);
45c32f1362SMatthew Dillon static void sigint_handler(int signo __unused);
46e0163549SMatthew Dillon 
47e0163549SMatthew Dillon static struct server_info **servers;
48e0163549SMatthew Dillon static int nservers;
49e0163549SMatthew Dillon static int maxservers;
50e0163549SMatthew Dillon 
5197c30a15SMatthew Dillon int daemon_opt = 1;
52c44548fcSMatthew Dillon int debug_opt = 0;
533d15852bSMatthew Dillon int debug_level = -1;		/* (set to default later) */
5475349a56SMatthew Dillon int quickset_opt = 0;		/* immediately set time of day on startup */
55c44548fcSMatthew Dillon int no_update_opt = 0;		/* do not make any actual updates */
56fdd4337fSMatthew Dillon int min_sleep_opt = 5;		/* 5 seconds minimum poll interval */
57fdd4337fSMatthew Dillon int nom_sleep_opt = 300;	/* 5 minutes nominal poll interval */
58fdd4337fSMatthew Dillon int max_sleep_opt = 1800;	/* 30 minutes maximum poll interval */
5997c30a15SMatthew Dillon const char *config_opt;		/* config file */
6097c30a15SMatthew Dillon const char *pid_opt = "/var/run/dntpd.pid";
61e0163549SMatthew Dillon 
62e0163549SMatthew Dillon int
63e0163549SMatthew Dillon main(int ac, char **av)
64e0163549SMatthew Dillon {
659b724d8cSMatthew Dillon     int test_opt = 0;
6697c30a15SMatthew Dillon     pid_t pid;
679b724d8cSMatthew Dillon     int rc;
68e0163549SMatthew Dillon     int ch;
69e0163549SMatthew Dillon     int i;
70e0163549SMatthew Dillon 
71e0163549SMatthew Dillon     /*
72e0163549SMatthew Dillon      * Really randomize
73e0163549SMatthew Dillon      */
74e0163549SMatthew Dillon     srandomdev();
759b724d8cSMatthew Dillon     rc = 0;
76e0163549SMatthew Dillon 
77e0163549SMatthew Dillon     /*
78e0163549SMatthew Dillon      * Process Options
79e0163549SMatthew Dillon      */
80c44548fcSMatthew Dillon     while ((ch = getopt(ac, av, "df:l:np:qstFL:QST:")) != -1) {
81e0163549SMatthew Dillon 	switch(ch) {
8297c30a15SMatthew Dillon 	case 'd':
8397c30a15SMatthew Dillon 	    debug_opt = 1;
8497c30a15SMatthew Dillon 	    daemon_opt = 0;
8597c30a15SMatthew Dillon 	    if (debug_level < 0)
8697c30a15SMatthew Dillon 		debug_level = 99;
8797c30a15SMatthew Dillon 	    if (config_opt == NULL)
8897c30a15SMatthew Dillon 		config_opt = "/dev/null";
8997c30a15SMatthew Dillon 	    break;
9097c30a15SMatthew Dillon 	case 'p':
9197c30a15SMatthew Dillon 	    pid_opt = optarg;
9297c30a15SMatthew Dillon 	    break;
9397c30a15SMatthew Dillon 	case 'f':
9497c30a15SMatthew Dillon 	    config_opt = optarg;
9597c30a15SMatthew Dillon 	    break;
9697c30a15SMatthew Dillon 	case 'l':
9797c30a15SMatthew Dillon 	    debug_level = strtol(optarg, NULL, 0);
9897c30a15SMatthew Dillon 	    break;
99c44548fcSMatthew Dillon 	case 'n':
100c44548fcSMatthew Dillon 	    no_update_opt = 1;
101c44548fcSMatthew Dillon 	    break;
10297c30a15SMatthew Dillon 	case 'q':
10397c30a15SMatthew Dillon 	    debug_level = 0;
10497c30a15SMatthew Dillon 	    break;
10597c30a15SMatthew Dillon 	case 's':
10697c30a15SMatthew Dillon 	    quickset_opt = 1;
10797c30a15SMatthew Dillon 	    break;
10897c30a15SMatthew Dillon 	case 'S':
10997c30a15SMatthew Dillon 	    quickset_opt = 0;
11097c30a15SMatthew Dillon 	    break;
11197c30a15SMatthew Dillon 	case 't':
11297c30a15SMatthew Dillon 	    test_opt = 1;
11397c30a15SMatthew Dillon 	    debug_opt = 1;
11497c30a15SMatthew Dillon 	    daemon_opt = 0;
11597c30a15SMatthew Dillon 	    if (debug_level < 0)
11697c30a15SMatthew Dillon 		debug_level = 99;
11797c30a15SMatthew Dillon 	    if (config_opt == NULL)
11897c30a15SMatthew Dillon 		config_opt = "/dev/null";
11997c30a15SMatthew Dillon 	    break;
12097c30a15SMatthew Dillon 	case 'F':
12197c30a15SMatthew Dillon 	    daemon_opt = 0;
12297c30a15SMatthew Dillon 	    break;
12397c30a15SMatthew Dillon 	case 'L':
12497c30a15SMatthew Dillon 	    max_sleep_opt = strtol(optarg, NULL, 0);
12597c30a15SMatthew Dillon 	    break;
1269b724d8cSMatthew Dillon 	case 'T':
127fdd4337fSMatthew Dillon 	    nom_sleep_opt = strtol(optarg, NULL, 0);
128fdd4337fSMatthew Dillon 	    if (nom_sleep_opt < 1) {
129fdd4337fSMatthew Dillon 		fprintf(stderr, "Warning: nominal poll interval too small, "
130fdd4337fSMatthew Dillon 				"limiting to 1 second\n");
131fdd4337fSMatthew Dillon 		nom_sleep_opt = 1;
132fdd4337fSMatthew Dillon 	    }
133fdd4337fSMatthew Dillon 	    if (nom_sleep_opt > 24 * 60 * 60) {
134fdd4337fSMatthew Dillon 		fprintf(stderr, "Warning: nominal poll interval too large, "
135fdd4337fSMatthew Dillon 				"limiting to 24 hours\n");
136fdd4337fSMatthew Dillon 		nom_sleep_opt = 24 * 60 * 60;
137fdd4337fSMatthew Dillon 	    }
138fdd4337fSMatthew Dillon 	    if (min_sleep_opt > nom_sleep_opt)
139fdd4337fSMatthew Dillon 		min_sleep_opt = nom_sleep_opt;
140fdd4337fSMatthew Dillon 	    if (max_sleep_opt < nom_sleep_opt * 5)
141fdd4337fSMatthew Dillon 		max_sleep_opt = nom_sleep_opt * 5;
142fdd4337fSMatthew Dillon 	    break;
14397c30a15SMatthew Dillon 	case 'Q':
14497c30a15SMatthew Dillon 	    if ((pid = check_pid()) != 0) {
14597c30a15SMatthew Dillon 		fprintf(stderr, "%s: killing old daemon\n", av[0]);
14697c30a15SMatthew Dillon 		kill(pid, SIGINT);
14797c30a15SMatthew Dillon 		usleep(100000);
14897c30a15SMatthew Dillon 		if (check_pid())
14997c30a15SMatthew Dillon 		    sleep(1);
15097c30a15SMatthew Dillon 		if (check_pid())
15197c30a15SMatthew Dillon 		    sleep(9);
15297c30a15SMatthew Dillon 		if (check_pid()) {
153c44548fcSMatthew Dillon 		    fprintf(stderr, "%s: Unable to kill running daemon.\n", av[0]);
15497c30a15SMatthew Dillon 		} else {
155c44548fcSMatthew Dillon 		    fprintf(stderr, "%s: Running daemon has been terminated.\n", av[0]);
15697c30a15SMatthew Dillon 		}
15797c30a15SMatthew Dillon 	    } else {
158c44548fcSMatthew Dillon 		fprintf(stderr, "%s: There is no daemon running to kill.\n", av[0]);
15997c30a15SMatthew Dillon 	    }
16097c30a15SMatthew Dillon 	    exit(0);
1619b724d8cSMatthew Dillon 	    break;
162e0163549SMatthew Dillon 	case 'h':
163e0163549SMatthew Dillon 	default:
164e0163549SMatthew Dillon 	    usage(av[0]);
165e0163549SMatthew Dillon 	    /* not reached */
166e0163549SMatthew Dillon 	}
167e0163549SMatthew Dillon     }
168*2408d859SMatthew Dillon 
169*2408d859SMatthew Dillon     /*
170*2408d859SMatthew Dillon      * Make sure min and nom intervals are less then or equal to the maximum
171*2408d859SMatthew Dillon      * interval.
172*2408d859SMatthew Dillon      */
173*2408d859SMatthew Dillon     if (min_sleep_opt > max_sleep_opt)
174*2408d859SMatthew Dillon 	min_sleep_opt = max_sleep_opt;
175*2408d859SMatthew Dillon     if (nom_sleep_opt > max_sleep_opt)
176*2408d859SMatthew Dillon 	nom_sleep_opt = max_sleep_opt;
177*2408d859SMatthew Dillon 
178*2408d859SMatthew Dillon     /*
179*2408d859SMatthew Dillon      * Set default config file
180*2408d859SMatthew Dillon      */
18197c30a15SMatthew Dillon     if (config_opt == NULL) {
18297c30a15SMatthew Dillon 	if (optind != ac)
18397c30a15SMatthew Dillon 	    config_opt = "/dev/null";
18497c30a15SMatthew Dillon 	else
18597c30a15SMatthew Dillon 	    config_opt = "/etc/dntpd.conf";
18697c30a15SMatthew Dillon     }
187e0163549SMatthew Dillon 
1883d15852bSMatthew Dillon     if (debug_level < 0)
1893d15852bSMatthew Dillon 	debug_level = 1;
1903d15852bSMatthew Dillon 
19197c30a15SMatthew Dillon     process_config_file(config_opt);
19297c30a15SMatthew Dillon 
1933d15852bSMatthew Dillon     if (debug_opt == 0)
1943d15852bSMatthew Dillon 	openlog("dntpd", LOG_CONS|LOG_PID, LOG_DAEMON);
1953d15852bSMatthew Dillon 
1969b724d8cSMatthew Dillon     if (test_opt) {
1979b724d8cSMatthew Dillon 	if (optind != ac - 1)
1989b724d8cSMatthew Dillon 	    usage(av[0]);
1999b724d8cSMatthew Dillon 	dotest(av[optind]);
2009b724d8cSMatthew Dillon 	/* not reached */
2019b724d8cSMatthew Dillon     }
2029b724d8cSMatthew Dillon 
203e0163549SMatthew Dillon     /*
204e0163549SMatthew Dillon      * Add additional hosts.
205e0163549SMatthew Dillon      */
206e0163549SMatthew Dillon     for (i = optind; i < ac; ++i) {
207e0163549SMatthew Dillon 	add_server(av[i]);
208e0163549SMatthew Dillon     }
209e0163549SMatthew Dillon     if (nservers == 0) {
210e0163549SMatthew Dillon 	usage(av[0]);
211e0163549SMatthew Dillon 	/* not reached */
212e0163549SMatthew Dillon     }
213e0163549SMatthew Dillon 
214e0163549SMatthew Dillon     /*
21597c30a15SMatthew Dillon      * Do an initial course time setting if requested using the first
21697c30a15SMatthew Dillon      * host successfully polled.
21797c30a15SMatthew Dillon      */
21897c30a15SMatthew Dillon     /* XXX */
21997c30a15SMatthew Dillon 
22097c30a15SMatthew Dillon     /*
22197c30a15SMatthew Dillon      * Daemonize, stop logging to stderr.
22297c30a15SMatthew Dillon      */
22397c30a15SMatthew Dillon     if (daemon_opt) {
22497c30a15SMatthew Dillon 	if ((pid = check_pid()) != 0) {
22597c30a15SMatthew Dillon 	    logerrstr("%s: NOTE: killing old daemon and starting a new one",
22697c30a15SMatthew Dillon 			av[0]);
22797c30a15SMatthew Dillon 	    kill(pid, SIGINT);
22897c30a15SMatthew Dillon 	    usleep(100000);
22997c30a15SMatthew Dillon 	    if (check_pid())
23097c30a15SMatthew Dillon 		sleep(1);
23197c30a15SMatthew Dillon 	    if (check_pid())
23297c30a15SMatthew Dillon 		sleep(9);
23397c30a15SMatthew Dillon 	    if (check_pid()) {
23497c30a15SMatthew Dillon 		logerrstr("%s: Unable to kill running daemon, exiting", av[0]);
23597c30a15SMatthew Dillon 		exit(1);
23697c30a15SMatthew Dillon 	    }
23797c30a15SMatthew Dillon 	}
23897c30a15SMatthew Dillon 	daemon(0, 0);
23997c30a15SMatthew Dillon     } else if (check_pid() != 0) {
24097c30a15SMatthew Dillon 	logerrstr("%s: A background dntpd is running, you must kill it first",
24197c30a15SMatthew Dillon 		av[0]);
24297c30a15SMatthew Dillon 	exit(1);
24397c30a15SMatthew Dillon     }
24497c30a15SMatthew Dillon     if (debug_opt == 0) {
24597c30a15SMatthew Dillon 	log_stderr = 0;
24697c30a15SMatthew Dillon 	set_pid(av[0]);
24797c30a15SMatthew Dillon 	signal(SIGINT, sigint_handler);
24897c30a15SMatthew Dillon 	logdebug(0, "dntpd version %s started\n", DNTPD_VERSION);
24997c30a15SMatthew Dillon     }
25097c30a15SMatthew Dillon 
25197c30a15SMatthew Dillon     /*
252e0163549SMatthew Dillon      * And go.
253e0163549SMatthew Dillon      */
254c44548fcSMatthew Dillon     sysntp_clear_alternative_corrections();
255e0163549SMatthew Dillon     client_init();
256*2408d859SMatthew Dillon     client_check_duplicate_ips(servers, nservers);
257e0163549SMatthew Dillon     rc = client_main(servers, nservers);
258e0163549SMatthew Dillon     return(rc);
259e0163549SMatthew Dillon }
260e0163549SMatthew Dillon 
261e0163549SMatthew Dillon static
262e0163549SMatthew Dillon void
263e0163549SMatthew Dillon usage(const char *av0)
264e0163549SMatthew Dillon {
265d399b893SMatthew Dillon     fprintf(stderr, "%s [-dnqstFSQ] [-f config_file] [-l log_level] [-T poll_interval] [-L poll_limit] [additional_targets]\n", av0);
26697c30a15SMatthew Dillon     fprintf(stderr,
26797c30a15SMatthew Dillon 	"\t-d\tDebugging mode, implies -F, -l 99, and logs to stderr\n"
26897c30a15SMatthew Dillon 	"\t-f file\tSpecify the config file (/etc/dntpd.conf)\n"
26997c30a15SMatthew Dillon 	"\t-l int\tSet log level (0-4), default 1\n"
270c44548fcSMatthew Dillon 	"\t-n\tNo-update mode.  No offset or frequency corrections are made\n"
27197c30a15SMatthew Dillon 	"\t-q\tQuiet-mode, same as -L 0\n"
27297c30a15SMatthew Dillon 	"\t-s\tSet the time immediately on startup\n"
273c44548fcSMatthew Dillon 	"\t-t\tTest mode, implies -F, -l 99, -n, logs to stderr\n"
274c44548fcSMatthew Dillon 	"\t-F\tRun in foreground (log still goes to syslog)\n"
27597c30a15SMatthew Dillon 	"\t-L int\tMaximum polling interval\n"
27697c30a15SMatthew Dillon 	"\t-S\tDo not set the time immediately on startup\n"
27797c30a15SMatthew Dillon 	"\t-T int\tNominal polling interval\n"
27897c30a15SMatthew Dillon 	"\t-Q\tTerminate any running background daemon\n"
279c44548fcSMatthew Dillon 	"\n"
280c44548fcSMatthew Dillon 	"\t\tNOTE: in debug and test modes -f must be specified if\n"
281c44548fcSMatthew Dillon 	"\t\tyou want to use a config file.\n"
28297c30a15SMatthew Dillon     );
283e0163549SMatthew Dillon     exit(1);
284e0163549SMatthew Dillon }
285e0163549SMatthew Dillon 
286e0163549SMatthew Dillon static
287e0163549SMatthew Dillon void
288e0163549SMatthew Dillon dotest(const char *target)
289e0163549SMatthew Dillon {
290e0163549SMatthew Dillon     struct server_info info;
291e0163549SMatthew Dillon 
292e0163549SMatthew Dillon     bzero(&info, sizeof(info));
293*2408d859SMatthew Dillon     info.fd = udp_socket(target, 123, &info.sam);
294e0163549SMatthew Dillon     if (info.fd < 0) {
295e0163549SMatthew Dillon 	logerrstr("unable to create UDP socket for %s", target);
296e0163549SMatthew Dillon 	return;
297e0163549SMatthew Dillon     }
298e0163549SMatthew Dillon     info.target = strdup(target);
299e0163549SMatthew Dillon     client_init();
300e0163549SMatthew Dillon 
3019b724d8cSMatthew Dillon     fprintf(stderr,
302fdd4337fSMatthew Dillon 	    "Will run %d-second polls until interrupted.\n", nom_sleep_opt);
3039b724d8cSMatthew Dillon 
304e0163549SMatthew Dillon     for (;;) {
305c32f1362SMatthew Dillon 	client_poll(&info, nom_sleep_opt, 1);
306fdd4337fSMatthew Dillon 	sleep(nom_sleep_opt);
307e0163549SMatthew Dillon     }
3089b724d8cSMatthew Dillon     /* not reached */
309e0163549SMatthew Dillon }
310e0163549SMatthew Dillon 
311e0163549SMatthew Dillon static void
312e0163549SMatthew Dillon add_server(const char *target)
313e0163549SMatthew Dillon {
314e0163549SMatthew Dillon     server_info_t info;
315*2408d859SMatthew Dillon     const char *ipstr;
316e0163549SMatthew Dillon 
317e0163549SMatthew Dillon     if (nservers == maxservers) {
318e0163549SMatthew Dillon 	maxservers += 16;
319e0163549SMatthew Dillon 	servers = realloc(servers, maxservers * sizeof(server_info_t));
320e0163549SMatthew Dillon 	assert(servers != NULL);
321e0163549SMatthew Dillon     }
322e0163549SMatthew Dillon     info = malloc(sizeof(struct server_info));
323e0163549SMatthew Dillon     servers[nservers] = info;
324e0163549SMatthew Dillon     bzero(info, sizeof(struct server_info));
325*2408d859SMatthew Dillon     info->fd = udp_socket(target, 123, &info->sam);
326e0163549SMatthew Dillon     info->target = strdup(target);
327*2408d859SMatthew Dillon     if (info->fd >= 0) {
328*2408d859SMatthew Dillon 	ipstr = addr2ascii(AF_INET, &info->sam.sin_addr,
329*2408d859SMatthew Dillon 			   sizeof(info->sam.sin_addr), NULL);
330*2408d859SMatthew Dillon 	info->ipstr = strdup(ipstr);
331*2408d859SMatthew Dillon     } else {
332*2408d859SMatthew Dillon 	client_setserverstate(info, -1, "DNS or IP lookup failure");
333*2408d859SMatthew Dillon     }
334e0163549SMatthew Dillon     ++nservers;
335e0163549SMatthew Dillon }
336*2408d859SMatthew Dillon 
337*2408d859SMatthew Dillon void
338*2408d859SMatthew Dillon disconnect_server(server_info_t info)
339*2408d859SMatthew Dillon {
340*2408d859SMatthew Dillon     if (info->fd >= 0)
341*2408d859SMatthew Dillon 	close(info->fd);
342*2408d859SMatthew Dillon     info->fd = -1;
343*2408d859SMatthew Dillon     if (info->ipstr) {
344*2408d859SMatthew Dillon 	free(info->ipstr);
345*2408d859SMatthew Dillon 	info->ipstr = NULL;
346*2408d859SMatthew Dillon     }
347*2408d859SMatthew Dillon }
348*2408d859SMatthew Dillon 
349*2408d859SMatthew Dillon void
350*2408d859SMatthew Dillon reconnect_server(server_info_t info)
351*2408d859SMatthew Dillon {
352*2408d859SMatthew Dillon     const char *ipstr;
353*2408d859SMatthew Dillon 
354*2408d859SMatthew Dillon     if (info->fd >= 0)
355*2408d859SMatthew Dillon 	close(info->fd);
356*2408d859SMatthew Dillon     if (info->ipstr) {
357*2408d859SMatthew Dillon 	free(info->ipstr);
358*2408d859SMatthew Dillon 	info->ipstr = NULL;
359*2408d859SMatthew Dillon     }
360*2408d859SMatthew Dillon     info->fd = udp_socket(info->target, 123, &info->sam);
361*2408d859SMatthew Dillon     if (info->fd >= 0) {
362*2408d859SMatthew Dillon 	ipstr = addr2ascii(AF_INET, &info->sam.sin_addr,
363*2408d859SMatthew Dillon 			   sizeof(info->sam.sin_addr), NULL);
364*2408d859SMatthew Dillon 	info->ipstr = strdup(ipstr);
365*2408d859SMatthew Dillon     }
366e0163549SMatthew Dillon }
367e0163549SMatthew Dillon 
36897c30a15SMatthew Dillon static void
36997c30a15SMatthew Dillon process_config_file(const char *path)
37097c30a15SMatthew Dillon {
37197c30a15SMatthew Dillon     const char *ws = " \t\r\n";
37297c30a15SMatthew Dillon     char buf[1024];
37397c30a15SMatthew Dillon     char *keyword;
37497c30a15SMatthew Dillon     char *data;
37597c30a15SMatthew Dillon     int line;
37697c30a15SMatthew Dillon     FILE *fi;
37797c30a15SMatthew Dillon 
37897c30a15SMatthew Dillon     if ((fi = fopen(path, "r")) != NULL) {
37997c30a15SMatthew Dillon 	line = 1;
38097c30a15SMatthew Dillon 	while (fgets(buf, sizeof(buf), fi) != NULL) {
38197c30a15SMatthew Dillon 	    if (strchr(buf, '#'))
38297c30a15SMatthew Dillon 		*strchr(buf, '#') = 0;
38397c30a15SMatthew Dillon 	    if ((keyword = strtok(buf, ws)) != NULL) {
38497c30a15SMatthew Dillon 		data = strtok(NULL, ws);
38597c30a15SMatthew Dillon 		if (strcmp(keyword, "server") == 0) {
38697c30a15SMatthew Dillon 		    if (data == NULL) {
38797c30a15SMatthew Dillon 			logerr("%s:%d server missing host specification",
38897c30a15SMatthew Dillon 				path, line);
38997c30a15SMatthew Dillon 		    } else {
39097c30a15SMatthew Dillon 			add_server(data);
39197c30a15SMatthew Dillon 		    }
39297c30a15SMatthew Dillon 		} else {
39397c30a15SMatthew Dillon 		    logerr("%s:%d unknown keyword %s", path, line, keyword);
39497c30a15SMatthew Dillon 		}
39597c30a15SMatthew Dillon 	    }
39697c30a15SMatthew Dillon 	    ++line;
39797c30a15SMatthew Dillon 	}
39897c30a15SMatthew Dillon 	fclose(fi);
39997c30a15SMatthew Dillon     } else {
40097c30a15SMatthew Dillon 	logerr("Unable to open %s", path);
40197c30a15SMatthew Dillon 	exit(1);
40297c30a15SMatthew Dillon     }
40397c30a15SMatthew Dillon }
40497c30a15SMatthew Dillon 
40597c30a15SMatthew Dillon static
40697c30a15SMatthew Dillon pid_t
40797c30a15SMatthew Dillon check_pid(void)
40897c30a15SMatthew Dillon {
40997c30a15SMatthew Dillon     char buf[32];
41097c30a15SMatthew Dillon     pid_t pid;
41197c30a15SMatthew Dillon     FILE *fi;
41297c30a15SMatthew Dillon 
41397c30a15SMatthew Dillon     pid = 0;
41497c30a15SMatthew Dillon     if ((fi = fopen(pid_opt, "r")) != NULL) {
41597c30a15SMatthew Dillon 	if (fgets(buf, sizeof(buf), fi) != NULL) {
41697c30a15SMatthew Dillon 	    pid = strtol(buf, NULL, 0);
41797c30a15SMatthew Dillon 	    if (kill(pid, 0) != 0)
41897c30a15SMatthew Dillon 		pid = 0;
41997c30a15SMatthew Dillon 	}
42097c30a15SMatthew Dillon 	fclose(fi);
42197c30a15SMatthew Dillon     }
42297c30a15SMatthew Dillon     return(pid);
42397c30a15SMatthew Dillon }
42497c30a15SMatthew Dillon 
42597c30a15SMatthew Dillon static
42697c30a15SMatthew Dillon void
42797c30a15SMatthew Dillon set_pid(const char *av0)
42897c30a15SMatthew Dillon {
42997c30a15SMatthew Dillon     pid_t pid;
43097c30a15SMatthew Dillon     FILE *fo;
43197c30a15SMatthew Dillon 
43297c30a15SMatthew Dillon     pid = getpid();
43397c30a15SMatthew Dillon     if ((fo = fopen(pid_opt, "w")) != NULL) {
43497c30a15SMatthew Dillon 	fprintf(fo, "%d\n", (int)pid);
43597c30a15SMatthew Dillon 	fclose(fo);
43697c30a15SMatthew Dillon     } else {
43797c30a15SMatthew Dillon 	logerr("%s: Unable to create %s, continuing anyway.", av0, pid_opt);
43897c30a15SMatthew Dillon     }
43997c30a15SMatthew Dillon }
44097c30a15SMatthew Dillon 
44197c30a15SMatthew Dillon static
44297c30a15SMatthew Dillon void
443c32f1362SMatthew Dillon sigint_handler(int signo __unused)
44497c30a15SMatthew Dillon {
44597c30a15SMatthew Dillon     remove(pid_opt);
44697c30a15SMatthew Dillon     /* dangerous, but we are exiting anyway so pray... */
44797c30a15SMatthew Dillon     logdebug(0, "dntpd version %s stopped\n", DNTPD_VERSION);
44897c30a15SMatthew Dillon     exit(0);
44997c30a15SMatthew Dillon }
45097c30a15SMatthew Dillon 
451