1 #ifndef lint 2 static char sccsid[] = "@(#)main.c 4.7 (Berkeley) 85/04/01"; 3 #endif 4 5 /* 6 * getty -- adapt to terminal speed on dialup, and call login 7 * 8 * Melbourne getty, June 83, kre. 9 */ 10 11 #include <sgtty.h> 12 #include <signal.h> 13 #include <ctype.h> 14 #include <setjmp.h> 15 #include <syslog.h> 16 #include <sys/file.h> 17 #include "gettytab.h" 18 19 extern char **environ; 20 21 struct sgttyb tmode = { 22 0, 0, CERASE, CKILL, 0 23 }; 24 struct tchars tc = { 25 CINTR, CQUIT, CSTART, 26 CSTOP, CEOF, CBRK, 27 }; 28 struct ltchars ltc = { 29 CSUSP, CDSUSP, CRPRNT, 30 CFLUSH, CWERASE, CLNEXT 31 }; 32 33 int crmod; 34 int upper; 35 int lower; 36 int digit; 37 38 char hostname[32]; 39 char name[16]; 40 char dev[] = "/dev/"; 41 char ctty[] = "/dev/console"; 42 char ttyn[32]; 43 char *portselector(); 44 char *ttyname(); 45 46 #define OBUFSIZ 128 47 #define TABBUFSIZ 512 48 49 char defent[TABBUFSIZ]; 50 char defstrs[TABBUFSIZ]; 51 char tabent[TABBUFSIZ]; 52 char tabstrs[TABBUFSIZ]; 53 54 char *env[128]; 55 56 char partab[] = { 57 0001,0201,0201,0001,0201,0001,0001,0201, 58 0202,0004,0003,0205,0005,0206,0201,0001, 59 0201,0001,0001,0201,0001,0201,0201,0001, 60 0001,0201,0201,0001,0201,0001,0001,0201, 61 0200,0000,0000,0200,0000,0200,0200,0000, 62 0000,0200,0200,0000,0200,0000,0000,0200, 63 0000,0200,0200,0000,0200,0000,0000,0200, 64 0200,0000,0000,0200,0000,0200,0200,0000, 65 0200,0000,0000,0200,0000,0200,0200,0000, 66 0000,0200,0200,0000,0200,0000,0000,0200, 67 0000,0200,0200,0000,0200,0000,0000,0200, 68 0200,0000,0000,0200,0000,0200,0200,0000, 69 0000,0200,0200,0000,0200,0000,0000,0200, 70 0200,0000,0000,0200,0000,0200,0200,0000, 71 0200,0000,0000,0200,0000,0200,0200,0000, 72 0000,0200,0200,0000,0200,0000,0000,0201 73 }; 74 75 #define ERASE tmode.sg_erase 76 #define KILL tmode.sg_kill 77 #define EOT tc.t_eofc 78 79 jmp_buf timeout; 80 81 dingdong() 82 { 83 84 alarm(0); 85 signal(SIGALRM, SIG_DFL); 86 longjmp(timeout, 1); 87 } 88 89 jmp_buf intrupt; 90 91 interrupt() 92 { 93 94 signal(SIGINT, interrupt); 95 longjmp(intrupt, 1); 96 } 97 98 main(argc, argv) 99 char *argv[]; 100 { 101 char *tname; 102 long allflags; 103 int repcnt = 0; 104 105 signal(SIGINT, SIG_IGN); 106 /* 107 signal(SIGQUIT, SIG_DFL); 108 */ 109 openlog("getty", LOG_ODELAY|LOG_CONS, 0); 110 gethostname(hostname, sizeof(hostname)); 111 if (hostname[0] == '\0') 112 strcpy(hostname, "Amnesiac"); 113 /* 114 * The following is a work around for vhangup interactions 115 * which cause great problems getting window systems started. 116 * If the tty line is "-", we do the old style getty presuming 117 * that the file descriptors are already set up for us. 118 * J. Gettys - MIT Project Athena. 119 */ 120 if (argc <= 2 || strcmp(argv[2], "-") == 0) 121 strcpy(ttyn, ttyname(0)); 122 else { 123 strcpy(ttyn, dev); 124 strncat(ttyn, argv[2], sizeof(ttyn)-sizeof(dev)); 125 chown(ttyn, 0, 0); 126 chmod(ttyn, 0622); 127 while (open(ttyn, O_RDWR) != 0) { 128 if (repcnt % 10 == 0) { 129 syslog(LOG_FAIL, "%s: %m", ttyn); 130 closelog(); 131 } 132 repcnt++; 133 sleep(60); 134 } 135 signal(SIGHUP, SIG_IGN); 136 vhangup(); 137 (void) open(ttyn, O_RDWR); 138 close(0); 139 dup(1); 140 dup(0); 141 signal(SIGHUP, SIG_DFL); 142 } 143 144 gettable("default", defent, defstrs); 145 gendefaults(); 146 tname = "default"; 147 if (argc > 1) 148 tname = argv[1]; 149 for (;;) { 150 int ldisp = OTTYDISC; 151 152 gettable(tname, tabent, tabstrs); 153 if (OPset || EPset || APset) 154 APset++, OPset++, EPset++; 155 setdefaults(); 156 ioctl(0, TIOCFLUSH, 0); /* clear out the crap */ 157 if (IS) 158 tmode.sg_ispeed = speed(IS); 159 else if (SP) 160 tmode.sg_ispeed = speed(SP); 161 if (OS) 162 tmode.sg_ospeed = speed(OS); 163 else if (SP) 164 tmode.sg_ospeed = speed(SP); 165 tmode.sg_flags = setflags(0); 166 ioctl(0, TIOCSETP, &tmode); 167 setchars(); 168 ioctl(0, TIOCSETC, &tc); 169 ioctl(0, TIOCSETD, &ldisp); 170 if (HC) 171 ioctl(0, TIOCHPCL, 0); 172 if (AB) { 173 extern char *autobaud(); 174 175 tname = autobaud(); 176 continue; 177 } 178 if (PS) { 179 tname = portselector(); 180 continue; 181 } 182 if (CL && *CL) 183 putpad(CL); 184 edithost(HE); 185 if (IM && *IM) 186 putf(IM); 187 if (setjmp(timeout)) { 188 tmode.sg_ispeed = tmode.sg_ospeed = 0; 189 ioctl(0, TIOCSETP, &tmode); 190 exit(1); 191 } 192 if (TO) { 193 signal(SIGALRM, dingdong); 194 alarm(TO); 195 } 196 if (getname()) { 197 register int i; 198 199 oflush(); 200 alarm(0); 201 signal(SIGALRM, SIG_DFL); 202 if (!(upper || lower || digit)) 203 continue; 204 allflags = setflags(2); 205 tmode.sg_flags = allflags & 0xffff; 206 allflags >>= 16; 207 if (crmod || NL) 208 tmode.sg_flags |= CRMOD; 209 if (upper || UC) 210 tmode.sg_flags |= LCASE; 211 if (lower || LC) 212 tmode.sg_flags &= ~LCASE; 213 ioctl(0, TIOCSETP, &tmode); 214 ioctl(0, TIOCSLTC, <c); 215 ioctl(0, TIOCLSET, &allflags); 216 signal(SIGINT, SIG_DFL); 217 for (i = 0; environ[i] != (char *)0; i++) 218 env[i] = environ[i]; 219 makeenv(&env[i]); 220 execle(LO, "login", "-p", name, (char *) 0, env); 221 exit(1); 222 } 223 alarm(0); 224 signal(SIGALRM, SIG_DFL); 225 signal(SIGINT, SIG_IGN); 226 if (NX && *NX) 227 tname = NX; 228 } 229 } 230 231 getname() 232 { 233 register char *np; 234 register c; 235 char cs; 236 237 /* 238 * Interrupt may happen if we use CBREAK mode 239 */ 240 if (setjmp(intrupt)) { 241 signal(SIGINT, SIG_IGN); 242 return (0); 243 } 244 signal(SIGINT, interrupt); 245 tmode.sg_flags = setflags(0); 246 ioctl(0, TIOCSETP, &tmode); 247 tmode.sg_flags = setflags(1); 248 prompt(); 249 if (PF > 0) { 250 oflush(); 251 sleep(PF); 252 PF = 0; 253 } 254 ioctl(0, TIOCSETP, &tmode); 255 crmod = 0; 256 upper = 0; 257 lower = 0; 258 digit = 0; 259 np = name; 260 for (;;) { 261 oflush(); 262 if (read(0, &cs, 1) <= 0) 263 exit(0); 264 if ((c = cs&0177) == 0) 265 return (0); 266 if (c == EOT) 267 exit(1); 268 if (c == '\r' || c == '\n' || np >= &name[sizeof name]) { 269 putf("\r\n"); 270 break; 271 } 272 if (c >= 'a' && c <= 'z') 273 lower++; 274 else if (c >= 'A' && c <= 'Z') 275 upper++; 276 else if (c == ERASE || c == '#' || c == '\b') { 277 if (np > name) { 278 np--; 279 if (tmode.sg_ospeed >= B1200) 280 puts("\b \b"); 281 else 282 putchr(cs); 283 } 284 continue; 285 } else if (c == KILL || c == '@') { 286 putchr(cs); 287 putchr('\r'); 288 if (tmode.sg_ospeed < B1200) 289 putchr('\n'); 290 /* this is the way they do it down under ... */ 291 else if (np > name) 292 puts(" \r"); 293 prompt(); 294 np = name; 295 continue; 296 } else if (c >= '0' && c <= '9') 297 digit++; 298 if (IG && (c <= ' ' || c > 0176)) 299 continue; 300 *np++ = c; 301 putchr(cs); 302 } 303 signal(SIGINT, SIG_IGN); 304 *np = 0; 305 if (c == '\r') 306 crmod++; 307 if (upper && !lower && !LC || UC) 308 for (np = name; *np; np++) 309 if (isupper(*np)) 310 *np = tolower(*np); 311 return (1); 312 } 313 314 static 315 short tmspc10[] = { 316 0, 2000, 1333, 909, 743, 666, 500, 333, 166, 83, 55, 41, 20, 10, 5, 15 317 }; 318 319 putpad(s) 320 register char *s; 321 { 322 register pad = 0; 323 register mspc10; 324 325 if (isdigit(*s)) { 326 while (isdigit(*s)) { 327 pad *= 10; 328 pad += *s++ - '0'; 329 } 330 pad *= 10; 331 if (*s == '.' && isdigit(s[1])) { 332 pad += s[1] - '0'; 333 s += 2; 334 } 335 } 336 337 puts(s); 338 /* 339 * If no delay needed, or output speed is 340 * not comprehensible, then don't try to delay. 341 */ 342 if (pad == 0) 343 return; 344 if (tmode.sg_ospeed <= 0 || 345 tmode.sg_ospeed >= (sizeof tmspc10 / sizeof tmspc10[0])) 346 return; 347 348 /* 349 * Round up by a half a character frame, 350 * and then do the delay. 351 * Too bad there are no user program accessible programmed delays. 352 * Transmitting pad characters slows many 353 * terminals down and also loads the system. 354 */ 355 mspc10 = tmspc10[tmode.sg_ospeed]; 356 pad += mspc10 / 2; 357 for (pad /= mspc10; pad > 0; pad--) 358 putchr(*PC); 359 } 360 361 puts(s) 362 register char *s; 363 { 364 365 while (*s) 366 putchr(*s++); 367 } 368 369 char outbuf[OBUFSIZ]; 370 int obufcnt = 0; 371 372 putchr(cc) 373 { 374 char c; 375 376 c = cc; 377 c |= partab[c&0177] & 0200; 378 if (OP) 379 c ^= 0200; 380 if (!UB) { 381 outbuf[obufcnt++] = c; 382 if (obufcnt >= OBUFSIZ) 383 oflush(); 384 } else 385 write(1, &c, 1); 386 } 387 388 oflush() 389 { 390 if (obufcnt) 391 write(1, outbuf, obufcnt); 392 obufcnt = 0; 393 } 394 395 prompt() 396 { 397 398 putf(LM); 399 if (CO) 400 putchr('\n'); 401 } 402 403 putf(cp) 404 register char *cp; 405 { 406 char *ttyn, *slash; 407 char datebuffer[60]; 408 extern char editedhost[]; 409 extern char *ttyname(), *rindex(); 410 411 while (*cp) { 412 if (*cp != '%') { 413 putchr(*cp++); 414 continue; 415 } 416 switch (*++cp) { 417 418 case 't': 419 ttyn = ttyname(0); 420 slash = rindex(ttyn, '/'); 421 if (slash == (char *) 0) 422 puts(ttyn); 423 else 424 puts(&slash[1]); 425 break; 426 427 case 'h': 428 puts(editedhost); 429 break; 430 431 case 'd': 432 get_date(datebuffer); 433 puts(datebuffer); 434 break; 435 436 case '%': 437 putchr('%'); 438 break; 439 } 440 cp++; 441 } 442 } 443