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 } 388