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