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