properly print to end of doc when -o#- is requested (4.3BSD-tahoe/usr.bin/31)
[unix-history] / usr / src / old / htable / htable.c
CommitLineData
ab6da654
DF
1/*
2 * Copyright (c) 1983 Regents of the University of California.
8f66080b
KB
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms are permitted
b8c620d6
KB
6 * provided that the above copyright notice and this paragraph are
7 * duplicated in all such forms and that any documentation,
8 * advertising materials, and other materials related to such
9 * distribution and use acknowledge that the software was developed
10 * by the University of California, Berkeley. The name of the
11 * University may not be used to endorse or promote products derived
12 * from this software without specific prior written permission.
13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
ab6da654
DF
16 */
17
dd020e70 18#ifndef lint
2de3e885
KM
19char copyright[] =
20"@(#) Copyright (c) 1983 Regents of the University of California.\n\
21 All rights reserved.\n";
8f66080b 22#endif /* not lint */
2de3e885
KM
23
24#ifndef lint
b8c620d6 25static char sccsid[] = "@(#)htable.c 5.8 (Berkeley) %G%";
8f66080b 26#endif /* not lint */
dd020e70
SL
27
28/*
29 * htable - convert NIC host table into a UNIX format.
30 * NIC format is described in RFC 810, 1 March 1982.
31 */
32#include <stdio.h>
33#include <ctype.h>
5494cf94 34#include <errno.h>
7df00d98 35#include <netdb.h>
7df00d98 36
5494cf94 37#include "htable.h" /* includes <sys/types.h> */
dd020e70 38
f7a7a9a9 39#include <sys/socket.h>
8f66080b 40#include <arpa/inet.h>
5494cf94 41
1750308c 42#define DATELINES 3 /* these lines usually contain the date */
99d3ae94 43#define MAXNETS 30 /* array size for local, connected nets */
1750308c 44
5494cf94
SL
45FILE *hf; /* hosts file */
46FILE *gf; /* gateways file */
47FILE *nf; /* networks file */
99d3ae94
MK
48struct gateway *savegateway(), *gatewayto();
49
50int connected_nets[MAXNETS];
51int nconnected;
52int local_nets[MAXNETS];
53int nlocal;
54char *myname;
dd020e70
SL
55
56main(argc, argv)
57 int argc;
58 char *argv[];
59{
99d3ae94
MK
60 int errs;
61
dd020e70 62 infile = "(stdin)";
99d3ae94
MK
63 myname = argv[0];
64 argc--;
65 argv++;
66 while (argc--) {
67 if (*argv[0] == '-') {
68 switch (argv[0][1]) {
69 case 'c':
70 nconnected = addlocal(argv[1], connected_nets);
71 argv++;
72 argc--;
73 break;
74 case 'l':
75 nlocal = addlocal(argv[1], local_nets);
76 argv++;
77 argc--;
78 break;
79 default:
80 usage();
81 /*NOTREACHED*/
82 }
83 } else {
84 infile = argv[0];
85 if (freopen(infile, "r", stdin) == NULL) {
86 perror(infile);
87 exit(1);
88 }
dd020e70 89 }
99d3ae94 90 argv++;
dd020e70
SL
91 }
92 hf = fopen("hosts", "w");
93 if (hf == NULL) {
94 perror("hosts");
95 exit(1);
96 }
5494cf94
SL
97 copylocal(hf, "localhosts");
98 gf = fopen("gateways", "w");
99 if (gf == NULL) {
dd020e70
SL
100 perror("gateways");
101 exit(1);
102 }
8f66080b 103 copygateways("localgateways");
5494cf94
SL
104 nf = fopen("networks", "w");
105 if (nf == NULL) {
106 perror("networks");
107 exit(1);
108 }
109 copylocal(nf, "localnetworks");
1750308c 110 copycomments(stdin, hf, DATELINES);
99d3ae94
MK
111 errs = yyparse();
112 dogateways();
113 exit(errs);
114}
115
116usage()
117{
118 fprintf(stderr,
119 "usage: %s [ -c connected-nets ] [-l local-nets ] [ input-file ]\n",
120 myname);
121 exit(1);
122}
123
124/*
125 * Turn a comma-separated list of network names or numbers in dot notation
126 * (e.g. "arpanet, 128.32") into an array of net numbers.
127 */
128addlocal(arg, nets)
129 char *arg;
130 int *nets;
131{
132 register char *p, c;
133 register int nfound = 0;
134
135 do {
136 p = arg;
137 while (*p && *p != ',' && !isspace(*p))
138 p++;
139 c = *p;
140 *p = 0;
141 while (*arg && isspace(*arg))
142 arg++;
143 if (*arg == 0)
144 continue;
145 if (nfound == MAXNETS) {
146 fprintf(stderr, "%s: Too many networks in list\n",
147 myname);
148 return (nfound);
149 }
150 if (getnetaddr(arg, &nets[nfound]))
151 nfound++;
152 else {
153 fprintf(stderr, "%s: %s: unknown network\n",
154 myname, arg);
155 exit(1);
156 }
573c06ae 157 arg = p + 1;
99d3ae94
MK
158 } while (c);
159 return (nfound);
dd020e70
SL
160}
161
162struct name *
163newname(str)
164 char *str;
165{
166 char *p;
167 struct name *nm;
168
169 p = malloc(strlen(str) + 1);
170 strcpy(p, str);
5494cf94 171 nm = (struct name *)malloc(sizeof (struct name));
dd020e70
SL
172 nm->name_val = p;
173 nm->name_link = NONAME;
174 return (nm);
175}
176
177char *
178lower(str)
179 char *str;
180{
181 register char *cp = str;
182
183 while (*cp) {
184 if (isupper(*cp))
185 *cp = tolower(*cp);
1bcba0d9
MK
186 if (*cp == '.')
187 break;
dd020e70
SL
188 cp++;
189 }
190 return (str);
191}
192
193do_entry(keyword, addrlist, namelist, cputype, opsys, protos)
194 int keyword;
195 struct addr *addrlist;
196 struct name *namelist, *cputype, *opsys, *protos;
197{
198 register struct addr *al, *al2;
5494cf94 199 register struct name *nl;
99d3ae94
MK
200 struct addr *connect_addr;
201 char *cp;
dd020e70
SL
202
203 switch (keyword) {
204
205 case KW_NET:
5494cf94
SL
206 nl = namelist;
207 if (nl == NONAME) {
208 fprintf(stderr, "htable: net");
6e2735e4 209 putnet(stderr, inet_netof(addrlist->addr_val));
5494cf94
SL
210 fprintf(stderr, " missing names.\n");
211 break;
212 }
213 fprintf(nf, "%-16.16s", lower(nl->name_val));
214 al2 = addrlist;
215 while (al = al2) {
216 char *cp;
217
6e2735e4 218 putnet(nf, inet_netof(al->addr_val));
5494cf94
SL
219 cp = "\t%s";
220 while (nl = nl->name_link) {
221 fprintf(nf, cp, lower(nl->name_val));
222 cp = " %s";
223 }
224 putc('\n', nf);
225 al2 = al->addr_link;
226 free((char *)al);
227 }
99d3ae94 228 break;
dd020e70
SL
229
230 case KW_GATEWAY:
99d3ae94 231 /* locate locally connected address, if one */
7df00d98 232 for (al = addrlist; al; al = al->addr_link)
99d3ae94 233 if (connectedto(inet_netof(al->addr_val)))
7df00d98 234 break;
99d3ae94
MK
235 if (al == NULL) {
236 /*
237 * Not connected to known networks. Save for later.
238 */
239 struct gateway *gw, *firstgw = (struct gateway *) NULL;
240
241 for (al = addrlist; al; al = al->addr_link) {
242 register int net;
243
244 net = inet_netof(al->addr_val);
245 gw = savegateway(namelist, net,
246 al->addr_val, 0);
247 if (firstgw == (struct gateway *) NULL)
248 firstgw = gw;
249 gw->g_firstent = firstgw;
250 }
251 freeaddrs(addrlist);
252 goto dontfree;
253 }
254 /*
255 * Connected to a known network.
256 * Mark this as the gateway to all other networks
257 * that are on the addrlist (unless we already have
258 * gateways to them).
259 */
260 connect_addr = al;
261 for (al = addrlist; al; al = al->addr_link) {
7df00d98 262 register int net;
5494cf94
SL
263
264 /* suppress duplicates -- not optimal */
7df00d98 265 net = inet_netof(al->addr_val);
49cdcf9f 266 if (connectedto(net) || gatewayto(net))
99d3ae94
MK
267 continue;
268 printgateway(net, namelist->name_val, 1);
269 (void) savegateway(namelist, net, al->addr_val, 1);
7df00d98 270 }
99d3ae94
MK
271 /*
272 * Put the gateway in the hosts file.
273 */
274 putaddr(hf, connect_addr->addr_val);
275 cp = "%s";
276 for (nl = namelist; nl; nl = nl->name_link) {
277 fprintf(hf, cp, lower(nl->name_val));
278 cp = " %s";
5494cf94 279 }
99d3ae94
MK
280 fprintf(hf, "\t# gateway\n");
281 freeaddrs(addrlist);
282 goto dontfree;
dd020e70
SL
283
284 case KW_HOST:
5494cf94
SL
285 al2 = addrlist;
286 while (al = al2) {
99d3ae94 287 if (!local(inet_netof(al->addr_val))) {
5494cf94
SL
288 char *cp;
289
290 putaddr(hf, al->addr_val);
291 cp = "%s";
292 for (nl = namelist; nl; nl = nl->name_link) {
293 fprintf(hf, cp, lower(nl->name_val));
294 cp = " %s";
295 }
dd020e70
SL
296 putc('\n', hf);
297 }
298 al2 = al->addr_link;
5494cf94 299 free((char *)al);
dd020e70 300 }
99d3ae94 301 break;
dd020e70
SL
302
303 default:
304 fprintf(stderr, "Unknown keyword: %d.\n", keyword);
305 }
5494cf94 306 freenames(namelist);
99d3ae94 307dontfree:
5494cf94 308 freenames(protos);
dd020e70
SL
309}
310
99d3ae94
MK
311printgateway(net, name, metric)
312 int net;
313 char *name;
314 int metric;
315{
316 struct netent *np;
317
318 fprintf(gf, "net ");
319 np = getnetbyaddr(net, AF_INET);
320 if (np)
321 fprintf(gf, "%s", np->n_name);
322 else
323 putnet(gf, net);
324 fprintf(gf, " gateway %s metric %d passive\n",
325 lower(name), metric);
326}
327
5494cf94
SL
328copylocal(f, filename)
329 FILE *f;
330 char *filename;
dd020e70
SL
331{
332 register FILE *lhf;
333 register cc;
334 char buf[BUFSIZ];
5494cf94 335 extern int errno;
dd020e70 336
5494cf94 337 lhf = fopen(filename, "r");
dd020e70 338 if (lhf == NULL) {
5494cf94
SL
339 if (errno != ENOENT) {
340 perror(filename);
341 exit(1);
342 }
343 fprintf(stderr, "Warning, no %s file.\n", filename);
dd020e70
SL
344 return;
345 }
346 while (cc = fread(buf, 1, sizeof(buf), lhf))
5494cf94 347 fwrite(buf, 1, cc, f);
dd020e70
SL
348 fclose(lhf);
349}
5494cf94 350
8f66080b 351copygateways(filename)
99d3ae94
MK
352 char *filename;
353{
354 register FILE *lhf;
99d3ae94
MK
355 struct name *nl;
356 char type[80];
357 char dname[80];
358 char gname[80];
359 char junk[80];
581d366a 360 char buf[500];
8f66080b 361 struct in_addr addr;
99d3ae94
MK
362 int net, metric;
363 extern int errno;
364
365 lhf = fopen(filename, "r");
366 if (lhf == NULL) {
367 if (errno != ENOENT) {
368 perror(filename);
369 exit(1);
370 }
371 fprintf(stderr, "Warning, no %s file.\n", filename);
372 return;
373 }
374 /* format: {net | host} XX gateway XX metric DD [passive]\n */
6e2735e4
MK
375 for (;;) {
376 junk[0] = 0;
581d366a 377 if (fgets(buf, sizeof(buf), lhf) == (char *)NULL)
6e2735e4 378 break;
581d366a
MK
379 fputs(buf, gf);
380 if (buf[0] == '#' ||
381 sscanf(buf, "%s %s gateway %s metric %d %s",
382 type, dname, gname, &metric, junk) < 5)
383 continue;
99d3ae94 384 if (strcmp(type, "net"))
581d366a 385 continue;
99d3ae94 386 if (!getnetaddr(dname, &net))
581d366a 387 continue;
8f66080b 388 if (!gethostaddr(gname, &addr.s_addr))
581d366a 389 continue;
99d3ae94
MK
390 nl = newname(gname);
391 (void) savegateway(nl, net, addr, metric);
99d3ae94
MK
392 }
393 fclose(lhf);
394}
395
396getnetaddr(name, addr)
397 char *name;
398 int *addr;
399{
400 struct netent *np = getnetbyname(name);
99d3ae94
MK
401
402 if (np == 0) {
403 *addr = inet_network(name);
404 return (*addr != -1);
405 } else {
406 if (np->n_addrtype != AF_INET)
407 return (0);
408 *addr = np->n_net;
409 return (1);
410 }
411}
412
413gethostaddr(name, addr)
414 char *name;
415 u_long *addr;
416{
417 struct hostent *hp;
418
419 hp = gethostbyname(name);
420 if (hp) {
421 *addr = *(u_long *)(hp->h_addr);
422 return (1);
423 }
424 *addr = inet_addr(name);
425 return (*addr != -1);
426}
427
1750308c
MD
428copycomments(in, out, ccount)
429 FILE *in, *out;
430 int ccount;
431{
1750308c 432 int count;
8f66080b 433 char buf[BUFSIZ], *fgets();
1750308c
MD
434
435 for (count=0; count < ccount; count++) {
436 if ((fgets(buf, sizeof(buf), in) == NULL) || (buf[0] != ';'))
437 return;
438 buf[0] = '#';
439 fputs(buf, out);
440 }
441 return;
442}
5494cf94
SL
443#define UC(b) (((int)(b))&0xff)
444
3dbccebd
MK
445/*
446 * Print network number in internet-standard dot notation;
447 * v is in host byte order.
448 */
5494cf94
SL
449putnet(f, v)
450 FILE *f;
6e2735e4 451 register int v;
5494cf94 452{
3dbccebd
MK
453 if (v < 128)
454 fprintf(f, "%d", v);
455 else if (v < 65536)
6e2735e4 456 fprintf(f, "%d.%d", UC(v >> 8), UC(v));
5494cf94 457 else
6e2735e4 458 fprintf(f, "%d.%d.%d", UC(v >> 16), UC(v >> 8), UC(v));
5494cf94
SL
459}
460
461putaddr(f, v)
462 FILE *f;
8f66080b 463 struct in_addr v;
5494cf94 464{
8f66080b 465 fprintf(f, "%-16.16s", inet_ntoa(v));
5494cf94
SL
466}
467
468freenames(list)
469 struct name *list;
470{
471 register struct name *nl, *nl2;
472
473 nl2 = list;
474 while (nl = nl2) {
475 nl2 = nl->name_link;
476 free(nl->name_val);
477 free((char *)nl);
478 }
479}
99d3ae94
MK
480
481freeaddrs(list)
482 struct addr *list;
483{
484 register struct addr *al, *al2;
485
486 al2 = list;
487 while (al = al2)
488 al2 = al->addr_link, free((char *)al);
489}
5494cf94
SL
490
491struct gateway *gateways = 0;
99d3ae94 492struct gateway *lastgateway = 0;
5494cf94 493
99d3ae94
MK
494struct gateway *
495gatewayto(net)
5494cf94
SL
496 register int net;
497{
498 register struct gateway *gp;
499
500 for (gp = gateways; gp; gp = gp->g_link)
99d3ae94
MK
501 if ((gp->g_net == net) && (gp->g_metric > 0))
502 return (gp);
503 return ((struct gateway *) NULL);
5494cf94
SL
504}
505
99d3ae94
MK
506struct gateway *
507savegateway(namelist, net, addr, metric)
508 struct name *namelist;
8f66080b 509 struct in_addr addr;
99d3ae94 510 int net, metric;
5494cf94
SL
511{
512 register struct gateway *gp;
513
514 gp = (struct gateway *)malloc(sizeof (struct gateway));
515 if (gp == 0) {
516 fprintf(stderr, "htable: out of memory\n");
517 exit(1);
518 }
99d3ae94
MK
519 gp->g_link = (struct gateway *) NULL;
520 if (lastgateway)
521 lastgateway->g_link = gp;
522 else
523 gateways = gp;
524 lastgateway = gp;
525 gp->g_name = namelist;
5494cf94 526 gp->g_net = net;
99d3ae94
MK
527 gp->g_addr = addr;
528 gp->g_metric = metric;
529 if (metric == 1)
530 gp->g_dst = gp;
2d474861 531 return (gp);
99d3ae94
MK
532}
533
534connectedto(net)
535 u_long net;
536{
537 register i;
538
539 for (i = 0; i < nconnected; i++)
540 if (connected_nets[i] == net)
541 return(1);
542 return(0);
543}
544
545local(net)
546 u_long net;
547{
548 register i;
549
550 for (i = 0; i < nlocal; i++)
551 if (local_nets[i] == net)
552 return(1);
553 return(0);
554}
555
556#define MAXHOPS 10
557
558/*
559 * Go through list of gateways, finding connections for gateways
560 * that are not yet connected.
561 */
562dogateways()
563{
564 register struct gateway *gp, *gw, *ggp;
565 register int hops, changed = 1;
566 struct name *nl;
567 char *cp;
568
569 for (hops = 0; hops < MAXHOPS && changed; hops++, changed = 0) {
570 for (gp = gateways; gp; gp = gp->g_link)
571 if ((gp->g_metric == 0) && (gw = gatewayto(gp->g_net))) {
572 /*
573 * Found a new connection.
574 * For each other network that this gateway is on,
575 * add a new gateway to that network.
576 */
577 changed = 1;
578 gp->g_dst = gw->g_dst;
579 gp->g_metric = gw->g_metric + 1;
580 for (ggp = gp->g_firstent; ggp->g_name == gp->g_name;
581 ggp = ggp->g_link) {
582 if (ggp == gp)
583 continue;
584 if (gatewayto(ggp->g_net))
585 continue;
586 ggp->g_dst = gp->g_dst;
587 ggp->g_metric = gp->g_metric;
588 printgateway(ggp->g_net,
589 gw->g_dst->g_name->name_val, gp->g_metric);
590 }
591 /*
592 * Put the gateway in the hosts file,
593 * using the address for the connected net.
594 */
595 putaddr(hf, gp->g_addr);
596 cp = "%s";
597 for (nl = gp->g_name; nl; nl = nl->name_link) {
598 fprintf(hf, cp, lower(nl->name_val));
599 cp = " %s";
600 }
601 fprintf(hf, "\t# gateway\n");
602 }
603 }
5494cf94 604}