[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.6

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