1/* $OpenBSD: subr.c,v 1.28 2018/06/14 23:19:27 gsoares 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 46extern struct termios tmode, omode; 47 48/* 49 * Get a table entry. 50 */ 51void 52gettable(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 96void 97gendefaults(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 116void 117setdefaults(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 134static char ** 135charnames[] = { 136 &ER, &KL, &IN, &QU, &XN, &XF, &ET, &BK, 137 &SU, &DS, &RP, &FL, &WE, &LN, 0 138}; 139 140static char * 141charvars[] = { 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 149void 150setchars(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 169void 170setflags(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 263 if (n == 1) { /* read mode flags */ 264 if (RW) { 265 iflag = 0; 266 CLR(oflag, OPOST); 267 CLR(cflag, CSIZE|PARENB); 268 SET(cflag, CS8); 269 lflag = 0; 270 } else { 271 CLR(lflag, ICANON); 272 } 273 goto out; 274 } 275 276 if (n == 0) 277 goto out; 278 279#if 0 280 if (CB) 281 SET(f, CRTBS); 282#endif 283 284 if (CE) 285 SET(lflag, ECHOE); 286 else 287 CLR(lflag, ECHOE); 288 289 if (CK) 290 SET(lflag, ECHOKE); 291 else 292 CLR(lflag, ECHOKE); 293 294 if (PE) 295 SET(lflag, ECHOPRT); 296 else 297 CLR(lflag, ECHOPRT); 298 299 if (EC) 300 SET(lflag, ECHO); 301 else 302 CLR(lflag, ECHO); 303 304 if (XC) 305 SET(lflag, ECHOCTL); 306 else 307 CLR(lflag, ECHOCTL); 308 309 if (DX) 310 SET(lflag, IXANY); 311 else 312 CLR(lflag, IXANY); 313 314out: 315 tmode.c_iflag = iflag; 316 tmode.c_oflag = oflag; 317 tmode.c_cflag = cflag; 318 tmode.c_lflag = lflag; 319} 320 321 322void 323makeenv(char *env[]) 324{ 325 static char termbuf[128] = "TERM="; 326 char *p, *q; 327 char **ep; 328 329 ep = env; 330 if (TT && *TT) { 331 strlcat(termbuf, TT, sizeof(termbuf)); 332 *ep++ = termbuf; 333 } 334 if ((p = EV)) { 335 q = p; 336 while ((q = strchr(q, ','))) { 337 *q++ = '\0'; 338 *ep++ = p; 339 p = q; 340 } 341 if (*p) 342 *ep++ = p; 343 } 344 *ep = NULL; 345} 346 347/* 348 * This speed select mechanism is written for the Develcon DATASWITCH. 349 * The Develcon sends a string of the form "B{speed}\n" at a predefined 350 * baud rate. This string indicates the user's actual speed. 351 * The routine below returns the terminal type mapped from derived speed. 352 */ 353struct portselect { 354 char *ps_baud; 355 char *ps_type; 356} portspeeds[] = { 357 { "B110", "std.110" }, 358 { "B134", "std.134" }, 359 { "B150", "std.150" }, 360 { "B300", "std.300" }, 361 { "B600", "std.600" }, 362 { "B1200", "std.1200" }, 363 { "B2400", "std.2400" }, 364 { "B4800", "std.4800" }, 365 { "B9600", "std.9600" }, 366 { "B19200", "std.19200" }, 367 { 0 } 368}; 369 370char * 371portselector(void) 372{ 373 char c, baud[20], *type = "default"; 374 struct portselect *ps; 375 size_t len; 376 377 alarm(5*60); 378 for (len = 0; len < sizeof (baud) - 1; len++) { 379 if (read(STDIN_FILENO, &c, 1) <= 0) 380 break; 381 c &= 0177; 382 if (c == '\n' || c == '\r') 383 break; 384 if (c == 'B') 385 len = 0; /* in case of leading garbage */ 386 baud[len] = c; 387 } 388 baud[len] = '\0'; 389 for (ps = portspeeds; ps->ps_baud; ps++) 390 if (strcmp(ps->ps_baud, baud) == 0) { 391 type = ps->ps_type; 392 break; 393 } 394 sleep(2); /* wait for connection to complete */ 395 return (type); 396} 397 398/* 399 * This auto-baud speed select mechanism is written for the Micom 600 400 * portselector. Selection is done by looking at how the character '\r' 401 * is garbled at the different speeds. 402 */ 403#include <sys/time.h> 404 405char * 406autobaud(void) 407{ 408 struct pollfd pfd[1]; 409 struct timespec ts; 410 char c, *type = "9600-baud"; 411 412 (void)tcflush(0, TCIOFLUSH); 413 pfd[0].fd = 0; 414 pfd[0].events = POLLIN; 415 if (poll(pfd, 1, 5 * 1000) <= 0) 416 return (type); 417 if (read(STDIN_FILENO, &c, sizeof(char)) != sizeof(char)) 418 return (type); 419 420 ts.tv_sec = 0; 421 ts.tv_nsec = 20 * 1000; 422 nanosleep(&ts, NULL); 423 (void)tcflush(0, TCIOFLUSH); 424 switch (c & 0377) { 425 426 case 0200: /* 300-baud */ 427 type = "300-baud"; 428 break; 429 430 case 0346: /* 1200-baud */ 431 type = "1200-baud"; 432 break; 433 434 case 015: /* 2400-baud */ 435 case 0215: 436 type = "2400-baud"; 437 break; 438 439 default: /* 4800-baud */ 440 type = "4800-baud"; 441 break; 442 443 case 0377: /* 9600-baud */ 444 type = "9600-baud"; 445 break; 446 } 447 return (type); 448} 449