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