Add the DragonFly cvs id and perform general cleanups on cvs/rcs/sccs ids. Most
[dragonfly.git] / libexec / bootpd / tools / bootpef / bootpef.c
1 /************************************************************************
2           Copyright 1988, 1991 by Carnegie Mellon University
3
4                           All Rights Reserved
5
6 Permission to use, copy, modify, and distribute this software and its
7 documentation for any purpose and without fee is hereby granted, provided
8 that the above copyright notice appear in all copies and that both that
9 copyright notice and this permission notice appear in supporting
10 documentation, and that the name of Carnegie Mellon University not be used
11 in advertising or publicity pertaining to distribution of the software
12 without specific, written prior permission.
13
14 CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
15 SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
16 IN NO EVENT SHALL CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
17 DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
18 PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
19 ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
20 SOFTWARE.
21
22  $FreeBSD: src/libexec/bootpd/tools/bootpef/bootpef.c,v 1.6 1999/08/28 00:09:24 peter Exp $
23  $DragonFly: src/libexec/bootpd/tools/bootpef/bootpef.c,v 1.2 2003/06/17 04:27:07 dillon Exp $
24
25 ************************************************************************/
26
27 /*
28  * bootpef - BOOTP Extension File generator
29  *      Makes an "Extension File" for each host entry that
30  *      defines an and Extension File. (See RFC1497, tag 18.)
31  *
32  * HISTORY
33  *      See ./Changes
34  *
35  * BUGS
36  *      See ./ToDo
37  */
38 \f
39
40
41 #ifdef  __STDC__
42 #include <stdarg.h>
43 #else
44 #include <varargs.h>
45 #endif
46
47 #include <sys/types.h>
48 #include <sys/time.h>
49
50 #include <netinet/in.h>
51 #include <arpa/inet.h>                  /* inet_ntoa */
52
53 #ifndef NO_UNISTD
54 #include <unistd.h>
55 #endif
56 #include <stdlib.h>
57 #include <stdio.h>
58 #include <string.h>
59 #include <errno.h>
60 #include <ctype.h>
61 #include <syslog.h>
62
63 #ifndef USE_BFUNCS
64 #include <memory.h>
65 /* Yes, memcpy is OK here (no overlapped copies). */
66 #define bcopy(a,b,c)    memcpy(b,a,c)
67 #define bzero(p,l)      memset(p,0,l)
68 #define bcmp(a,b,c)     memcmp(a,b,c)
69 #endif
70
71 #include "bootp.h"
72 #include "hash.h"
73 #include "hwaddr.h"
74 #include "bootpd.h"
75 #include "dovend.h"
76 #include "readfile.h"
77 #include "report.h"
78 #include "tzone.h"
79 #include "patchlevel.h"
80
81 #define BUFFERSIZE              0x4000
82
83 #ifndef CONFIG_FILE
84 #define CONFIG_FILE             "/etc/bootptab"
85 #endif
86 \f
87
88
89 /*
90  * Externals, forward declarations, and global variables
91  */
92
93 #ifdef  __STDC__
94 #define P(args) args
95 #else
96 #define P(args) ()
97 #endif
98
99 static void mktagfile P((struct host *));
100 static void usage P((void));
101
102 #undef P
103
104
105 /*
106  * General
107  */
108
109 char *progname;
110 char *chdir_path;
111 int debug = 0;                                  /* Debugging flag (level) */
112 byte *buffer;
113
114 /*
115  * Globals below are associated with the bootp database file (bootptab).
116  */
117
118 char *bootptab = CONFIG_FILE;
119 \f
120
121 /*
122  * Print "usage" message and exit
123  */
124 static void
125 usage()
126 {
127         fprintf(stderr,
128            "usage:  $s [ -c chdir ] [-d level] [-f configfile] [host...]\n");
129         fprintf(stderr, "\t -c n\tset current directory\n");
130         fprintf(stderr, "\t -d n\tset debug level\n");
131         fprintf(stderr, "\t -f n\tconfig file name\n");
132         exit(1);
133 }
134
135
136 /*
137  * Initialization such as command-line processing is done and then the
138  * main server loop is started.
139  */
140 int
141 main(argc, argv)
142         int argc;
143         char **argv;
144 {
145         struct host *hp;
146         char *stmp;
147         int n;
148
149         progname = strrchr(argv[0], '/');
150         if (progname) progname++;
151         else progname = argv[0];
152
153         /* Get work space for making tag 18 files. */
154         buffer = (byte *) malloc(BUFFERSIZE);
155         if (!buffer) {
156                 report(LOG_ERR, "malloc failed");
157                 exit(1);
158         }
159         /*
160          * Set defaults that might be changed by option switches.
161          */
162         stmp = NULL;
163
164         /*
165          * Read switches.
166          */
167         for (argc--, argv++; argc > 0; argc--, argv++) {
168                 if (argv[0][0] != '-')
169                         break;
170                 switch (argv[0][1]) {
171
172                 case 'c':                               /* chdir_path */
173                         if (argv[0][2]) {
174                                 stmp = &(argv[0][2]);
175                         } else {
176                                 argc--;
177                                 argv++;
178                                 stmp = argv[0];
179                         }
180                         if (!stmp || (stmp[0] != '/')) {
181                                 fprintf(stderr,
182                                                 "bootpd: invalid chdir specification\n");
183                                 break;
184                         }
185                         chdir_path = stmp;
186                         break;
187
188                 case 'd':                               /* debug */
189                         if (argv[0][2]) {
190                                 stmp = &(argv[0][2]);
191                         } else if (argv[1] && argv[1][0] == '-') {
192                                 /*
193                                  * Backwards-compatible behavior:
194                                  * no parameter, so just increment the debug flag.
195                                  */
196                                 debug++;
197                                 break;
198                         } else {
199                                 argc--;
200                                 argv++;
201                                 stmp = argv[0];
202                         }
203                         if (!stmp || (sscanf(stmp, "%d", &n) != 1) || (n < 0)) {
204                                 fprintf(stderr,
205                                                 "bootpd: invalid debug level\n");
206                                 break;
207                         }
208                         debug = n;
209                         break;
210
211                 case 'f':                               /* config file */
212                         if (argv[0][2]) {
213                                 stmp = &(argv[0][2]);
214                         } else {
215                                 argc--;
216                                 argv++;
217                                 stmp = argv[0];
218                         }
219                         bootptab = stmp;
220                         break;
221
222                 default:
223                         fprintf(stderr, "bootpd: unknown switch: -%c\n",
224                                         argv[0][1]);
225                         usage();
226                         break;
227                 }
228         }
229
230         /* Get the timezone. */
231         tzone_init();
232
233         /* Allocate hash tables. */
234         rdtab_init();
235
236         /*
237          * Read the bootptab file.
238          */
239         readtab(1);                                     /* force read */
240
241         /* Set the cwd (i.e. to /tftpboot) */
242         if (chdir_path) {
243                 if (chdir(chdir_path) < 0)
244                         report(LOG_ERR, "%s: chdir failed", chdir_path);
245         }
246         /* If there are host names on the command line, do only those. */
247         if (argc > 0) {
248                 unsigned int tlen, hashcode;
249
250                 while (argc) {
251                         tlen = strlen(argv[0]);
252                         hashcode = hash_HashFunction((u_char *)argv[0], tlen);
253                         hp = (struct host *) hash_Lookup(nmhashtable,
254                                                                                          hashcode,
255                                                                                          nmcmp, argv[0]);
256                         if (!hp) {
257                                 printf("%s: no matching entry\n", argv[0]);
258                                 exit(1);
259                         }
260                         if (!hp->flags.exten_file) {
261                                 printf("%s: no extension file\n", argv[0]);
262                                 exit(1);
263                         }
264                         mktagfile(hp);
265                         argv++;
266                         argc--;
267                 }
268                 exit(0);
269         }
270         /* No host names specified.  Do them all. */
271         hp = (struct host *) hash_FirstEntry(nmhashtable);
272         while (hp != NULL) {
273                 mktagfile(hp);
274                 hp = (struct host *) hash_NextEntry(nmhashtable);
275         }
276         return (0);
277 }
278 \f
279
280
281 /*
282  * Make a "TAG 18" file for this host.
283  * (Insert the RFC1497 options.)
284  */
285
286 static void
287 mktagfile(hp)
288         struct host *hp;
289 {
290         FILE *fp;
291         int bytesleft, len;
292         byte *vp;
293
294         if (!hp->flags.exten_file)
295                 return;
296
297         vp = buffer;
298         bytesleft = BUFFERSIZE;
299         bcopy(vm_rfc1048, vp, 4);       /* Copy in the magic cookie */
300         vp += 4;
301         bytesleft -= 4;
302
303         /*
304          * The "extension file" options are appended by the following
305          * function (which is shared with bootpd.c).
306          */
307         len = dovend_rfc1497(hp, vp, bytesleft);
308         vp += len;
309         bytesleft -= len;
310
311         if (bytesleft < 1) {
312                 report(LOG_ERR, "%s: too much option data",
313                            hp->exten_file->string);
314                 return;
315         }
316         *vp++ = TAG_END;
317         bytesleft--;
318
319         /* Write the buffer to the extension file. */
320         printf("Updating \"%s\"\n", hp->exten_file->string);
321         if ((fp = fopen(hp->exten_file->string, "w")) == NULL) {
322                 report(LOG_ERR, "error opening \"%s\": %s",
323                            hp->exten_file->string, get_errmsg());
324                 return;
325         }
326         len = vp - buffer;
327         if (len != fwrite(buffer, 1, len, fp)) {
328                 report(LOG_ERR, "write failed on \"%s\" : %s",
329                            hp->exten_file->string, get_errmsg());
330         }
331         fclose(fp);
332
333 } /* mktagfile */
334
335 /*
336  * Local Variables:
337  * tab-width: 4
338  * c-indent-level: 4
339  * c-argdecl-indent: 4
340  * c-continued-statement-offset: 4
341  * c-continued-brace-offset: -4
342  * c-label-offset: -4
343  * c-brace-offset: 0
344  * End:
345  */