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.3 Berkeley 05/19/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 if (exists(etc_conf)) 310 return (0); /* hope user has it together! */ 311 perror(etc_ttys); 312 quit(1); 313 } 314 315 lineno = 0; 316 ty = ttys; 317 while (fgets(buf, sizeof buf, tyf)) 318 { 319 lineno++; 320 if (sscanf(buf, "%c%c%s", 321 &ty->ty_active, &ty->ty_speed, ty->ty_port) == 3) 322 ty++; 323 else 324 { 325 error++; 326 fprintf(stderr, "bad line %d in %s: %s", 327 lineno, etc_ttys, buf); 328 } 329 } 330 fclose(tyf); 331 ty->ty_active = '\0'; 332 return(error); 333 } 334 335 writettys() 336 { 337 int rtn = 0; 338 char temp[1024]; 339 FILE *tyf, *tpf; 340 register struct ttys *ty; 341 342 sprintf(temp, "%s.tmp", etc_ttys); 343 if ((tyf = fopen(temp, "w")) == NULL) 344 { 345 perror(temp); 346 quit(1); 347 } 348 349 for (ty = ttys; ty->ty_active; ty++) 350 fprintf(tyf, "%c%c%s\n", 351 ty->ty_active, ty->ty_speed, ty->ty_port); 352 fclose(tyf); 353 354 if (rename(temp, etc_ttys) != 0) 355 { 356 fprintf(stderr, "Can't rename %s\n", temp); 357 rtn = 1; 358 } 359 360 sprintf(temp, "%s.tmp", etc_ttytype); 361 if ((tpf = fopen(temp, "w")) == NULL) 362 { 363 perror(temp); 364 quit(1); 365 } 366 367 for (ty = ttys; ty->ty_active; ty++) /* same ports! */ 368 fprintf(tpf, "%s %s\n", 369 type(ty->ty_port)->tp_term, ty->ty_port); 370 fclose(tpf); 371 372 if (rename(temp, etc_ttytype) != 0) 373 { 374 fprintf(stderr, "Can't rename %s\n", temp); 375 rtn = 1; 376 } 377 378 return (rtn); 379 } 380 381 382 edit() 383 { 384 /* 385 * invoke editor 386 */ 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 } 411 412 413 quit (n) 414 int n; 415 { 416 unlink (lockfile); 417 if (n > 1) 418 { 419 signal (n, SIG_DFL); 420 kill (getpid(), n); 421 } 422 exit (n); 423 } 424 425 getlockfile () 426 { 427 char *p; 428 char locktmp[64]; 429 int fd; 430 431 strcpy(locktmp, lockfile); 432 if (p = rindex(locktmp, '/')) 433 p++; 434 else 435 p = locktmp; 436 strcpy(p, "confttysXXXXXX"); 437 mktemp(locktmp); 438 439 if ((fd = creat(locktmp, 0600)) < 0) 440 { 441 perror(locktmp); 442 exit(1); 443 } 444 445 if (link(locktmp, lockfile) < 0) 446 { 447 perror(lockfile); 448 unlink(locktmp); 449 exit(1); 450 } 451 452 signal(SIGINT, quit); 453 signal(SIGQUIT, quit); 454 455 unlink(locktmp); 456 return(0); 457 } 458 459 struct speeds { 460 char *sp_name; /* human readable name */ 461 char sp_table; /* getty table name */ 462 } speeds[] = { 463 { "dialup", GT_DIALUP }, /* normal dialup rotation */ 464 { "selector", GT_SELECTOR }, /* port selector pseudo-table autobaud*/ 465 { "b110", GT_B110 }, /* 110 baud */ 466 { "b134", GT_B134 }, /* 134.5 baud selectric */ 467 { "b150", GT_B150 }, /* 150 baud */ 468 { "b300", GT_B300 }, /* 300 baud */ 469 { "b600", GT_B600 }, /* 600 baud */ 470 { "b1200", GT_B1200 }, /* 1200 baud */ 471 { "b2400", GT_B2400 }, /* 2400 baud */ 472 { "b4800", GT_B4800 }, /* 4800 baud */ 473 { "b9600", GT_B9600 }, /* 9600 baud */ 474 { "dw2console", GT_DW2CONSOLE },/* Decwriter Console - 300 baud */ 475 { "fastdialup", GT_FASTDIALUP },/* 1200-300 baud rotation for dialup */ 476 { "fastdialup1",GT_FASTDIALUP1},/* 300-1200 " " " " */ 477 { "crt_hcpy", GT_CRT_HCPY }, /* 9600-300 CRT + hardcopy rotation */ 478 { "hcpy_crt", GT_HCPY_CRT }, /* 300-9600 " " " */ 479 { "plugboard", GT_PLUGBOARD }, /* 9600-300-1200 rotation */ 480 { "plugboard1", GT_PLUGBOARD2 },/* 300-1200-9600 rotation */ 481 { "plugboard2", GT_PLUGBOARD2 },/* 1200-9600-300 rotation */ 482 { "interdata", GT_INTERDATA }, /* Interdata Console */ 483 { "chess", GT_CHESS }, /* LSI Chess Terminal */ 484 { "tty33", GT_TTY33 }, /* 110 baud Model 33 TTY */ 485 { "network", GT_NETWORK }, /* ethernet port */ 486 { "", 0 } 487 }; 488 489 char * 490 speedname (c) 491 char c; 492 { 493 struct speeds *sp; 494 static char sbuf[32]; 495 496 for (sp = speeds; sp->sp_table; sp++) 497 if (sp->sp_table == c) 498 break; 499 500 if (sp->sp_table) 501 strcpy(sbuf, sp->sp_name); 502 else 503 strcpy(sbuf, "-"); 504 505 if (strlen(sbuf) < 8) 506 strcat(sbuf, "\t"); 507 508 return (sbuf); 509 } 510 511 char * 512 termname (port) 513 char *port; 514 { 515 register struct ttytype *tp; 516 517 for (tp = ttytype; tp->tp_term[0]; tp++) 518 if (strcmp(port, tp->tp_port) == 0) 519 return (tp->tp_term); 520 521 if (tp < &ttytype[(sizeof ttytype / sizeof (struct ttytype)) -1]) 522 { 523 strcpy(tp->tp_port, port); 524 strcpy(tp->tp_term, "unknown"); 525 (++tp)->tp_term[0] = '\0'; 526 } 527 528 return ("unknown"); 529 } 530 531 char 532 speedchar (speed) 533 char *speed; 534 { 535 register struct speeds *sp; 536 537 for (sp = speeds; sp->sp_table; sp++) 538 if (strcmp(sp->sp_name, speed) == 0) 539 return (sp->sp_table); 540 return ('\0'); 541 } 542 543 struct ttytype * 544 type (port) 545 char *port; 546 { 547 register struct ttytype *tp; 548 549 for (tp = ttytype; tp->tp_term[0]; tp++) 550 if (strcmp(tp->tp_port, port) == 0) 551 return (tp); 552 553 if (tp < &ttytype[(sizeof ttytype / sizeof (struct ttytype)) -1]) 554 { 555 strcpy(tp->tp_port, port); 556 strcpy(tp->tp_term, "unknown"); 557 return(tp); 558 } 559 560 return((struct ttytype *)0); 561 } 562