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