1: #
   2: /*
   3:  * @(#)getty.c	1.5 -- adapt to terminal speed on dialup, and call login
   4:  */
   5: #include <whoami.h>
   6: #include <sgtty.h>
   7: #include <signal.h>
   8: #include <sys/types.h>
   9: #include <sys/file.h>
  10: 
  11: #define IDENT   "/etc/ident"    /* contains login banner for sys */
  12: 
  13: #define SP_SESS         /* "special session"-- root logins only */
  14: #define DO_CRTBS    /* allow backspace as erase; stty erase if >2400 baud */
  15: 
  16: #define ERASE   '#'
  17: #define KILL    '@'
  18: #define CNTL(x) ('x'&037)
  19: #define DEL '\177'
  20: #define UNDEF   '\377'
  21: 
  22: struct sgttyb tmode;
  23: struct tchars tchars =
  24:     { DEL, CNTL(\\), CNTL(Q), CNTL(S), CNTL(D), UNDEF
  25: };
  26: #ifdef UCB_NTTY
  27: struct  ltchars ltc =
  28:     { CNTL(z), CNTL(y), CNTL(r), CNTL(o), CNTL(w), CNTL(v)
  29: };
  30: #endif
  31: 
  32: struct  tab {
  33:     char    tname;      /* this table name */
  34:     char    nname;      /* successor table name */
  35:     int iflags;     /* initial flags */
  36:     int fflags;     /* final flags */
  37:     int ispeed;     /* input speed */
  38:     int ospeed;     /* output speed */
  39:     char    *message;   /* login message */
  40: } itab[] = {
  41: 
  42: /* table '0'-1-2-3 300,1200,150,110 */
  43: 
  44:     '0', 1,
  45:     ANYP+RAW+NL1+CR1, ANYP+ECHO+CR1,
  46:     B300, B300,
  47:     "\n\r\033;\007login: ",
  48: 
  49:     1, 2,
  50:     ANYP+RAW+NL1+CR1, ANYP+XTABS+ECHO+CRMOD+FF1,
  51:     B1200, B1200,
  52:     "\n\r\033;login: ",
  53: 
  54:     2, 3,
  55:     ANYP+RAW+NL1+CR1, EVENP+ECHO+FF1+CR2+TAB1+NL1,
  56:     B150, B150,
  57:     "\n\r\033:\006\006\017login: ",
  58: 
  59:     3, '0',
  60:     ANYP+RAW+NL1+CR1, ANYP+ECHO+CRMOD+XTABS+LCASE+CR1,
  61:     B110, B110,
  62:     "\n\r:login: ",
  63: 
  64: /* table '-' -- Console TTY 110 */
  65:     '-', '-',
  66:     ANYP+RAW+NL1+CR1, ANYP+ECHO+CRMOD+XTABS+LCASE+CR1,
  67:     B110, B110,
  68:     "\n\r:login: ",
  69: 
  70: /* table '1' -- 150 */
  71:     '1', '1',
  72:     ANYP+RAW+NL1+CR1, EVENP+ECHO+FF1+CR2+TAB1+NL1,
  73:     B150, B150,
  74:     "\n\r\033:\006\006\017login: ",
  75: 
  76: /* table '2' -- 9600 */
  77:     '2', '2',
  78:     ANYP+RAW+NL1+CR1, ANYP+XTABS+ECHO+CRMOD,
  79:     B9600, B9600,
  80:     "\n\r;login: ",
  81: 
  82: /* table '3'-'5' -- 1200,300 */
  83:     '3', '5',
  84:     ANYP+RAW+NL1+CR1, ANYP+XTABS+ECHO+CRMOD+FF1,
  85:     B1200, B1200,
  86:     "\n\r:login: ",
  87: 
  88: /* table '5'-'3' -- 300,1200 */
  89:     '5', '3',
  90:     ANYP+RAW+NL1+CR1, ANYP+ECHO+CR1+XTABS,
  91:     B300, B300,
  92:     "\n\r:login: ",
  93: 
  94: /* table '4' -- Console Decwriter */
  95:     '4', '4',
  96:     ANYP+RAW+NL1+CR2, ANYP+ECHO+CRMOD+XTABS+CR2,
  97:     B300, B300,
  98:     "\n\r:login: ",
  99: 
 100: /* table '6' -- 1200 */
 101:     '6', '6',
 102:     ANYP+RAW+NL1+CR1, ANYP+XTABS+ECHO+CRMOD,
 103:     B1200, B1200,
 104:     "\n\r;login: ",
 105: 
 106: /* table '7' -- 2400 */
 107:     '7', '7',
 108:     ANYP+RAW+NL1+CR1, ANYP+XTABS+ECHO+CRMOD,
 109:     B2400, B2400,
 110:     "\n\r;login: ",
 111: 
 112: /* table '8' -- 4800 */
 113:     '8', '8',
 114:     ANYP+RAW+NL1+CR1, ANYP+XTABS+ECHO+CRMOD,
 115:     B4800, B4800,
 116:     "\n\r;login: ",
 117: 
 118: /* table '9' -- 9600 */
 119:     '9', '9',
 120:     ANYP+RAW+NL1+CR1, ANYP+XTABS+ECHO+CRMOD,
 121:     B9600, B9600,
 122:     "\n\r;login: ",
 123: 
 124: /* table 'i' -- Interdata Console */
 125:     'i', 'i',
 126:     RAW+CRMOD, CRMOD+ECHO+LCASE,
 127:     0, 0,
 128:     "\n\r:login: ",
 129: 
 130: #ifdef  TEXAS_AUTOBAUD
 131: /* table 'B' -- Do autobauding */
 132: 
 133: #define NTRIES  5
 134: #define WAITSEC 60
 135: #define TB_AUTOBAUD 'B'
 136:     TB_AUTOBAUD, TB_AUTOBAUD,
 137:     ANYP+RAW,   ANYP+XTABS+ECHO+CRMOD,
 138:     B9600, B9600,
 139:     "\n\r;login: ",
 140: #endif
 141: 
 142: /* table 'T' -- 9600 tektronix 4014 */
 143:     'T', 'T',
 144:     ANYP+RAW+NL1+CR1, ANYP+XTABS+ECHO+CRMOD+FF1,
 145:     B9600, B9600,
 146:     "\n\r\033;login: ",
 147: };
 148: 
 149: #define NITAB   sizeof itab/sizeof itab[0]
 150: #define EOT 04      /* EOT char */
 151: 
 152: char    name[16];
 153: int crmod;
 154: int upper;
 155: int lower;
 156: #ifdef  DO_CRTBS
 157: int can_erase;
 158: #endif
 159: #ifdef  SP_SESS
 160: int sp_sess = { 0 };    /* flag special session */
 161: #endif
 162: 
 163: char partab[] = {
 164:     0001,0201,0201,0001,0201,0001,0001,0201,
 165:     0202,0004,0003,0205,0005,0206,0201,0001,
 166:     0201,0001,0001,0201,0001,0201,0201,0001,
 167:     0001,0201,0201,0001,0201,0001,0001,0201,
 168:     0200,0000,0000,0200,0000,0200,0200,0000,
 169:     0000,0200,0200,0000,0200,0000,0000,0200,
 170:     0000,0200,0200,0000,0200,0000,0000,0200,
 171:     0200,0000,0000,0200,0000,0200,0200,0000,
 172:     0200,0000,0000,0200,0000,0200,0200,0000,
 173:     0000,0200,0200,0000,0200,0000,0000,0200,
 174:     0000,0200,0200,0000,0200,0000,0000,0200,
 175:     0200,0000,0000,0200,0000,0200,0200,0000,
 176:     0000,0200,0200,0000,0200,0000,0000,0200,
 177:     0200,0000,0000,0200,0000,0200,0200,0000,
 178:     0200,0000,0000,0200,0000,0200,0200,0000,
 179:     0000,0200,0200,0000,0200,0000,0000,0201
 180: };
 181: 
 182: main(argc, argv)
 183: char **argv;
 184: {
 185:     register struct tab *tabp;
 186:     int tname;
 187:     int ldisc;
 188:     int bf;
 189: #ifdef  UCB_NTTY
 190:     int lmode = 0;
 191: #endif
 192: 
 193:     ldisc = DFLT_LDISC;
 194:     ioctl(0, TIOCSETD, &ldisc);
 195: #ifdef UCB_NTTY
 196:     ioctl(0, TIOCLSET, &lmode);
 197:     ioctl(0, TIOCSLTC, &ltc);
 198: #endif
 199:     ioctl(0, TIOCSETC, &tchars);
 200: 
 201:     tname = '0';
 202: #ifdef  SP_SESS
 203:     /*
 204: 	 * If we are called with a "+" name, flag special session.
 205: 	 */
 206:     if(argv[0][0] == '+')
 207:         sp_sess++;
 208: #endif
 209: 
 210:     if (argc > 1)
 211:         tname = argv[1][0];
 212: 
 213: 
 214:     switch (tname) {
 215: 
 216:     /*
 217: 	 *	If hardware has decoded high speed (or line is open),
 218: 	 *	get the line speed.
 219: 	 */
 220:     case '5':
 221:         ioctl(0,TIOCGETP, &tmode);
 222:         if (tmode.sg_ispeed == B1200)
 223:             tname = '3';
 224:         break;
 225: 
 226: #ifdef  DO_CRTBS
 227:     /*
 228: 	 *	Hard-wired crt ports (2400-9600 baud)
 229: 	 *	allow use of backspace-erase.
 230: 	 */
 231:     case '7':
 232:     case '8':
 233:     case '9':
 234:         can_erase++;
 235:         lmode = LCRTERA | LCRTBS;
 236:         ioctl(0, TIOCLSET, &lmode);
 237:         break;
 238: #endif
 239:     }
 240:     for (;;) {
 241:         for(tabp = itab; tabp < &itab[NITAB]; tabp++)
 242:             if(tabp->tname == tname)
 243:                 break;
 244:         if(tabp >= &itab[NITAB])
 245:             tabp = itab;
 246:         tmode.sg_flags = tabp->iflags;
 247:         tmode.sg_ispeed = tabp->ispeed;
 248:         tmode.sg_ospeed = tabp->ospeed;
 249:         ioctl(0, TIOCSETP, &tmode);
 250:         ioctl(0, TIOCSETC, &tchars);
 251: #ifdef  TEXAS_AUTOBAUD
 252:         if ((tabp->tname == TB_AUTOBAUD) && set_baud_rate())
 253:         {   /* autobaud line */
 254:             ioctl(0, TIOCGETP, &tmode); /* pick up baud rate */
 255:             ioctl(0, TIOCSETP, &tmode); /* flush input */
 256:         }
 257: #endif
 258: 
 259:         if(tmode.sg_ospeed > B1200)
 260:             puts("\n\r");
 261:         else
 262:             puts("\n\r\r\r\r\r\n\r\r\r\r\r");
 263:         if ((bf = open(IDENT, FATT_RDONLY)) > 0) {
 264:             char buf[81];
 265:             int i;
 266:             register char *s;
 267:             while ((i = read(bf, buf, sizeof (buf) - 1)) > 0) {
 268:                 buf[i] = 0;
 269:                 for (s = buf; *s; s++) {
 270:                     if (*s == '\n')
 271:                         putchr('\r');
 272:                     putchr(*s);
 273:                 }
 274:             }
 275:             close(bf);
 276:         }
 277: #ifdef  SP_SESS
 278:         if(sp_sess)
 279:             puts("\n\r\r\r>>> Unix Maintenance Mode <<<");
 280: #endif
 281:         puts(tabp->message);
 282:         /*
 283: 		 * wait, then flush input to get rid
 284: 		 * of line noise
 285: 		 */
 286:         sleep(1);
 287:         ioctl(0, TIOCSETP, &tmode);
 288:         if(getname()) {
 289:             if(upper==0 && lower==0)
 290:                 continue;
 291: #ifdef  DO_CRTBS
 292:             tmode.sg_erase = can_erase? '\b': ERASE;
 293: #else
 294:             tmode.sg_erase = ERASE;
 295: #endif
 296:             tmode.sg_kill = KILL;
 297:             tmode.sg_flags = tabp->fflags;
 298:             if(crmod)
 299:                 tmode.sg_flags |= CRMOD;
 300:             if(upper)
 301:                 tmode.sg_flags |= LCASE;
 302:             if(lower)
 303:                 tmode.sg_flags &= ~LCASE;
 304:             ioctl(0, TIOCSETP, &tmode);
 305:             putchr('\n');
 306: #ifdef  SP_SESS
 307:             if(sp_sess)
 308:                 execl("/bin/login", "slogin", name, 0);
 309: #endif
 310:             execl("/bin/login", "login", name, 0);
 311:             exit(1);
 312:         }
 313:         tname = tabp->nname;
 314:     }
 315: }
 316: 
 317: getname()
 318: {
 319:     register char *np;
 320:     register c;
 321:     char cs;
 322: 
 323:     crmod = 0;
 324:     upper = 0;
 325:     lower = 0;
 326:     np = name;
 327:     for (;;) {
 328:         if (read(0, &cs, 1) <= 0)
 329:             exit(0);
 330:         if ((c = cs&0177) == 0)
 331:             return(0);
 332:         if (c==EOT)
 333:             exit(1);
 334:         if (c=='\r' || c=='\n' || np >= &name[16])
 335:             break;
 336: #ifdef  DO_CRTBS
 337:         if (c != '\b')
 338: #endif
 339:             putchr(cs);
 340:         if (c>='a' && c <='z')
 341:             lower++;
 342:         else if (c>='A' && c<='Z') {
 343:             upper++;
 344:             c += 'a'-'A';
 345: #ifdef  DO_CRTBS
 346:         } else if (c=='\b') {
 347:             if (np > name) {
 348:                 np--;
 349:                 puts("\b \b");
 350:             }
 351:             continue;
 352: #endif
 353:         } else if (c==ERASE) {
 354:             if (np > name)
 355:                 np--;
 356:             continue;
 357:         } else if (c==KILL) {
 358:             putchr('\r');
 359:             putchr('\n');
 360:             np = name;
 361:             continue;
 362:         } else if(c == ' ')
 363:             c = '_';
 364:         *np++ = c;
 365:     }
 366:     *np = 0;
 367:     if (c == '\r')
 368:         crmod++;
 369:     return(1);
 370: }
 371: 
 372: puts(as)
 373: char *as;
 374: {
 375:     register char *s;
 376: 
 377:     s = as;
 378:     while (*s)
 379:         putchr(*s++);
 380: }
 381: 
 382: putchr(cc)
 383: {
 384:     char c;
 385:     c = cc;
 386:     c |= partab[c&0177] & 0200;
 387:     write(1, &c, 1);
 388: }
 389: 
 390: #ifdef  TEXAS_AUTOBAUD
 391: 
 392: /* Autobauding tables */
 393: struct match
 394: {
 395:     char  m_char;   /* bit pattern to look for */
 396:     char  m_mask;   /* bits to ignore in input character */
 397:     short m_speed;  /* what speed to set if matched */
 398: };
 399: 
 400: struct match match[] = {    /* cr,int            */
 401:     { 0xfc, 0x03, B9600 },  /* 111111xx (cr,int) */
 402:     { 0x0d, 0x80, B4800 },  /* x0001101 (cr)     */
 403:     { 0x03, 0x80, B4800 },  /* x0000011 (int)    */
 404:     { 0xe6, 0x00, B2400 },  /* 11100110 (cr)     */
 405:     { 0x1e, 0x00, B2400 },  /* 00011110 (int)    */
 406:     { 0x8c, 0x12, B1800 },  /* 100x11x0 (cr)     */
 407:     { 0x7c, 0x02, B1800 },  /* 011111x0 (int)    */
 408:     { 0x78, 0x80, B1200 },  /* x1111000 (cr,int) */
 409:     { 0x80, 0x00, B600  },  /* 10000000 (cr,int) */
 410:     { 0x00, 0x00, B300  },  /* 00000000 (cr,int) */
 411:     { 0,    0,    0     }
 412: };
 413: 
 414: /* Determine baud rate of terminal line
 415:  *     Rich Wales (UCLA), June 1982
 416:  *
 417:  * Determine the baud rate of a terminal from a single
 418:  * carriage-return or ^C.  It can identify 300, 600, 1200, 1800, 2400,
 419:  * 4800, and 9600 baud.
 420:  *
 421:  * If the new speed is below 2400 baud, it is advisable to do a "sleep"
 422:  * before the "ioctl".  This allows any extra garbage from the input to
 423:  * make it from the multiplexer (DH or DZ) to the kernel input queue,
 424:  * where the speed change will cause it to be flushed.
 425:  */
 426: timeout()
 427: {
 428:     puts("\7Connection timed out.\n\r");
 429:     exit(1);
 430: };
 431: 
 432: set_baud_rate()
 433: {
 434:     register struct match *m;
 435:     register int i;
 436:     int lmode;
 437:     struct sgttyb sv, st;
 438:     char c;
 439: 
 440:     /* save current TTY mode, set new mode */
 441:     ioctl(0, TIOCGETP, &sv);
 442:     st = sv;
 443:     st.sg_flags  = RAW | ANYP;
 444:     ioctl(0, TIOCLGET, &lmode);
 445:     st.sg_ispeed = st.sg_ospeed = B4800;
 446:     ioctl(0, TIOCSETP, &st);
 447:     ioctl(0, TIOCLSET, &lmode);
 448:     if (ioctl(0, TIOCSIMG, 0) < 0)
 449:         return(0);
 450:     alarm(0);
 451:     for (i=0; i < NTRIES; i++) {
 452:         /* read a character and try to match it */
 453:         signal(14,timeout);
 454:         alarm(WAITSEC);
 455:         read(0,&c,1);
 456:         alarm(0);
 457:         c &= 0377;
 458:         for (m = match; m->m_speed != 0; m++) {
 459:             if ((c &~ m->m_mask) == m->m_char) {
 460:             /* success -- restore old modes, but with new speed */
 461:                 sv.sg_ispeed = sv.sg_ospeed = m->m_speed;
 462:                 if (sv.sg_ispeed < B2400)
 463:                     sleep(1);
 464:                 ioctl(0, TIOCCIMG, 0);
 465:                 ioctl(0, TIOCSETP, &sv);
 466:                 ioctl(0, TIOCLSET, &lmode);
 467:                 return(1);
 468:             }
 469:         }
 470:     }
 471:     /* no match -- restore old modes */
 472:     sleep(1);
 473:     ioctl(0, TIOCCIMG, 0);
 474:     ioctl(0, TIOCSETP, &sv);
 475:     ioctl(0, TIOCLSET, &lmode);
 476:     return(0);
 477: }
 478: #endif

