1 2 #ifndef lint 3 char sccsid[] = "@(#)configttys.c 4.4 (Berkeley) 06/19/83"; 4 #endif 5 6 /* 7 * configttys - configure "tty" ports 8 * 9 * David L. Wasley 10 * U.C.Berkeley 11 */ 12 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) 51 int argc; 52 char **argv; 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 178 fprintf(conf, conformat, "port", "login", "speed\t", "terminal type"); 179 fprintf(conf, conformat, "----", "-----", "-----\t", "-------------"); 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 297 /* 298 * read ttys file 299 */ 300 readttys() 301 { 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 { 310 if (exists(etc_conf)) 311 return (0); /* hope user has it together! */ 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 382 /* 383 * invoke editor 384 */ 385 edit() 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 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 } 457 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 " " " " */ 476 { "crt", GT_CRT_HCPY }, /* 9600-300 CRT + hardcopy rotation */ 477 { "hardcopy", GT_HCPY_CRT }, /* 300-9600 " " " */ 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 */ 484 { "network", GT_NETWORK }, /* network port */ 485 { "", 0 } 486 }; 487 488 char * 489 speedname (c) 490 char c; 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) 512 char *port; 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) 532 char *speed; 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) 544 char *port; 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 } 561