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