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