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