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