[BACK]Return to vgrindefs.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / vgrind

Annotation of src/usr.bin/vgrind/vgrindefs.c, Revision 1.8

1.8     ! millert     1: /*     $OpenBSD: vgrindefs.c,v 1.7 2003/04/26 03:35:15 deraadt Exp $   */
1.1       deraadt     2: /*     $NetBSD: vgrindefs.c,v 1.5 1994/12/20 12:05:29 cgd Exp $        */
                      3:
                      4: /*
                      5:  * Copyright (c) 1980, 1993
                      6:  *     The Regents of the University of California.  All rights reserved.
                      7:  *
                      8:  * Redistribution and use in source and binary forms, with or without
                      9:  * modification, are permitted provided that the following conditions
                     10:  * are met:
                     11:  * 1. Redistributions of source code must retain the above copyright
                     12:  *    notice, this list of conditions and the following disclaimer.
                     13:  * 2. Redistributions in binary form must reproduce the above copyright
                     14:  *    notice, this list of conditions and the following disclaimer in the
                     15:  *    documentation and/or other materials provided with the distribution.
1.8     ! millert    16:  * 3. Neither the name of the University nor the names of its contributors
1.1       deraadt    17:  *    may be used to endorse or promote products derived from this software
                     18:  *    without specific prior written permission.
                     19:  *
                     20:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     21:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     22:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     23:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     24:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     25:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     26:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     27:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     28:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     29:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     30:  * SUCH DAMAGE.
                     31:  */
                     32:
                     33: #ifndef lint
                     34: #if 0
                     35: static char sccsid[] = "@(#)vgrindefs.c        8.1 (Berkeley) 6/6/93";
                     36: #endif
1.8     ! millert    37: static char rcsid[] = "$OpenBSD: vgrindefs.c,v 1.7 2003/04/26 03:35:15 deraadt Exp $";
1.1       deraadt    38: #endif /* not lint */
                     39:
                     40: #define        BUFSIZ  1024
                     41: #define MAXHOP 32      /* max number of tc= indirections */
                     42:
                     43: #include <stdlib.h>
                     44: #include <string.h>
                     45: #include <ctype.h>
                     46: /*
                     47:  * grindcap - routines for dealing with the language definitions data base
                     48:  *     (code stolen almost totally from termcap)
                     49:  *
                     50:  * BUG:                Should use a "last" pointer in tbuf, so that searching
                     51:  *             for capabilities alphabetically would not be a n**2/2
                     52:  *             process when large numbers of capabilities are given.
                     53:  * Note:       If we add a last pointer now we will screw up the
                     54:  *             tc capability. We really should compile termcap.
                     55:  *
                     56:  * Essentially all the work here is scanning and decoding escapes
                     57:  * in string capabilities.  We don't use stdio because the editor
                     58:  * doesn't, and because living w/o it is not hard.
                     59:  */
                     60:
                     61: static char *tbuf;
                     62: static char *filename;
                     63: static int hopcount;   /* detect infinite loops in termcap, init 0 */
                     64: static char *tskip();
                     65: static char *tdecode();
                     66: char   *tgetstr();
                     67:
                     68: /*
                     69:  * Get an entry for terminal name in buffer bp,
                     70:  * from the termcap file.  Parse is very rudimentary;
                     71:  * we just notice escaped newlines.
                     72:  */
