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