17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 57c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 67c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 77c478bd9Sstevel@tonic-gate * with the License. 87c478bd9Sstevel@tonic-gate * 97c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 107c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 117c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 127c478bd9Sstevel@tonic-gate * and limitations under the License. 137c478bd9Sstevel@tonic-gate * 147c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 157c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 167c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 177c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 187c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 197c478bd9Sstevel@tonic-gate * 207c478bd9Sstevel@tonic-gate * CDDL HEADER END 217c478bd9Sstevel@tonic-gate */ 227c478bd9Sstevel@tonic-gate /* 237c478bd9Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 247c478bd9Sstevel@tonic-gate * Use is subject to license terms. 257c478bd9Sstevel@tonic-gate */ 267c478bd9Sstevel@tonic-gate 27*b5514887Smuffin /* Copyright (c) 1988 AT&T */ 28*b5514887Smuffin /* All Rights Reserved */ 29*b5514887Smuffin 307c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 317c478bd9Sstevel@tonic-gate 327c478bd9Sstevel@tonic-gate /* Copyright (c) 1979 Regents of the University of California */ 337c478bd9Sstevel@tonic-gate /* Modified to: */ 347c478bd9Sstevel@tonic-gate /* 1) remember the name of the first tc= parameter */ 357c478bd9Sstevel@tonic-gate /* encountered during parsing. */ 367c478bd9Sstevel@tonic-gate /* 2) handle multiple invocations of tgetent(). */ 377c478bd9Sstevel@tonic-gate /* 3) tskip() is now available outside of the library. */ 387c478bd9Sstevel@tonic-gate /* 4) remember $TERM name for error messages. */ 397c478bd9Sstevel@tonic-gate /* 5) have a larger buffer. */ 407c478bd9Sstevel@tonic-gate /* 6) really fix the bug that 5) got around. This fix by */ 417c478bd9Sstevel@tonic-gate /* Marion Hakanson, orstcs!hakanson */ 427c478bd9Sstevel@tonic-gate 437c478bd9Sstevel@tonic-gate 447c478bd9Sstevel@tonic-gate #include "otermcap.h" 457c478bd9Sstevel@tonic-gate #define MAXHOP 32 /* max number of tc= indirections */ 467c478bd9Sstevel@tonic-gate 477c478bd9Sstevel@tonic-gate #include <sys/types.h> 487c478bd9Sstevel@tonic-gate #include <sys/stat.h> 497c478bd9Sstevel@tonic-gate #include <fcntl.h> 507c478bd9Sstevel@tonic-gate #include <sys/uio.h> 517c478bd9Sstevel@tonic-gate #include <unistd.h> 527c478bd9Sstevel@tonic-gate #include <stdio.h> 537c478bd9Sstevel@tonic-gate #include <stdlib.h> 547c478bd9Sstevel@tonic-gate #include <string.h> 557c478bd9Sstevel@tonic-gate #include <ctype.h> 567c478bd9Sstevel@tonic-gate 577c478bd9Sstevel@tonic-gate #include <signal.h> /* use this file to determine if this is SVR4.0 system */ 587c478bd9Sstevel@tonic-gate #ifdef SIGSTOP /* SVR4.0 and beyond */ 597c478bd9Sstevel@tonic-gate #define E_TERMCAP "/usr/share/lib/termcap" 607c478bd9Sstevel@tonic-gate #else 617c478bd9Sstevel@tonic-gate #define E_TERMCAP "/etc/termcap" 627c478bd9Sstevel@tonic-gate #endif 637c478bd9Sstevel@tonic-gate 647c478bd9Sstevel@tonic-gate /* 657c478bd9Sstevel@tonic-gate * termcap - routines for dealing with the terminal capability data base 667c478bd9Sstevel@tonic-gate * 677c478bd9Sstevel@tonic-gate * BUG: Should use a "last" pointer in tbuf, so that searching 687c478bd9Sstevel@tonic-gate * for capabilities alphabetically would not be a n**2/2 697c478bd9Sstevel@tonic-gate * process when large numbers of capabilities are given. 707c478bd9Sstevel@tonic-gate * Note: If we add a last pointer now we will screw up the 717c478bd9Sstevel@tonic-gate * tc capability. We really should compile termcap. 727c478bd9Sstevel@tonic-gate * 737c478bd9Sstevel@tonic-gate * Essentially all the work here is scanning and decoding escapes 747c478bd9Sstevel@tonic-gate * in string capabilities. We don't use stdio because the editor 757c478bd9Sstevel@tonic-gate * doesn't, and because living w/o it is not hard. 767c478bd9Sstevel@tonic-gate */ 777c478bd9Sstevel@tonic-gate 787c478bd9Sstevel@tonic-gate static char *tbuf; 797c478bd9Sstevel@tonic-gate static int hopcount; /* detect infinite loops in termcap, init 0 */ 80*b5514887Smuffin char *tskip(char *); 81*b5514887Smuffin char *otgetstr(char *, char **); 827c478bd9Sstevel@tonic-gate 837c478bd9Sstevel@tonic-gate /* Tony Hansen */ 847c478bd9Sstevel@tonic-gate int TLHtcfound = 0; 857c478bd9Sstevel@tonic-gate char TLHtcname[16]; 867c478bd9Sstevel@tonic-gate static char *termname; 877c478bd9Sstevel@tonic-gate 887c478bd9Sstevel@tonic-gate static int _tgetent(char *, char *); 89*b5514887Smuffin static int otnchktc(void); 907c478bd9Sstevel@tonic-gate static char *tdecode(char *, char **); 917c478bd9Sstevel@tonic-gate static int otnamatch(char *); 927c478bd9Sstevel@tonic-gate /* 937c478bd9Sstevel@tonic-gate * Get an entry for terminal name in buffer bp, 947c478bd9Sstevel@tonic-gate * from the termcap file. Parse is very rudimentary; 957c478bd9Sstevel@tonic-gate * we just notice escaped newlines. 967c478bd9Sstevel@tonic-gate */ 97*b5514887Smuffin int 987c478bd9Sstevel@tonic-gate otgetent(char *bp, char *name) 997c478bd9Sstevel@tonic-gate { 1007c478bd9Sstevel@tonic-gate /* Tony Hansen */ 1017c478bd9Sstevel@tonic-gate int ret; 1027c478bd9Sstevel@tonic-gate TLHtcfound = 0; 1037c478bd9Sstevel@tonic-gate hopcount = 0; 1047c478bd9Sstevel@tonic-gate termname = name; 1057c478bd9Sstevel@tonic-gate ret = _tgetent(bp, name); 1067c478bd9Sstevel@tonic-gate /* 1077c478bd9Sstevel@tonic-gate * There is some sort of bug in the check way down below to prevent 1087c478bd9Sstevel@tonic-gate * buffer overflow. I really don't want to track it down, so I 1097c478bd9Sstevel@tonic-gate * upped the standard buffer size and check here to see if the created 1107c478bd9Sstevel@tonic-gate * buffer is larger than the old buffer size. 1117c478bd9Sstevel@tonic-gate */ 1127c478bd9Sstevel@tonic-gate if (strlen(bp) >= 1024) 1137c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 1147c478bd9Sstevel@tonic-gate "tgetent(): TERM=%s: Termcap entry is too long.\n", 1157c478bd9Sstevel@tonic-gate termname); 1167c478bd9Sstevel@tonic-gate return (ret); 1177c478bd9Sstevel@tonic-gate } 1187c478bd9Sstevel@tonic-gate 1197c478bd9Sstevel@tonic-gate static int 1207c478bd9Sstevel@tonic-gate _tgetent(char *bp, char *name) 1217c478bd9Sstevel@tonic-gate { 1227c478bd9Sstevel@tonic-gate char *cp; 1237c478bd9Sstevel@tonic-gate int c; 1247c478bd9Sstevel@tonic-gate int i = 0, cnt = 0; 1257c478bd9Sstevel@tonic-gate char ibuf[TBUFSIZE]; 1267c478bd9Sstevel@tonic-gate char *cp2; 1277c478bd9Sstevel@tonic-gate int tf; 1287c478bd9Sstevel@tonic-gate 1297c478bd9Sstevel@tonic-gate tbuf = bp; 1307c478bd9Sstevel@tonic-gate tf = 0; 1317c478bd9Sstevel@tonic-gate #ifndef V6 1327c478bd9Sstevel@tonic-gate cp = getenv("TERMCAP"); 1337c478bd9Sstevel@tonic-gate /* 1347c478bd9Sstevel@tonic-gate * TERMCAP can have one of two things in it. It can be the 1357c478bd9Sstevel@tonic-gate * name of a file to use instead of /etc/termcap. In this 1367c478bd9Sstevel@tonic-gate * case it better start with a "/". Or it can be an entry to 1377c478bd9Sstevel@tonic-gate * use so we don't have to read the file. In this case it 1387c478bd9Sstevel@tonic-gate * has to already have the newlines crunched out. 1397c478bd9Sstevel@tonic-gate */ 1407c478bd9Sstevel@tonic-gate if (cp && *cp) { 1417c478bd9Sstevel@tonic-gate if (*cp != '/') { 1427c478bd9Sstevel@tonic-gate cp2 = getenv("TERM"); 1437c478bd9Sstevel@tonic-gate if (cp2 == (char *)0 || strcmp(name, cp2) == 0) { 1447c478bd9Sstevel@tonic-gate (void) strcpy(bp, cp); 1457c478bd9Sstevel@tonic-gate return (otnchktc()); 1467c478bd9Sstevel@tonic-gate } else { 1477c478bd9Sstevel@tonic-gate tf = open(E_TERMCAP, 0); 1487c478bd9Sstevel@tonic-gate } 1497c478bd9Sstevel@tonic-gate } else 1507c478bd9Sstevel@tonic-gate tf = open(cp, 0); 1517c478bd9Sstevel@tonic-gate } 1527c478bd9Sstevel@tonic-gate if (tf == 0) 1537c478bd9Sstevel@tonic-gate tf = open(E_TERMCAP, 0); 1547c478bd9Sstevel@tonic-gate #else 1557c478bd9Sstevel@tonic-gate tf = open(E_TERMCAP, 0); 1567c478bd9Sstevel@tonic-gate #endif 1577c478bd9Sstevel@tonic-gate if (tf < 0) 1587c478bd9Sstevel@tonic-gate return (-1); 1597c478bd9Sstevel@tonic-gate for (; ; ) { 1607c478bd9Sstevel@tonic-gate cp = bp; 1617c478bd9Sstevel@tonic-gate for (; ; ) { 1627c478bd9Sstevel@tonic-gate if (i == cnt) { 1637c478bd9Sstevel@tonic-gate cnt = read(tf, ibuf, TBUFSIZE); 1647c478bd9Sstevel@tonic-gate if (cnt <= 0) { 1657c478bd9Sstevel@tonic-gate (void) close(tf); 1667c478bd9Sstevel@tonic-gate return (0); 1677c478bd9Sstevel@tonic-gate } 1687c478bd9Sstevel@tonic-gate i = 0; 1697c478bd9Sstevel@tonic-gate } 1707c478bd9Sstevel@tonic-gate c = ibuf[i++]; 1717c478bd9Sstevel@tonic-gate if (c == '\n') { 1727c478bd9Sstevel@tonic-gate if (cp > bp && cp[-1] == '\\') { 1737c478bd9Sstevel@tonic-gate cp--; 1747c478bd9Sstevel@tonic-gate continue; 1757c478bd9Sstevel@tonic-gate } 1767c478bd9Sstevel@tonic-gate break; 1777c478bd9Sstevel@tonic-gate } 1787c478bd9Sstevel@tonic-gate if (cp >= bp + TBUFSIZE) { 1797c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "tgetent(): TERM=%s: " 1807c478bd9Sstevel@tonic-gate "Termcap entry too long\n", termname); 1817c478bd9Sstevel@tonic-gate break; 1827c478bd9Sstevel@tonic-gate } else 1837c478bd9Sstevel@tonic-gate *cp++ = c; 1847c478bd9Sstevel@tonic-gate } 1857c478bd9Sstevel@tonic-gate *cp = 0; 1867c478bd9Sstevel@tonic-gate 1877c478bd9Sstevel@tonic-gate /* 1887c478bd9Sstevel@tonic-gate * The real work for the match. 1897c478bd9Sstevel@tonic-gate */ 1907c478bd9Sstevel@tonic-gate if (otnamatch(name)) { 1917c478bd9Sstevel@tonic-gate (void) close(tf); 1927c478bd9Sstevel@tonic-gate return (otnchktc()); 1937c478bd9Sstevel@tonic-gate } 1947c478bd9Sstevel@tonic-gate } 1957c478bd9Sstevel@tonic-gate } 1967c478bd9Sstevel@tonic-gate 1977c478bd9Sstevel@tonic-gate /* 1987c478bd9Sstevel@tonic-gate * otnchktc: check the last entry, see if it's tc=xxx. If so, 1997c478bd9Sstevel@tonic-gate * recursively find xxx and append that entry (minus the names) 2007c478bd9Sstevel@tonic-gate * to take the place of the tc=xxx entry. This allows termcap 2017c478bd9Sstevel@tonic-gate * entries to say "like an HP2621 but doesn't turn on the labels". 2027c478bd9Sstevel@tonic-gate * Note that this works because of the left to right scan. 2037c478bd9Sstevel@tonic-gate */ 2047c478bd9Sstevel@tonic-gate static int 205*b5514887Smuffin otnchktc(void) 2067c478bd9Sstevel@tonic-gate { 2077c478bd9Sstevel@tonic-gate char *p, *q; 2087c478bd9Sstevel@tonic-gate #define TERMNAMESIZE 16 2097c478bd9Sstevel@tonic-gate char tcname[TERMNAMESIZE]; /* name of similar terminal */ 2107c478bd9Sstevel@tonic-gate char tcbuf[TBUFSIZE]; 2117c478bd9Sstevel@tonic-gate char *holdtbuf = tbuf; 2127c478bd9Sstevel@tonic-gate int l; 2137c478bd9Sstevel@tonic-gate 2147c478bd9Sstevel@tonic-gate p = tbuf + strlen(tbuf) - 2; /* before the last colon */ 2157c478bd9Sstevel@tonic-gate while (*--p != ':') 2167c478bd9Sstevel@tonic-gate if (p < tbuf) { 2177c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "tnchktc(): TERM=%s: Bad " 2187c478bd9Sstevel@tonic-gate "termcap entry\n", termname); 2197c478bd9Sstevel@tonic-gate return (0); 2207c478bd9Sstevel@tonic-gate } 2217c478bd9Sstevel@tonic-gate p++; 2227c478bd9Sstevel@tonic-gate /* p now points to beginning of last field */ 2237c478bd9Sstevel@tonic-gate if (p[0] != 't' || p[1] != 'c') 2247c478bd9Sstevel@tonic-gate return (1); 2257c478bd9Sstevel@tonic-gate (void) strncpy(tcname, p + 3, TERMNAMESIZE); /* TLH */ 2267c478bd9Sstevel@tonic-gate q = tcname; 2277c478bd9Sstevel@tonic-gate while (*q && *q != ':') 2287c478bd9Sstevel@tonic-gate q++; 2297c478bd9Sstevel@tonic-gate *q = 0; 2307c478bd9Sstevel@tonic-gate if (++hopcount > MAXHOP) { 2317c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "tnchktc(): TERM=%s: Infinite tc= " 2327c478bd9Sstevel@tonic-gate "loop\n", termname); 2337c478bd9Sstevel@tonic-gate return (0); 2347c478bd9Sstevel@tonic-gate } 2357c478bd9Sstevel@tonic-gate if (_tgetent(tcbuf, tcname) != 1) 2367c478bd9Sstevel@tonic-gate return (0); 2377c478bd9Sstevel@tonic-gate /* Tony Hansen */ 2387c478bd9Sstevel@tonic-gate TLHtcfound++; 2397c478bd9Sstevel@tonic-gate (void) strcpy(TLHtcname, tcname); 2407c478bd9Sstevel@tonic-gate 2417c478bd9Sstevel@tonic-gate for (q = tcbuf; *q != ':'; q++) 2427c478bd9Sstevel@tonic-gate ; 2437c478bd9Sstevel@tonic-gate l = p - holdtbuf + strlen(q); 2447c478bd9Sstevel@tonic-gate if (l > TBUFSIZE) { 2457c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "tnchktc(): TERM=%s: Termcap entry " 2467c478bd9Sstevel@tonic-gate "too long\n", termname); 2477c478bd9Sstevel@tonic-gate q[TBUFSIZE - (p - holdtbuf)] = 0; 2487c478bd9Sstevel@tonic-gate } 2497c478bd9Sstevel@tonic-gate (void) strcpy(p, q + 1); 2507c478bd9Sstevel@tonic-gate tbuf = holdtbuf; 2517c478bd9Sstevel@tonic-gate return (1); 2527c478bd9Sstevel@tonic-gate } 2537c478bd9Sstevel@tonic-gate 2547c478bd9Sstevel@tonic-gate /* 2557c478bd9Sstevel@tonic-gate * Tnamatch deals with name matching. The first field of the termcap 2567c478bd9Sstevel@tonic-gate * entry is a sequence of names separated by |'s, so we compare 2577c478bd9Sstevel@tonic-gate * against each such name. The normal : terminator after the last 2587c478bd9Sstevel@tonic-gate * name (before the first field) stops us. 2597c478bd9Sstevel@tonic-gate */ 2607c478bd9Sstevel@tonic-gate static int 2617c478bd9Sstevel@tonic-gate otnamatch(char *np) 2627c478bd9Sstevel@tonic-gate { 2637c478bd9Sstevel@tonic-gate char *Np, *Bp; 2647c478bd9Sstevel@tonic-gate 2657c478bd9Sstevel@tonic-gate Bp = tbuf; 2667c478bd9Sstevel@tonic-gate if (*Bp == '#') 2677c478bd9Sstevel@tonic-gate return (0); 2687c478bd9Sstevel@tonic-gate for (;;) { 2697c478bd9Sstevel@tonic-gate for (Np = np; *Np && *Bp == *Np; Bp++, Np++) 2707c478bd9Sstevel@tonic-gate continue; 2717c478bd9Sstevel@tonic-gate if (*Np == 0 && (*Bp == '|' || *Bp == ':' || *Bp == 0)) 2727c478bd9Sstevel@tonic-gate return (1); 2737c478bd9Sstevel@tonic-gate while (*Bp && *Bp != ':' && *Bp != '|') 2747c478bd9Sstevel@tonic-gate Bp++; 2757c478bd9Sstevel@tonic-gate if (*Bp == 0 || *Bp == ':') 2767c478bd9Sstevel@tonic-gate return (0); 2777c478bd9Sstevel@tonic-gate Bp++; 2787c478bd9Sstevel@tonic-gate } 2797c478bd9Sstevel@tonic-gate } 2807c478bd9Sstevel@tonic-gate 2817c478bd9Sstevel@tonic-gate /* 2827c478bd9Sstevel@tonic-gate * Skip to the next field. Notice that this is very dumb, not 2837c478bd9Sstevel@tonic-gate * knowing about \: escapes or any such. If necessary, :'s can be put 2847c478bd9Sstevel@tonic-gate * into the termcap file in octal. 2857c478bd9Sstevel@tonic-gate */ 286*b5514887Smuffin char * 2877c478bd9Sstevel@tonic-gate tskip(char *bp) 2887c478bd9Sstevel@tonic-gate { 2897c478bd9Sstevel@tonic-gate 2907c478bd9Sstevel@tonic-gate while (*bp && *bp != ':') 2917c478bd9Sstevel@tonic-gate bp++; 2927c478bd9Sstevel@tonic-gate if (*bp == ':') 2937c478bd9Sstevel@tonic-gate bp++; 2947c478bd9Sstevel@tonic-gate return (bp); 2957c478bd9Sstevel@tonic-gate } 2967c478bd9Sstevel@tonic-gate 2977c478bd9Sstevel@tonic-gate /* 2987c478bd9Sstevel@tonic-gate * Return the (numeric) option id. 2997c478bd9Sstevel@tonic-gate * Numeric options look like 3007c478bd9Sstevel@tonic-gate * li#80 3017c478bd9Sstevel@tonic-gate * i.e. the option string is separated from the numeric value by 3027c478bd9Sstevel@tonic-gate * a # character. If the option is not found we return -1. 3037c478bd9Sstevel@tonic-gate * Note that we handle octal numbers beginning with 0. 3047c478bd9Sstevel@tonic-gate */ 305*b5514887Smuffin int 3067c478bd9Sstevel@tonic-gate otgetnum(char *id) 3077c478bd9Sstevel@tonic-gate { 3087c478bd9Sstevel@tonic-gate int i, base; 3097c478bd9Sstevel@tonic-gate char *bp = tbuf; 3107c478bd9Sstevel@tonic-gate 3117c478bd9Sstevel@tonic-gate for (;;) { 3127c478bd9Sstevel@tonic-gate bp = tskip(bp); 3137c478bd9Sstevel@tonic-gate if (*bp == 0) 3147c478bd9Sstevel@tonic-gate return (-1); 3157c478bd9Sstevel@tonic-gate if (*bp++ != id[0] || *bp == 0 || *bp++ != id[1]) 3167c478bd9Sstevel@tonic-gate continue; 3177c478bd9Sstevel@tonic-gate if (*bp == '@') 3187c478bd9Sstevel@tonic-gate return (-1); 3197c478bd9Sstevel@tonic-gate if (*bp != '#') 3207c478bd9Sstevel@tonic-gate continue; 3217c478bd9Sstevel@tonic-gate bp++; 3227c478bd9Sstevel@tonic-gate base = 10; 3237c478bd9Sstevel@tonic-gate if (*bp == '0') 3247c478bd9Sstevel@tonic-gate base = 8; 3257c478bd9Sstevel@tonic-gate i = 0; 3267c478bd9Sstevel@tonic-gate while (isdigit(*bp)) 3277c478bd9Sstevel@tonic-gate i *= base, i += *bp++ - '0'; 3287c478bd9Sstevel@tonic-gate return (i); 3297c478bd9Sstevel@tonic-gate } 3307c478bd9Sstevel@tonic-gate } 3317c478bd9Sstevel@tonic-gate 3327c478bd9Sstevel@tonic-gate /* 3337c478bd9Sstevel@tonic-gate * Handle a flag option. 3347c478bd9Sstevel@tonic-gate * Flag options are given "naked", i.e. followed by a : or the end 3357c478bd9Sstevel@tonic-gate * of the buffer. Return 1 if we find the option, or 0 if it is 3367c478bd9Sstevel@tonic-gate * not given. 3377c478bd9Sstevel@tonic-gate */ 338*b5514887Smuffin int 3397c478bd9Sstevel@tonic-gate otgetflag(char *id) 3407c478bd9Sstevel@tonic-gate { 3417c478bd9Sstevel@tonic-gate char *bp = tbuf; 3427c478bd9Sstevel@tonic-gate 3437c478bd9Sstevel@tonic-gate for (;;) { 3447c478bd9Sstevel@tonic-gate bp = tskip(bp); 3457c478bd9Sstevel@tonic-gate if (!*bp) 3467c478bd9Sstevel@tonic-gate return (0); 3477c478bd9Sstevel@tonic-gate if (*bp++ == id[0] && *bp != 0 && *bp++ == id[1]) { 3487c478bd9Sstevel@tonic-gate if (!*bp || *bp == ':') 3497c478bd9Sstevel@tonic-gate return (1); 3507c478bd9Sstevel@tonic-gate else if (*bp == '@') 3517c478bd9Sstevel@tonic-gate return (0); 3527c478bd9Sstevel@tonic-gate } 3537c478bd9Sstevel@tonic-gate } 3547c478bd9Sstevel@tonic-gate } 3557c478bd9Sstevel@tonic-gate 3567c478bd9Sstevel@tonic-gate /* 3577c478bd9Sstevel@tonic-gate * Get a string valued option. 3587c478bd9Sstevel@tonic-gate * These are given as 3597c478bd9Sstevel@tonic-gate * cl=^Z 3607c478bd9Sstevel@tonic-gate * Much decoding is done on the strings, and the strings are 3617c478bd9Sstevel@tonic-gate * placed in area, which is a ref parameter which is updated. 3627c478bd9Sstevel@tonic-gate * No checking on area overflow. 3637c478bd9Sstevel@tonic-gate */ 3647c478bd9Sstevel@tonic-gate char * 3657c478bd9Sstevel@tonic-gate otgetstr(char *id, char **area) 3667c478bd9Sstevel@tonic-gate { 3677c478bd9Sstevel@tonic-gate char *bp = tbuf; 3687c478bd9Sstevel@tonic-gate 3697c478bd9Sstevel@tonic-gate for (; ; ) { 3707c478bd9Sstevel@tonic-gate bp = tskip(bp); 3717c478bd9Sstevel@tonic-gate if (!*bp) 3727c478bd9Sstevel@tonic-gate return (0); 3737c478bd9Sstevel@tonic-gate if (*bp++ != id[0] || *bp == 0 || *bp++ != id[1]) 3747c478bd9Sstevel@tonic-gate continue; 3757c478bd9Sstevel@tonic-gate if (*bp == '@') 3767c478bd9Sstevel@tonic-gate return (0); 3777c478bd9Sstevel@tonic-gate if (*bp != '=') 3787c478bd9Sstevel@tonic-gate continue; 3797c478bd9Sstevel@tonic-gate bp++; 3807c478bd9Sstevel@tonic-gate return (tdecode(bp, area)); 3817c478bd9Sstevel@tonic-gate } 3827c478bd9Sstevel@tonic-gate } 3837c478bd9Sstevel@tonic-gate 3847c478bd9Sstevel@tonic-gate /* 3857c478bd9Sstevel@tonic-gate * Tdecode does the grung work to decode the 3867c478bd9Sstevel@tonic-gate * string capability escapes. 3877c478bd9Sstevel@tonic-gate */ 3887c478bd9Sstevel@tonic-gate static char * 3897c478bd9Sstevel@tonic-gate tdecode(char *str, char **area) 3907c478bd9Sstevel@tonic-gate { 3917c478bd9Sstevel@tonic-gate char *cp; 3927c478bd9Sstevel@tonic-gate int c; 3937c478bd9Sstevel@tonic-gate char *dp; 3947c478bd9Sstevel@tonic-gate int i; 3957c478bd9Sstevel@tonic-gate 3967c478bd9Sstevel@tonic-gate cp = *area; 3977c478bd9Sstevel@tonic-gate while ((c = *str++) != '\0' && c != ':') { 3987c478bd9Sstevel@tonic-gate switch (c) { 3997c478bd9Sstevel@tonic-gate 4007c478bd9Sstevel@tonic-gate case '^': 4017c478bd9Sstevel@tonic-gate c = *str++ & 037; 4027c478bd9Sstevel@tonic-gate break; 4037c478bd9Sstevel@tonic-gate 4047c478bd9Sstevel@tonic-gate case '\\': 4057c478bd9Sstevel@tonic-gate dp = "E\033^^\\\\::n\nr\rt\tb\bf\f"; 4067c478bd9Sstevel@tonic-gate c = *str++; 4077c478bd9Sstevel@tonic-gate nextc: 4087c478bd9Sstevel@tonic-gate if (*dp++ == c) { 4097c478bd9Sstevel@tonic-gate c = *dp++; 4107c478bd9Sstevel@tonic-gate break; 4117c478bd9Sstevel@tonic-gate } 4127c478bd9Sstevel@tonic-gate dp++; 4137c478bd9Sstevel@tonic-gate if (*dp) 4147c478bd9Sstevel@tonic-gate goto nextc; 4157c478bd9Sstevel@tonic-gate if (isdigit(c)) { 4167c478bd9Sstevel@tonic-gate c -= '0', i = 2; 4177c478bd9Sstevel@tonic-gate do 4187c478bd9Sstevel@tonic-gate c <<= 3, c |= *str++ - '0'; 419*b5514887Smuffin while (--i && isdigit(*str)) 420*b5514887Smuffin ; 4217c478bd9Sstevel@tonic-gate } 4227c478bd9Sstevel@tonic-gate break; 4237c478bd9Sstevel@tonic-gate } 4247c478bd9Sstevel@tonic-gate *cp++ = c; 4257c478bd9Sstevel@tonic-gate } 4267c478bd9Sstevel@tonic-gate *cp++ = 0; 4277c478bd9Sstevel@tonic-gate str = *area; 4287c478bd9Sstevel@tonic-gate *area = cp; 4297c478bd9Sstevel@tonic-gate return (str); 4307c478bd9Sstevel@tonic-gate } 431