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