1.6       deraadt    73: tgetent(char *bp, char *name, char *file)
1.1       deraadt    74: {
1.6       deraadt    75:        char ibuf[BUFSIZ], *cp, *cp2;
                     76:        int i = 0, cnt = 0, c;
1.1       deraadt    77:        int tf;
                     78:
                     79:        tbuf = bp;
                     80:        tf = 0;
                     81:        filename = file;
                     82:        tf = open(filename, 0);
                     83:        if (tf < 0)
                     84:                return (-1);
                     85:        for (;;) {
                     86:                cp = bp;
                     87:                for (;;) {
                     88:                        if (i == cnt) {
                     89:                                cnt = read(tf, ibuf, BUFSIZ);
                     90:                                if (cnt <= 0) {
                     91:                                        close(tf);
                     92:                                        return (0);
                     93:                                }
                     94:                                i = 0;
                     95:                        }
                     96:                        c = ibuf[i++];
                     97:                        if (c == '\n') {
                     98:                                if (cp > bp && cp[-1] == '\\'){
                     99:                                        cp--;
                    100:                                        continue;
                    101:                                }
                    102:                                break;
                    103:                        }
                    104:                        if (cp >= bp+BUFSIZ) {
                    105:                                write(2,"Vgrind entry too long\n", 23);
                    106:                                break;
                    107:                        } else
                    108:                                *cp++ = c;
                    109:                }
                    110:                *cp = 0;
                    111:
                    112:                /*
                    113:                 * The real work for the match.
                    114:                 */
                    115:                if (tnamatch(name)) {
                    116:                        close(tf);
                    117:                        return(tnchktc());
                    118:                }
                    119:        }
                    120: }
                    121:
                    122: /*
                    123:  * tnchktc: check the last entry, see if it's tc=xxx. If so,
                    124:  * recursively find xxx and append that entry (minus the names)
                    125:  * to take the place of the tc=xxx entry. This allows termcap
                    126:  * entries to say "like an HP2621 but doesn't turn on the labels".
                    127:  * Note that this works because of the left to right scan.
                    128:  */
1.6       deraadt   129: tnchktc(void)
1.1       deraadt   130: {
1.3       mpech     131:        char *p, *q;
1.1       deraadt   132:        char tcname[16];        /* name of similar terminal */
                    133:        char tcbuf[BUFSIZ];
                    134:        char *holdtbuf = tbuf;
                    135:        int l;
                    136:
                    137:        p = tbuf + strlen(tbuf) - 2;    /* before the last colon */
                    138:        while (*--p != ':')
                    139:                if (p<tbuf) {
                    140:                        write(2, "Bad vgrind entry\n", 18);
                    141:                        return (0);
                    142:                }
                    143:        p++;
                    144:        /* p now points to beginning of last field */
                    145:        if (p[0] != 't' || p[1] != 'c')
                    146:                return(1);
1.5       deraadt   147:        strlcpy(tcname, p+3, sizeof tcname);
1.1       deraadt   148:        q = tcname;
                    149:        while (q && *q != ':')
                    150:                q++;
                    151:        *q = 0;
                    152:        if (++hopcount > MAXHOP) {
                    153:                write(2, "Infinite tc= loop\n", 18);
                    154:                return (0);
                    155:        }
                    156:        if (tgetent(tcbuf, tcname, filename) != 1)
                    157:                return(0);
                    158:        for (q=tcbuf; *q != ':'; q++)
                    159:                ;
                    160:        l = p - holdtbuf + strlen(q);
                    161:        if (l > BUFSIZ) {
                    162:                write(2, "Vgrind entry too long\n", 23);
                    163:                q[BUFSIZ - (p-tbuf)] = 0;
                    164:        }
1.7       deraadt   165:        strlcpy(p, q+1, l);
1.1       deraadt   166:        tbuf = holdtbuf;
                    167:        return(1);
                    168: }
                    169:
                    170: /*
                    171:  * Tnamatch deals with name matching.  The first field of the termcap
                    172:  * entry is a sequence of names separated by |'s, so we compare
                    173:  * against each such name.  The normal : terminator after the last
                    174:  * name (before the first field) stops us.
                    175:  */
1.6       deraadt   176: tnamatch(char *np)
1.1       deraadt   177: {
1.3       mpech     178:        char *Np, *Bp;
1.1       deraadt   179:
                    180:        Bp = tbuf;
                    181:        if (*Bp == '#')
                    182:                return(0);
                    183:        for (;;) {
                    184:                for (Np = np; *Np && *Bp == *Np; Bp++, Np++)
                    185:                        continue;
                    186:                if (*Np == 0 && (*Bp == '|' || *Bp == ':' || *Bp == 0))
                    187:                        return (1);
                    188:                while (*Bp && *Bp != ':' && *Bp != '|')
                    189:                        Bp++;
                    190:                if (*Bp == 0 || *Bp == ':')
                    191:                        return (0);
                    192:                Bp++;
                    193:        }
                    194: }
                    195:
                    196: /*
                    197:  * Skip to the next field.  Notice that this is very dumb, not
                    198:  * knowing about \: escapes or any such.  If necessary, :'s can be put
                    199:  * into the termcap file in octal.
                    200:  */
                    201: static char *
