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