1*8f957290SDavid van Moolenbroek /* $NetBSD: advcap.c,v 1.15 2015/06/05 15:41:59 roy Exp $ */
2*8f957290SDavid van Moolenbroek /* $KAME: advcap.c,v 1.11 2003/05/19 09:46:50 keiichi Exp $ */
3*8f957290SDavid van Moolenbroek
4*8f957290SDavid van Moolenbroek /*
5*8f957290SDavid van Moolenbroek * Copyright (c) 1983 The Regents of the University of California.
6*8f957290SDavid van Moolenbroek * All rights reserved.
7*8f957290SDavid van Moolenbroek *
8*8f957290SDavid van Moolenbroek * Redistribution and use in source and binary forms, with or without
9*8f957290SDavid van Moolenbroek * modification, are permitted provided that the following conditions
10*8f957290SDavid van Moolenbroek * are met:
11*8f957290SDavid van Moolenbroek * 1. Redistributions of source code must retain the above copyright
12*8f957290SDavid van Moolenbroek * notice, this list of conditions and the following disclaimer.
13*8f957290SDavid van Moolenbroek * 2. Redistributions in binary form must reproduce the above copyright
14*8f957290SDavid van Moolenbroek * notice, this list of conditions and the following disclaimer in the
15*8f957290SDavid van Moolenbroek * documentation and/or other materials provided with the distribution.
16*8f957290SDavid van Moolenbroek * 3. Neither the name of the University nor the names of its contributors
17*8f957290SDavid van Moolenbroek * may be used to endorse or promote products derived from this software
18*8f957290SDavid van Moolenbroek * without specific prior written permission.
19*8f957290SDavid van Moolenbroek *
20*8f957290SDavid van Moolenbroek * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21*8f957290SDavid van Moolenbroek * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22*8f957290SDavid van Moolenbroek * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23*8f957290SDavid van Moolenbroek * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24*8f957290SDavid van Moolenbroek * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25*8f957290SDavid van Moolenbroek * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26*8f957290SDavid van Moolenbroek * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27*8f957290SDavid van Moolenbroek * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28*8f957290SDavid van Moolenbroek * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29*8f957290SDavid van Moolenbroek * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30*8f957290SDavid van Moolenbroek * SUCH DAMAGE.
31*8f957290SDavid van Moolenbroek */
32*8f957290SDavid van Moolenbroek
33*8f957290SDavid van Moolenbroek /*
34*8f957290SDavid van Moolenbroek * remcap - routines for dealing with the remote host data base
35*8f957290SDavid van Moolenbroek *
36*8f957290SDavid van Moolenbroek * derived from termcap
37*8f957290SDavid van Moolenbroek */
38*8f957290SDavid van Moolenbroek #include <sys/types.h>
39*8f957290SDavid van Moolenbroek #include <sys/uio.h>
40*8f957290SDavid van Moolenbroek #include <unistd.h>
41*8f957290SDavid van Moolenbroek #include <fcntl.h>
42*8f957290SDavid van Moolenbroek #include <ctype.h>
43*8f957290SDavid van Moolenbroek #include <stdlib.h>
44*8f957290SDavid van Moolenbroek #include <stdio.h>
45*8f957290SDavid van Moolenbroek #include <syslog.h>
46*8f957290SDavid van Moolenbroek #include <errno.h>
47*8f957290SDavid van Moolenbroek #include <string.h>
48*8f957290SDavid van Moolenbroek #include "pathnames.h"
49*8f957290SDavid van Moolenbroek
50*8f957290SDavid van Moolenbroek #ifndef __UNCONST
51*8f957290SDavid van Moolenbroek #define __UNCONST(a) ((void *)(unsigned long)(const void *)(a))
52*8f957290SDavid van Moolenbroek #endif
53*8f957290SDavid van Moolenbroek
54*8f957290SDavid van Moolenbroek #ifndef BUFSIZ
55*8f957290SDavid van Moolenbroek #define BUFSIZ 1024
56*8f957290SDavid van Moolenbroek #endif
57*8f957290SDavid van Moolenbroek #define MAXHOP 32 /* max number of tc= indirections */
58*8f957290SDavid van Moolenbroek
59*8f957290SDavid van Moolenbroek #define tgetent agetent
60*8f957290SDavid van Moolenbroek #define tnchktc anchktc
61*8f957290SDavid van Moolenbroek #define tnamatch anamatch
62*8f957290SDavid van Moolenbroek #define tgetnum agetnum
63*8f957290SDavid van Moolenbroek #define tgetflag agetflag
64*8f957290SDavid van Moolenbroek #define tgetstr agetstr
65*8f957290SDavid van Moolenbroek
66*8f957290SDavid van Moolenbroek #if 0
67*8f957290SDavid van Moolenbroek #define V_TERMCAP "REMOTE"
68*8f957290SDavid van Moolenbroek #define V_TERM "HOST"
69*8f957290SDavid van Moolenbroek #endif
70*8f957290SDavid van Moolenbroek
71*8f957290SDavid van Moolenbroek char *RM;
72*8f957290SDavid van Moolenbroek
73*8f957290SDavid van Moolenbroek /*
74*8f957290SDavid van Moolenbroek * termcap - routines for dealing with the terminal capability data base
75*8f957290SDavid van Moolenbroek *
76*8f957290SDavid van Moolenbroek * BUG: Should use a "last" pointer in tbuf, so that searching
77*8f957290SDavid van Moolenbroek * for capabilities alphabetically would not be a n**2/2
78*8f957290SDavid van Moolenbroek * process when large numbers of capabilities are given.
79*8f957290SDavid van Moolenbroek * Note: If we add a last pointer now we will screw up the
80*8f957290SDavid van Moolenbroek * tc capability. We really should compile termcap.
81*8f957290SDavid van Moolenbroek *
82*8f957290SDavid van Moolenbroek * Essentially all the work here is scanning and decoding escapes
83*8f957290SDavid van Moolenbroek * in string capabilities. We don't use stdio because the editor
84*8f957290SDavid van Moolenbroek * doesn't, and because living w/o it is not hard.
85*8f957290SDavid van Moolenbroek */
86*8f957290SDavid van Moolenbroek
87*8f957290SDavid van Moolenbroek static char *tbuf;
88*8f957290SDavid van Moolenbroek static int hopcount; /* detect infinite loops in termcap, init 0 */
89*8f957290SDavid van Moolenbroek
90*8f957290SDavid van Moolenbroek static char *remotefile;
91*8f957290SDavid van Moolenbroek
92*8f957290SDavid van Moolenbroek extern char *conffile;
93*8f957290SDavid van Moolenbroek
94*8f957290SDavid van Moolenbroek int tgetent(char *, char *);
95*8f957290SDavid van Moolenbroek int getent(char *, char *, char *);
96*8f957290SDavid van Moolenbroek int tnchktc(void);
97*8f957290SDavid van Moolenbroek int tnamatch(char *);
98*8f957290SDavid van Moolenbroek static char *tskip(char *);
99*8f957290SDavid van Moolenbroek int64_t tgetnum(char *);
100*8f957290SDavid van Moolenbroek int tgetflag(char *);
101*8f957290SDavid van Moolenbroek char *tgetstr(char *, char **);
102*8f957290SDavid van Moolenbroek static char *tdecode(char *, char **);
103*8f957290SDavid van Moolenbroek
104*8f957290SDavid van Moolenbroek /*
105*8f957290SDavid van Moolenbroek * Get an entry for terminal name in buffer bp,
106*8f957290SDavid van Moolenbroek * from the termcap file. Parse is very rudimentary;
107*8f957290SDavid van Moolenbroek * we just notice escaped newlines.
108*8f957290SDavid van Moolenbroek */
109*8f957290SDavid van Moolenbroek int
tgetent(char * bp,char * name)110*8f957290SDavid van Moolenbroek tgetent(char *bp, char *name)
111*8f957290SDavid van Moolenbroek {
112*8f957290SDavid van Moolenbroek char *cp;
113*8f957290SDavid van Moolenbroek
114*8f957290SDavid van Moolenbroek remotefile = cp = conffile ? conffile : __UNCONST(_PATH_RTADVDCONF);
115*8f957290SDavid van Moolenbroek return (getent(bp, name, cp));
116*8f957290SDavid van Moolenbroek }
117*8f957290SDavid van Moolenbroek
118*8f957290SDavid van Moolenbroek int
getent(char * bp,char * name,char * cp)119*8f957290SDavid van Moolenbroek getent(char *bp, char *name, char *cp)
120*8f957290SDavid van Moolenbroek {
121*8f957290SDavid van Moolenbroek int c;
122*8f957290SDavid van Moolenbroek int i = 0, cnt = 0;
123*8f957290SDavid van Moolenbroek char ibuf[BUFSIZ];
124*8f957290SDavid van Moolenbroek int tf;
125*8f957290SDavid van Moolenbroek
126*8f957290SDavid van Moolenbroek tbuf = bp;
127*8f957290SDavid van Moolenbroek tf = 0;
128*8f957290SDavid van Moolenbroek /*
129*8f957290SDavid van Moolenbroek * TERMCAP can have one of two things in it. It can be the
130*8f957290SDavid van Moolenbroek * name of a file to use instead of /etc/termcap. In this
131*8f957290SDavid van Moolenbroek * case it better start with a "/". Or it can be an entry to
132*8f957290SDavid van Moolenbroek * use so we don't have to read the file. In this case it
133*8f957290SDavid van Moolenbroek * has to already have the newlines crunched out.
134*8f957290SDavid van Moolenbroek */
135*8f957290SDavid van Moolenbroek if (cp && *cp) {
136*8f957290SDavid van Moolenbroek tf = open(RM = cp, O_RDONLY);
137*8f957290SDavid van Moolenbroek }
138*8f957290SDavid van Moolenbroek if (tf < 0) {
139*8f957290SDavid van Moolenbroek syslog(LOG_INFO, "<%s> open: %m", __func__);
140*8f957290SDavid van Moolenbroek return (-2);
141*8f957290SDavid van Moolenbroek }
142*8f957290SDavid van Moolenbroek for (;;) {
143*8f957290SDavid van Moolenbroek cp = bp;
144*8f957290SDavid van Moolenbroek for (;;) {
145*8f957290SDavid van Moolenbroek if (i == cnt) {
146*8f957290SDavid van Moolenbroek cnt = read(tf, ibuf, BUFSIZ);
147*8f957290SDavid van Moolenbroek if (cnt <= 0) {
148*8f957290SDavid van Moolenbroek close(tf);
149*8f957290SDavid van Moolenbroek return (0);
150*8f957290SDavid van Moolenbroek }
151*8f957290SDavid van Moolenbroek i = 0;
152*8f957290SDavid van Moolenbroek }
153*8f957290SDavid van Moolenbroek c = ibuf[i++];
154*8f957290SDavid van Moolenbroek if (c == '\n') {
155*8f957290SDavid van Moolenbroek if (cp > bp && cp[-1] == '\\') {
156*8f957290SDavid van Moolenbroek cp--;
157*8f957290SDavid van Moolenbroek continue;
158*8f957290SDavid van Moolenbroek }
159*8f957290SDavid van Moolenbroek break;
160*8f957290SDavid van Moolenbroek }
161*8f957290SDavid van Moolenbroek if (cp >= bp + BUFSIZ) {
162*8f957290SDavid van Moolenbroek write(2,"Remcap entry too long\n", 23);
163*8f957290SDavid van Moolenbroek break;
164*8f957290SDavid van Moolenbroek } else
165*8f957290SDavid van Moolenbroek *cp++ = c;
166*8f957290SDavid van Moolenbroek }
167*8f957290SDavid van Moolenbroek *cp = 0;
168*8f957290SDavid van Moolenbroek
169*8f957290SDavid van Moolenbroek /*
170*8f957290SDavid van Moolenbroek * The real work for the match.
171*8f957290SDavid van Moolenbroek */
172*8f957290SDavid van Moolenbroek if (tnamatch(name)) {
173*8f957290SDavid van Moolenbroek close(tf);
174*8f957290SDavid van Moolenbroek return (tnchktc());
175*8f957290SDavid van Moolenbroek }
176*8f957290SDavid van Moolenbroek }
177*8f957290SDavid van Moolenbroek }
178*8f957290SDavid van Moolenbroek
179*8f957290SDavid van Moolenbroek /*
180*8f957290SDavid van Moolenbroek * tnchktc: check the last entry, see if it's tc=xxx. If so,
181*8f957290SDavid van Moolenbroek * recursively find xxx and append that entry (minus the names)
182*8f957290SDavid van Moolenbroek * to take the place of the tc=xxx entry. This allows termcap
183*8f957290SDavid van Moolenbroek * entries to say "like an HP2621 but doesn't turn on the labels".
184*8f957290SDavid van Moolenbroek * Note that this works because of the left to right scan.
185*8f957290SDavid van Moolenbroek */
186*8f957290SDavid van Moolenbroek int
tnchktc(void)187*8f957290SDavid van Moolenbroek tnchktc(void)
188*8f957290SDavid van Moolenbroek {
189*8f957290SDavid van Moolenbroek char *p, *q;
190*8f957290SDavid van Moolenbroek char tcname[16]; /* name of similar terminal */
191*8f957290SDavid van Moolenbroek char tcbuf[BUFSIZ];
192*8f957290SDavid van Moolenbroek char *holdtbuf = tbuf;
193*8f957290SDavid van Moolenbroek int l;
194*8f957290SDavid van Moolenbroek
195*8f957290SDavid van Moolenbroek p = tbuf + strlen(tbuf) - 2; /* before the last colon */
196*8f957290SDavid van Moolenbroek while (*--p != ':')
197*8f957290SDavid van Moolenbroek if (p < tbuf) {
198*8f957290SDavid van Moolenbroek write(2, "Bad remcap entry\n", 18);
199*8f957290SDavid van Moolenbroek return (0);
200*8f957290SDavid van Moolenbroek }
201*8f957290SDavid van Moolenbroek p++;
202*8f957290SDavid van Moolenbroek /* p now points to beginning of last field */
203*8f957290SDavid van Moolenbroek if (p[0] != 't' || p[1] != 'c')
204*8f957290SDavid van Moolenbroek return (1);
205*8f957290SDavid van Moolenbroek strlcpy(tcname, p + 3, sizeof tcname);
206*8f957290SDavid van Moolenbroek q = tcname;
207*8f957290SDavid van Moolenbroek while (*q && *q != ':')
208*8f957290SDavid van Moolenbroek q++;
209*8f957290SDavid van Moolenbroek *q = 0;
210*8f957290SDavid van Moolenbroek if (++hopcount > MAXHOP) {
211*8f957290SDavid van Moolenbroek write(2, "Infinite tc= loop\n", 18);
212*8f957290SDavid van Moolenbroek return (0);
213*8f957290SDavid van Moolenbroek }
214*8f957290SDavid van Moolenbroek if (getent(tcbuf, tcname, remotefile) != 1) {
215*8f957290SDavid van Moolenbroek return (0);
216*8f957290SDavid van Moolenbroek }
217*8f957290SDavid van Moolenbroek for (q = tcbuf; *q++ != ':'; )
218*8f957290SDavid van Moolenbroek ;
219*8f957290SDavid van Moolenbroek l = p - holdtbuf + strlen(q);
220*8f957290SDavid van Moolenbroek if (l > BUFSIZ) {
221*8f957290SDavid van Moolenbroek write(2, "Remcap entry too long\n", 23);
222*8f957290SDavid van Moolenbroek q[BUFSIZ - (p-holdtbuf)] = 0;
223*8f957290SDavid van Moolenbroek }
224*8f957290SDavid van Moolenbroek strcpy(p, q);
225*8f957290SDavid van Moolenbroek tbuf = holdtbuf;
226*8f957290SDavid van Moolenbroek return (1);
227*8f957290SDavid van Moolenbroek }
228*8f957290SDavid van Moolenbroek
229*8f957290SDavid van Moolenbroek /*
230*8f957290SDavid van Moolenbroek * Tnamatch deals with name matching. The first field of the termcap
231*8f957290SDavid van Moolenbroek * entry is a sequence of names separated by |'s, so we compare
232*8f957290SDavid van Moolenbroek * against each such name. The normal : terminator after the last
233*8f957290SDavid van Moolenbroek * name (before the first field) stops us.
234*8f957290SDavid van Moolenbroek */
235*8f957290SDavid van Moolenbroek int
tnamatch(char * np)236*8f957290SDavid van Moolenbroek tnamatch(char *np)
237*8f957290SDavid van Moolenbroek {
238*8f957290SDavid van Moolenbroek char *Np, *Bp;
239*8f957290SDavid van Moolenbroek
240*8f957290SDavid van Moolenbroek Bp = tbuf;
241*8f957290SDavid van Moolenbroek if (*Bp == '#')
242*8f957290SDavid van Moolenbroek return (0);
243*8f957290SDavid van Moolenbroek for (;;) {
244*8f957290SDavid van Moolenbroek for (Np = np; *Np && *Bp == *Np; Bp++, Np++)
245*8f957290SDavid van Moolenbroek continue;
246*8f957290SDavid van Moolenbroek if (*Np == 0 && (*Bp == '|' || *Bp == ':' || *Bp == 0))
247*8f957290SDavid van Moolenbroek return (1);
248*8f957290SDavid van Moolenbroek while (*Bp && *Bp != ':' && *Bp != '|')
249*8f957290SDavid van Moolenbroek Bp++;
250*8f957290SDavid van Moolenbroek if (*Bp == 0 || *Bp == ':')
251*8f957290SDavid van Moolenbroek return (0);
252*8f957290SDavid van Moolenbroek Bp++;
253*8f957290SDavid van Moolenbroek }
254*8f957290SDavid van Moolenbroek }
255*8f957290SDavid van Moolenbroek
256*8f957290SDavid van Moolenbroek /*
257*8f957290SDavid van Moolenbroek * Skip to the next field. Notice that this is very dumb, not
258*8f957290SDavid van Moolenbroek * knowing about \: escapes or any such. If necessary, :'s can be put
259*8f957290SDavid van Moolenbroek * into the termcap file in octal.
260*8f957290SDavid van Moolenbroek */
261*8f957290SDavid van Moolenbroek static char *
tskip(char * bp)262*8f957290SDavid van Moolenbroek tskip(char *bp)
263*8f957290SDavid van Moolenbroek {
264*8f957290SDavid van Moolenbroek int dquote;
265*8f957290SDavid van Moolenbroek
266*8f957290SDavid van Moolenbroek dquote = 0;
267*8f957290SDavid van Moolenbroek while (*bp) {
268*8f957290SDavid van Moolenbroek switch (*bp) {
269*8f957290SDavid van Moolenbroek case ':':
270*8f957290SDavid van Moolenbroek if (!dquote)
271*8f957290SDavid van Moolenbroek goto breakbreak;
272*8f957290SDavid van Moolenbroek else
273*8f957290SDavid van Moolenbroek bp++;
274*8f957290SDavid van Moolenbroek break;
275*8f957290SDavid van Moolenbroek case '\\':
276*8f957290SDavid van Moolenbroek bp++;
277*8f957290SDavid van Moolenbroek if (isdigit((unsigned char)*bp)) {
278*8f957290SDavid van Moolenbroek while (isdigit((unsigned char)*bp++))
279*8f957290SDavid van Moolenbroek ;
280*8f957290SDavid van Moolenbroek } else
281*8f957290SDavid van Moolenbroek bp++;
282*8f957290SDavid van Moolenbroek case '"':
283*8f957290SDavid van Moolenbroek dquote = (dquote ? 0 : 1);
284*8f957290SDavid van Moolenbroek bp++;
285*8f957290SDavid van Moolenbroek break;
286*8f957290SDavid van Moolenbroek default:
287*8f957290SDavid van Moolenbroek bp++;
288*8f957290SDavid van Moolenbroek break;
289*8f957290SDavid van Moolenbroek }
290*8f957290SDavid van Moolenbroek }
291*8f957290SDavid van Moolenbroek breakbreak:
292*8f957290SDavid van Moolenbroek if (*bp == ':')
293*8f957290SDavid van Moolenbroek bp++;
294*8f957290SDavid van Moolenbroek return (bp);
295*8f957290SDavid van Moolenbroek }
296*8f957290SDavid van Moolenbroek
297*8f957290SDavid van Moolenbroek /*
298*8f957290SDavid van Moolenbroek * Return the (numeric) option id.
299*8f957290SDavid van Moolenbroek * Numeric options look like
300*8f957290SDavid van Moolenbroek * li#80
301*8f957290SDavid van Moolenbroek * i.e. the option string is separated from the numeric value by
302*8f957290SDavid van Moolenbroek * a # character. If the option is not found we return -1.
303*8f957290SDavid van Moolenbroek * Note that we handle octal numbers beginning with 0.
304*8f957290SDavid van Moolenbroek */
305*8f957290SDavid van Moolenbroek int64_t
tgetnum(char * id)306*8f957290SDavid van Moolenbroek tgetnum(char *id)
307*8f957290SDavid van Moolenbroek {
308*8f957290SDavid van Moolenbroek int64_t i;
309*8f957290SDavid van Moolenbroek int base;
310*8f957290SDavid van Moolenbroek char *bp = tbuf;
311*8f957290SDavid van Moolenbroek
312*8f957290SDavid van Moolenbroek for (;;) {
313*8f957290SDavid van Moolenbroek bp = tskip(bp);
314*8f957290SDavid van Moolenbroek if (*bp == 0)
315*8f957290SDavid van Moolenbroek return (-1);
316*8f957290SDavid van Moolenbroek if (strncmp(bp, id, strlen(id)) != 0)
317*8f957290SDavid van Moolenbroek continue;
318*8f957290SDavid van Moolenbroek bp += strlen(id);
319*8f957290SDavid van Moolenbroek if (*bp == '@')
320*8f957290SDavid van Moolenbroek return (-1);
321*8f957290SDavid van Moolenbroek if (*bp != '#')
322*8f957290SDavid van Moolenbroek continue;
323*8f957290SDavid van Moolenbroek bp++;
324*8f957290SDavid van Moolenbroek base = 10;
325*8f957290SDavid van Moolenbroek if (*bp == '0')
326*8f957290SDavid van Moolenbroek base = 8;
327*8f957290SDavid van Moolenbroek i = 0;
328*8f957290SDavid van Moolenbroek while (isdigit((unsigned char)*bp))
329*8f957290SDavid van Moolenbroek i *= base, i += *bp++ - '0';
330*8f957290SDavid van Moolenbroek return (i);
331*8f957290SDavid van Moolenbroek }
332*8f957290SDavid van Moolenbroek }
333*8f957290SDavid van Moolenbroek
334*8f957290SDavid van Moolenbroek /*
335*8f957290SDavid van Moolenbroek * Handle a flag option.
336*8f957290SDavid van Moolenbroek * Flag options are given "naked", i.e. followed by a : or the end
337*8f957290SDavid van Moolenbroek * of the buffer. Return 1 if we find the option, or 0 if it is
338*8f957290SDavid van Moolenbroek * not given.
339*8f957290SDavid van Moolenbroek */
340*8f957290SDavid van Moolenbroek int
tgetflag(char * id)341*8f957290SDavid van Moolenbroek tgetflag(char *id)
342*8f957290SDavid van Moolenbroek {
343*8f957290SDavid van Moolenbroek char *bp = tbuf;
344*8f957290SDavid van Moolenbroek
345*8f957290SDavid van Moolenbroek for (;;) {
346*8f957290SDavid van Moolenbroek bp = tskip(bp);
347*8f957290SDavid van Moolenbroek if (!*bp)
348*8f957290SDavid van Moolenbroek return (0);
349*8f957290SDavid van Moolenbroek if (strncmp(bp, id, strlen(id)) == 0) {
350*8f957290SDavid van Moolenbroek bp += strlen(id);
351*8f957290SDavid van Moolenbroek if (!*bp || *bp == ':')
352*8f957290SDavid van Moolenbroek return (1);
353*8f957290SDavid van Moolenbroek else if (*bp == '@')
354*8f957290SDavid van Moolenbroek return (0);
355*8f957290SDavid van Moolenbroek }
356*8f957290SDavid van Moolenbroek }
357*8f957290SDavid van Moolenbroek }
358*8f957290SDavid van Moolenbroek
359*8f957290SDavid van Moolenbroek /*
360*8f957290SDavid van Moolenbroek * Get a string valued option.
361*8f957290SDavid van Moolenbroek * These are given as
362*8f957290SDavid van Moolenbroek * cl=^Z
363*8f957290SDavid van Moolenbroek * Much decoding is done on the strings, and the strings are
364*8f957290SDavid van Moolenbroek * placed in area, which is a ref parameter which is updated.
365*8f957290SDavid van Moolenbroek * No checking on area overflow.
366*8f957290SDavid van Moolenbroek */
367*8f957290SDavid van Moolenbroek char *
tgetstr(char * id,char ** area)368*8f957290SDavid van Moolenbroek tgetstr(char *id, char **area)
369*8f957290SDavid van Moolenbroek {
370*8f957290SDavid van Moolenbroek char *bp = tbuf;
371*8f957290SDavid van Moolenbroek
372*8f957290SDavid van Moolenbroek for (;;) {
373*8f957290SDavid van Moolenbroek bp = tskip(bp);
374*8f957290SDavid van Moolenbroek if (!*bp)
375*8f957290SDavid van Moolenbroek return (0);
376*8f957290SDavid van Moolenbroek if (strncmp(bp, id, strlen(id)) != 0)
377*8f957290SDavid van Moolenbroek continue;
378*8f957290SDavid van Moolenbroek bp += strlen(id);
379*8f957290SDavid van Moolenbroek if (*bp == '@')
380*8f957290SDavid van Moolenbroek return (0);
381*8f957290SDavid van Moolenbroek if (*bp != '=')
382*8f957290SDavid van Moolenbroek continue;
383*8f957290SDavid van Moolenbroek bp++;
384*8f957290SDavid van Moolenbroek return (tdecode(bp, area));
385*8f957290SDavid van Moolenbroek }
386*8f957290SDavid van Moolenbroek }
387*8f957290SDavid van Moolenbroek
388*8f957290SDavid van Moolenbroek /*
389*8f957290SDavid van Moolenbroek * Tdecode does the grung work to decode the
390*8f957290SDavid van Moolenbroek * string capability escapes.
391*8f957290SDavid van Moolenbroek */
392*8f957290SDavid van Moolenbroek static char *
tdecode(char * str,char ** area)393*8f957290SDavid van Moolenbroek tdecode(char *str, char **area)
394*8f957290SDavid van Moolenbroek {
395*8f957290SDavid van Moolenbroek char *cp;
396*8f957290SDavid van Moolenbroek int c;
397*8f957290SDavid van Moolenbroek const char *dps = "E\033^^\\\\::n\nr\rt\tb\bf\f\"\"", *dp;
398*8f957290SDavid van Moolenbroek int i;
399*8f957290SDavid van Moolenbroek char term;
400*8f957290SDavid van Moolenbroek
401*8f957290SDavid van Moolenbroek term = ':';
402*8f957290SDavid van Moolenbroek cp = *area;
403*8f957290SDavid van Moolenbroek again:
404*8f957290SDavid van Moolenbroek if (*str == '"') {
405*8f957290SDavid van Moolenbroek term = '"';
406*8f957290SDavid van Moolenbroek str++;
407*8f957290SDavid van Moolenbroek }
408*8f957290SDavid van Moolenbroek while ((c = *str++) && c != term) {
409*8f957290SDavid van Moolenbroek switch (c) {
410*8f957290SDavid van Moolenbroek
411*8f957290SDavid van Moolenbroek case '^':
412*8f957290SDavid van Moolenbroek c = *str++ & 037;
413*8f957290SDavid van Moolenbroek break;
414*8f957290SDavid van Moolenbroek
415*8f957290SDavid van Moolenbroek case '\\':
416*8f957290SDavid van Moolenbroek dp = dps;
417*8f957290SDavid van Moolenbroek c = *str++;
418*8f957290SDavid van Moolenbroek nextc:
419*8f957290SDavid van Moolenbroek if (*dp++ == c) {
420*8f957290SDavid van Moolenbroek c = *dp++;
421*8f957290SDavid van Moolenbroek break;
422*8f957290SDavid van Moolenbroek }
423*8f957290SDavid van Moolenbroek dp++;
424*8f957290SDavid van Moolenbroek if (*dp)
425*8f957290SDavid van Moolenbroek goto nextc;
426*8f957290SDavid van Moolenbroek if (isdigit((unsigned char)c)) {
427*8f957290SDavid van Moolenbroek c -= '0', i = 2;
428*8f957290SDavid van Moolenbroek do
429*8f957290SDavid van Moolenbroek c <<= 3, c |= *str++ - '0';
430*8f957290SDavid van Moolenbroek while (--i && isdigit((unsigned char)*str));
431*8f957290SDavid van Moolenbroek }
432*8f957290SDavid van Moolenbroek break;
433*8f957290SDavid van Moolenbroek }
434*8f957290SDavid van Moolenbroek *cp++ = c;
435*8f957290SDavid van Moolenbroek }
436*8f957290SDavid van Moolenbroek if (c == term && term != ':') {
437*8f957290SDavid van Moolenbroek term = ':';
438*8f957290SDavid van Moolenbroek goto again;
439*8f957290SDavid van Moolenbroek }
440*8f957290SDavid van Moolenbroek *cp++ = 0;
441*8f957290SDavid van Moolenbroek str = *area;
442*8f957290SDavid van Moolenbroek *area = cp;
443*8f957290SDavid van Moolenbroek return (str);
444*8f957290SDavid van Moolenbroek }
445