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