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