xref: /dragonfly/usr.sbin/dntpd/main.c (revision d399b893)
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*d399b893SMatthew Dillon  * $DragonFly: src/usr.sbin/dntpd/main.c,v 1.9 2005/04/27 00:42:13 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     }
16897c30a15SMatthew Dillon     if (config_opt == NULL) {
16997c30a15SMatthew Dillon 	if (optind != ac)
17097c30a15SMatthew Dillon 	    config_opt = "/dev/null";
17197c30a15SMatthew Dillon 	else
17297c30a15SMatthew Dillon 	    config_opt = "/etc/dntpd.conf";
17397c30a15SMatthew Dillon     }
174e0163549SMatthew Dillon 
1753d15852bSMatthew Dillon     if (debug_level < 0)
1763d15852bSMatthew Dillon 	debug_level = 1;
1773d15852bSMatthew Dillon 
17897c30a15SMatthew Dillon     process_config_file(config_opt);
17997c30a15SMatthew Dillon 
1803d15852bSMatthew Dillon     if (debug_opt == 0)
1813d15852bSMatthew Dillon 	openlog("dntpd", LOG_CONS|LOG_PID, LOG_DAEMON);
1823d15852bSMatthew Dillon 
1839b724d8cSMatthew Dillon     if (test_opt) {
1849b724d8cSMatthew Dillon 	if (optind != ac - 1)
1859b724d8cSMatthew Dillon 	    usage(av[0]);
1869b724d8cSMatthew Dillon 	dotest(av[optind]);
1879b724d8cSMatthew Dillon 	/* not reached */
1889b724d8cSMatthew Dillon     }
1899b724d8cSMatthew Dillon 
190e0163549SMatthew Dillon     /*
191e0163549SMatthew Dillon      * Add additional hosts.
192e0163549SMatthew Dillon      */
193e0163549SMatthew Dillon     for (i = optind; i < ac; ++i) {
194e0163549SMatthew Dillon 	add_server(av[i]);
195e0163549SMatthew Dillon     }
196e0163549SMatthew Dillon     if (nservers == 0) {
197e0163549SMatthew Dillon 	usage(av[0]);
198e0163549SMatthew Dillon 	/* not reached */
199e0163549SMatthew Dillon     }
200e0163549SMatthew Dillon 
201e0163549SMatthew Dillon     /*
20297c30a15SMatthew Dillon      * Do an initial course time setting if requested using the first
20397c30a15SMatthew Dillon      * host successfully polled.
20497c30a15SMatthew Dillon      */
20597c30a15SMatthew Dillon     /* XXX */
20697c30a15SMatthew Dillon 
20797c30a15SMatthew Dillon     /*
20897c30a15SMatthew Dillon      * Daemonize, stop logging to stderr.
20997c30a15SMatthew Dillon      */
21097c30a15SMatthew Dillon     if (daemon_opt) {
21197c30a15SMatthew Dillon 	if ((pid = check_pid()) != 0) {
21297c30a15SMatthew Dillon 	    logerrstr("%s: NOTE: killing old daemon and starting a new one",
21397c30a15SMatthew Dillon 			av[0]);
21497c30a15SMatthew Dillon 	    kill(pid, SIGINT);
21597c30a15SMatthew Dillon 	    usleep(100000);
21697c30a15SMatthew Dillon 	    if (check_pid())
21797c30a15SMatthew Dillon 		sleep(1);
21897c30a15SMatthew Dillon 	    if (check_pid())
21997c30a15SMatthew Dillon 		sleep(9);
22097c30a15SMatthew Dillon 	    if (check_pid()) {
22197c30a15SMatthew Dillon 		logerrstr("%s: Unable to kill running daemon, exiting", av[0]);
22297c30a15SMatthew Dillon 		exit(1);
22397c30a15SMatthew Dillon 	    }
22497c30a15SMatthew Dillon 	}
22597c30a15SMatthew Dillon 	daemon(0, 0);
22697c30a15SMatthew Dillon     } else if (check_pid() != 0) {
22797c30a15SMatthew Dillon 	logerrstr("%s: A background dntpd is running, you must kill it first",
22897c30a15SMatthew Dillon 		av[0]);
22997c30a15SMatthew Dillon 	exit(1);
23097c30a15SMatthew Dillon     }
23197c30a15SMatthew Dillon     if (debug_opt == 0) {
23297c30a15SMatthew Dillon 	log_stderr = 0;
23397c30a15SMatthew Dillon 	set_pid(av[0]);
23497c30a15SMatthew Dillon 	signal(SIGINT, sigint_handler);
23597c30a15SMatthew Dillon 	logdebug(0, "dntpd version %s started\n", DNTPD_VERSION);
23697c30a15SMatthew Dillon     }
23797c30a15SMatthew Dillon 
23897c30a15SMatthew Dillon     /*
239e0163549SMatthew Dillon      * And go.
240e0163549SMatthew Dillon      */
241c44548fcSMatthew Dillon     sysntp_clear_alternative_corrections();
242e0163549SMatthew Dillon     client_init();
243e0163549SMatthew Dillon     rc = client_main(servers, nservers);
244e0163549SMatthew Dillon     return(rc);
245e0163549SMatthew Dillon }
246e0163549SMatthew Dillon 
247e0163549SMatthew Dillon static
248e0163549SMatthew Dillon void
249e0163549SMatthew Dillon usage(const char *av0)
250e0163549SMatthew Dillon {
251*d399b893SMatthew Dillon     fprintf(stderr, "%s [-dnqstFSQ] [-f config_file] [-l log_level] [-T poll_interval] [-L poll_limit] [additional_targets]\n", av0);
25297c30a15SMatthew Dillon     fprintf(stderr,
25397c30a15SMatthew Dillon 	"\t-d\tDebugging mode, implies -F, -l 99, and logs to stderr\n"
25497c30a15SMatthew Dillon 	"\t-f file\tSpecify the config file (/etc/dntpd.conf)\n"
25597c30a15SMatthew Dillon 	"\t-l int\tSet log level (0-4), default 1\n"
256c44548fcSMatthew Dillon 	"\t-n\tNo-update mode.  No offset or frequency corrections are made\n"
25797c30a15SMatthew Dillon 	"\t-q\tQuiet-mode, same as -L 0\n"
25897c30a15SMatthew Dillon 	"\t-s\tSet the time immediately on startup\n"
259c44548fcSMatthew Dillon 	"\t-t\tTest mode, implies -F, -l 99, -n, logs to stderr\n"
260c44548fcSMatthew Dillon 	"\t-F\tRun in foreground (log still goes to syslog)\n"
26197c30a15SMatthew Dillon 	"\t-L int\tMaximum polling interval\n"
26297c30a15SMatthew Dillon 	"\t-S\tDo not set the time immediately on startup\n"
26397c30a15SMatthew Dillon 	"\t-T int\tNominal polling interval\n"
26497c30a15SMatthew Dillon 	"\t-Q\tTerminate any running background daemon\n"
265c44548fcSMatthew Dillon 	"\n"
266c44548fcSMatthew Dillon 	"\t\tNOTE: in debug and test modes -f must be specified if\n"
267c44548fcSMatthew Dillon 	"\t\tyou want to use a config file.\n"
26897c30a15SMatthew Dillon     );
269e0163549SMatthew Dillon     exit(1);
270e0163549SMatthew Dillon }
271e0163549SMatthew Dillon 
272e0163549SMatthew Dillon static
273e0163549SMatthew Dillon void
274e0163549SMatthew Dillon dotest(const char *target)
275e0163549SMatthew Dillon {
276e0163549SMatthew Dillon     struct server_info info;
277e0163549SMatthew Dillon 
278e0163549SMatthew Dillon     bzero(&info, sizeof(info));
279e0163549SMatthew Dillon     info.fd = udp_socket(target, 123);
280e0163549SMatthew Dillon     if (info.fd < 0) {
281e0163549SMatthew Dillon 	logerrstr("unable to create UDP socket for %s", target);
282e0163549SMatthew Dillon 	return;
283e0163549SMatthew Dillon     }
284e0163549SMatthew Dillon     info.target = strdup(target);
285e0163549SMatthew Dillon     client_init();
286e0163549SMatthew Dillon 
2879b724d8cSMatthew Dillon     fprintf(stderr,
288fdd4337fSMatthew Dillon 	    "Will run %d-second polls until interrupted.\n", nom_sleep_opt);
2899b724d8cSMatthew Dillon 
290e0163549SMatthew Dillon     for (;;) {
291c32f1362SMatthew Dillon 	client_poll(&info, nom_sleep_opt, 1);
292fdd4337fSMatthew Dillon 	sleep(nom_sleep_opt);
293e0163549SMatthew Dillon     }
2949b724d8cSMatthew Dillon     /* not reached */
295e0163549SMatthew Dillon }
296e0163549SMatthew Dillon 
297e0163549SMatthew Dillon static void
298e0163549SMatthew Dillon add_server(const char *target)
299e0163549SMatthew Dillon {
300e0163549SMatthew Dillon     server_info_t info;
301e0163549SMatthew Dillon 
302e0163549SMatthew Dillon     if (nservers == maxservers) {
303e0163549SMatthew Dillon 	maxservers += 16;
304e0163549SMatthew Dillon 	servers = realloc(servers, maxservers * sizeof(server_info_t));
305e0163549SMatthew Dillon 	assert(servers != NULL);
306e0163549SMatthew Dillon     }
307e0163549SMatthew Dillon     info = malloc(sizeof(struct server_info));
308e0163549SMatthew Dillon     servers[nservers] = info;
309e0163549SMatthew Dillon     bzero(info, sizeof(struct server_info));
310e0163549SMatthew Dillon     info->fd = udp_socket(target, 123);
311e0163549SMatthew Dillon     if (info->fd < 0) {
312e0163549SMatthew Dillon 	logerrstr("Unable to add server %s", target);
313e0163549SMatthew Dillon     } else {
314e0163549SMatthew Dillon 	info->target = strdup(target);
315e0163549SMatthew Dillon 	++nservers;
316e0163549SMatthew Dillon     }
317e0163549SMatthew Dillon }
318e0163549SMatthew Dillon 
31997c30a15SMatthew Dillon static void
32097c30a15SMatthew Dillon process_config_file(const char *path)
32197c30a15SMatthew Dillon {
32297c30a15SMatthew Dillon     const char *ws = " \t\r\n";
32397c30a15SMatthew Dillon     char buf[1024];
32497c30a15SMatthew Dillon     char *keyword;
32597c30a15SMatthew Dillon     char *data;
32697c30a15SMatthew Dillon     int line;
32797c30a15SMatthew Dillon     FILE *fi;
32897c30a15SMatthew Dillon 
32997c30a15SMatthew Dillon     if ((fi = fopen(path, "r")) != NULL) {
33097c30a15SMatthew Dillon 	line = 1;
33197c30a15SMatthew Dillon 	while (fgets(buf, sizeof(buf), fi) != NULL) {
33297c30a15SMatthew Dillon 	    if (strchr(buf, '#'))
33397c30a15SMatthew Dillon 		*strchr(buf, '#') = 0;
33497c30a15SMatthew Dillon 	    if ((keyword = strtok(buf, ws)) != NULL) {
33597c30a15SMatthew Dillon 		data = strtok(NULL, ws);
33697c30a15SMatthew Dillon 		if (strcmp(keyword, "server") == 0) {
33797c30a15SMatthew Dillon 		    if (data == NULL) {
33897c30a15SMatthew Dillon 			logerr("%s:%d server missing host specification",
33997c30a15SMatthew Dillon 				path, line);
34097c30a15SMatthew Dillon 		    } else {
34197c30a15SMatthew Dillon 			add_server(data);
34297c30a15SMatthew Dillon 		    }
34397c30a15SMatthew Dillon 		} else {
34497c30a15SMatthew Dillon 		    logerr("%s:%d unknown keyword %s", path, line, keyword);
34597c30a15SMatthew Dillon 		}
34697c30a15SMatthew Dillon 	    }
34797c30a15SMatthew Dillon 	    ++line;
34897c30a15SMatthew Dillon 	}
34997c30a15SMatthew Dillon 	fclose(fi);
35097c30a15SMatthew Dillon     } else {
35197c30a15SMatthew Dillon 	logerr("Unable to open %s", path);
35297c30a15SMatthew Dillon 	exit(1);
35397c30a15SMatthew Dillon     }
35497c30a15SMatthew Dillon }
35597c30a15SMatthew Dillon 
35697c30a15SMatthew Dillon static
35797c30a15SMatthew Dillon pid_t
35897c30a15SMatthew Dillon check_pid(void)
35997c30a15SMatthew Dillon {
36097c30a15SMatthew Dillon     char buf[32];
36197c30a15SMatthew Dillon     pid_t pid;
36297c30a15SMatthew Dillon     FILE *fi;
36397c30a15SMatthew Dillon 
36497c30a15SMatthew Dillon     pid = 0;
36597c30a15SMatthew Dillon     if ((fi = fopen(pid_opt, "r")) != NULL) {
36697c30a15SMatthew Dillon 	if (fgets(buf, sizeof(buf), fi) != NULL) {
36797c30a15SMatthew Dillon 	    pid = strtol(buf, NULL, 0);
36897c30a15SMatthew Dillon 	    if (kill(pid, 0) != 0)
36997c30a15SMatthew Dillon 		pid = 0;
37097c30a15SMatthew Dillon 	}
37197c30a15SMatthew Dillon 	fclose(fi);
37297c30a15SMatthew Dillon     }
37397c30a15SMatthew Dillon     return(pid);
37497c30a15SMatthew Dillon }
37597c30a15SMatthew Dillon 
37697c30a15SMatthew Dillon static
37797c30a15SMatthew Dillon void
37897c30a15SMatthew Dillon set_pid(const char *av0)
37997c30a15SMatthew Dillon {
38097c30a15SMatthew Dillon     pid_t pid;
38197c30a15SMatthew Dillon     FILE *fo;
38297c30a15SMatthew Dillon 
38397c30a15SMatthew Dillon     pid = getpid();
38497c30a15SMatthew Dillon     if ((fo = fopen(pid_opt, "w")) != NULL) {
38597c30a15SMatthew Dillon 	fprintf(fo, "%d\n", (int)pid);
38697c30a15SMatthew Dillon 	fclose(fo);
38797c30a15SMatthew Dillon     } else {
38897c30a15SMatthew Dillon 	logerr("%s: Unable to create %s, continuing anyway.", av0, pid_opt);
38997c30a15SMatthew Dillon     }
39097c30a15SMatthew Dillon }
39197c30a15SMatthew Dillon 
39297c30a15SMatthew Dillon static
39397c30a15SMatthew Dillon void
394c32f1362SMatthew Dillon sigint_handler(int signo __unused)
39597c30a15SMatthew Dillon {
39697c30a15SMatthew Dillon     remove(pid_opt);
39797c30a15SMatthew Dillon     /* dangerous, but we are exiting anyway so pray... */
39897c30a15SMatthew Dillon     logdebug(0, "dntpd version %s stopped\n", DNTPD_VERSION);
39997c30a15SMatthew Dillon     exit(0);
40097c30a15SMatthew Dillon }
40197c30a15SMatthew Dillon 
402