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