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.6 (Berkeley) 09/16/87"; 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 if (strcmp(argv[0], "+") != 0) { 138 chown(ttyn, 0, 0); 139 chmod(ttyn, 0622); 140 /* 141 * Delay the open so DTR stays down long enough to be detected. 142 */ 143 sleep(2); 144 while (open(ttyn, O_RDWR) != 0) { 145 if (repcnt % 10 == 0) { 146 syslog(LOG_ERR, "%s: %m", ttyn); 147 closelog(); 148 } 149 repcnt++; 150 sleep(60); 151 } 152 signal(SIGHUP, SIG_IGN); 153 vhangup(); 154 (void) open(ttyn, O_RDWR); 155 close(0); 156 dup(1); 157 dup(0); 158 signal(SIGHUP, SIG_DFL); 159 } 160 } 161 162 gettable("default", defent, defstrs); 163 gendefaults(); 164 tname = "default"; 165 if (argc > 1) 166 tname = argv[1]; 167 for (;;) { 168 int ldisp = OTTYDISC; 169 int off = 0; 170 171 gettable(tname, tabent, tabstrs); 172 if (OPset || EPset || APset) 173 APset++, OPset++, EPset++; 174 setdefaults(); 175 ioctl(0, TIOCFLUSH, 0); /* clear out the crap */ 176 ioctl(0, FIONBIO, &off); /* turn off non-blocking mode */ 177 ioctl(0, FIOASYNC, &off); /* ditto for asynchronous mode */ 178 if (IS) 179 tmode.sg_ispeed = speed(IS); 180 else if (SP) 181 tmode.sg_ispeed = speed(SP); 182 if (OS) 183 tmode.sg_ospeed = speed(OS); 184 else if (SP) 185 tmode.sg_ospeed = speed(SP); 186 tmode.sg_flags = setflags(0); 187 ioctl(0, TIOCSETP, &tmode); 188 setchars(); 189 ioctl(0, TIOCSETC, &tc); 190 ioctl(0, TIOCSETD, &ldisp); 191 if (HC) 192 ioctl(0, TIOCHPCL, 0); 193 if (AB) { 194 extern char *autobaud(); 195 196 tname = autobaud(); 197 continue; 198 } 199 if (PS) { 200 tname = portselector(); 201 continue; 202 } 203 if (CL && *CL) 204 putpad(CL); 205 edithost(HE); 206 if (IM && *IM) 207 putf(IM); 208 if (setjmp(timeout)) { 209 tmode.sg_ispeed = tmode.sg_ospeed = 0; 210 ioctl(0, TIOCSETP, &tmode); 211 exit(1); 212 } 213 if (TO) { 214 signal(SIGALRM, dingdong); 215 alarm(TO); 216 } 217 if (getname()) { 218 register int i; 219 220 oflush(); 221 alarm(0); 222 signal(SIGALRM, SIG_DFL); 223 if (!(upper || lower || digit)) 224 continue; 225 allflags = setflags(2); 226 tmode.sg_flags = allflags & 0xffff; 227 allflags >>= 16; 228 if (crmod || NL) 229 tmode.sg_flags |= CRMOD; 230 if (upper || UC) 231 tmode.sg_flags |= LCASE; 232 if (lower || LC) 233 tmode.sg_flags &= ~LCASE; 234 ioctl(0, TIOCSETP, &tmode); 235 ioctl(0, TIOCSLTC, <c); 236 ioctl(0, TIOCLSET, &allflags); 237 signal(SIGINT, SIG_DFL); 238 for (i = 0; environ[i] != (char *)0; i++) 239 env[i] = environ[i]; 240 makeenv(&env[i]); 241 execle(LO, "login", "-p", name, (char *) 0, env); 242 syslog(LOG_ERR, "%s: %m", LO); 243 exit(1); 244 } 245 alarm(0); 246 signal(SIGALRM, SIG_DFL); 247 signal(SIGINT, SIG_IGN); 248 if (NX && *NX) 249 tname = NX; 250 } 251 } 252 253 getname() 254 { 255 register char *np; 256 register c; 257 char cs; 258 259 /* 260 * Interrupt may happen if we use CBREAK mode 261 */ 262 if (setjmp(intrupt)) { 263 signal(SIGINT, SIG_IGN); 264 return (0); 265 } 266 signal(SIGINT, interrupt); 267 tmode.sg_flags = setflags(0); 268 ioctl(0, TIOCSETP, &tmode); 269 tmode.sg_flags = setflags(1); 270 prompt(); 271 if (PF > 0) { 272 oflush(); 273 sleep(PF); 274 PF = 0; 275 } 276 ioctl(0, TIOCSETP, &tmode); 277 crmod = 0; 278 upper = 0; 279 lower = 0; 280 digit = 0; 281 np = name; 282 for (;;) { 283 oflush(); 284 if (read(0, &cs, 1) <= 0) 285 exit(0); 286 if ((c = cs&0177) == 0) 287 return (0); 288 if (c == EOT) 289 exit(1); 290 if (c == '\r' || c == '\n' || np >= &name[sizeof name]) { 291 putf("\r\n"); 292 break; 293 } 294 if (c >= 'a' && c <= 'z') 295 lower++; 296 else if (c >= 'A' && c <= 'Z') 297 upper++; 298 else if (c == ERASE || c == '#' || c == '\b') { 299 if (np > name) { 300 np--; 301 if (tmode.sg_ospeed >= B1200) 302 puts("\b \b"); 303 else 304 putchr(cs); 305 } 306 continue; 307 } else if (c == KILL || c == '@') { 308 putchr(cs); 309 putchr('\r'); 310 if (tmode.sg_ospeed < B1200) 311 putchr('\n'); 312 /* this is the way they do it down under ... */ 313 else if (np > name) 314 puts(" \r"); 315 prompt(); 316 np = name; 317 continue; 318 } else if (c >= '0' && c <= '9') 319 digit++; 320 if (IG && (c <= ' ' || c > 0176)) 321 continue; 322 *np++ = c; 323 putchr(cs); 324 } 325 signal(SIGINT, SIG_IGN); 326 *np = 0; 327 if (c == '\r') 328 crmod++; 329 if (upper && !lower && !LC || UC) 330 for (np = name; *np; np++) 331 if (isupper(*np)) 332 *np = tolower(*np); 333 return (1); 334 } 335 336 static 337 short tmspc10[] = { 338 0, 2000, 1333, 909, 743, 666, 500, 333, 166, 83, 55, 41, 20, 10, 5, 15 339 }; 340 341 putpad(s) 342 register char *s; 343 { 344 register pad = 0; 345 register mspc10; 346 347 if (isdigit(*s)) { 348 while (isdigit(*s)) { 349 pad *= 10; 350 pad += *s++ - '0'; 351 } 352 pad *= 10; 353 if (*s == '.' && isdigit(s[1])) { 354 pad += s[1] - '0'; 355 s += 2; 356 } 357 } 358 359 puts(s); 360 /* 361 * If no delay needed, or output speed is 362 * not comprehensible, then don't try to delay. 363 */ 364 if (pad == 0) 365 return; 366 if (tmode.sg_ospeed <= 0 || 367 tmode.sg_ospeed >= (sizeof tmspc10 / sizeof tmspc10[0])) 368 return; 369 370 /* 371 * Round up by a half a character frame, 372 * and then do the delay. 373 * Too bad there are no user program accessible programmed delays. 374 * Transmitting pad characters slows many 375 * terminals down and also loads the system. 376 */ 377 mspc10 = tmspc10[tmode.sg_ospeed]; 378 pad += mspc10 / 2; 379 for (pad /= mspc10; pad > 0; pad--) 380 putchr(*PC); 381 } 382 383 puts(s) 384 register char *s; 385 { 386 387 while (*s) 388 putchr(*s++); 389 } 390 391 char outbuf[OBUFSIZ]; 392 int obufcnt = 0; 393 394 putchr(cc) 395 { 396 char c; 397 398 c = cc; 399 c |= partab[c&0177] & 0200; 400 if (OP) 401 c ^= 0200; 402 if (!UB) { 403 outbuf[obufcnt++] = c; 404 if (obufcnt >= OBUFSIZ) 405 oflush(); 406 } else 407 write(1, &c, 1); 408 } 409 410 oflush() 411 { 412 if (obufcnt) 413 write(1, outbuf, obufcnt); 414 obufcnt = 0; 415 } 416 417 prompt() 418 { 419 420 putf(LM); 421 if (CO) 422 putchr('\n'); 423 } 424 425 putf(cp) 426 register char *cp; 427 { 428 char *ttyn, *slash; 429 char datebuffer[60]; 430 extern char editedhost[]; 431 extern char *ttyname(), *rindex(); 432 433 while (*cp) { 434 if (*cp != '%') { 435 putchr(*cp++); 436 continue; 437 } 438 switch (*++cp) { 439 440 case 't': 441 ttyn = ttyname(0); 442 slash = rindex(ttyn, '/'); 443 if (slash == (char *) 0) 444 puts(ttyn); 445 else 446 puts(&slash[1]); 447 break; 448 449 case 'h': 450 puts(editedhost); 451 break; 452 453 case 'd': 454 get_date(datebuffer); 455 puts(datebuffer); 456 break; 457 458 case '%': 459 putchr('%'); 460 break; 461 } 462 cp++; 463 } 464 } 465