Defined functions

getname defined in line 317; used 1 times
main defined in line 182; never used
putchr defined in line 382; used 7 times
puts defined in line 372; used 6 times
set_baud_rate defined in line 432; used 1 times
timeout defined in line 426; used 1 times

Defined variables

can_erase defined in line 157; used 2 times
crmod defined in line 153; used 3 times
itab defined in line 40; used 6 times
lower defined in line 155; used 4 times
ltc defined in line 27; used 1 times
match defined in line 400; used 1 times
name defined in line 152; used 7 times
partab defined in line 163; used 1 times
sp_sess defined in line 160; used 3 times
tchars defined in line 23; used 2 times
tmode defined in line 22; used 18 times
upper defined in line 154; used 4 times

Defined struct's

match defined in line 393; used 4 times
tab defined in line 32; used 2 times
  • in line 185(2)

Defined macros

CNTL defined in line 18; used 7 times
DEL defined in line 19; used 1 times
  • in line 24
DO_CRTBS defined in line 14; used 5 times
EOT defined in line 150; used 1 times
ERASE defined in line 16; used 3 times
IDENT defined in line 11; used 1 times
KILL defined in line 17; used 2 times
NITAB defined in line 149; used 2 times
NTRIES defined in line 133; used 1 times
SP_SESS defined in line 13; used 4 times
TB_AUTOBAUD defined in line 135; used 3 times
UNDEF defined in line 20; never used
WAITSEC defined in line 134; used 1 times
Last modified: 1983-06-01
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1350
Valid CSS Valid XHTML 1.0 Strict