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