1 #ident "$Id: gettydefs.c,v 4.1 1997/01/12 14:53:39 gert Exp $ Copyright (c) 1993 Gert Doering/Chris Lewis" 2 3 /* gettydefs.c 4 * 5 * Read /etc/gettydefs file, and permit retrieval of individual entries. 6 * 7 * Code in this module by Chris Lewis 8 */ 9 10 #include <stdio.h> 11 #include <string.h> 12 #include <ctype.h> 13 #include <fcntl.h> 14 #include <unistd.h> 15 #include "syslibs.h" 16 17 #include "mgetty.h" 18 #include "policy.h" 19 20 boolean verbose; 21 22 char * mydup _P1 ((s), register char *s) 23 { 24 register char *p = (char *) malloc(strlen(s) + 1); 25 if (!p) { 26 lprintf(L_ERROR, "mydup can't malloc"); 27 exit(1); 28 } 29 strcpy(p, s); 30 return(p); 31 } 32 #ifdef USE_GETTYDEFS 33 34 static char gettydefs_ID[] = "@(#)gettydefs.c compiled with USE_GETTYDEFS"; 35 36 #include "tio.h" 37 38 struct modeword { 39 char *name; 40 tioflag_t turnon; 41 tioflag_t turnoff; 42 unsigned short metaon; 43 unsigned short metaoff; 44 }; 45 46 /* Meta tokens */ 47 #define SANE 0x0001 48 #define ODDP 0x0002 49 50 #define PARITY 0x0004 51 #define NPARITY 0x0008 52 53 #define RAW 0x0010 54 #define COOKED 0x0020 55 56 #define NL 0x0040 57 #define NNL 0x0080 58 59 #define LCASE 0x0100 60 #define NLCASE 0x0200 61 62 #define TABS 0x0400 63 #define NTABS 0x0800 64 65 /* input modes */ 66 67 static struct modeword iflags[] = { 68 { "IGNBRK", IGNBRK, IGNBRK }, 69 { "BRKINT", BRKINT, BRKINT, SANE }, 70 { "IGNPAR", IGNPAR, IGNPAR, SANE }, 71 { "PARMRK", PARMRK, PARMRK }, 72 { "INPCK", INPCK, INPCK }, 73 { "ISTRIP", ISTRIP, ISTRIP, SANE }, 74 { "INLCR", INLCR, INLCR, 0, NNL }, 75 { "IGNCR", IGNCR, IGNCR, 0, NNL }, 76 { "ICRNL", ICRNL, ICRNL, (SANE|NL), NNL }, 77 { "IUCLC", IUCLC, IUCLC, LCASE, NLCASE }, 78 { "IXON", IXON, IXON, SANE }, 79 { "IXANY", IXANY, IXANY }, 80 { "IXOFF", IXOFF, IXOFF }, 81 { NULL } 82 }; 83 84 /* output modes */ 85 86 static struct modeword oflags[] = { 87 { "OPOST", OPOST, OPOST, (SANE|COOKED), RAW }, 88 { "OLCUC", OLCUC, OLCUC, LCASE, NLCASE }, 89 { "ONLCR", ONLCR, ONLCR, NL, NNL }, 90 { "OCRNL", OCRNL, OCRNL, 0, NNL }, 91 { "ONOCR", ONOCR, ONOCR }, 92 { "ONLRET", ONLRET, ONLRET, NNL }, 93 { "OFILL", OFILL, OFILL }, 94 { "OFDEL", OFDEL, OFDEL }, 95 { "NLDLY", NLDLY, NLDLY }, 96 { "NL0", NL0, NLDLY }, 97 { "NL1", NL1, NLDLY }, 98 { "CR0", CR0, CRDLY }, 99 { "CR1", CR1, CRDLY }, 100 { "CR2", CR2, CRDLY }, 101 { "CR3", CR3, CRDLY }, 102 { "TAB0", TAB0, TABDLY, TABS }, 103 { "TAB1", TAB1, TABDLY }, 104 { "TAB2", TAB2, TABDLY }, 105 { "TAB3", TAB3, TABDLY, NTABS }, 106 { "BS0", BS0, BSDLY }, 107 { "BS1", BS1, BSDLY }, 108 { "VT0", VT0, VTDLY }, 109 { "VT1", VT1, VTDLY }, 110 { "FF0", FF0, FFDLY }, 111 { "FF1", FF1, FFDLY }, 112 { NULL } 113 }; 114 115 /* control modes */ 116 117 static struct modeword cflags[] = { 118 { "B0", B0, CBAUD }, 119 { "B50", B50, CBAUD }, 120 { "B75", B75, CBAUD }, 121 { "B110", B110, CBAUD }, 122 { "B134", B134, CBAUD }, 123 { "B150", B150, CBAUD }, 124 { "B200", B200, CBAUD }, 125 { "B300", B300, CBAUD }, 126 { "B600", B600, CBAUD }, 127 #ifdef B900 128 { "B900", B900, CBAUD }, 129 #endif 130 { "B1200", B1200, CBAUD }, 131 { "B1800", B1800, CBAUD }, 132 { "B2400", B2400, CBAUD }, 133 #ifdef B3600 134 { "B3600", B3600, CBAUD }, 135 #endif 136 { "B4800", B4800, CBAUD }, 137 #ifdef B7200 138 { "B7200", B7200, CBAUD }, 139 #endif 140 { "B9600", B9600, CBAUD }, 141 #ifdef B19200 142 { "B19200", B19200, CBAUD }, 143 #endif 144 #ifdef B38400 145 { "B38400", B38400, CBAUD }, 146 #endif 147 #ifdef B57600 148 { "B57600", B57600, CBAUD }, 149 #endif 150 #ifdef B76800 151 { "B76800", B76800, CBAUD }, 152 #endif 153 #ifdef B115200 154 { "B115200", B115200, CBAUD }, 155 #endif 156 #ifdef B230400 157 { "B230400", B230400, CBAUD }, 158 #endif 159 #ifdef B230400 160 { "B230400", B230400, CBAUD }, 161 #endif 162 #ifdef B460800 163 { "B460800", B460800, CBAUD }, 164 #endif 165 { "EXTA", EXTA, CBAUD }, 166 { "EXTB", EXTB, CBAUD }, 167 { "CS5", CS5, CSIZE }, 168 { "CS6", CS6, CSIZE }, 169 { "CS7", CS7, CSIZE, (ODDP|PARITY) }, 170 { "CS8", CS8, CSIZE, (SANE|NPARITY) }, 171 { "CSTOPB", CSTOPB, CSTOPB }, 172 { "CREAD", CREAD, CREAD, SANE }, 173 { "PARENB", PARENB, PARENB, (ODDP|PARITY), (NPARITY) }, 174 { "PARODD", PARODD, PARODD, ODDP }, 175 { "HUPCL", HUPCL, HUPCL }, 176 { "CLOCAL", CLOCAL, CLOCAL }, 177 /* Various handshaking defines */ 178 #ifdef CTSCD 179 { "CTSCD", CTSCD, CTSCD }, 180 #endif 181 #ifdef CRTSCTS 182 { "CRTSCTS", CRTSCTS, CRTSCTS }, 183 #endif 184 #ifdef CRTSFL 185 { "CRTSFL", CRTSFL, CRTSFL }, 186 #endif 187 #ifdef RTSFLOW 188 { "RTSFLOW", RTSFLOW, RTSFLOW }, 189 { "CTSFLOW", CTSFLOW, CTSFLOW }, 190 #endif 191 #ifdef HDX 192 { "HDX", HDX, HDX }, 193 #endif 194 { NULL } 195 }; 196 197 /* line discipline */ 198 static struct modeword lflags[] = { 199 { "ISIG", ISIG, ISIG, SANE }, 200 { "ICANON", ICANON, ICANON, (SANE|COOKED), RAW }, 201 { "XCASE", XCASE, XCASE, LCASE, NLCASE }, 202 { "ECHO", ECHO, ECHO, SANE }, 203 { "ECHOE", ECHOE, ECHOE }, 204 { "ECHOK", ECHOK, ECHOK, SANE }, 205 { "ECHONL", ECHONL, ECHONL }, 206 { "NOFLSH", NOFLSH, NOFLSH }, 207 { NULL } 208 }; 209 210 /* c_cc special characters */ 211 static struct modeword ccchars[] = { 212 {"VINTR", VINTR, CINTR}, 213 {"VQUIT", VQUIT, CQUIT}, 214 {"VERASE", VERASE, CERASE}, 215 {"VKILL", VKILL, CKILL}, 216 {"VEOF", VEOF, CEOF}, 217 #if defined(VEOL) && VEOL < TIONCC 218 {"VEOL", VEOL, CEOL}, 219 #endif 220 #if defined(CEOL2) && defined(VEOL2) && VEOL2 < TIONCC 221 {"VEOL2", VEOL2, CEOL2}, 222 #endif 223 #if defined(VSUSP) && VSUSP < TIONCC 224 {"VSUSP", VSUSP, CSUSP}, 225 #endif 226 #if defined(VSTART) && VSTART < TIONCC 227 {"VSTART", VSTART, CSTART}, 228 #endif 229 #if defined(VSTOP) && VSTOP < TIONCC 230 {"VSTOP", VSTOP, CSTOP}, 231 #endif 232 #if defined(VSWTCH) && VSWTCH < TIONCC 233 {"VSWTCH", VSWTCH, CSWTCH}, 234 #endif 235 /* SVR4.2 */ 236 #if defined(VDSUSP) && VDSUSP < TIONCC 237 {"VDSUSP", VDSUSP, CDSUSP}, 238 #endif 239 #if defined(VREPRINT) && VREPRINT < TIONCC 240 {"VREPRINT", VREPRINT, CRPRNT}, 241 #endif 242 #if defined(VDISCARD) && VDISCARD < TIONCC 243 {"VDISCARD", VDISCARD, CFLUSH}, 244 #endif 245 #if defined(VWERASE) && VWERASE < TIONCC 246 {"VWERASE", VWERASE, CWERASE}, 247 #endif 248 #if defined(VLNEXT) && VLNEXT < TIONCC 249 {"VLNEXT", VLNEXT, CLNEXT}, 250 #endif 251 {"VMIN", VMIN, 0}, 252 {"VTIME", VTIME, 0}, 253 { NULL } 254 }; 255 256 struct modeword metatokens[] = { 257 { "SANE", SANE }, 258 { "ODDP", ODDP }, 259 260 { "PARITY", PARITY }, 261 { "EVENP", PARITY }, 262 { "-ODDP", NPARITY }, 263 { "-PARITY", NPARITY }, 264 { "-EVENP", NPARITY }, 265 266 { "RAW", RAW }, 267 { "-RAW", COOKED }, 268 { "COOKED", COOKED }, 269 270 { "NL", NL }, 271 { "-NL", NNL }, 272 273 { "LCASE", LCASE }, 274 { "-LCASE", NLCASE }, 275 276 { "TABS", TABS }, 277 { "-TABS", NTABS }, 278 { "TAB3", NTABS }, 279 280 { NULL } 281 }; 282 283 #define GDCHUNK 5 284 285 GDE *gdep = (GDE *) NULL; 286 GDE *cur = (GDE *) NULL; 287 static int cntalloc = 0; 288 289 static struct modeword * 290 findmode _P2 ((modes, tok), struct modeword *modes, register char *tok) 291 { 292 for( ; modes->name; modes++) 293 if (strcmp(modes->name, tok) == 0) 294 return(modes); 295 return((struct modeword *) NULL); 296 } 297 298 static void 299 metaset _P3((tc, modes, key), tioflag_t *tc, struct modeword *modes, int key) 300 { 301 for ( ; modes->name; modes++) { 302 if (modes->metaon&key) 303 *tc = (*tc & ~ modes->turnoff) | modes->turnon; 304 if (modes->metaoff&key) 305 *tc = (*tc & ~ modes->turnoff); 306 } 307 } 308 309 static void 310 parsetermio _P2((ti, str), TIO *ti, char *str) 311 { 312 register char *p; 313 struct modeword *m; 314 tioflag_t *flag; 315 int metakey; 316 317 /* initialize c_cc[] array (tio_* doesn't init INTR/ERASE!) */ 318 tio_default_cc( ti ); 319 ti->c_cc[VINTR] = CINTR; 320 ti->c_cc[VERASE] = CERASE; 321 322 #ifndef POSIX_TERMIOS 323 ti->c_line = 0; 324 #endif 325 326 for (p = str; *p; p++) 327 if (islower(*p)) 328 *p = toupper(*p); 329 330 while ( (p = strtok(str, " \t")) != NULL ) { 331 int not = FALSE; 332 333 str = NULL; 334 335 metakey = 0; 336 337 if (strcmp(p, "EK") == 0) { 338 ti->c_cc[VERASE] = '#'; 339 ti->c_cc[VKILL] = CKILL; 340 continue; 341 } 342 343 for (m = metatokens; m->name; m++) 344 if (strcmp(p, m->name) == 0) { 345 metakey = m->turnon; 346 break; 347 } 348 349 if (metakey) { 350 metaset(&ti->c_lflag, lflags, metakey); 351 metaset(&ti->c_oflag, oflags, metakey); 352 metaset(&ti->c_iflag, iflags, metakey); 353 metaset(&ti->c_cflag, cflags, metakey); 354 continue; 355 } 356 357 if (*p == '-') { 358 not = TRUE; 359 p++; 360 } 361 362 if ((m = findmode(lflags, p)) != NULL) 363 flag = &ti->c_lflag; 364 else if ((m = findmode(oflags, p)) != NULL) 365 flag = &ti->c_oflag; 366 else if ((m = findmode(iflags, p)) != NULL) 367 flag = &ti->c_iflag; 368 else if ((m = findmode(cflags, p)) != NULL) 369 flag = &ti->c_cflag; 370 if (m) { 371 if (not) 372 *flag = (*flag & ~ m->turnoff); 373 else 374 *flag = (*flag & ~ m->turnoff) | m->turnon; 375 } else { 376 if ((m = findmode(ccchars, p)) != NULL) { 377 char *p2; 378 p2 = strtok(str, " \t"); 379 if (!p2) { 380 if (verbose) 381 fprintf(stderr, "No value after %s\n", p); 382 return; 383 } 384 if (*p2 == '\\') 385 switch(*(p2+1)) { 386 case 'n': *p2 = '\n'; break; 387 case 'r': *p2 = '\r'; break; 388 case 'b': *p2 = '\010'; break; 389 case 'v': *p2 = '\013'; break; 390 case 'g': *p2 = '\007'; break; 391 case 'f': *p2 = '\f'; break; 392 case '0': case '1': case '2': case '3': 393 case '4': case '5': case '6': case '7': { 394 char tbuf[4]; 395 strncpy(tbuf, p2+1, 3); 396 tbuf[3] = '\0'; 397 *p2 = strtol(tbuf, (char **) NULL, 8); 398 break; 399 } 400 default: 401 *p2 = *(p2+1); 402 } 403 else if (*p2 == '^') /* ^x means C-x, ^? is DEL */ 404 *p2 = (*(p2+1) == '?')? 0x7f : *(p2+1) - '@'; 405 406 ti->c_cc[m->turnon] = *p2; 407 } else 408 if (verbose) 409 fprintf(stderr, "Can't parse %s\n", p); 410 } 411 } 412 413 } 414 415 static char * 416 stripblanks _P1 ((s), register char *s) 417 { 418 register char *p; 419 while(*s && isspace(*s)) s++; 420 p = s; 421 while(*p && !isspace(*p)) p++; 422 *p = '\0'; 423 return(s); 424 } 425 426 #define GETTYBUFSIZE (10*BUFSIZ) 427 428 int 429 getentry _P3((entry, elen, f), char *entry, int elen, FILE *f) { 430 char buf[BUFSIZ*2]; 431 register char *p; 432 433 entry[0] = '\0'; 434 435 do { 436 if (!fgets(buf, sizeof(buf), f)) 437 return(0); 438 for (p = buf; isspace(*p); p++); 439 } while(*p == '#' || *p == '\n'); 440 441 p = strchr(buf, '\n'); 442 if (p) 443 *p = '\0'; 444 strcat(entry, buf); 445 446 while (1) { 447 if (!fgets(buf, sizeof(buf), f)) 448 break; 449 p = strchr(buf, '\n'); 450 if (p) 451 *p = '\0'; 452 for (p = buf; isspace(*p); p++); 453 if (!*p) 454 break; 455 strcat(entry, " "); 456 strcat(entry, p); 457 } 458 return(1); 459 } 460 461 /* 462 * loads all of the entries from the gettydefs file 463 * returns 0 if it fails. 464 */ 465 int 466 loadgettydefs _P1((file), char *file ) { 467 FILE *gd = fopen(file, "r"); 468 char buf[GETTYBUFSIZE]; 469 register char *p; 470 char *tag, *prompt, *nexttag, *before, *after; 471 472 if (!gd) { 473 lprintf(L_WARN, "Can't open %s\n", file); 474 return(0); 475 } 476 477 while(getentry(buf, sizeof(buf), gd)) { 478 479 p = buf; 480 481 tag = strtok(p, "#"); 482 if (!tag) 483 continue; 484 tag = stripblanks(tag); 485 tag = mydup(tag); 486 487 before = strtok(NULL, "#"); 488 if (!before) 489 continue; 490 491 after = strtok(NULL, "#"); 492 if (!after) 493 continue; 494 495 prompt = strtok(NULL, "#"); 496 if (!prompt) 497 continue; 498 499 /* do NOT escape prompt here - it may contain \D and \T, and 500 * for that, the real time at login should be used 501 */ 502 prompt = mydup(prompt); 503 504 nexttag = strtok(NULL, "#"); 505 if (!nexttag) 506 continue; 507 508 p = strchr(nexttag, '\n'); 509 if (p) 510 *p = '\0'; 511 512 nexttag = stripblanks(nexttag); 513 nexttag = mydup(nexttag); 514 515 #ifdef NEVER 516 printf("tag: %s\nbefore: %s\nafter: %s\nprompt: %s\nnexttag: %s\n\n", 517 tag, before, after, prompt, nexttag); 518 #endif 519 520 if (cur - gdep >= cntalloc-2) { 521 GDE *sav; 522 sav = gdep; 523 if (!gdep) { 524 gdep = (GDE *) malloc(sizeof(GDE) * GDCHUNK); 525 cur = gdep; 526 } else { 527 gdep = (GDE *) realloc(gdep, sizeof(GDE) * (GDCHUNK + cntalloc)); 528 cur = gdep + (cur - sav); 529 } 530 cntalloc += GDCHUNK; 531 } 532 533 memset(cur, sizeof(*cur), '\0'); 534 535 cur->tag = tag; 536 cur->prompt = prompt; 537 cur->nexttag = nexttag; 538 parsetermio(&cur->before, before); 539 parsetermio(&cur->after, after); 540 if (verbose) 541 printf("Processed `%s' gettydefs entry\n", tag); 542 cur++; 543 cur->tag = (char *) NULL; 544 } 545 fclose(gd); 546 return(1); 547 } 548 549 GDE * 550 getgettydef _P1 ((s), register char *s) 551 { 552 for (cur = gdep; cur && cur->tag; cur++) 553 if (strcmp(cur->tag, s) == 0) 554 return(cur); 555 if (gdep && gdep->tag) { 556 lprintf(L_WARN, "getgettydef(%s) entry not found using %s", 557 s, gdep->tag); 558 return(gdep); 559 } 560 lprintf(L_WARN, "getgettydef(%s) no entry found", s); 561 return((GDE *) NULL); 562 } 563 564 void 565 dumpflag _P3((type, modes, flag), 566 char *type, 567 struct modeword *modes, tioflag_t flag) 568 { 569 printf("%s: %08lo", type, (unsigned long) flag); 570 for(; modes->name; modes++) 571 if ((flag&modes->turnoff) == modes->turnon) 572 printf(" %s", modes->name); 573 putchar('\n'); 574 } 575 576 void 577 dump _P2((ti, s), TIO *ti, char *s) 578 { 579 register int i; 580 register struct modeword *modes; 581 582 printf("%s:", s); 583 dumpflag("\tiflags", iflags, ti->c_iflag); 584 dumpflag("\toflags", oflags, ti->c_oflag); 585 dumpflag("\tcflags", cflags, ti->c_cflag); 586 dumpflag("\tlflags", lflags, ti->c_lflag); 587 printf("\tc_cc:\t"); 588 for (i = 0; i < TIONCC; i++) { 589 if (i == 6) 590 printf("\n\t\t"); 591 for (modes = ccchars; modes->name; modes++) 592 if (modes->turnon == i) { 593 printf("%s(", modes->name); 594 break; 595 } 596 if (!modes->name) /* skip unallocated ones */ 597 continue; 598 /* Yeah, I know. But who's ever heard of getty on a EBCDIC system ;-) */ 599 if (ti->c_cc[i] < ' ') 600 printf("^%c", ti->c_cc[i] + '@'); 601 else if (ti->c_cc[i] == (0xff & _POSIX_VDISABLE)) 602 printf("disabled"); 603 else if (ti->c_cc[i] >= 0x7f) 604 printf("\\%03o", 0xff&ti->c_cc[i]); 605 else 606 putchar(ti->c_cc[i]); 607 printf(") "); 608 } 609 printf("\n\n"); 610 } 611 612 static void 613 spew _P1 ((gd), GDE *gd) 614 { 615 printf("tag: `%s'\nprompt: `%s'\nnexttag: `%s'\n", 616 gd->tag, gd->prompt, gd->nexttag); 617 dump(&gd->before, "before"); 618 dump(&gd->after, "after"); 619 printf("\n"); 620 } 621 622 void 623 dumpgettydefs _P1((file), char *file) { 624 if (! loadgettydefs(file)) { 625 fprintf(stderr, "Couldn't read %s\n", file); 626 exit(1); 627 } 628 printf("loaded entries:\n"); 629 for (cur = gdep; cur->tag; cur++) 630 spew(cur); 631 632 } 633 #endif 634