1.6       deraadt   202: tskip(char *bp)
1.1       deraadt   203: {
                    204:
                    205:        while (*bp && *bp != ':')
                    206:                bp++;
                    207:        if (*bp == ':')
                    208:                bp++;
                    209:        return (bp);
                    210: }
                    211:
                    212: /*
                    213:  * Return the (numeric) option id.
                    214:  * Numeric options look like
                    215:  *     li#80
                    216:  * i.e. the option string is separated from the numeric value by
                    217:  * a # character.  If the option is not found we return -1.
                    218:  * Note that we handle octal numbers beginning with 0.
                    219:  */
1.6       deraadt   220: tgetnum(char *id)
1.1       deraadt   221: {
1.3       mpech     222:        int i, base;
                    223:        char *bp = tbuf;
1.1       deraadt   224:
                    225:        for (;;) {
                    226:                bp = tskip(bp);
                    227:                if (*bp == 0)
                    228:                        return (-1);
                    229:                if (*bp++ != id[0] || *bp == 0 || *bp++ != id[1])
                    230:                        continue;
                    231:                if (*bp == '@')
                    232:                        return(-1);
                    233:                if (*bp != '#')
                    234:                        continue;
                    235:                bp++;
                    236:                base = 10;
                    237:                if (*bp == '0')
                    238:                        base = 8;
                    239:                i = 0;
                    240:                while (isdigit(*bp))
                    241:                        i *= base, i += *bp++ - '0';
                    242:                return (i);
                    243:        }
                    244: }
                    245:
                    246: /*
                    247:  * Handle a flag option.
                    248:  * Flag options are given "naked", i.e. followed by a : or the end
                    249:  * of the buffer.  Return 1 if we find the option, or 0 if it is
                    250:  * not given.
                    251:  */
1.6       deraadt   252: tgetflag(char *id)
1.1       deraadt   253: {
1.3       mpech     254:        char *bp = tbuf;
1.1       deraadt   255:
                    256:        for (;;) {
                    257:                bp = tskip(bp);
                    258:                if (!*bp)
                    259:                        return (0);
                    260:                if (*bp++ == id[0] && *bp != 0 && *bp++ == id[1]) {
                    261:                        if (!*bp || *bp == ':')
                    262:                                return (1);
                    263:                        else if (*bp == '@')
                    264:                                return(0);
                    265:                }
                    266:        }
                    267: }
                    268:
                    269: /*
                    270:  * Get a string valued option.
                    271:  * These are given as
                    272:  *     cl=^Z
                    273:  * Much decoding is done on the strings, and the strings are
                    274:  * placed in area, which is a ref parameter which is updated.
                    275:  * No checking on area overflow.
                    276:  */
                    277: char *
1.6       deraadt   278: tgetstr(char *id, char **area)
1.1       deraadt   279: {
1.3       mpech     280:        char *bp = tbuf;
1.1       deraadt   281:
                    282:        for (;;) {
                    283:                bp = tskip(bp);
                    284:                if (!*bp)
                    285:                        return (0);
                    286:                if (*bp++ != id[0] || *bp == 0 || *bp++ != id[1])
                    287:                        continue;
                    288:                if (*bp == '@')
                    289:                        return(0);
                    290:                if (*bp != '=')
                    291:                        continue;
                    292:                bp++;
                    293:                return (tdecode(bp, area));
                    294:        }
                    295: }
                    296:
                    297: /*
1.4       deraadt   298:  * Tdecode does the grunt work to decode the
1.1       deraadt   299:  * string capability escapes.
                    300:  */
                    301: static char *
1.6       deraadt   302: tdecode(char *str, char **area)
1.1       deraadt   303: {
1.3       mpech     304:        char *cp;
                    305:        int c;
1.1       deraadt   306:        int i;
                    307:
                    308:        cp = *area;
                    309:        while (c = *str++) {
                    310:            if (c == ':' && *(cp-1) != '\\')
                    311:                break;
                    312:            *cp++ = c;
                    313:        }
                    314:        *cp++ = 0;
                    315:        str = *area;
                    316:        *area = cp;
                    317:        return (str);
                    318: }