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