1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* Copyright (c) 1988 AT&T */ 23*7c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 24*7c478bd9Sstevel@tonic-gate 25*7c478bd9Sstevel@tonic-gate 26*7c478bd9Sstevel@tonic-gate /* 27*7c478bd9Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 28*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 29*7c478bd9Sstevel@tonic-gate */ 30*7c478bd9Sstevel@tonic-gate 31*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 32*7c478bd9Sstevel@tonic-gate 33*7c478bd9Sstevel@tonic-gate /* Copyright (c) 1979 Regents of the University of California */ 34*7c478bd9Sstevel@tonic-gate /* Modified to: */ 35*7c478bd9Sstevel@tonic-gate /* 1) remember the name of the first tc= parameter */ 36*7c478bd9Sstevel@tonic-gate /* encountered during parsing. */ 37*7c478bd9Sstevel@tonic-gate /* 2) handle multiple invocations of tgetent(). */ 38*7c478bd9Sstevel@tonic-gate /* 3) tskip() is now available outside of the library. */ 39*7c478bd9Sstevel@tonic-gate /* 4) remember $TERM name for error messages. */ 40*7c478bd9Sstevel@tonic-gate /* 5) have a larger buffer. */ 41*7c478bd9Sstevel@tonic-gate /* 6) really fix the bug that 5) got around. This fix by */ 42*7c478bd9Sstevel@tonic-gate /* Marion Hakanson, orstcs!hakanson */ 43*7c478bd9Sstevel@tonic-gate 44*7c478bd9Sstevel@tonic-gate 45*7c478bd9Sstevel@tonic-gate #include "otermcap.h" 46*7c478bd9Sstevel@tonic-gate #define MAXHOP 32 /* max number of tc= indirections */ 47*7c478bd9Sstevel@tonic-gate 48*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 49*7c478bd9Sstevel@tonic-gate #include <sys/stat.h> 50*7c478bd9Sstevel@tonic-gate #include <fcntl.h> 51*7c478bd9Sstevel@tonic-gate #include <sys/uio.h> 52*7c478bd9Sstevel@tonic-gate #include <unistd.h> 53*7c478bd9Sstevel@tonic-gate #include <stdio.h> 54*7c478bd9Sstevel@tonic-gate #include <stdlib.h> 55*7c478bd9Sstevel@tonic-gate #include <string.h> 56*7c478bd9Sstevel@tonic-gate #include <ctype.h> 57*7c478bd9Sstevel@tonic-gate 58*7c478bd9Sstevel@tonic-gate #include <signal.h> /* use this file to determine if this is SVR4.0 system */ 59*7c478bd9Sstevel@tonic-gate #ifdef SIGSTOP /* SVR4.0 and beyond */ 60*7c478bd9Sstevel@tonic-gate #define E_TERMCAP "/usr/share/lib/termcap" 61*7c478bd9Sstevel@tonic-gate #else 62*7c478bd9Sstevel@tonic-gate #define E_TERMCAP "/etc/termcap" 63*7c478bd9Sstevel@tonic-gate #endif 64*7c478bd9Sstevel@tonic-gate 65*7c478bd9Sstevel@tonic-gate /* 66*7c478bd9Sstevel@tonic-gate * termcap - routines for dealing with the terminal capability data base 67*7c478bd9Sstevel@tonic-gate * 68*7c478bd9Sstevel@tonic-gate * BUG: Should use a "last" pointer in tbuf, so that searching 69*7c478bd9Sstevel@tonic-gate * for capabilities alphabetically would not be a n**2/2 70*7c478bd9Sstevel@tonic-gate * process when large numbers of capabilities are given. 71*7c478bd9Sstevel@tonic-gate * Note: If we add a last pointer now we will screw up the 72*7c478bd9Sstevel@tonic-gate * tc capability. We really should compile termcap. 73*7c478bd9Sstevel@tonic-gate * 74*7c478bd9Sstevel@tonic-gate * Essentially all the work here is scanning and decoding escapes 75*7c478bd9Sstevel@tonic-gate * in string capabilities. We don't use stdio because the editor 76*7c478bd9Sstevel@tonic-gate * doesn't, and because living w/o it is not hard. 77*7c478bd9Sstevel@tonic-gate */ 78*7c478bd9Sstevel@tonic-gate 79*7c478bd9Sstevel@tonic-gate static char *tbuf; 80*7c478bd9Sstevel@tonic-gate static int hopcount; /* detect infinite loops in termcap, init 0 */ 81*7c478bd9Sstevel@tonic-gate char *tskip(); 82*7c478bd9Sstevel@tonic-gate char *otgetstr(); 83*7c478bd9Sstevel@tonic-gate 84*7c478bd9Sstevel@tonic-gate /* Tony Hansen */ 85*7c478bd9Sstevel@tonic-gate int TLHtcfound = 0; 86*7c478bd9Sstevel@tonic-gate char TLHtcname[16]; 87*7c478bd9Sstevel@tonic-gate static char *termname; 88*7c478bd9Sstevel@tonic-gate 89*7c478bd9Sstevel@tonic-gate static int _tgetent(char *, char *); 90*7c478bd9Sstevel@tonic-gate static int otnchktc(); 91*7c478bd9Sstevel@tonic-gate static char *tdecode(char *, char **); 92*7c478bd9Sstevel@tonic-gate static int otnamatch(char *); 93*7c478bd9Sstevel@tonic-gate /* 94*7c478bd9Sstevel@tonic-gate * Get an entry for terminal name in buffer bp, 95*7c478bd9Sstevel@tonic-gate * from the termcap file. Parse is very rudimentary; 96*7c478bd9Sstevel@tonic-gate * we just notice escaped newlines. 97*7c478bd9Sstevel@tonic-gate */ 98*7c478bd9Sstevel@tonic-gate otgetent(char *bp, char *name) 99*7c478bd9Sstevel@tonic-gate { 100*7c478bd9Sstevel@tonic-gate /* Tony Hansen */ 101*7c478bd9Sstevel@tonic-gate int ret; 102*7c478bd9Sstevel@tonic-gate TLHtcfound = 0; 103*7c478bd9Sstevel@tonic-gate hopcount = 0; 104*7c478bd9Sstevel@tonic-gate termname = name; 105*7c478bd9Sstevel@tonic-gate ret = _tgetent(bp, name); 106*7c478bd9Sstevel@tonic-gate /* 107*7c478bd9Sstevel@tonic-gate * There is some sort of bug in the check way down below to prevent 108*7c478bd9Sstevel@tonic-gate * buffer overflow. I really don't want to track it down, so I 109*7c478bd9Sstevel@tonic-gate * upped the standard buffer size and check here to see if the created 110*7c478bd9Sstevel@tonic-gate * buffer is larger than the old buffer size. 111*7c478bd9Sstevel@tonic-gate */ 112*7c478bd9Sstevel@tonic-gate if (strlen(bp) >= 1024) 113*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 114*7c478bd9Sstevel@tonic-gate "tgetent(): TERM=%s: Termcap entry is too long.\n", 115*7c478bd9Sstevel@tonic-gate termname); 116*7c478bd9Sstevel@tonic-gate return (ret); 117*7c478bd9Sstevel@tonic-gate } 118*7c478bd9Sstevel@tonic-gate 119*7c478bd9Sstevel@tonic-gate static int 120*7c478bd9Sstevel@tonic-gate _tgetent(char *bp, char *name) 121*7c478bd9Sstevel@tonic-gate { 122*7c478bd9Sstevel@tonic-gate char *cp; 123*7c478bd9Sstevel@tonic-gate int c; 124*7c478bd9Sstevel@tonic-gate int i = 0, cnt = 0; 125*7c478bd9Sstevel@tonic-gate char ibuf[TBUFSIZE]; 126*7c478bd9Sstevel@tonic-gate char *cp2; 127*7c478bd9Sstevel@tonic-gate int tf; 128*7c478bd9Sstevel@tonic-gate 129*7c478bd9Sstevel@tonic-gate tbuf = bp; 130*7c478bd9Sstevel@tonic-gate tf = 0; 131*7c478bd9Sstevel@tonic-gate #ifndef V6 132*7c478bd9Sstevel@tonic-gate cp = getenv("TERMCAP"); 133*7c478bd9Sstevel@tonic-gate /* 134*7c478bd9Sstevel@tonic-gate * TERMCAP can have one of two things in it. It can be the 135*7c478bd9Sstevel@tonic-gate * name of a file to use instead of /etc/termcap. In this 136*7c478bd9Sstevel@tonic-gate * case it better start with a "/". Or it can be an entry to 137*7c478bd9Sstevel@tonic-gate * use so we don't have to read the file. In this case it 138*7c478bd9Sstevel@tonic-gate * has to already have the newlines crunched out. 139*7c478bd9Sstevel@tonic-gate */ 140*7c478bd9Sstevel@tonic-gate if (cp && *cp) { 141*7c478bd9Sstevel@tonic-gate if (*cp != '/') { 142*7c478bd9Sstevel@tonic-gate cp2 = getenv("TERM"); 143*7c478bd9Sstevel@tonic-gate if (cp2 == (char *)0 || strcmp(name, cp2) == 0) { 144*7c478bd9Sstevel@tonic-gate (void) strcpy(bp, cp); 145*7c478bd9Sstevel@tonic-gate return (otnchktc()); 146*7c478bd9Sstevel@tonic-gate } else { 147*7c478bd9Sstevel@tonic-gate tf = open(E_TERMCAP, 0); 148*7c478bd9Sstevel@tonic-gate } 149*7c478bd9Sstevel@tonic-gate } else 150*7c478bd9Sstevel@tonic-gate tf = open(cp, 0); 151*7c478bd9Sstevel@tonic-gate } 152*7c478bd9Sstevel@tonic-gate if (tf == 0) 153*7c478bd9Sstevel@tonic-gate tf = open(E_TERMCAP, 0); 154*7c478bd9Sstevel@tonic-gate #else 155*7c478bd9Sstevel@tonic-gate tf = open(E_TERMCAP, 0); 156*7c478bd9Sstevel@tonic-gate #endif 157*7c478bd9Sstevel@tonic-gate if (tf < 0) 158*7c478bd9Sstevel@tonic-gate return (-1); 159*7c478bd9Sstevel@tonic-gate for (; ; ) { 160*7c478bd9Sstevel@tonic-gate cp = bp; 161*7c478bd9Sstevel@tonic-gate for (; ; ) { 162*7c478bd9Sstevel@tonic-gate if (i == cnt) { 163*7c478bd9Sstevel@tonic-gate cnt = read(tf, ibuf, TBUFSIZE); 164*7c478bd9Sstevel@tonic-gate if (cnt <= 0) { 165*7c478bd9Sstevel@tonic-gate (void) close(tf); 166*7c478bd9Sstevel@tonic-gate return (0); 167*7c478bd9Sstevel@tonic-gate } 168*7c478bd9Sstevel@tonic-gate i = 0; 169*7c478bd9Sstevel@tonic-gate } 170*7c478bd9Sstevel@tonic-gate c = ibuf[i++]; 171*7c478bd9Sstevel@tonic-gate if (c == '\n') { 172*7c478bd9Sstevel@tonic-gate if (cp > bp && cp[-1] == '\\') { 173*7c478bd9Sstevel@tonic-gate cp--; 174*7c478bd9Sstevel@tonic-gate continue; 175*7c478bd9Sstevel@tonic-gate } 176*7c478bd9Sstevel@tonic-gate break; 177*7c478bd9Sstevel@tonic-gate } 178*7c478bd9Sstevel@tonic-gate if (cp >= bp + TBUFSIZE) { 179*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "tgetent(): TERM=%s: " 180*7c478bd9Sstevel@tonic-gate "Termcap entry too long\n", termname); 181*7c478bd9Sstevel@tonic-gate break; 182*7c478bd9Sstevel@tonic-gate } else 183*7c478bd9Sstevel@tonic-gate *cp++ = c; 184*7c478bd9Sstevel@tonic-gate } 185*7c478bd9Sstevel@tonic-gate *cp = 0; 186*7c478bd9Sstevel@tonic-gate 187*7c478bd9Sstevel@tonic-gate /* 188*7c478bd9Sstevel@tonic-gate * The real work for the match. 189*7c478bd9Sstevel@tonic-gate */ 190*7c478bd9Sstevel@tonic-gate if (otnamatch(name)) { 191*7c478bd9Sstevel@tonic-gate (void) close(tf); 192*7c478bd9Sstevel@tonic-gate return (otnchktc()); 193*7c478bd9Sstevel@tonic-gate } 194*7c478bd9Sstevel@tonic-gate } 195*7c478bd9Sstevel@tonic-gate } 196*7c478bd9Sstevel@tonic-gate 197*7c478bd9Sstevel@tonic-gate /* 198*7c478bd9Sstevel@tonic-gate * otnchktc: check the last entry, see if it's tc=xxx. If so, 199*7c478bd9Sstevel@tonic-gate * recursively find xxx and append that entry (minus the names) 200*7c478bd9Sstevel@tonic-gate * to take the place of the tc=xxx entry. This allows termcap 201*7c478bd9Sstevel@tonic-gate * entries to say "like an HP2621 but doesn't turn on the labels". 202*7c478bd9Sstevel@tonic-gate * Note that this works because of the left to right scan. 203*7c478bd9Sstevel@tonic-gate */ 204*7c478bd9Sstevel@tonic-gate static int 205*7c478bd9Sstevel@tonic-gate otnchktc() 206*7c478bd9Sstevel@tonic-gate { 207*7c478bd9Sstevel@tonic-gate char *p, *q; 208*7c478bd9Sstevel@tonic-gate #define TERMNAMESIZE 16 209*7c478bd9Sstevel@tonic-gate char tcname[TERMNAMESIZE]; /* name of similar terminal */ 210*7c478bd9Sstevel@tonic-gate char tcbuf[TBUFSIZE]; 211*7c478bd9Sstevel@tonic-gate char *holdtbuf = tbuf; 212*7c478bd9Sstevel@tonic-gate int l; 213*7c478bd9Sstevel@tonic-gate 214*7c478bd9Sstevel@tonic-gate p = tbuf + strlen(tbuf) - 2; /* before the last colon */ 215*7c478bd9Sstevel@tonic-gate while (*--p != ':') 216*7c478bd9Sstevel@tonic-gate if (p < tbuf) { 217*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "tnchktc(): TERM=%s: Bad " 218*7c478bd9Sstevel@tonic-gate "termcap entry\n", termname); 219*7c478bd9Sstevel@tonic-gate return (0); 220*7c478bd9Sstevel@tonic-gate } 221*7c478bd9Sstevel@tonic-gate p++; 222*7c478bd9Sstevel@tonic-gate /* p now points to beginning of last field */ 223*7c478bd9Sstevel@tonic-gate if (p[0] != 't' || p[1] != 'c') 224*7c478bd9Sstevel@tonic-gate return (1); 225*7c478bd9Sstevel@tonic-gate (void) strncpy(tcname, p + 3, TERMNAMESIZE); /* TLH */ 226*7c478bd9Sstevel@tonic-gate q = tcname; 227*7c478bd9Sstevel@tonic-gate while (*q && *q != ':') 228*7c478bd9Sstevel@tonic-gate q++; 229*7c478bd9Sstevel@tonic-gate *q = 0; 230*7c478bd9Sstevel@tonic-gate if (++hopcount > MAXHOP) { 231*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "tnchktc(): TERM=%s: Infinite tc= " 232*7c478bd9Sstevel@tonic-gate "loop\n", termname); 233*7c478bd9Sstevel@tonic-gate return (0); 234*7c478bd9Sstevel@tonic-gate } 235*7c478bd9Sstevel@tonic-gate if (_tgetent(tcbuf, tcname) != 1) 236*7c478bd9Sstevel@tonic-gate return (0); 237*7c478bd9Sstevel@tonic-gate /* Tony Hansen */ 238*7c478bd9Sstevel@tonic-gate TLHtcfound++; 239*7c478bd9Sstevel@tonic-gate (void) strcpy(TLHtcname, tcname); 240*7c478bd9Sstevel@tonic-gate 241*7c478bd9Sstevel@tonic-gate for (q = tcbuf; *q != ':'; q++) 242*7c478bd9Sstevel@tonic-gate ; 243*7c478bd9Sstevel@tonic-gate l = p - holdtbuf + strlen(q); 244*7c478bd9Sstevel@tonic-gate if (l > TBUFSIZE) { 245*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "tnchktc(): TERM=%s: Termcap entry " 246*7c478bd9Sstevel@tonic-gate "too long\n", termname); 247*7c478bd9Sstevel@tonic-gate q[TBUFSIZE - (p - holdtbuf)] = 0; 248*7c478bd9Sstevel@tonic-gate } 249*7c478bd9Sstevel@tonic-gate (void) strcpy(p, q + 1); 250*7c478bd9Sstevel@tonic-gate tbuf = holdtbuf; 251*7c478bd9Sstevel@tonic-gate return (1); 252*7c478bd9Sstevel@tonic-gate } 253*7c478bd9Sstevel@tonic-gate 254*7c478bd9Sstevel@tonic-gate /* 255*7c478bd9Sstevel@tonic-gate * Tnamatch deals with name matching. The first field of the termcap 256*7c478bd9Sstevel@tonic-gate * entry is a sequence of names separated by |'s, so we compare 257*7c478bd9Sstevel@tonic-gate * against each such name. The normal : terminator after the last 258*7c478bd9Sstevel@tonic-gate * name (before the first field) stops us. 259*7c478bd9Sstevel@tonic-gate */ 260*7c478bd9Sstevel@tonic-gate static int 261*7c478bd9Sstevel@tonic-gate otnamatch(char *np) 262*7c478bd9Sstevel@tonic-gate { 263*7c478bd9Sstevel@tonic-gate char *Np, *Bp; 264*7c478bd9Sstevel@tonic-gate 265*7c478bd9Sstevel@tonic-gate Bp = tbuf; 266*7c478bd9Sstevel@tonic-gate if (*Bp == '#') 267*7c478bd9Sstevel@tonic-gate return (0); 268*7c478bd9Sstevel@tonic-gate for (;;) { 269*7c478bd9Sstevel@tonic-gate for (Np = np; *Np && *Bp == *Np; Bp++, Np++) 270*7c478bd9Sstevel@tonic-gate continue; 271*7c478bd9Sstevel@tonic-gate if (*Np == 0 && (*Bp == '|' || *Bp == ':' || *Bp == 0)) 272*7c478bd9Sstevel@tonic-gate return (1); 273*7c478bd9Sstevel@tonic-gate while (*Bp && *Bp != ':' && *Bp != '|') 274*7c478bd9Sstevel@tonic-gate Bp++; 275*7c478bd9Sstevel@tonic-gate if (*Bp == 0 || *Bp == ':') 276*7c478bd9Sstevel@tonic-gate return (0); 277*7c478bd9Sstevel@tonic-gate Bp++; 278*7c478bd9Sstevel@tonic-gate } 279*7c478bd9Sstevel@tonic-gate } 280*7c478bd9Sstevel@tonic-gate 281*7c478bd9Sstevel@tonic-gate /* 282*7c478bd9Sstevel@tonic-gate * Skip to the next field. Notice that this is very dumb, not 283*7c478bd9Sstevel@tonic-gate * knowing about \: escapes or any such. If necessary, :'s can be put 284*7c478bd9Sstevel@tonic-gate * into the termcap file in octal. 285*7c478bd9Sstevel@tonic-gate */ 286*7c478bd9Sstevel@tonic-gate /* static - TLH removed */ char * 287*7c478bd9Sstevel@tonic-gate tskip(char *bp) 288*7c478bd9Sstevel@tonic-gate { 289*7c478bd9Sstevel@tonic-gate 290*7c478bd9Sstevel@tonic-gate while (*bp && *bp != ':') 291*7c478bd9Sstevel@tonic-gate bp++; 292*7c478bd9Sstevel@tonic-gate if (*bp == ':') 293*7c478bd9Sstevel@tonic-gate bp++; 294*7c478bd9Sstevel@tonic-gate return (bp); 295*7c478bd9Sstevel@tonic-gate } 296*7c478bd9Sstevel@tonic-gate 297*7c478bd9Sstevel@tonic-gate /* 298*7c478bd9Sstevel@tonic-gate * Return the (numeric) option id. 299*7c478bd9Sstevel@tonic-gate * Numeric options look like 300*7c478bd9Sstevel@tonic-gate * li#80 301*7c478bd9Sstevel@tonic-gate * i.e. the option string is separated from the numeric value by 302*7c478bd9Sstevel@tonic-gate * a # character. If the option is not found we return -1. 303*7c478bd9Sstevel@tonic-gate * Note that we handle octal numbers beginning with 0. 304*7c478bd9Sstevel@tonic-gate */ 305*7c478bd9Sstevel@tonic-gate otgetnum(char *id) 306*7c478bd9Sstevel@tonic-gate { 307*7c478bd9Sstevel@tonic-gate int i, base; 308*7c478bd9Sstevel@tonic-gate char *bp = tbuf; 309*7c478bd9Sstevel@tonic-gate 310*7c478bd9Sstevel@tonic-gate for (;;) { 311*7c478bd9Sstevel@tonic-gate bp = tskip(bp); 312*7c478bd9Sstevel@tonic-gate if (*bp == 0) 313*7c478bd9Sstevel@tonic-gate return (-1); 314*7c478bd9Sstevel@tonic-gate if (*bp++ != id[0] || *bp == 0 || *bp++ != id[1]) 315*7c478bd9Sstevel@tonic-gate continue; 316*7c478bd9Sstevel@tonic-gate if (*bp == '@') 317*7c478bd9Sstevel@tonic-gate return (-1); 318*7c478bd9Sstevel@tonic-gate if (*bp != '#') 319*7c478bd9Sstevel@tonic-gate continue; 320*7c478bd9Sstevel@tonic-gate bp++; 321*7c478bd9Sstevel@tonic-gate base = 10; 322*7c478bd9Sstevel@tonic-gate if (*bp == '0') 323*7c478bd9Sstevel@tonic-gate base = 8; 324*7c478bd9Sstevel@tonic-gate i = 0; 325*7c478bd9Sstevel@tonic-gate while (isdigit(*bp)) 326*7c478bd9Sstevel@tonic-gate i *= base, i += *bp++ - '0'; 327*7c478bd9Sstevel@tonic-gate return (i); 328*7c478bd9Sstevel@tonic-gate } 329*7c478bd9Sstevel@tonic-gate } 330*7c478bd9Sstevel@tonic-gate 331*7c478bd9Sstevel@tonic-gate /* 332*7c478bd9Sstevel@tonic-gate * Handle a flag option. 333*7c478bd9Sstevel@tonic-gate * Flag options are given "naked", i.e. followed by a : or the end 334*7c478bd9Sstevel@tonic-gate * of the buffer. Return 1 if we find the option, or 0 if it is 335*7c478bd9Sstevel@tonic-gate * not given. 336*7c478bd9Sstevel@tonic-gate */ 337*7c478bd9Sstevel@tonic-gate otgetflag(char *id) 338*7c478bd9Sstevel@tonic-gate { 339*7c478bd9Sstevel@tonic-gate char *bp = tbuf; 340*7c478bd9Sstevel@tonic-gate 341*7c478bd9Sstevel@tonic-gate for (;;) { 342*7c478bd9Sstevel@tonic-gate bp = tskip(bp); 343*7c478bd9Sstevel@tonic-gate if (!*bp) 344*7c478bd9Sstevel@tonic-gate return (0); 345*7c478bd9Sstevel@tonic-gate if (*bp++ == id[0] && *bp != 0 && *bp++ == id[1]) { 346*7c478bd9Sstevel@tonic-gate if (!*bp || *bp == ':') 347*7c478bd9Sstevel@tonic-gate return (1); 348*7c478bd9Sstevel@tonic-gate else if (*bp == '@') 349*7c478bd9Sstevel@tonic-gate return (0); 350*7c478bd9Sstevel@tonic-gate } 351*7c478bd9Sstevel@tonic-gate } 352*7c478bd9Sstevel@tonic-gate } 353*7c478bd9Sstevel@tonic-gate 354*7c478bd9Sstevel@tonic-gate /* 355*7c478bd9Sstevel@tonic-gate * Get a string valued option. 356*7c478bd9Sstevel@tonic-gate * These are given as 357*7c478bd9Sstevel@tonic-gate * cl=^Z 358*7c478bd9Sstevel@tonic-gate * Much decoding is done on the strings, and the strings are 359*7c478bd9Sstevel@tonic-gate * placed in area, which is a ref parameter which is updated. 360*7c478bd9Sstevel@tonic-gate * No checking on area overflow. 361*7c478bd9Sstevel@tonic-gate */ 362*7c478bd9Sstevel@tonic-gate char * 363*7c478bd9Sstevel@tonic-gate otgetstr(char *id, char **area) 364*7c478bd9Sstevel@tonic-gate { 365*7c478bd9Sstevel@tonic-gate char *bp = tbuf; 366*7c478bd9Sstevel@tonic-gate 367*7c478bd9Sstevel@tonic-gate for (; ; ) { 368*7c478bd9Sstevel@tonic-gate bp = tskip(bp); 369*7c478bd9Sstevel@tonic-gate if (!*bp) 370*7c478bd9Sstevel@tonic-gate return (0); 371*7c478bd9Sstevel@tonic-gate if (*bp++ != id[0] || *bp == 0 || *bp++ != id[1]) 372*7c478bd9Sstevel@tonic-gate continue; 373*7c478bd9Sstevel@tonic-gate if (*bp == '@') 374*7c478bd9Sstevel@tonic-gate return (0); 375*7c478bd9Sstevel@tonic-gate if (*bp != '=') 376*7c478bd9Sstevel@tonic-gate continue; 377*7c478bd9Sstevel@tonic-gate bp++; 378*7c478bd9Sstevel@tonic-gate return (tdecode(bp, area)); 379*7c478bd9Sstevel@tonic-gate } 380*7c478bd9Sstevel@tonic-gate } 381*7c478bd9Sstevel@tonic-gate 382*7c478bd9Sstevel@tonic-gate /* 383*7c478bd9Sstevel@tonic-gate * Tdecode does the grung work to decode the 384*7c478bd9Sstevel@tonic-gate * string capability escapes. 385*7c478bd9Sstevel@tonic-gate */ 386*7c478bd9Sstevel@tonic-gate static char * 387*7c478bd9Sstevel@tonic-gate tdecode(char *str, char **area) 388*7c478bd9Sstevel@tonic-gate { 389*7c478bd9Sstevel@tonic-gate char *cp; 390*7c478bd9Sstevel@tonic-gate int c; 391*7c478bd9Sstevel@tonic-gate char *dp; 392*7c478bd9Sstevel@tonic-gate int i; 393*7c478bd9Sstevel@tonic-gate 394*7c478bd9Sstevel@tonic-gate cp = *area; 395*7c478bd9Sstevel@tonic-gate while ((c = *str++) != '\0' && c != ':') { 396*7c478bd9Sstevel@tonic-gate switch (c) { 397*7c478bd9Sstevel@tonic-gate 398*7c478bd9Sstevel@tonic-gate case '^': 399*7c478bd9Sstevel@tonic-gate c = *str++ & 037; 400*7c478bd9Sstevel@tonic-gate break; 401*7c478bd9Sstevel@tonic-gate 402*7c478bd9Sstevel@tonic-gate case '\\': 403*7c478bd9Sstevel@tonic-gate dp = "E\033^^\\\\::n\nr\rt\tb\bf\f"; 404*7c478bd9Sstevel@tonic-gate c = *str++; 405*7c478bd9Sstevel@tonic-gate nextc: 406*7c478bd9Sstevel@tonic-gate if (*dp++ == c) { 407*7c478bd9Sstevel@tonic-gate c = *dp++; 408*7c478bd9Sstevel@tonic-gate break; 409*7c478bd9Sstevel@tonic-gate } 410*7c478bd9Sstevel@tonic-gate dp++; 411*7c478bd9Sstevel@tonic-gate if (*dp) 412*7c478bd9Sstevel@tonic-gate goto nextc; 413*7c478bd9Sstevel@tonic-gate if (isdigit(c)) { 414*7c478bd9Sstevel@tonic-gate c -= '0', i = 2; 415*7c478bd9Sstevel@tonic-gate do 416*7c478bd9Sstevel@tonic-gate c <<= 3, c |= *str++ - '0'; 417*7c478bd9Sstevel@tonic-gate while (--i && isdigit(*str)); 418*7c478bd9Sstevel@tonic-gate } 419*7c478bd9Sstevel@tonic-gate break; 420*7c478bd9Sstevel@tonic-gate } 421*7c478bd9Sstevel@tonic-gate *cp++ = c; 422*7c478bd9Sstevel@tonic-gate } 423*7c478bd9Sstevel@tonic-gate *cp++ = 0; 424*7c478bd9Sstevel@tonic-gate str = *area; 425*7c478bd9Sstevel@tonic-gate *area = cp; 426*7c478bd9Sstevel@tonic-gate return (str); 427*7c478bd9Sstevel@tonic-gate } 428