1 #ifndef lint 2 static char sccsid[] = "@(#)main.c 4.4 (Berkeley) 83/07/09"; 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 sleep(PF); 201 PF = 0; 202 } 203 ioctl(0, TIOCSETP, &tmode); 204 crmod = 0; 205 upper = 0; 206 lower = 0; 207 digit = 0; 208 np = name; 209 for (;;) { 210 oflush(); 211 if (read(0, &cs, 1) <= 0) 212 exit(0); 213 if ((c = cs&0177) == 0) 214 return (0); 215 if (c == EOT) 216 exit(1); 217 if (c == '\r' || c == '\n' || np >= &name[16]) 218 break; 219 220 if (c >= 'a' && c <= 'z') 221 lower++; 222 else if (c >= 'A' && c <= 'Z') { 223 upper++; 224 } else if (c == ERASE || c == '#' || c == '\b') { 225 if (np > name) { 226 np--; 227 if (tmode.sg_ospeed >= B1200) 228 puts("\b \b"); 229 else 230 putchr(cs); 231 } 232 continue; 233 } else if (c == KILL || c == '@') { 234 putchr(cs); 235 putchr('\r'); 236 if (tmode.sg_ospeed < B1200) 237 putchr('\n'); 238 /* this is the way they do it down under ... */ 239 else if (np > name) 240 puts(" \r"); 241 prompt(); 242 np = name; 243 continue; 244 } else if (c == ' ') 245 c = '_'; 246 else if (c >= '0' && c <= '9') 247 digit++; 248 if (IG && (c < ' ' || c > 0176)) 249 continue; 250 *np++ = c; 251 putchr(cs); 252 } 253 signal(SIGINT, SIG_IGN); 254 *np = 0; 255 if (c == '\r') 256 crmod++; 257 if (upper && !lower && !LC || UC) 258 for (np = name; *np; np++) 259 if (isupper(*np)) 260 *np = tolower(*np); 261 return (1); 262 } 263 264 static 265 short tmspc10[] = { 266 0, 2000, 1333, 909, 743, 666, 500, 333, 166, 83, 55, 41, 20, 10, 5, 15 267 }; 268 269 putpad(s) 270 register char *s; 271 { 272 register pad = 0; 273 register mspc10; 274 275 if (isdigit(*s)) { 276 while (isdigit(*s)) { 277 pad *= 10; 278 pad += *s++ - '0'; 279 } 280 pad *= 10; 281 if (*s == '.' && isdigit(s[1])) { 282 pad += s[1] - '0'; 283 s += 2; 284 } 285 } 286 287 puts(s); 288 /* 289 * If no delay needed, or output speed is 290 * not comprehensible, then don't try to delay. 291 */ 292 if (pad == 0) 293 return; 294 if (tmode.sg_ospeed <= 0 || 295 tmode.sg_ospeed >= (sizeof tmspc10 / sizeof tmspc10[0])) 296 return; 297 298 /* 299 * Round up by a half a character frame, 300 * and then do the delay. 301 * Too bad there are no user program accessible programmed delays. 302 * Transmitting pad characters slows many 303 * terminals down and also loads the system. 304 */ 305 mspc10 = tmspc10[tmode.sg_ospeed]; 306 pad += mspc10 / 2; 307 for (pad /= mspc10; pad > 0; pad--) 308 putchr(*PC); 309 } 310 311 puts(s) 312 register char *s; 313 { 314 315 while (*s) 316 putchr(*s++); 317 } 318 319 char outbuf[OBUFSIZ]; 320 int obufcnt = 0; 321 322 putchr(cc) 323 { 324 char c; 325 326 c = cc; 327 c |= partab[c&0177] & 0200; 328 if (OP) 329 c ^= 0200; 330 if (!UB) { 331 outbuf[obufcnt++] = c; 332 if (obufcnt >= OBUFSIZ) 333 oflush(); 334 } else 335 write(1, &c, 1); 336 } 337 338 oflush() 339 { 340 if (obufcnt) 341 write(1, outbuf, obufcnt); 342 obufcnt = 0; 343 } 344 345 prompt() 346 { 347 348 putf(LM); 349 if (CO) 350 putchr('\n'); 351 } 352 353 putf(cp) 354 register char *cp; 355 { 356 extern char editedhost[]; 357 358 while (*cp) { 359 if (*cp != '%') { 360 putchr(*cp++); 361 continue; 362 } 363 switch (*++cp) { 364 365 case 'h': 366 puts(editedhost); 367 break; 368 369 case '%': 370 putchr('%'); 371 break; 372 } 373 cp++; 374 } 375 } 376