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