Commit | Line | Data |
---|---|---|
10c529ad DW |
1 | /* |
2 | * configttys - configure "tty" ports | |
3 | * | |
4 | * David L. Wasley | |
5 | * U.C.Berkeley | |
6 | */ | |
7 | ||
8 | #ifndef lint | |
9 | char sccsid[] = "@(#)configttys.c 4.1 Berkeley %G%"; | |
10 | #endif | |
11 | ||
12 | #include <stdio.h> | |
13 | #include <getty.h> | |
14 | #include <signal.h> | |
15 | ||
16 | #define exists(file) (access(file, 0) == 0) | |
17 | ||
18 | char *etc_ttys = "/etc/ttys"; /* active port speed table */ | |
19 | char *etc_ttytype = "/etc/ttytype"; /* terminal type table */ | |
20 | char *etc_conf = "/etc/ttyconf"; /* master config file */ | |
21 | char *lockfile = "/etc/ttyconf.lock"; /* interlock file */ | |
22 | ||
23 | struct ttys { | |
24 | char ty_active; /* active login port */ | |
25 | char ty_speed; /* speed table character */ | |
26 | char ty_port[32]; /* port name */ | |
27 | } ttys[256]; | |
28 | ||
29 | struct ttytype { | |
30 | char tp_term[64]; /* terminal type name */ | |
31 | char tp_port[32]; /* port name */ | |
32 | } ttytype[256]; | |
33 | ||
34 | char conformat[] = "%s\t%s\t%s\t%s\n"; | |
35 | ||
36 | int error = 0; | |
37 | int renamed = 0; | |
38 | int debug = 0; /* debug mode */ | |
39 | int backup = 0; /* create backup copies of old data */ | |
40 | int interactive = 1; /* interactive mode */ | |
41 | ||
42 | char *speedname(); /* port speed code name */ | |
43 | char speedchar(); /* getty table name */ | |
44 | char *termname(); /* name of terminal on this port */ | |
45 | char *rindex(); | |
46 | struct ttytype *type(); /* find ttytype for port */ | |
47 | FILE *fopen(); | |
48 | ||
49 | main (argc, argv) | |
50 | int argc; | |
51 | char **argv; | |
52 | { | |
53 | int lineno; | |
54 | int child; | |
55 | int status; | |
56 | char c; | |
57 | struct ttys *ty; | |
58 | struct ttytype *tp; | |
59 | char port[32]; | |
60 | char active[16]; | |
61 | char speed[32]; | |
62 | char term[64]; | |
63 | FILE *tyf, *tpf, *conf; | |
64 | char buf[1024]; | |
65 | char ans[32]; | |
66 | ||
67 | while (--argc > 0) | |
68 | { | |
69 | if (**++argv == '-') switch (*++*argv) | |
70 | { | |
71 | case 'd': | |
72 | debug = 1; | |
73 | break; | |
74 | ||
75 | case 'n': /* non-interactive */ | |
76 | interactive = 0; | |
77 | break; | |
78 | ||
79 | case 'b': /* backup old databases */ | |
80 | backup = 1; | |
81 | break; | |
82 | ||
83 | default: | |
84 | fprintf(stderr, "unknown option %c\n", **argv); | |
85 | exit(1); | |
86 | } | |
87 | } | |
88 | ||
89 | if (debug) | |
90 | { | |
91 | etc_ttys = rindex(etc_ttys, '/') + 1; | |
92 | etc_ttytype = rindex(etc_ttytype, '/') + 1; | |
93 | etc_conf = rindex(etc_conf, '/') + 1; | |
94 | lockfile = rindex(lockfile, '/') + 1; | |
95 | } | |
96 | ||
97 | /* | |
98 | * create backup copies of the databases? | |
99 | */ | |
100 | if (backup) | |
101 | { | |
102 | if (exists(etc_ttys)) | |
103 | { | |
104 | sprintf(buf, "/bin/cp %s %s.bak", etc_ttys, etc_ttys); | |
105 | system(buf); | |
106 | } | |
107 | if (exists(etc_ttys)) | |
108 | { | |
109 | sprintf(buf, "/bin/cp %s %s.bak", etc_ttytype, etc_ttytype); | |
110 | system(buf); | |
111 | } | |
112 | if (exists(etc_conf)) | |
113 | { | |
114 | sprintf(buf, "/bin/cp %s %s.bak", etc_conf, etc_conf); | |
115 | system(buf); | |
116 | } | |
117 | } | |
118 | ||
119 | /* | |
120 | * create interlock file | |
121 | */ | |
122 | getlockfile(lockfile); | |
123 | ||
124 | /* | |
125 | * always read ttys file for comparison | |
126 | * It is afterall what really counts! | |
127 | */ | |
128 | if (readttys() != 0) | |
129 | quit(1); | |
130 | ||
131 | /* | |
132 | * read old ttytypes if necessary | |
133 | */ | |
134 | if (! exists(etc_conf)) | |
135 | { | |
136 | /* | |
137 | * open old ttytype file | |
138 | */ | |
139 | if ((tpf = fopen(etc_ttytype, "r")) == NULL) | |
140 | { | |
141 | perror(etc_ttytype); | |
142 | quit(1); | |
143 | } | |
144 | ||
145 | /* | |
146 | * read ttytype file | |
147 | */ | |
148 | lineno = 0; | |
149 | tp = ttytype; | |
150 | while (fgets(buf, sizeof buf, tpf)) | |
151 | { | |
152 | lineno++; | |
153 | if (sscanf(buf, "%s %s", tp->tp_term, tp->tp_port) == 2) | |
154 | tp++; | |
155 | else | |
156 | { | |
157 | error++; | |
158 | fprintf(stderr, "bad line %d in %s: %s", | |
159 | lineno, etc_ttytype, buf); | |
160 | } | |
161 | } | |
162 | fclose(tpf); | |
163 | tp->tp_term[0] = '\0'; | |
164 | ||
165 | if (error > 0) | |
166 | quit(1); | |
167 | ||
168 | /* | |
169 | * create master config file | |
170 | */ | |
171 | if ((conf = fopen(etc_conf, "w")) == NULL) | |
172 | { | |
173 | perror(etc_conf); | |
174 | quit(1); | |
175 | } | |
176 | ||
177 | fprintf(conf, conformat, "port", "active", "speed\t", "terminal name"); | |
178 | fprintf(conf, conformat, "----", "------", "-----\t", "-------------"); | |
179 | for (ty = ttys; ty->ty_active; ty++) | |
180 | { | |
181 | fprintf(conf, conformat, ty->ty_port, | |
182 | ty->ty_active == '1'? "active":"-", | |
183 | speedname(ty->ty_speed), | |
184 | termname(ty->ty_port)); | |
185 | } | |
186 | fclose(conf); | |
187 | } | |
188 | ||
189 | /* | |
190 | * open master config file | |
191 | */ | |
192 | if ((conf = fopen(etc_conf, "r")) == NULL) | |
193 | { | |
194 | perror(etc_conf); | |
195 | quit(1); | |
196 | } | |
197 | ||
198 | if (interactive) | |
199 | edit(); | |
200 | ||
201 | /* | |
202 | * read conf file | |
203 | */ | |
204 | re_read: | |
205 | rewind(conf); | |
206 | ty = ttys; | |
207 | renamed = 0; | |
208 | error = 0; | |
209 | lineno = 0; | |
210 | ||
211 | while (fgets(buf, sizeof buf, conf)) /* skip heading */ | |
212 | { | |
213 | lineno++; | |
214 | if (buf[0] == '-') | |
215 | break; | |
216 | } | |
217 | ||
218 | while (fgets(buf, sizeof buf, conf)) | |
219 | { | |
220 | lineno++; | |
221 | if (sscanf(buf, "%s %s %s %s", port, active, speed, term) < 4) | |
222 | { | |
223 | fprintf(stderr, "line %d: field(s) missing: %s", | |
224 | lineno, buf); | |
225 | error++; | |
226 | break; | |
227 | } | |
228 | ||
229 | if (strcmp(port, ty->ty_port) != 0) | |
230 | { | |
231 | if (! ty->ty_active || renamed) | |
232 | strcpy(ty->ty_port, port); | |
233 | else | |
234 | { | |
235 | fprintf(stderr, "line %d: port name changed! %s -> %s\n", | |
236 | lineno, ty->ty_port, port); | |
237 | fprintf(stderr, "Are you sure this is OK? "); | |
238 | gets(ans); | |
239 | if (ans[0] != 'y') | |
240 | { | |
241 | edit(); | |
242 | goto re_read; | |
243 | } | |
244 | renamed++; | |
245 | strcpy(ty->ty_port, port); | |
246 | } | |
247 | } | |
248 | ||
249 | if (strcmp(active, "active") == 0) | |
250 | ty->ty_active = '1'; | |
251 | else | |
252 | ty->ty_active = '0'; | |
253 | ||
254 | if (c = speedchar(speed)) | |
255 | ty->ty_speed = c; | |
256 | else | |
257 | { | |
258 | fprintf(stderr, "line %d: speed name not known: %s\n", | |
259 | lineno, speed); | |
260 | error++; | |
261 | } | |
262 | ||
263 | if (tp = type(port)) | |
264 | strcpy(tp->tp_term, term); | |
265 | /* else ?? */ | |
266 | ||
267 | ty++; | |
268 | } | |
269 | ||
270 | if (ty == ttys) | |
271 | { | |
272 | fprintf(stderr, "%s empty??\n", etc_conf); | |
273 | error++; | |
274 | } | |
275 | ||
276 | if (error) | |
277 | { | |
278 | if (interactive) | |
279 | { | |
280 | fprintf(stderr, "re-edit? "); | |
281 | gets(ans); | |
282 | if (ans[0] == 'y') | |
283 | { | |
284 | edit(); | |
285 | goto re_read; | |
286 | } | |
287 | } | |
288 | fprintf(stderr, "Files not modified.\n"); | |
289 | quit(1); | |
290 | } | |
291 | ||
292 | writettys(); | |
293 | quit(0); | |
294 | } | |
295 | ||
296 | readttys() | |
297 | { | |
298 | /* | |
299 | * read ttys file | |
300 | */ | |
301 | FILE *tyf; | |
302 | register struct ttys *ty; | |
303 | char buf[1024]; | |
304 | int lineno; | |
305 | int error = 0; | |
306 | ||
307 | if ((tyf = fopen(etc_ttys, "r")) == NULL) | |
308 | { | |
309 | perror(etc_ttys); | |
310 | quit(1); | |
311 | } | |
312 | ||
313 | lineno = 0; | |
314 | ty = ttys; | |
315 | while (fgets(buf, sizeof buf, tyf)) | |
316 | { | |
317 | lineno++; | |
318 | if (sscanf(buf, "%c%c%s", | |
319 | &ty->ty_active, &ty->ty_speed, ty->ty_port) == 3) | |
320 | ty++; | |
321 | else | |
322 | { | |
323 | error++; | |
324 | fprintf(stderr, "bad line %d in %s: %s", | |
325 | lineno, etc_ttys, buf); | |
326 | } | |
327 | } | |
328 | fclose(tyf); | |
329 | ty->ty_active = '\0'; | |
330 | return(error); | |
331 | } | |
332 | ||
333 | writettys() | |
334 | { | |
335 | int rtn = 0; | |
336 | char temp[1024]; | |
337 | FILE *tyf, *tpf; | |
338 | register struct ttys *ty; | |
339 | ||
340 | sprintf(temp, "%s.tmp", etc_ttys); | |
341 | if ((tyf = fopen(temp, "w")) == NULL) | |
342 | { | |
343 | perror(temp); | |
344 | quit(1); | |
345 | } | |
346 | ||
347 | for (ty = ttys; ty->ty_active; ty++) | |
348 | fprintf(tyf, "%c%c%s\n", | |
349 | ty->ty_active, ty->ty_speed, ty->ty_port); | |
350 | fclose(tyf); | |
351 | ||
352 | if (rename(temp, etc_ttys) != 0) | |
353 | { | |
354 | fprintf(stderr, "Can't rename %s\n", temp); | |
355 | rtn = 1; | |
356 | } | |
357 | ||
358 | sprintf(temp, "%s.tmp", etc_ttytype); | |
359 | if ((tpf = fopen(temp, "w")) == NULL) | |
360 | { | |
361 | perror(temp); | |
362 | quit(1); | |
363 | } | |
364 | ||
365 | for (ty = ttys; ty->ty_active; ty++) /* same ports! */ | |
366 | fprintf(tpf, "%s %s\n", | |
367 | type(ty->ty_port)->tp_term, ty->ty_port); | |
368 | fclose(tpf); | |
369 | ||
370 | if (rename(temp, etc_ttytype) != 0) | |
371 | { | |
372 | fprintf(stderr, "Can't rename %s\n", temp); | |
373 | rtn = 1; | |
374 | } | |
375 | ||
376 | return (rtn); | |
377 | } | |
378 | ||
379 | \f | |
380 | edit() | |
381 | { | |
382 | /* | |
383 | * invoke editor | |
384 | */ | |
385 | int child; | |
386 | int status; | |
387 | ||
388 | if ((child = fork()) == 0) | |
389 | { | |
390 | execl("/usr/ucb/vi", "vi", etc_conf, 0); | |
391 | execl("/bin/ed", "ed", etc_conf, 0); | |
392 | exit(1); | |
393 | } | |
394 | ||
395 | if (child < 0) | |
396 | { | |
397 | perror("can't fork editor"); | |
398 | quit(1); | |
399 | } | |
400 | ||
401 | /* | |
402 | * wait for editor | |
403 | */ | |
404 | while (wait(&status) >= 0) | |
405 | ; | |
406 | ||
407 | return (status); | |
408 | } | |
409 | \f | |
410 | ||
411 | quit (n) | |
412 | int n; | |
413 | { | |
414 | unlink (lockfile); | |
415 | if (n > 1) | |
416 | { | |
417 | signal (n, SIG_DFL); | |
418 | kill (getpid(), n); | |
419 | } | |
420 | exit (n); | |
421 | } | |
422 | ||
423 | getlockfile () | |
424 | { | |
425 | char *p; | |
426 | char locktmp[64]; | |
427 | int fd; | |
428 | ||
429 | strcpy(locktmp, lockfile); | |
430 | if (p = rindex(locktmp, '/')) | |
431 | p++; | |
432 | else | |
433 | p = locktmp; | |
434 | strcpy(p, "confttysXXXXXX"); | |
435 | mktemp(locktmp); | |
436 | ||
437 | if ((fd = creat(locktmp, 0600)) < 0) | |
438 | { | |
439 | perror(locktmp); | |
440 | exit(1); | |
441 | } | |
442 | ||
443 | if (link(locktmp, lockfile) < 0) | |
444 | { | |
445 | perror(lockfile); | |
446 | unlink(locktmp); | |
447 | exit(1); | |
448 | } | |
449 | ||
450 | signal(SIGINT, quit); | |
451 | signal(SIGQUIT, quit); | |
452 | ||
453 | unlink(locktmp); | |
454 | return(0); | |
455 | } | |
456 | \f | |
457 | struct speeds { | |
458 | char *sp_name; /* human readable name */ | |
459 | char sp_table; /* getty table name */ | |
460 | } speeds[] = { | |
461 | { "dialup", GT_DIALUP }, /* normal dialup rotation */ | |
462 | { "selector", GT_SELECTOR }, /* port selector pseudo-table autobaud*/ | |
463 | { "b110", GT_B110 }, /* 110 baud */ | |
464 | { "b134", GT_B134 }, /* 134.5 baud selectric */ | |
465 | { "b150", GT_B150 }, /* 150 baud */ | |
466 | { "b300", GT_B300 }, /* 300 baud */ | |
467 | { "b600", GT_B600 }, /* 600 baud */ | |
468 | { "b1200", GT_B1200 }, /* 1200 baud */ | |
469 | { "b2400", GT_B2400 }, /* 2400 baud */ | |
470 | { "b4800", GT_B4800 }, /* 4800 baud */ | |
471 | { "b9600", GT_B9600 }, /* 9600 baud */ | |
472 | { "dw2console", GT_DW2CONSOLE },/* Decwriter Console - 300 baud */ | |
473 | { "fastdialup", GT_FASTDIALUP },/* 1200-300 baud rotation for dialup */ | |
474 | { "fastdialup1",GT_FASTDIALUP1},/* 300-1200 " " " " */ | |
475 | { "crt_hcpy", GT_CRT_HCPY }, /* 9600-300 CRT + hardcopy rotation */ | |
476 | { "hcpy_crt", GT_HCPY_CRT }, /* 300-9600 " " " */ | |
477 | { "plugboard", GT_PLUGBOARD }, /* 9600-300-1200 rotation */ | |
478 | { "plugboard1", GT_PLUGBOARD2 },/* 300-1200-9600 rotation */ | |
479 | { "plugboard2", GT_PLUGBOARD2 },/* 1200-9600-300 rotation */ | |
480 | { "interdata", GT_INTERDATA }, /* Interdata Console */ | |
481 | { "chess", GT_CHESS }, /* LSI Chess Terminal */ | |
482 | { "tty33", GT_TTY33 }, /* 110 baud Model 33 TTY */ | |
483 | { "network", GT_NETWORK }, /* ethernet port */ | |
484 | { "", 0 } | |
485 | }; | |
486 | ||
487 | char * | |
488 | speedname (c) | |
489 | char c; | |
490 | { | |
491 | struct speeds *sp; | |
492 | static char sbuf[32]; | |
493 | ||
494 | for (sp = speeds; sp->sp_table; sp++) | |
495 | if (sp->sp_table == c) | |
496 | break; | |
497 | ||
498 | if (sp->sp_table) | |
499 | strcpy(sbuf, sp->sp_name); | |
500 | else | |
501 | strcpy(sbuf, "-"); | |
502 | ||
503 | if (strlen(sbuf) < 8) | |
504 | strcat(sbuf, "\t"); | |
505 | ||
506 | return (sbuf); | |
507 | } | |
508 | ||
509 | char * | |
510 | termname (port) | |
511 | char *port; | |
512 | { | |
513 | register struct ttytype *tp; | |
514 | ||
515 | for (tp = ttytype; tp->tp_term[0]; tp++) | |
516 | if (strcmp(port, tp->tp_port) == 0) | |
517 | return (tp->tp_term); | |
518 | ||
519 | if (tp < &ttytype[(sizeof ttytype / sizeof (struct ttytype)) -1]) | |
520 | { | |
521 | strcpy(tp->tp_port, port); | |
522 | strcpy(tp->tp_term, "unknown"); | |
523 | (++tp)->tp_term[0] = '\0'; | |
524 | } | |
525 | ||
526 | return ("unknown"); | |
527 | } | |
528 | ||
529 | char | |
530 | speedchar (speed) | |
531 | char *speed; | |
532 | { | |
533 | register struct speeds *sp; | |
534 | ||
535 | for (sp = speeds; sp->sp_table; sp++) | |
536 | if (strcmp(sp->sp_name, speed) == 0) | |
537 | return (sp->sp_table); | |
538 | return ('\0'); | |
539 | } | |
540 | ||
541 | struct ttytype * | |
542 | type (port) | |
543 | char *port; | |
544 | { | |
545 | register struct ttytype *tp; | |
546 | ||
547 | for (tp = ttytype; tp->tp_term[0]; tp++) | |
548 | if (strcmp(tp->tp_port, port) == 0) | |
549 | return (tp); | |
550 | ||
551 | if (tp < &ttytype[(sizeof ttytype / sizeof (struct ttytype)) -1]) | |
552 | { | |
553 | strcpy(tp->tp_port, port); | |
554 | strcpy(tp->tp_term, "unknown"); | |
555 | return(tp); | |
556 | } | |
557 | ||
558 | return((struct ttytype *)0); | |
559 | } | |
560 | \f | |
561 | /* DELETE this for 4.2bsd */ | |
562 | ||
563 | #include <errno.h> | |
564 | ||
565 | rename (from, to) | |
566 | char *from, *to; | |
567 | { | |
568 | extern int errno; | |
569 | ||
570 | if (unlink(to) < 0) | |
571 | if (errno != ENOENT) | |
572 | return(-1); | |
573 | if (link(from, to) == 0) | |
574 | return (unlink(from)); | |
575 | else | |
576 | return(-1); | |
577 | } | |
578 |