Initial commit for the DragonFly home-made ntpd client. Why? Because
[dragonfly.git] / usr.sbin / dntpd / main.c
1 /*
2  * Copyright (c) 2005 The DragonFly Project.  All rights reserved.
3  * 
4  * This code is derived from software contributed to The DragonFly Project
5  * by Matthew Dillon <dillon@backplane.com>
6  * 
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in
15  *    the documentation and/or other materials provided with the
16  *    distribution.
17  * 3. Neither the name of The DragonFly Project nor the names of its
18  *    contributors may be used to endorse or promote products derived
19  *    from this software without specific, prior written permission.
20  * 
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
25  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26  * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
27  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
31  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32  * SUCH DAMAGE.
33  * 
34  * $DragonFly: src/usr.sbin/dntpd/main.c,v 1.1 2005/04/24 02:36:50 dillon Exp $
35  */
36
37 #include "defs.h"
38
39 static void usage(const char *av0);
40 static void dotest(const char *target);
41 static void add_server(const char *target);
42
43 static struct server_info **servers;
44 static int nservers;
45 static int maxservers;
46
47 int debug_opt;
48
49 int
50 main(int ac, char **av)
51 {
52     int rc = 0;
53     int ch;
54     int i;
55
56     /*
57      * Really randomize
58      */
59     srandomdev();
60
61     /*
62      * Process Options
63      */
64     while ((ch = getopt(ac, av, "t:d")) != -1) {
65         switch(ch) {
66         case 'd':
67             debug_opt = 1;
68             break;
69         case 't':
70             dotest(optarg);
71             exit(0);
72             /* not reached */
73         case 'h':
74         default:
75             usage(av[0]);
76             /* not reached */
77         }
78     }
79
80     /*
81      * Add additional hosts.
82      */
83     for (i = optind; i < ac; ++i) {
84         add_server(av[i]);
85     }
86     if (nservers == 0) {
87         usage(av[0]);
88         /* not reached */
89     }
90
91     /*
92      * And go.
93      */
94     client_init();
95     rc = client_main(servers, nservers);
96     return(rc);
97 }
98
99 static
100 void
101 usage(const char *av0)
102 {
103     fprintf(stderr, "%s [-d] [-t target] [additional_targets]\n", av0);
104     exit(1);
105 }
106
107 static
108 void
109 dotest(const char *target)
110 {
111     struct server_info info;
112
113     bzero(&info, sizeof(info));
114     info.fd = udp_socket(target, 123);
115     if (info.fd < 0) {
116         logerrstr("unable to create UDP socket for %s", target);
117         return;
118     }
119     info.target = strdup(target);
120     client_init();
121
122     debug_opt = 1;
123
124     for (;;) {
125         client_poll(&info);
126         usleep(5 * 1000000 + random() % 100000);
127     }
128 }
129
130 static void
131 add_server(const char *target)
132 {
133     server_info_t info;
134
135     if (nservers == maxservers) {
136         maxservers += 16;
137         servers = realloc(servers, maxservers * sizeof(server_info_t));
138         assert(servers != NULL);
139     }
140     info = malloc(sizeof(struct server_info));
141     servers[nservers] = info;
142     bzero(info, sizeof(struct server_info));
143     info->fd = udp_socket(target, 123);
144     if (info->fd < 0) {
145         logerrstr("Unable to add server %s", target);
146     } else {
147         info->target = strdup(target);
148         ++nservers;
149     }
150 }
151