1ae326725SJun-ichiro itojun Hagino /* $FreeBSD$ */ 2bb58b617SHajimu UMEMOTO /* $KAME: advcap.c,v 1.11 2003/05/19 09:46:50 keiichi Exp $ */ 3b26e03e9SKris Kennaway 49a4365d0SYoshinobu Inoue /* 59a4365d0SYoshinobu Inoue * Copyright (c) 1983 The Regents of the University of California. 69a4365d0SYoshinobu Inoue * All rights reserved. 79a4365d0SYoshinobu Inoue * 89a4365d0SYoshinobu Inoue * Redistribution and use in source and binary forms, with or without 99a4365d0SYoshinobu Inoue * modification, are permitted provided that the following conditions 109a4365d0SYoshinobu Inoue * are met: 119a4365d0SYoshinobu Inoue * 1. Redistributions of source code must retain the above copyright 129a4365d0SYoshinobu Inoue * notice, this list of conditions and the following disclaimer. 139a4365d0SYoshinobu Inoue * 2. Redistributions in binary form must reproduce the above copyright 149a4365d0SYoshinobu Inoue * notice, this list of conditions and the following disclaimer in the 159a4365d0SYoshinobu Inoue * documentation and/or other materials provided with the distribution. 169a4365d0SYoshinobu Inoue * 3. All advertising materials mentioning features or use of this software 179a4365d0SYoshinobu Inoue * must display the following acknowledgement: 189a4365d0SYoshinobu Inoue * This product includes software developed by the University of 199a4365d0SYoshinobu Inoue * California, Berkeley and its contributors. 209a4365d0SYoshinobu Inoue * 4. Neither the name of the University nor the names of its contributors 219a4365d0SYoshinobu Inoue * may be used to endorse or promote products derived from this software 229a4365d0SYoshinobu Inoue * without specific prior written permission. 239a4365d0SYoshinobu Inoue * 249a4365d0SYoshinobu Inoue * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 259a4365d0SYoshinobu Inoue * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 269a4365d0SYoshinobu Inoue * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 279a4365d0SYoshinobu Inoue * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 289a4365d0SYoshinobu Inoue * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 299a4365d0SYoshinobu Inoue * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 309a4365d0SYoshinobu Inoue * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 319a4365d0SYoshinobu Inoue * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 329a4365d0SYoshinobu Inoue * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 339a4365d0SYoshinobu Inoue * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 349a4365d0SYoshinobu Inoue * SUCH DAMAGE. 359a4365d0SYoshinobu Inoue */ 369a4365d0SYoshinobu Inoue 379a4365d0SYoshinobu Inoue /* 389a4365d0SYoshinobu Inoue * remcap - routines for dealing with the remote host data base 399a4365d0SYoshinobu Inoue * 409a4365d0SYoshinobu Inoue * derived from termcap 419a4365d0SYoshinobu Inoue */ 429a4365d0SYoshinobu Inoue #include <sys/types.h> 439a4365d0SYoshinobu Inoue #include <sys/uio.h> 449a4365d0SYoshinobu Inoue #include <unistd.h> 459a4365d0SYoshinobu Inoue #include <fcntl.h> 469a4365d0SYoshinobu Inoue #include <ctype.h> 479a4365d0SYoshinobu Inoue #include <stdlib.h> 489a4365d0SYoshinobu Inoue #include <stdio.h> 499a4365d0SYoshinobu Inoue #include <syslog.h> 509a4365d0SYoshinobu Inoue #include <errno.h> 519a4365d0SYoshinobu Inoue #include <string.h> 529a4365d0SYoshinobu Inoue #include "pathnames.h" 539a4365d0SYoshinobu Inoue 549a4365d0SYoshinobu Inoue #ifndef BUFSIZ 559a4365d0SYoshinobu Inoue #define BUFSIZ 1024 569a4365d0SYoshinobu Inoue #endif 579a4365d0SYoshinobu Inoue #define MAXHOP 32 /* max number of tc= indirections */ 589a4365d0SYoshinobu Inoue 599a4365d0SYoshinobu Inoue #define tgetent agetent 609a4365d0SYoshinobu Inoue #define tnchktc anchktc 619a4365d0SYoshinobu Inoue #define tnamatch anamatch 629a4365d0SYoshinobu Inoue #define tgetnum agetnum 639a4365d0SYoshinobu Inoue #define tgetflag agetflag 649a4365d0SYoshinobu Inoue #define tgetstr agetstr 659a4365d0SYoshinobu Inoue 66b26e03e9SKris Kennaway #if 0 67b26e03e9SKris Kennaway #define V_TERMCAP "REMOTE" 68b26e03e9SKris Kennaway #define V_TERM "HOST" 69b26e03e9SKris Kennaway #endif 70b26e03e9SKris Kennaway 719a4365d0SYoshinobu Inoue char *RM; 729a4365d0SYoshinobu Inoue 739a4365d0SYoshinobu Inoue /* 749a4365d0SYoshinobu Inoue * termcap - routines for dealing with the terminal capability data base 759a4365d0SYoshinobu Inoue * 769a4365d0SYoshinobu Inoue * BUG: Should use a "last" pointer in tbuf, so that searching 779a4365d0SYoshinobu Inoue * for capabilities alphabetically would not be a n**2/2 789a4365d0SYoshinobu Inoue * process when large numbers of capabilities are given. 799a4365d0SYoshinobu Inoue * Note: If we add a last pointer now we will screw up the 809a4365d0SYoshinobu Inoue * tc capability. We really should compile termcap. 819a4365d0SYoshinobu Inoue * 829a4365d0SYoshinobu Inoue * Essentially all the work here is scanning and decoding escapes 839a4365d0SYoshinobu Inoue * in string capabilities. We don't use stdio because the editor 849a4365d0SYoshinobu Inoue * doesn't, and because living w/o it is not hard. 859a4365d0SYoshinobu Inoue */ 869a4365d0SYoshinobu Inoue 879a4365d0SYoshinobu Inoue static char *tbuf; 889a4365d0SYoshinobu Inoue static int hopcount; /* detect infinite loops in termcap, init 0 */ 899a4365d0SYoshinobu Inoue 909a4365d0SYoshinobu Inoue static char *remotefile; 919a4365d0SYoshinobu Inoue 929a4365d0SYoshinobu Inoue extern char *conffile; 939a4365d0SYoshinobu Inoue 949a4365d0SYoshinobu Inoue int tgetent __P((char *, char *)); 959a4365d0SYoshinobu Inoue int getent __P((char *, char *, char *)); 969a4365d0SYoshinobu Inoue int tnchktc __P((void)); 979a4365d0SYoshinobu Inoue int tnamatch __P((char *)); 989a4365d0SYoshinobu Inoue static char *tskip __P((char *)); 9947742de0SHajimu UMEMOTO int64_t tgetnum __P((char *)); 1009a4365d0SYoshinobu Inoue int tgetflag __P((char *)); 1019a4365d0SYoshinobu Inoue char *tgetstr __P((char *, char **)); 1029a4365d0SYoshinobu Inoue static char *tdecode __P((char *, char **)); 1039a4365d0SYoshinobu Inoue 1049a4365d0SYoshinobu Inoue /* 1059a4365d0SYoshinobu Inoue * Get an entry for terminal name in buffer bp, 1069a4365d0SYoshinobu Inoue * from the termcap file. Parse is very rudimentary; 1079a4365d0SYoshinobu Inoue * we just notice escaped newlines. 1089a4365d0SYoshinobu Inoue */ 1099a4365d0SYoshinobu Inoue int 1109a4365d0SYoshinobu Inoue tgetent(bp, name) 1119a4365d0SYoshinobu Inoue char *bp, *name; 1129a4365d0SYoshinobu Inoue { 1139a4365d0SYoshinobu Inoue char *cp; 1149a4365d0SYoshinobu Inoue 1159a4365d0SYoshinobu Inoue remotefile = cp = conffile ? conffile : _PATH_RTADVDCONF; 1169a4365d0SYoshinobu Inoue return (getent(bp, name, cp)); 1179a4365d0SYoshinobu Inoue } 1189a4365d0SYoshinobu Inoue 1199a4365d0SYoshinobu Inoue int 1209a4365d0SYoshinobu Inoue getent(bp, name, cp) 1219a4365d0SYoshinobu Inoue char *bp, *name, *cp; 1229a4365d0SYoshinobu Inoue { 12381982097SHajimu UMEMOTO int c; 12481982097SHajimu UMEMOTO int i = 0, cnt = 0; 1259a4365d0SYoshinobu Inoue char ibuf[BUFSIZ]; 1269a4365d0SYoshinobu Inoue int tf; 1279a4365d0SYoshinobu Inoue 1289a4365d0SYoshinobu Inoue tbuf = bp; 1299a4365d0SYoshinobu Inoue tf = 0; 1309a4365d0SYoshinobu Inoue /* 1319a4365d0SYoshinobu Inoue * TERMCAP can have one of two things in it. It can be the 1329a4365d0SYoshinobu Inoue * name of a file to use instead of /etc/termcap. In this 1339a4365d0SYoshinobu Inoue * case it better start with a "/". Or it can be an entry to 1349a4365d0SYoshinobu Inoue * use so we don't have to read the file. In this case it 1359a4365d0SYoshinobu Inoue * has to already have the newlines crunched out. 1369a4365d0SYoshinobu Inoue */ 1379a4365d0SYoshinobu Inoue if (cp && *cp) { 1389a4365d0SYoshinobu Inoue tf = open(RM = cp, O_RDONLY); 1399a4365d0SYoshinobu Inoue } 1409a4365d0SYoshinobu Inoue if (tf < 0) { 141b26e03e9SKris Kennaway syslog(LOG_INFO, 1421533bed0SHajimu UMEMOTO "<%s> open: %s", __func__, strerror(errno)); 1439a4365d0SYoshinobu Inoue return (-2); 1449a4365d0SYoshinobu Inoue } 1459a4365d0SYoshinobu Inoue for (;;) { 1469a4365d0SYoshinobu Inoue cp = bp; 1479a4365d0SYoshinobu Inoue for (;;) { 1489a4365d0SYoshinobu Inoue if (i == cnt) { 1499a4365d0SYoshinobu Inoue cnt = read(tf, ibuf, BUFSIZ); 1509a4365d0SYoshinobu Inoue if (cnt <= 0) { 1519a4365d0SYoshinobu Inoue close(tf); 1529a4365d0SYoshinobu Inoue return (0); 1539a4365d0SYoshinobu Inoue } 1549a4365d0SYoshinobu Inoue i = 0; 1559a4365d0SYoshinobu Inoue } 1569a4365d0SYoshinobu Inoue c = ibuf[i++]; 1579a4365d0SYoshinobu Inoue if (c == '\n') { 1589a4365d0SYoshinobu Inoue if (cp > bp && cp[-1] == '\\') { 1599a4365d0SYoshinobu Inoue cp--; 1609a4365d0SYoshinobu Inoue continue; 1619a4365d0SYoshinobu Inoue } 1629a4365d0SYoshinobu Inoue break; 1639a4365d0SYoshinobu Inoue } 1649a4365d0SYoshinobu Inoue if (cp >= bp + BUFSIZ) { 165e1b4d8d0SSheldon Hearn write(STDERR_FILENO, "Remcap entry too long\n", 166e1b4d8d0SSheldon Hearn 23); 1679a4365d0SYoshinobu Inoue break; 1689a4365d0SYoshinobu Inoue } else 1699a4365d0SYoshinobu Inoue *cp++ = c; 1709a4365d0SYoshinobu Inoue } 1719a4365d0SYoshinobu Inoue *cp = 0; 1729a4365d0SYoshinobu Inoue 1739a4365d0SYoshinobu Inoue /* 1749a4365d0SYoshinobu Inoue * The real work for the match. 1759a4365d0SYoshinobu Inoue */ 1769a4365d0SYoshinobu Inoue if (tnamatch(name)) { 1779a4365d0SYoshinobu Inoue close(tf); 1789a4365d0SYoshinobu Inoue return (tnchktc()); 1799a4365d0SYoshinobu Inoue } 1809a4365d0SYoshinobu Inoue } 1819a4365d0SYoshinobu Inoue } 1829a4365d0SYoshinobu Inoue 1839a4365d0SYoshinobu Inoue /* 1849a4365d0SYoshinobu Inoue * tnchktc: check the last entry, see if it's tc=xxx. If so, 1859a4365d0SYoshinobu Inoue * recursively find xxx and append that entry (minus the names) 1869a4365d0SYoshinobu Inoue * to take the place of the tc=xxx entry. This allows termcap 1879a4365d0SYoshinobu Inoue * entries to say "like an HP2621 but doesn't turn on the labels". 1889a4365d0SYoshinobu Inoue * Note that this works because of the left to right scan. 1899a4365d0SYoshinobu Inoue */ 1909a4365d0SYoshinobu Inoue int 1919a4365d0SYoshinobu Inoue tnchktc() 1929a4365d0SYoshinobu Inoue { 19381982097SHajimu UMEMOTO char *p, *q; 1949a4365d0SYoshinobu Inoue char tcname[16]; /* name of similar terminal */ 1959a4365d0SYoshinobu Inoue char tcbuf[BUFSIZ]; 1969a4365d0SYoshinobu Inoue char *holdtbuf = tbuf; 1979a4365d0SYoshinobu Inoue int l; 1989a4365d0SYoshinobu Inoue 1999a4365d0SYoshinobu Inoue p = tbuf + strlen(tbuf) - 2; /* before the last colon */ 2009a4365d0SYoshinobu Inoue while (*--p != ':') 2019a4365d0SYoshinobu Inoue if (p < tbuf) { 202e1b4d8d0SSheldon Hearn write(STDERR_FILENO, "Bad remcap entry\n", 18); 2039a4365d0SYoshinobu Inoue return (0); 2049a4365d0SYoshinobu Inoue } 2059a4365d0SYoshinobu Inoue p++; 2069a4365d0SYoshinobu Inoue /* p now points to beginning of last field */ 2079a4365d0SYoshinobu Inoue if (p[0] != 't' || p[1] != 'c') 2089a4365d0SYoshinobu Inoue return (1); 209bb58b617SHajimu UMEMOTO strlcpy(tcname, p + 3, sizeof tcname); 2109a4365d0SYoshinobu Inoue q = tcname; 2119a4365d0SYoshinobu Inoue while (*q && *q != ':') 2129a4365d0SYoshinobu Inoue q++; 2139a4365d0SYoshinobu Inoue *q = 0; 2149a4365d0SYoshinobu Inoue if (++hopcount > MAXHOP) { 215e1b4d8d0SSheldon Hearn write(STDERR_FILENO, "Infinite tc= loop\n", 18); 2169a4365d0SYoshinobu Inoue return (0); 2179a4365d0SYoshinobu Inoue } 2189a4365d0SYoshinobu Inoue if (getent(tcbuf, tcname, remotefile) != 1) { 2199a4365d0SYoshinobu Inoue return (0); 2209a4365d0SYoshinobu Inoue } 2219a4365d0SYoshinobu Inoue for (q = tcbuf; *q++ != ':'; ) 2229a4365d0SYoshinobu Inoue ; 2239a4365d0SYoshinobu Inoue l = p - holdtbuf + strlen(q); 2249a4365d0SYoshinobu Inoue if (l > BUFSIZ) { 225e1b4d8d0SSheldon Hearn write(STDERR_FILENO, "Remcap entry too long\n", 23); 2269a4365d0SYoshinobu Inoue q[BUFSIZ - (p-holdtbuf)] = 0; 2279a4365d0SYoshinobu Inoue } 2289a4365d0SYoshinobu Inoue strcpy(p, q); 2299a4365d0SYoshinobu Inoue tbuf = holdtbuf; 2309a4365d0SYoshinobu Inoue return (1); 2319a4365d0SYoshinobu Inoue } 2329a4365d0SYoshinobu Inoue 2339a4365d0SYoshinobu Inoue /* 2349a4365d0SYoshinobu Inoue * Tnamatch deals with name matching. The first field of the termcap 2359a4365d0SYoshinobu Inoue * entry is a sequence of names separated by |'s, so we compare 2369a4365d0SYoshinobu Inoue * against each such name. The normal : terminator after the last 2379a4365d0SYoshinobu Inoue * name (before the first field) stops us. 2389a4365d0SYoshinobu Inoue */ 2399a4365d0SYoshinobu Inoue int 2409a4365d0SYoshinobu Inoue tnamatch(np) 2419a4365d0SYoshinobu Inoue char *np; 2429a4365d0SYoshinobu Inoue { 24381982097SHajimu UMEMOTO char *Np, *Bp; 2449a4365d0SYoshinobu Inoue 2459a4365d0SYoshinobu Inoue Bp = tbuf; 2469a4365d0SYoshinobu Inoue if (*Bp == '#') 2479a4365d0SYoshinobu Inoue return (0); 2489a4365d0SYoshinobu Inoue for (;;) { 2499a4365d0SYoshinobu Inoue for (Np = np; *Np && *Bp == *Np; Bp++, Np++) 2509a4365d0SYoshinobu Inoue continue; 2519a4365d0SYoshinobu Inoue if (*Np == 0 && (*Bp == '|' || *Bp == ':' || *Bp == 0)) 2529a4365d0SYoshinobu Inoue return (1); 2539a4365d0SYoshinobu Inoue while (*Bp && *Bp != ':' && *Bp != '|') 2549a4365d0SYoshinobu Inoue Bp++; 2559a4365d0SYoshinobu Inoue if (*Bp == 0 || *Bp == ':') 2569a4365d0SYoshinobu Inoue return (0); 2579a4365d0SYoshinobu Inoue Bp++; 2589a4365d0SYoshinobu Inoue } 2599a4365d0SYoshinobu Inoue } 2609a4365d0SYoshinobu Inoue 2619a4365d0SYoshinobu Inoue /* 2629a4365d0SYoshinobu Inoue * Skip to the next field. Notice that this is very dumb, not 2639a4365d0SYoshinobu Inoue * knowing about \: escapes or any such. If necessary, :'s can be put 2649a4365d0SYoshinobu Inoue * into the termcap file in octal. 2659a4365d0SYoshinobu Inoue */ 2669a4365d0SYoshinobu Inoue static char * 2679a4365d0SYoshinobu Inoue tskip(bp) 26881982097SHajimu UMEMOTO char *bp; 2699a4365d0SYoshinobu Inoue { 2709a4365d0SYoshinobu Inoue int dquote; 2719a4365d0SYoshinobu Inoue 2729a4365d0SYoshinobu Inoue dquote = 0; 2739a4365d0SYoshinobu Inoue while (*bp) { 2749a4365d0SYoshinobu Inoue switch (*bp) { 2759a4365d0SYoshinobu Inoue case ':': 2769a4365d0SYoshinobu Inoue if (!dquote) 2779a4365d0SYoshinobu Inoue goto breakbreak; 2789a4365d0SYoshinobu Inoue else 2799a4365d0SYoshinobu Inoue bp++; 2809a4365d0SYoshinobu Inoue break; 2819a4365d0SYoshinobu Inoue case '\\': 2829a4365d0SYoshinobu Inoue bp++; 2839a4365d0SYoshinobu Inoue if (isdigit(*bp)) { 2849a4365d0SYoshinobu Inoue while (isdigit(*bp++)) 2859a4365d0SYoshinobu Inoue ; 2869a4365d0SYoshinobu Inoue } else 2879a4365d0SYoshinobu Inoue bp++; 2889a4365d0SYoshinobu Inoue case '"': 2899a4365d0SYoshinobu Inoue dquote = (dquote ? 1 : 0); 2909a4365d0SYoshinobu Inoue bp++; 2919a4365d0SYoshinobu Inoue break; 2929a4365d0SYoshinobu Inoue default: 2939a4365d0SYoshinobu Inoue bp++; 2949a4365d0SYoshinobu Inoue break; 2959a4365d0SYoshinobu Inoue } 2969a4365d0SYoshinobu Inoue } 2979a4365d0SYoshinobu Inoue breakbreak: 2989a4365d0SYoshinobu Inoue if (*bp == ':') 2999a4365d0SYoshinobu Inoue bp++; 3009a4365d0SYoshinobu Inoue return (bp); 3019a4365d0SYoshinobu Inoue } 3029a4365d0SYoshinobu Inoue 3039a4365d0SYoshinobu Inoue /* 3049a4365d0SYoshinobu Inoue * Return the (numeric) option id. 3059a4365d0SYoshinobu Inoue * Numeric options look like 3069a4365d0SYoshinobu Inoue * li#80 3079a4365d0SYoshinobu Inoue * i.e. the option string is separated from the numeric value by 3089a4365d0SYoshinobu Inoue * a # character. If the option is not found we return -1. 3099a4365d0SYoshinobu Inoue * Note that we handle octal numbers beginning with 0. 3109a4365d0SYoshinobu Inoue */ 31147742de0SHajimu UMEMOTO int64_t 3129a4365d0SYoshinobu Inoue tgetnum(id) 3139a4365d0SYoshinobu Inoue char *id; 3149a4365d0SYoshinobu Inoue { 31547742de0SHajimu UMEMOTO int64_t i; 31681982097SHajimu UMEMOTO int base; 31781982097SHajimu UMEMOTO char *bp = tbuf; 3189a4365d0SYoshinobu Inoue 3199a4365d0SYoshinobu Inoue for (;;) { 3209a4365d0SYoshinobu Inoue bp = tskip(bp); 3219a4365d0SYoshinobu Inoue if (*bp == 0) 3229a4365d0SYoshinobu Inoue return (-1); 3239a4365d0SYoshinobu Inoue if (strncmp(bp, id, strlen(id)) != 0) 3249a4365d0SYoshinobu Inoue continue; 3259a4365d0SYoshinobu Inoue bp += strlen(id); 3269a4365d0SYoshinobu Inoue if (*bp == '@') 3279a4365d0SYoshinobu Inoue return (-1); 3289a4365d0SYoshinobu Inoue if (*bp != '#') 3299a4365d0SYoshinobu Inoue continue; 3309a4365d0SYoshinobu Inoue bp++; 3319a4365d0SYoshinobu Inoue base = 10; 3329a4365d0SYoshinobu Inoue if (*bp == '0') 3339a4365d0SYoshinobu Inoue base = 8; 3349a4365d0SYoshinobu Inoue i = 0; 3359a4365d0SYoshinobu Inoue while (isdigit(*bp)) 3369a4365d0SYoshinobu Inoue i *= base, i += *bp++ - '0'; 3379a4365d0SYoshinobu Inoue return (i); 3389a4365d0SYoshinobu Inoue } 3399a4365d0SYoshinobu Inoue } 3409a4365d0SYoshinobu Inoue 3419a4365d0SYoshinobu Inoue /* 3429a4365d0SYoshinobu Inoue * Handle a flag option. 3439a4365d0SYoshinobu Inoue * Flag options are given "naked", i.e. followed by a : or the end 3449a4365d0SYoshinobu Inoue * of the buffer. Return 1 if we find the option, or 0 if it is 3459a4365d0SYoshinobu Inoue * not given. 3469a4365d0SYoshinobu Inoue */ 3479a4365d0SYoshinobu Inoue int 3489a4365d0SYoshinobu Inoue tgetflag(id) 3499a4365d0SYoshinobu Inoue char *id; 3509a4365d0SYoshinobu Inoue { 35181982097SHajimu UMEMOTO char *bp = tbuf; 3529a4365d0SYoshinobu Inoue 3539a4365d0SYoshinobu Inoue for (;;) { 3549a4365d0SYoshinobu Inoue bp = tskip(bp); 3559a4365d0SYoshinobu Inoue if (!*bp) 3569a4365d0SYoshinobu Inoue return (0); 3579a4365d0SYoshinobu Inoue if (strncmp(bp, id, strlen(id)) == 0) { 3589a4365d0SYoshinobu Inoue bp += strlen(id); 3599a4365d0SYoshinobu Inoue if (!*bp || *bp == ':') 3609a4365d0SYoshinobu Inoue return (1); 3619a4365d0SYoshinobu Inoue else if (*bp == '@') 3629a4365d0SYoshinobu Inoue return (0); 3639a4365d0SYoshinobu Inoue } 3649a4365d0SYoshinobu Inoue } 3659a4365d0SYoshinobu Inoue } 3669a4365d0SYoshinobu Inoue 3679a4365d0SYoshinobu Inoue /* 3689a4365d0SYoshinobu Inoue * Get a string valued option. 3699a4365d0SYoshinobu Inoue * These are given as 3709a4365d0SYoshinobu Inoue * cl=^Z 3719a4365d0SYoshinobu Inoue * Much decoding is done on the strings, and the strings are 3729a4365d0SYoshinobu Inoue * placed in area, which is a ref parameter which is updated. 3739a4365d0SYoshinobu Inoue * No checking on area overflow. 3749a4365d0SYoshinobu Inoue */ 3759a4365d0SYoshinobu Inoue char * 3769a4365d0SYoshinobu Inoue tgetstr(id, area) 3779a4365d0SYoshinobu Inoue char *id, **area; 3789a4365d0SYoshinobu Inoue { 37981982097SHajimu UMEMOTO char *bp = tbuf; 3809a4365d0SYoshinobu Inoue 3819a4365d0SYoshinobu Inoue for (;;) { 3829a4365d0SYoshinobu Inoue bp = tskip(bp); 3839a4365d0SYoshinobu Inoue if (!*bp) 3849a4365d0SYoshinobu Inoue return (0); 3859a4365d0SYoshinobu Inoue if (strncmp(bp, id, strlen(id)) != 0) 3869a4365d0SYoshinobu Inoue continue; 3879a4365d0SYoshinobu Inoue bp += strlen(id); 3889a4365d0SYoshinobu Inoue if (*bp == '@') 3899a4365d0SYoshinobu Inoue return (0); 3909a4365d0SYoshinobu Inoue if (*bp != '=') 3919a4365d0SYoshinobu Inoue continue; 3929a4365d0SYoshinobu Inoue bp++; 3939a4365d0SYoshinobu Inoue return (tdecode(bp, area)); 3949a4365d0SYoshinobu Inoue } 3959a4365d0SYoshinobu Inoue } 3969a4365d0SYoshinobu Inoue 3979a4365d0SYoshinobu Inoue /* 3989a4365d0SYoshinobu Inoue * Tdecode does the grung work to decode the 3999a4365d0SYoshinobu Inoue * string capability escapes. 4009a4365d0SYoshinobu Inoue */ 4019a4365d0SYoshinobu Inoue static char * 4029a4365d0SYoshinobu Inoue tdecode(str, area) 40381982097SHajimu UMEMOTO char *str; 4049a4365d0SYoshinobu Inoue char **area; 4059a4365d0SYoshinobu Inoue { 40681982097SHajimu UMEMOTO char *cp; 40781982097SHajimu UMEMOTO int c; 40881982097SHajimu UMEMOTO char *dp; 4099a4365d0SYoshinobu Inoue int i; 4109a4365d0SYoshinobu Inoue char term; 4119a4365d0SYoshinobu Inoue 4129a4365d0SYoshinobu Inoue term = ':'; 4139a4365d0SYoshinobu Inoue cp = *area; 4149a4365d0SYoshinobu Inoue again: 4159a4365d0SYoshinobu Inoue if (*str == '"') { 4169a4365d0SYoshinobu Inoue term = '"'; 4179a4365d0SYoshinobu Inoue str++; 4189a4365d0SYoshinobu Inoue } 4199a4365d0SYoshinobu Inoue while ((c = *str++) && c != term) { 4209a4365d0SYoshinobu Inoue switch (c) { 4219a4365d0SYoshinobu Inoue 4229a4365d0SYoshinobu Inoue case '^': 4239a4365d0SYoshinobu Inoue c = *str++ & 037; 4249a4365d0SYoshinobu Inoue break; 4259a4365d0SYoshinobu Inoue 4269a4365d0SYoshinobu Inoue case '\\': 4279a4365d0SYoshinobu Inoue dp = "E\033^^\\\\::n\nr\rt\tb\bf\f\"\""; 4289a4365d0SYoshinobu Inoue c = *str++; 4299a4365d0SYoshinobu Inoue nextc: 4309a4365d0SYoshinobu Inoue if (*dp++ == c) { 4319a4365d0SYoshinobu Inoue c = *dp++; 4329a4365d0SYoshinobu Inoue break; 4339a4365d0SYoshinobu Inoue } 4349a4365d0SYoshinobu Inoue dp++; 4359a4365d0SYoshinobu Inoue if (*dp) 4369a4365d0SYoshinobu Inoue goto nextc; 4379a4365d0SYoshinobu Inoue if (isdigit(c)) { 4389a4365d0SYoshinobu Inoue c -= '0', i = 2; 4399a4365d0SYoshinobu Inoue do 4409a4365d0SYoshinobu Inoue c <<= 3, c |= *str++ - '0'; 4419a4365d0SYoshinobu Inoue while (--i && isdigit(*str)); 4429a4365d0SYoshinobu Inoue } 4439a4365d0SYoshinobu Inoue break; 4449a4365d0SYoshinobu Inoue } 4459a4365d0SYoshinobu Inoue *cp++ = c; 4469a4365d0SYoshinobu Inoue } 4479a4365d0SYoshinobu Inoue if (c == term && term != ':') { 4489a4365d0SYoshinobu Inoue term = ':'; 4499a4365d0SYoshinobu Inoue goto again; 4509a4365d0SYoshinobu Inoue } 4519a4365d0SYoshinobu Inoue *cp++ = 0; 4529a4365d0SYoshinobu Inoue str = *area; 4539a4365d0SYoshinobu Inoue *area = cp; 4549a4365d0SYoshinobu Inoue return (str); 4559a4365d0SYoshinobu Inoue } 456