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.2 Berkeley 05/18/83"; 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", "login", "speed\t", "terminal type"); 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 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 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 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