| 1 | #ifndef lint |
| 2 | static char sccsid[] = "@(#)main.c 4.6 (Berkeley) 83/12/13"; |
| 3 | #endif |
| 4 | |
| 5 | /* |
| 6 | * getty -- adapt to terminal speed on dialup, and call login |
| 7 | * |
| 8 | * Melbourne getty, June 83, kre. |
| 9 | */ |
| 10 | |
| 11 | #include <sgtty.h> |
| 12 | #include <signal.h> |
| 13 | #include <ctype.h> |
| 14 | #include <setjmp.h> |
| 15 | #include "gettytab.h" |
| 16 | |
| 17 | struct sgttyb tmode = { |
| 18 | 0, 0, CERASE, CKILL, 0 |
| 19 | }; |
| 20 | struct tchars tc = { |
| 21 | CINTR, CQUIT, CSTART, |
| 22 | CSTOP, CEOF, CBRK, |
| 23 | }; |
| 24 | struct ltchars ltc = { |
| 25 | CSUSP, CDSUSP, CRPRNT, |
| 26 | CFLUSH, CWERASE, CLNEXT |
| 27 | }; |
| 28 | |
| 29 | int crmod; |
| 30 | int upper; |
| 31 | int lower; |
| 32 | int digit; |
| 33 | |
| 34 | char hostname[32]; |
| 35 | char name[16]; |
| 36 | char *portselector(); |
| 37 | |
| 38 | #define OBUFSIZ 128 |
| 39 | #define TABBUFSIZ 512 |
| 40 | |
| 41 | char defent[TABBUFSIZ]; |
| 42 | char defstrs[TABBUFSIZ]; |
| 43 | char tabent[TABBUFSIZ]; |
| 44 | char tabstrs[TABBUFSIZ]; |
| 45 | |
| 46 | char *env[128]; |
| 47 | |
| 48 | char partab[] = { |
| 49 | 0001,0201,0201,0001,0201,0001,0001,0201, |
| 50 | 0202,0004,0003,0205,0005,0206,0201,0001, |
| 51 | 0201,0001,0001,0201,0001,0201,0201,0001, |
| 52 | 0001,0201,0201,0001,0201,0001,0001,0201, |
| 53 | 0200,0000,0000,0200,0000,0200,0200,0000, |
| 54 | 0000,0200,0200,0000,0200,0000,0000,0200, |
| 55 | 0000,0200,0200,0000,0200,0000,0000,0200, |
| 56 | 0200,0000,0000,0200,0000,0200,0200,0000, |
| 57 | 0200,0000,0000,0200,0000,0200,0200,0000, |
| 58 | 0000,0200,0200,0000,0200,0000,0000,0200, |
| 59 | 0000,0200,0200,0000,0200,0000,0000,0200, |
| 60 | 0200,0000,0000,0200,0000,0200,0200,0000, |
| 61 | 0000,0200,0200,0000,0200,0000,0000,0200, |
| 62 | 0200,0000,0000,0200,0000,0200,0200,0000, |
| 63 | 0200,0000,0000,0200,0000,0200,0200,0000, |
| 64 | 0000,0200,0200,0000,0200,0000,0000,0201 |
| 65 | }; |
| 66 | |
| 67 | #define ERASE tmode.sg_erase |
| 68 | #define KILL tmode.sg_kill |
| 69 | #define EOT tc.t_eofc |
| 70 | |
| 71 | jmp_buf timeout; |
| 72 | |
| 73 | dingdong() |
| 74 | { |
| 75 | |
| 76 | alarm(0); |
| 77 | signal(SIGALRM, SIG_DFL); |
| 78 | longjmp(timeout, 1); |
| 79 | } |
| 80 | |
| 81 | jmp_buf intrupt; |
| 82 | |
| 83 | interrupt() |
| 84 | { |
| 85 | |
| 86 | signal(SIGINT, interrupt); |
| 87 | longjmp(intrupt, 1); |
| 88 | } |
| 89 | |
| 90 | main(argc, argv) |
| 91 | char *argv[]; |
| 92 | { |
| 93 | char *tname; |
| 94 | long allflags; |
| 95 | |
| 96 | signal(SIGINT, SIG_IGN); |
| 97 | /* |
| 98 | signal(SIGQUIT, SIG_DFL); |
| 99 | */ |
| 100 | gethostname(hostname, sizeof(hostname)); |
| 101 | if (hostname[0] == '\0') |
| 102 | strcpy(hostname, "Amnesiac"); |
| 103 | gettable("default", defent, defstrs); |
| 104 | gendefaults(); |
| 105 | tname = "default"; |
| 106 | if (argc > 1) |
| 107 | tname = argv[1]; |
| 108 | for (;;) { |
| 109 | int ldisp = OTTYDISC; |
| 110 | |
| 111 | gettable(tname, tabent, tabstrs); |
| 112 | if (OPset || EPset || APset) |
| 113 | APset++, OPset++, EPset++; |
| 114 | setdefaults(); |
| 115 | ioctl(0, TIOCFLUSH, 0); /* clear out the crap */ |
| 116 | if (IS) |
| 117 | tmode.sg_ispeed = speed(IS); |
| 118 | else if (SP) |
| 119 | tmode.sg_ispeed = speed(SP); |
| 120 | if (OS) |
| 121 | tmode.sg_ospeed = speed(OS); |
| 122 | else if (SP) |
| 123 | tmode.sg_ospeed = speed(SP); |
| 124 | tmode.sg_flags = setflags(0); |
| 125 | ioctl(0, TIOCSETP, &tmode); |
| 126 | setchars(); |
| 127 | ioctl(0, TIOCSETC, &tc); |
| 128 | ioctl(0, TIOCSETD, &ldisp); |
| 129 | if (HC) |
| 130 | ioctl(0, TIOCHPCL, 0); |
| 131 | if (PS) { |
| 132 | tname = portselector(); |
| 133 | continue; |
| 134 | } |
| 135 | if (CL && *CL) |
| 136 | putpad(CL); |
| 137 | edithost(HE); |
| 138 | if (IM && *IM) |
| 139 | putf(IM); |
| 140 | if (setjmp(timeout)) { |
| 141 | tmode.sg_ispeed = tmode.sg_ospeed = 0; |
| 142 | ioctl(0, TIOCSETP, &tmode); |
| 143 | exit(1); |
| 144 | } |
| 145 | if (TO) { |
| 146 | signal(SIGALRM, dingdong); |
| 147 | alarm(TO); |
| 148 | } |
| 149 | if (getname()) { |
| 150 | alarm(0); |
| 151 | signal(SIGALRM, SIG_DFL); |
| 152 | if (!(upper || lower || digit)) |
| 153 | continue; |
| 154 | allflags = setflags(2); |
| 155 | tmode.sg_flags = allflags & 0xffff; |
| 156 | allflags >>= 16; |
| 157 | if (crmod || NL) |
| 158 | tmode.sg_flags |= CRMOD; |
| 159 | if (upper || UC) |
| 160 | tmode.sg_flags |= LCASE; |
| 161 | if (lower || LC) |
| 162 | tmode.sg_flags &= ~LCASE; |
| 163 | ioctl(0, TIOCSETP, &tmode); |
| 164 | ioctl(0, TIOCSLTC, <c); |
| 165 | ioctl(0, TIOCLSET, &allflags); |
| 166 | putchr('\n'); |
| 167 | oflush(); |
| 168 | makeenv(env); |
| 169 | signal(SIGINT, SIG_DFL); |
| 170 | execle(LO, "login", name, (char *)0, env); |
| 171 | exit(1); |
| 172 | } |
| 173 | alarm(0); |
| 174 | signal(SIGALRM, SIG_DFL); |
| 175 | signal(SIGINT, SIG_IGN); |
| 176 | if (NX && *NX) |
| 177 | tname = NX; |
| 178 | } |
| 179 | } |
| 180 | |
| 181 | getname() |
| 182 | { |
| 183 | register char *np; |
| 184 | register c; |
| 185 | char cs; |
| 186 | |
| 187 | /* |
| 188 | * Interrupt may happen if we use CBREAK mode |
| 189 | */ |
| 190 | if (setjmp(intrupt)) { |
| 191 | signal(SIGINT, SIG_IGN); |
| 192 | return (0); |
| 193 | } |
| 194 | signal(SIGINT, interrupt); |
| 195 | tmode.sg_flags = setflags(0); |
| 196 | ioctl(0, TIOCSETP, &tmode); |
| 197 | tmode.sg_flags = setflags(1); |
| 198 | prompt(); |
| 199 | if (PF > 0) { |
| 200 | oflush(); |
| 201 | sleep(PF); |
| 202 | PF = 0; |
| 203 | } |
| 204 | ioctl(0, TIOCSETP, &tmode); |
| 205 | crmod = 0; |
| 206 | upper = 0; |
| 207 | lower = 0; |
| 208 | digit = 0; |
| 209 | np = name; |
| 210 | for (;;) { |
| 211 | oflush(); |
| 212 | if (read(0, &cs, 1) <= 0) |
| 213 | exit(0); |
| 214 | if ((c = cs&0177) == 0) |
| 215 | return (0); |
| 216 | if (c == EOT) |
| 217 | exit(1); |
| 218 | if (c == '\r' || c == '\n' || np >= &name[16]) |
| 219 | break; |
| 220 | |
| 221 | if (c >= 'a' && c <= 'z') |
| 222 | lower++; |
| 223 | else if (c >= 'A' && c <= 'Z') { |
| 224 | upper++; |
| 225 | } else if (c == ERASE || c == '#' || c == '\b') { |
| 226 | if (np > name) { |
| 227 | np--; |
| 228 | if (tmode.sg_ospeed >= B1200) |
| 229 | puts("\b \b"); |
| 230 | else |
| 231 | putchr(cs); |
| 232 | } |
| 233 | continue; |
| 234 | } else if (c == KILL || c == '@') { |
| 235 | putchr(cs); |
| 236 | putchr('\r'); |
| 237 | if (tmode.sg_ospeed < B1200) |
| 238 | putchr('\n'); |
| 239 | /* this is the way they do it down under ... */ |
| 240 | else if (np > name) |
| 241 | puts(" \r"); |
| 242 | prompt(); |
| 243 | np = name; |
| 244 | continue; |
| 245 | } else if (c == ' ') |
| 246 | c = '_'; |
| 247 | else if (c >= '0' && c <= '9') |
| 248 | digit++; |
| 249 | if (IG && (c < ' ' || c > 0176)) |
| 250 | continue; |
| 251 | *np++ = c; |
| 252 | putchr(cs); |
| 253 | } |
| 254 | signal(SIGINT, SIG_IGN); |
| 255 | *np = 0; |
| 256 | if (c == '\r') |
| 257 | crmod++; |
| 258 | if (upper && !lower && !LC || UC) |
| 259 | for (np = name; *np; np++) |
| 260 | if (isupper(*np)) |
| 261 | *np = tolower(*np); |
| 262 | return (1); |
| 263 | } |
| 264 | |
| 265 | static |
| 266 | short tmspc10[] = { |
| 267 | 0, 2000, 1333, 909, 743, 666, 500, 333, 166, 83, 55, 41, 20, 10, 5, 15 |
| 268 | }; |
| 269 | |
| 270 | putpad(s) |
| 271 | register char *s; |
| 272 | { |
| 273 | register pad = 0; |
| 274 | register mspc10; |
| 275 | |
| 276 | if (isdigit(*s)) { |
| 277 | while (isdigit(*s)) { |
| 278 | pad *= 10; |
| 279 | pad += *s++ - '0'; |
| 280 | } |
| 281 | pad *= 10; |
| 282 | if (*s == '.' && isdigit(s[1])) { |
| 283 | pad += s[1] - '0'; |
| 284 | s += 2; |
| 285 | } |
| 286 | } |
| 287 | |
| 288 | puts(s); |
| 289 | /* |
| 290 | * If no delay needed, or output speed is |
| 291 | * not comprehensible, then don't try to delay. |
| 292 | */ |
| 293 | if (pad == 0) |
| 294 | return; |
| 295 | if (tmode.sg_ospeed <= 0 || |
| 296 | tmode.sg_ospeed >= (sizeof tmspc10 / sizeof tmspc10[0])) |
| 297 | return; |
| 298 | |
| 299 | /* |
| 300 | * Round up by a half a character frame, |
| 301 | * and then do the delay. |
| 302 | * Too bad there are no user program accessible programmed delays. |
| 303 | * Transmitting pad characters slows many |
| 304 | * terminals down and also loads the system. |
| 305 | */ |
| 306 | mspc10 = tmspc10[tmode.sg_ospeed]; |
| 307 | pad += mspc10 / 2; |
| 308 | for (pad /= mspc10; pad > 0; pad--) |
| 309 | putchr(*PC); |
| 310 | } |
| 311 | |
| 312 | puts(s) |
| 313 | register char *s; |
| 314 | { |
| 315 | |
| 316 | while (*s) |
| 317 | putchr(*s++); |
| 318 | } |
| 319 | |
| 320 | char outbuf[OBUFSIZ]; |
| 321 | int obufcnt = 0; |
| 322 | |
| 323 | putchr(cc) |
| 324 | { |
| 325 | char c; |
| 326 | |
| 327 | c = cc; |
| 328 | c |= partab[c&0177] & 0200; |
| 329 | if (OP) |
| 330 | c ^= 0200; |
| 331 | if (!UB) { |
| 332 | outbuf[obufcnt++] = c; |
| 333 | if (obufcnt >= OBUFSIZ) |
| 334 | oflush(); |
| 335 | } else |
| 336 | write(1, &c, 1); |
| 337 | } |
| 338 | |
| 339 | oflush() |
| 340 | { |
| 341 | if (obufcnt) |
| 342 | write(1, outbuf, obufcnt); |
| 343 | obufcnt = 0; |
| 344 | } |
| 345 | |
| 346 | prompt() |
| 347 | { |
| 348 | |
| 349 | putf(LM); |
| 350 | if (CO) |
| 351 | putchr('\n'); |
| 352 | } |
| 353 | |
| 354 | putf(cp) |
| 355 | register char *cp; |
| 356 | { |
| 357 | char *tp; |
| 358 | extern char editedhost[]; |
| 359 | extern char *ttyname(); |
| 360 | |
| 361 | while (*cp) { |
| 362 | if (*cp != '%') { |
| 363 | putchr(*cp++); |
| 364 | continue; |
| 365 | } |
| 366 | switch (*++cp) { |
| 367 | |
| 368 | case 'h': |
| 369 | puts(editedhost); |
| 370 | break; |
| 371 | |
| 372 | case 't': |
| 373 | tp = ttyname(0); |
| 374 | if (tp != (char *)0) { |
| 375 | if (strncmp(tp, "/dev/", 5) == 0) |
| 376 | tp += 5; |
| 377 | puts(tp); |
| 378 | } |
| 379 | break; |
| 380 | |
| 381 | case '%': |
| 382 | putchr('%'); |
| 383 | break; |
| 384 | } |
| 385 | cp++; |
| 386 | } |
| 387 | } |