1 /* 2 * Copyright (c) 1983 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 */ 7 8 #ifndef lint 9 static char sccsid[] = "@(#)subr.c 5.12 (Berkeley) 05/27/93"; 10 #endif /* not lint */ 11 12 /* 13 * Melbourne getty. 14 */ 15 #define USE_OLD_TTY 16 #include <stdlib.h> 17 #include <sgtty.h> 18 #include <string.h> 19 #include <unistd.h> 20 21 #include "gettytab.h" 22 #include "extern.h" 23 #include "pathnames.h" 24 25 extern struct sgttyb tmode; 26 extern struct tchars tc; 27 extern struct ltchars ltc; 28 29 /* 30 * Get a table entry. 31 */ 32 void 33 gettable(name, buf) 34 char *name, *buf; 35 { 36 register struct gettystrs *sp; 37 register struct gettynums *np; 38 register struct gettyflags *fp; 39 long n; 40 char *dba[2]; 41 dba[0] = _PATH_GETTYTAB; 42 dba[1] = 0; 43 44 if (cgetent(&buf, dba, name) != 0) 45 return; 46 47 for (sp = gettystrs; sp->field; sp++) 48 cgetstr(buf, sp->field, &sp->value); 49 for (np = gettynums; np->field; np++) { 50 if (cgetnum(buf, np->field, &n) == -1) 51 np->set = 0; 52 else { 53 np->set = 1; 54 np->value = n; 55 } 56 } 57 for (fp = gettyflags; fp->field; fp++) { 58 if (cgetcap(buf, fp->field, ':') == NULL) 59 fp->set = 0; 60 else { 61 fp->set = 1; 62 fp->value = 1 ^ fp->invrt; 63 } 64 } 65 #define DEBUG 66 #ifdef DEBUG 67 printf("name=\"%s\", buf=\"%s\"\n", name, buf); 68 for (sp = gettystrs; sp->field; sp++) 69 printf("cgetstr: %s=%s\n", sp->field, sp->value); 70 for (np = gettynums; np->field; np++) 71 printf("cgetnum: %s=%d\n", np->field, np->value); 72 for (fp = gettyflags; fp->field; fp++) 73 printf("cgetflags: %s='%c' set='%c'\n", fp->field, 74 fp->value + '0', fp->set + '0'); 75 exit(1); 76 #endif /* DEBUG */ 77 } 78 79 void 80 gendefaults() 81 { 82 register struct gettystrs *sp; 83 register struct gettynums *np; 84 register struct gettyflags *fp; 85 86 for (sp = gettystrs; sp->field; sp++) 87 if (sp->value) 88 sp->defalt = sp->value; 89 for (np = gettynums; np->field; np++) 90 if (np->set) 91 np->defalt = np->value; 92 for (fp = gettyflags; fp->field; fp++) 93 if (fp->set) 94 fp->defalt = fp->value; 95 else 96 fp->defalt = fp->invrt; 97 } 98 99 void 100 setdefaults() 101 { 102 register struct gettystrs *sp; 103 register struct gettynums *np; 104 register struct gettyflags *fp; 105 106 for (sp = gettystrs; sp->field; sp++) 107 if (!sp->value) 108 sp->value = sp->defalt; 109 for (np = gettynums; np->field; np++) 110 if (!np->set) 111 np->value = np->defalt; 112 for (fp = gettyflags; fp->field; fp++) 113 if (!fp->set) 114 fp->value = fp->defalt; 115 } 116 117 static char ** 118 charnames[] = { 119 &ER, &KL, &IN, &QU, &XN, &XF, &ET, &BK, 120 &SU, &DS, &RP, &FL, &WE, &LN, 0 121 }; 122 123 static char * 124 charvars[] = { 125 &tmode.sg_erase, &tmode.sg_kill, &tc.t_intrc, 126 &tc.t_quitc, &tc.t_startc, &tc.t_stopc, 127 &tc.t_eofc, &tc.t_brkc, <c.t_suspc, 128 <c.t_dsuspc, <c.t_rprntc, <c.t_flushc, 129 <c.t_werasc, <c.t_lnextc, 0 130 }; 131 132 void 133 setchars() 134 { 135 register int i; 136 register char *p; 137 138 for (i = 0; charnames[i]; i++) { 139 p = *charnames[i]; 140 if (p && *p) 141 *charvars[i] = *p; 142 else 143 *charvars[i] = '\377'; 144 } 145 } 146 147 long 148 setflags(n) 149 int n; 150 { 151 register long f; 152 153 switch (n) { 154 case 0: 155 if (F0set) 156 return(F0); 157 break; 158 case 1: 159 if (F1set) 160 return(F1); 161 break; 162 default: 163 if (F2set) 164 return(F2); 165 break; 166 } 167 168 f = 0; 169 170 if (AP) 171 f |= ANYP; 172 else if (OP) 173 f |= ODDP; 174 else if (EP) 175 f |= EVENP; 176 177 if (UC) 178 f |= LCASE; 179 180 if (NL) 181 f |= CRMOD; 182 183 f |= delaybits(); 184 185 if (n == 1) { /* read mode flags */ 186 if (RW) 187 f |= RAW; 188 else 189 f |= CBREAK; 190 return (f); 191 } 192 193 if (!HT) 194 f |= XTABS; 195 196 if (n == 0) 197 return (f); 198 199 if (CB) 200 f |= CRTBS; 201 202 if (CE) 203 f |= CRTERA; 204 205 if (CK) 206 f |= CRTKIL; 207 208 if (PE) 209 f |= PRTERA; 210 211 if (EC) 212 f |= ECHO; 213 214 if (XC) 215 f |= CTLECH; 216 217 if (DX) 218 f |= DECCTQ; 219 220 return (f); 221 } 222 223 struct delayval { 224 unsigned delay; /* delay in ms */ 225 int bits; 226 }; 227 228 /* 229 * below are random guesses, I can't be bothered checking 230 */ 231 232 struct delayval crdelay[] = { 233 { 1, CR1 }, 234 { 2, CR2 }, 235 { 3, CR3 }, 236 { 83, CR1 }, 237 { 166, CR2 }, 238 { 0, CR3 }, 239 }; 240 241 struct delayval nldelay[] = { 242 { 1, NL1 }, /* special, calculated */ 243 { 2, NL2 }, 244 { 3, NL3 }, 245 { 100, NL2 }, 246 { 0, NL3 }, 247 }; 248 249 struct delayval bsdelay[] = { 250 { 1, BS1 }, 251 { 0, 0 }, 252 }; 253 254 struct delayval ffdelay[] = { 255 { 1, FF1 }, 256 { 1750, FF1 }, 257 { 0, FF1 }, 258 }; 259 260 struct delayval tbdelay[] = { 261 { 1, TAB1 }, 262 { 2, TAB2 }, 263 { 3, XTABS }, /* this is expand tabs */ 264 { 100, TAB1 }, 265 { 0, TAB2 }, 266 }; 267 268 int 269 delaybits() 270 { 271 register int f; 272 273 f = adelay(CD, crdelay); 274 f |= adelay(ND, nldelay); 275 f |= adelay(FD, ffdelay); 276 f |= adelay(TD, tbdelay); 277 f |= adelay(BD, bsdelay); 278 return (f); 279 } 280 281 int 282 adelay(ms, dp) 283 register ms; 284 register struct delayval *dp; 285 { 286 if (ms == 0) 287 return (0); 288 while (dp->delay && ms > dp->delay) 289 dp++; 290 return (dp->bits); 291 } 292 293 char editedhost[32]; 294 295 void 296 edithost(pat) 297 register char *pat; 298 { 299 register char *host = HN; 300 register char *res = editedhost; 301 302 if (!pat) 303 pat = ""; 304 while (*pat) { 305 switch (*pat) { 306 307 case '#': 308 if (*host) 309 host++; 310 break; 311 312 case '@': 313 if (*host) 314 *res++ = *host++; 315 break; 316 317 default: 318 *res++ = *pat; 319 break; 320 321 } 322 if (res == &editedhost[sizeof editedhost - 1]) { 323 *res = '\0'; 324 return; 325 } 326 pat++; 327 } 328 if (*host) 329 strncpy(res, host, sizeof editedhost - (res - editedhost) - 1); 330 else 331 *res = '\0'; 332 editedhost[sizeof editedhost - 1] = '\0'; 333 } 334 335 struct speedtab { 336 int speed; 337 int uxname; 338 } speedtab[] = { 339 { 50, B50 }, 340 { 75, B75 }, 341 { 110, B110 }, 342 { 134, B134 }, 343 { 150, B150 }, 344 { 200, B200 }, 345 { 300, B300 }, 346 { 600, B600 }, 347 { 1200, B1200 }, 348 { 1800, B1800 }, 349 { 2400, B2400 }, 350 { 4800, B4800 }, 351 { 9600, B9600 }, 352 { 19200, EXTA }, 353 { 19, EXTA }, /* for people who say 19.2K */ 354 { 38400, EXTB }, 355 { 38, EXTB }, 356 { 7200, EXTB }, /* alternative */ 357 { 0 } 358 }; 359 360 int 361 speed(val) 362 int val; 363 { 364 register struct speedtab *sp; 365 366 if (val <= 15) 367 return (val); 368 369 for (sp = speedtab; sp->speed; sp++) 370 if (sp->speed == val) 371 return (sp->uxname); 372 373 return (B300); /* default in impossible cases */ 374 } 375 376 void 377 makeenv(env) 378 char *env[]; 379 { 380 static char termbuf[128] = "TERM="; 381 register char *p, *q; 382 register char **ep; 383 384 ep = env; 385 if (TT && *TT) { 386 strcat(termbuf, TT); 387 *ep++ = termbuf; 388 } 389 if (p = EV) { 390 q = p; 391 while (q = strchr(q, ',')) { 392 *q++ = '\0'; 393 *ep++ = p; 394 p = q; 395 } 396 if (*p) 397 *ep++ = p; 398 } 399 *ep = (char *)0; 400 } 401 402 /* 403 * This speed select mechanism is written for the Develcon DATASWITCH. 404 * The Develcon sends a string of the form "B{speed}\n" at a predefined 405 * baud rate. This string indicates the user's actual speed. 406 * The routine below returns the terminal type mapped from derived speed. 407 */ 408 struct portselect { 409 char *ps_baud; 410 char *ps_type; 411 } portspeeds[] = { 412 { "B110", "std.110" }, 413 { "B134", "std.134" }, 414 { "B150", "std.150" }, 415 { "B300", "std.300" }, 416 { "B600", "std.600" }, 417 { "B1200", "std.1200" }, 418 { "B2400", "std.2400" }, 419 { "B4800", "std.4800" }, 420 { "B9600", "std.9600" }, 421 { "B19200", "std.19200" }, 422 { 0 } 423 }; 424 425 char * 426 portselector() 427 { 428 char c, baud[20], *type = "default"; 429 register struct portselect *ps; 430 int len; 431 432 alarm(5*60); 433 for (len = 0; len < sizeof (baud) - 1; len++) { 434 if (read(STDIN_FILENO, &c, 1) <= 0) 435 break; 436 c &= 0177; 437 if (c == '\n' || c == '\r') 438 break; 439 if (c == 'B') 440 len = 0; /* in case of leading garbage */ 441 baud[len] = c; 442 } 443 baud[len] = '\0'; 444 for (ps = portspeeds; ps->ps_baud; ps++) 445 if (strcmp(ps->ps_baud, baud) == 0) { 446 type = ps->ps_type; 447 break; 448 } 449 sleep(2); /* wait for connection to complete */ 450 return (type); 451 } 452 453 /* 454 * This auto-baud speed select mechanism is written for the Micom 600 455 * portselector. Selection is done by looking at how the character '\r' 456 * is garbled at the different speeds. 457 */ 458 #include <sys/time.h> 459 460 char * 461 autobaud() 462 { 463 int rfds; 464 struct timeval timeout; 465 char c, *type = "9600-baud"; 466 int null = 0; 467 468 ioctl(0, TIOCFLUSH, &null); 469 rfds = 1 << 0; 470 timeout.tv_sec = 5; 471 timeout.tv_usec = 0; 472 if (select(32, (fd_set *)&rfds, (fd_set *)NULL, 473 (fd_set *)NULL, &timeout) <= 0) 474 return (type); 475 if (read(STDIN_FILENO, &c, sizeof(char)) != sizeof(char)) 476 return (type); 477 timeout.tv_sec = 0; 478 timeout.tv_usec = 20; 479 (void) select(32, (fd_set *)NULL, (fd_set *)NULL, 480 (fd_set *)NULL, &timeout); 481 ioctl(0, TIOCFLUSH, &null); 482 switch (c & 0377) { 483 484 case 0200: /* 300-baud */ 485 type = "300-baud"; 486 break; 487 488 case 0346: /* 1200-baud */ 489 type = "1200-baud"; 490 break; 491 492 case 015: /* 2400-baud */ 493 case 0215: 494 type = "2400-baud"; 495 break; 496 497 default: /* 4800-baud */ 498 type = "4800-baud"; 499 break; 500 501 case 0377: /* 9600-baud */ 502 type = "9600-baud"; 503 break; 504 } 505 return (type); 506 } 507