[BACK]Return to termcap.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / lib / libterm

Annotation of src/lib/libterm/termcap.c, Revision 1.43.2.1

1.43.2.1! lukem       1: /*     $NetBSD$        */
1.6       cgd         2:
1.1       cgd         3: /*
1.6       cgd         4:  * Copyright (c) 1980, 1993
                      5:  *     The Regents of the University of California.  All rights reserved.
1.1       cgd         6:  *
                      7:  * Redistribution and use in source and binary forms, with or without
                      8:  * modification, are permitted provided that the following conditions
                      9:  * are met:
                     10:  * 1. Redistributions of source code must retain the above copyright
                     11:  *    notice, this list of conditions and the following disclaimer.
                     12:  * 2. Redistributions in binary form must reproduce the above copyright
                     13:  *    notice, this list of conditions and the following disclaimer in the
                     14:  *    documentation and/or other materials provided with the distribution.
                     15:  * 3. All advertising materials mentioning features or use of this software
                     16:  *    must display the following acknowledgement:
                     17:  *     This product includes software developed by the University of
                     18:  *     California, Berkeley and its contributors.
                     19:  * 4. Neither the name of the University nor the names of its contributors
                     20:  *    may be used to endorse or promote products derived from this software
                     21:  *    without specific prior written permission.
                     22:  *
                     23:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     24:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     25:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     26:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     27:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     28:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     29:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     30:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     31:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     32:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     33:  * SUCH DAMAGE.
                     34:  */
                     35:
1.12      lukem      36: #include <sys/cdefs.h>
1.1       cgd        37: #ifndef lint
1.6       cgd        38: #if 0
                     39: static char sccsid[] = "@(#)termcap.c  8.1 (Berkeley) 6/4/93";
                     40: #else
1.43.2.1! lukem      41: __RCSID("$NetBSD$");
1.6       cgd        42: #endif
1.1       cgd        43: #endif /* not lint */
                     44:
1.38      christos   45: #include <sys/types.h>
                     46: #include <sys/param.h>
1.21      lukem      47: #include <assert.h>
                     48: #include <ctype.h>
1.4       cgd        49: #include <stdio.h>
                     50: #include <stdlib.h>
                     51: #include <string.h>
1.13      lukem      52: #include <termcap.h>
1.18      blymn      53: #include <errno.h>
1.1       cgd        54: #include "pathnames.h"
1.23      blymn      55: #include "termcap_private.h"
1.18      blymn      56:
1.38      christos   57: #define        PBUFSIZ         MAXPATHLEN      /* max length of filename path */
                     58: #define        PVECSIZ         32              /* max number of names in path */
                     59:
1.1       cgd        60: /*
                     61:  * termcap - routines for dealing with the terminal capability data base
                     62:  *
                     63:  * BUG:                Should use a "last" pointer in tbuf, so that searching
                     64:  *             for capabilities alphabetically would not be a n**2/2
                     65:  *             process when large numbers of capabilities are given.
                     66:  * Note:       If we add a last pointer now we will screw up the
                     67:  *             tc capability. We really should compile termcap.
                     68:  *
                     69:  * Essentially all the work here is scanning and decoding escapes
                     70:  * in string capabilities.  We don't use stdio because the editor
                     71:  * doesn't, and because living w/o it is not hard.
                     72:  */
                     73:
1.43.2.1! lukem      74: static char *tbuf = NULL;              /* termcap buffer */
        !            75: static struct tinfo *fbuf = NULL;      /* untruncated termcap buffer */
1.1       cgd        76:
                     77: /*
1.31      blymn      78:  * Set the termcap entry to the arbitrary string passed in, this can
                     79:  * be used to provide a "dummy" termcap entry if a real one does not
                     80:  * exist.  This function will malloc the buffer and space for the
                     81:  * string.  If an error occurs return -1 otherwise return 0.
                     82:  */
                     83: int
                     84: t_setinfo(struct tinfo **bp, const char *entry)
                     85: {
1.36      blymn      86:        char capability[256], *cap_ptr;
                     87:        size_t limit;
                     88:
1.37      lukem      89:        _DIAGASSERT(bp != NULL);
                     90:        _DIAGASSERT(entry != NULL);
                     91:
1.31      blymn      92:        if ((*bp = malloc(sizeof(struct tinfo))) == NULL)
                     93:                return -1;
                     94:
                     95:        if (((*bp)->info = (char *) malloc(strlen(entry) + 1)) == NULL)
                     96:                return -1;
                     97:
                     98:        strcpy((*bp)->info, entry);
1.36      blymn      99:
                    100:        cap_ptr = capability;
                    101:        limit = 255;
                    102:        (*bp)->up = t_getstr(*bp, "up", &cap_ptr, &limit);
1.39      christos  103:        if ((*bp)->up)
                    104:                (*bp)->up = strdup((*bp)->up);
1.36      blymn     105:        cap_ptr = capability;
                    106:        limit = 255;
                    107:        (*bp)->bc = t_getstr(*bp, "bc", &cap_ptr, &limit);
1.39      christos  108:        if ((*bp)->bc)
                    109:                (*bp)->bc = strdup((*bp)->bc);
1.40      christos  110:        (*bp)->tbuf = NULL;
1.36      blymn     111:
1.31      blymn     112:        return 0;
                    113: }
                    114:
                    115: /*
1.18      blymn     116:  * Get an extended entry for the terminal name.  This differs from
                    117:  * tgetent only in a) the buffer is malloc'ed for the caller and
                    118:  * b) the termcap entry is not truncated to 1023 characters.
1.1       cgd       119:  */
1.18      blymn     120:
1.4       cgd       121: int
1.18      blymn     122: t_getent(bp, name)
                    123:        struct tinfo **bp;
1.14      mycroft   124:        const char *name;
1.1       cgd       125: {
1.13      lukem     126:        char  *p;
                    127:        char  *cp;
1.6       cgd       128:        char **fname;
                    129:        char  *home;
1.27      blymn     130:        int    i, did_getset;
1.36      blymn     131:        size_t limit;
1.6       cgd       132:        char   pathbuf[PBUFSIZ];        /* holds raw path of filenames */
                    133:        char  *pathvec[PVECSIZ];        /* to point to names in pathbuf */
                    134:        char  *termpath;
1.36      blymn     135:        char  capability[256], *cap_ptr;
1.43.2.1! lukem     136:        int error;
1.36      blymn     137:
1.1       cgd       138:
1.21      lukem     139:        _DIAGASSERT(bp != NULL);
                    140:        _DIAGASSERT(name != NULL);
                    141:
1.43.2.1! lukem     142:        if ((*bp = malloc(sizeof(struct tinfo))) == NULL)
        !           143:                return 0;
1.18      blymn     144:
1.6       cgd       145:        fname = pathvec;
1.1       cgd       146:        p = pathbuf;
                    147:        cp = getenv("TERMCAP");
                    148:        /*
                    149:         * TERMCAP can have one of two things in it. It can be the
1.9       mikel     150:         * name of a file to use instead of
                    151:         * /usr/share/misc/termcap. In this case it better start with
                    152:         * a "/". Or it can be an entry to use so we don't have to
1.16      abs       153:         * read the file. In this case cgetset() withh crunch out the
                    154:         * newlines.  If TERMCAP does not hold a file name then a path
                    155:         * of names is searched instead.  The path is found in the
                    156:         * TERMPATH variable, or becomes _PATH_DEF ("$HOME/.termcap
                    157:         * /usr/share/misc/termcap") if no TERMPATH exists.
1.1       cgd       158:         */
                    159:        if (!cp || *cp != '/') {        /* no TERMCAP or it holds an entry */
1.7       pk        160:                if ((termpath = getenv("TERMPATH")) != NULL)
1.38      christos  161:                        (void)strlcpy(pathbuf, termpath, sizeof(pathbuf));
1.1       cgd       162:                else {
1.7       pk        163:                        if ((home = getenv("HOME")) != NULL) {
                    164:                                /* set up default */
1.1       cgd       165:                                p += strlen(home);      /* path, looking in */
1.38      christos  166:                                (void)strlcpy(pathbuf, home,
                    167:                                    sizeof(pathbuf)); /* $HOME first */
                    168:                                if ((p - pathbuf) < sizeof(pathbuf) - 1)
                    169:                                    *p++ = '/';
1.1       cgd       170:                        }       /* if no $HOME look in current directory */
1.38      christos  171:                        if ((p - pathbuf) < sizeof(pathbuf) - 1) {
                    172:                            (void)strlcpy(p, _PATH_DEF,
                    173:                                sizeof(pathbuf) - (p - pathbuf));
                    174:                        }
1.1       cgd       175:                }
                    176:        }
1.38      christos  177:        else {
                    178:                /* user-defined name in TERMCAP; still can be tokenized */
                    179:                (void)strlcpy(pathbuf, cp, sizeof(pathbuf));
                    180:        }
1.1       cgd       181:
                    182:        *fname++ = pathbuf;     /* tokenize path into vector of names */
                    183:        while (*++p)
                    184:                if (*p == ' ' || *p == ':') {
                    185:                        *p = '\0';
                    186:                        while (*++p)
                    187:                                if (*p != ' ' && *p != ':')
                    188:                                        break;
                    189:                        if (*p == '\0')
                    190:                                break;
                    191:                        *fname++ = p;
                    192:                        if (fname >= pathvec + PVECSIZ) {
                    193:                                fname--;
                    194:                                break;
                    195:                        }
                    196:                }
1.38      christos  197:        *fname = NULL;                  /* mark end of vector */
1.27      blymn     198:
1.28      christos  199:        /*
                    200:         * try ignoring TERMCAP if it has a ZZ in it, we do this
                    201:         * because a TERMCAP with ZZ in it indicates the entry has been
                    202:         * exported by another program using the "old" interface, the
                    203:         * termcap entry has been truncated and ZZ points to an address
                    204:         * in the exporting programs memory space which is of no use
                    205:         * here - anyone who is exporting the termcap entry and then
                    206:         * reading it back again in the same program deserves to be
                    207:         * taken out, beaten up, dragged about, shot and then hurt some
                    208:         * more.
                    209:         */
1.27      blymn     210:        did_getset = 0;
                    211:        if (cp && *cp && *cp != '/' && strstr(cp, ":ZZ") == NULL) {
                    212:                did_getset = 1;
1.43.2.1! lukem     213:                if (cgetset(cp) < 0) {
        !           214:                        error = -2;
        !           215:                        goto out;
        !           216:                }
1.27      blymn     217:        }
                    218:
1.11      mrg       219:        /*
                    220:         * XXX potential security hole here in a set-id program if the
                    221:         * user had setup name to be built from a path they can not
                    222:         * normally read.
                    223:         */
1.18      blymn     224:        (*bp)->info = NULL;
                    225:        i = cgetent(&((*bp)->info), pathvec, name);
1.8       jtc       226:
1.28      christos  227:        /*
                    228:         * if we get an error and we skipped doing the cgetset before
                    229:         * we try with TERMCAP in place - we may be using a truncated
                    230:         * termcap entry but what else can one do?
                    231:         */
1.27      blymn     232:        if ((i < 0) && (did_getset == 0)) {
                    233:                if (cp && *cp && *cp != '/')
1.43.2.1! lukem     234:                        if (cgetset(cp) < 0) {
        !           235:                                error = -2;
        !           236:                                goto out;
        !           237:                        }
1.27      blymn     238:                i = cgetent(&((*bp)->info), pathvec, name);
                    239:        }
1.31      blymn     240:
1.6       cgd       241:        /* no tc reference loop return code in libterm XXX */
1.43.2.1! lukem     242:        if (i == -3) {
        !           243:                error = -1;
        !           244:                goto out;
        !           245:        }
1.36      blymn     246:
1.43.2.1! lukem     247:        /*
        !           248:         * fill in t_goto capabilities - this prevents memory leaks
        !           249:         * and is more efficient than fetching these capabilities
        !           250:         * every time t_goto is called.
        !           251:         */
1.36      blymn     252:        if (i >= 0) {
                    253:                cap_ptr = capability;
                    254:                limit = 255;
                    255:                (*bp)->up = t_getstr(*bp, "up", &cap_ptr, &limit);
1.39      christos  256:                if ((*bp)->up)
                    257:                        (*bp)->up = strdup((*bp)->up);
1.36      blymn     258:                cap_ptr = capability;
                    259:                limit = 255;
                    260:                (*bp)->bc = t_getstr(*bp, "bc", &cap_ptr, &limit);
1.39      christos  261:                if ((*bp)->bc)
                    262:                        (*bp)->bc = strdup((*bp)->bc);
1.40      christos  263:                (*bp)->tbuf = NULL;
1.43.2.1! lukem     264:        } else {
        !           265:                error = i + 1;
        !           266:                goto out;
1.36      blymn     267:        }
                    268:
1.6       cgd       269:        return (i + 1);
1.43.2.1! lukem     270: out:
        !           271:        free(*bp);
        !           272:        *bp = NULL;
        !           273:        return error;
1.1       cgd       274: }
                    275:
                    276: /*
1.18      blymn     277:  * Get an entry for terminal name in buffer bp from the termcap file.
                    278:  */
                    279: int
                    280: tgetent(bp, name)
                    281:        char *bp;
                    282:        const char *name;
                    283: {
                    284:        int i, plen, elen, c;
                    285:         char *ptrbuf = NULL;
                    286:
                    287:        i = t_getent(&fbuf, name);
                    288:
                    289:        if (i == 1) {
1.28      christos  290:                /*
                    291:                 * stash the full buffer pointer as the ZZ capability
                    292:                 * in the termcap buffer passed.
                    293:                 */
1.18      blymn     294:                 plen = asprintf(&ptrbuf, ":ZZ=%p", fbuf->info);
1.38      christos  295:                (void)strlcpy(bp, fbuf->info, 1024);
1.18      blymn     296:                 elen = strlen(bp);
1.28      christos  297:                /*
                    298:                 * backup over the entry if the addition of the full
                    299:                 * buffer pointer will overflow the buffer passed.  We
                    300:                 * want to truncate the termcap entry on a capability
                    301:                 * boundary.
                    302:                 */
1.18      blymn     303:                 if ((elen + plen) > 1023) {
                    304:                        bp[1023 - plen] = '\0';
                    305:                        for (c = (elen - plen); c > 0; c--) {
                    306:                                if (bp[c] == ':') {
                    307:                                        bp[c] = '\0';
                    308:                                        break;
                    309:                                }
                    310:                        }
                    311:                }
                    312:
                    313:                strcat(bp, ptrbuf);
                    314:                 tbuf = bp;
                    315:        }
                    316:
                    317:        return i;
                    318: }
                    319:
                    320: /*
1.1       cgd       321:  * Return the (numeric) option id.
                    322:  * Numeric options look like
                    323:  *     li#80
                    324:  * i.e. the option string is separated from the numeric value by
                    325:  * a # character.  If the option is not found we return -1.
                    326:  * Note that we handle octal numbers beginning with 0.
                    327:  */
1.4       cgd       328: int
1.18      blymn     329: t_getnum(info, id)
                    330:        struct tinfo *info;
1.14      mycroft   331:        const char *id;
1.1       cgd       332: {
1.4       cgd       333:        long num;
1.1       cgd       334:
1.28      christos  335:        _DIAGASSERT(info != NULL);
1.21      lukem     336:        _DIAGASSERT(id != NULL);
                    337:
1.18      blymn     338:        if (cgetnum(info->info, id, &num) == 0)
1.15      agc       339:                return (int)(num);
1.4       cgd       340:        else
1.6       cgd       341:                return (-1);
1.1       cgd       342: }
                    343:
1.18      blymn     344: int
                    345: tgetnum(id)
                    346:        const char *id;
                    347: {
1.43.2.1! lukem     348:        return fbuf ? t_getnum(fbuf, id) : -1;
1.18      blymn     349: }
                    350:
1.1       cgd       351: /*
                    352:  * Handle a flag option.
                    353:  * Flag options are given "naked", i.e. followed by a : or the end
                    354:  * of the buffer.  Return 1 if we find the option, or 0 if it is
                    355:  * not given.
                    356:  */
1.18      blymn     357: int t_getflag(info, id)
                    358:        struct tinfo *info;
                    359:        const char *id;
                    360: {
1.28      christos  361:        _DIAGASSERT(info != NULL);
                    362:        _DIAGASSERT(id != NULL);
                    363:
1.18      blymn     364:        return (cgetcap(info->info, id, ':') != NULL);
                    365: }
                    366:
1.6       cgd       367: int
1.1       cgd       368: tgetflag(id)
1.14      mycroft   369:        const char *id;
1.1       cgd       370: {
1.43.2.1! lukem     371:        return fbuf ? t_getflag(fbuf, id) : 0;
1.1       cgd       372: }
                    373:
                    374: /*
                    375:  * Get a string valued option.
                    376:  * These are given as
                    377:  *     cl=^Z
                    378:  * Much decoding is done on the strings, and the strings are
                    379:  * placed in area, which is a ref parameter which is updated.
1.18      blymn     380:  * limit is the number of characters allowed to be put into
                    381:  * area, this is updated.
1.1       cgd       382:  */
                    383: char *
1.18      blymn     384: t_getstr(info, id, area, limit)
                    385:        struct tinfo *info;
1.14      mycroft   386:        const char *id;
                    387:        char **area;
1.19      blymn     388:        size_t *limit;
1.1       cgd       389: {
1.4       cgd       390:        char *s;
1.1       cgd       391:        int i;
1.21      lukem     392:
1.28      christos  393:        _DIAGASSERT(info != NULL);
1.21      lukem     394:        _DIAGASSERT(id != NULL);
1.29      lukem     395:        /* area may be NULL */
1.17      simonb    396:
1.4       cgd       397:
1.28      christos  398:        if ((i = cgetstr(info->info, id, &s)) < 0) {
1.18      blymn     399:                errno = ENOENT;
1.26      blymn     400:                if ((area == NULL) && (limit != NULL))
1.25      blymn     401:                        *limit = 0;
1.18      blymn     402:                return NULL;
                    403:        }
                    404:
1.20      blymn     405:        if (area != NULL) {
1.28      christos  406:                /*
                    407:                 * check if there is room for the new entry to be put into
                    408:                 * area
                    409:                 */
1.20      blymn     410:                if (limit != NULL && (*limit < i)) {
1.35      thorpej   411:                        errno = E2BIG;
1.34      christos  412:                        free(s);
1.20      blymn     413:                        return NULL;
                    414:                }
1.35      thorpej   415:
1.39      christos  416:                (void)strcpy(*area, s);
                    417:                free(s);
                    418:                s = *area;
1.20      blymn     419:                *area += i + 1;
                    420:                if (limit != NULL) *limit -= i;
1.35      thorpej   421:
                    422:                return (s);
1.20      blymn     423:        } else {
1.28      christos  424:                _DIAGASSERT(limit != NULL);
1.20      blymn     425:                *limit = i;
1.33      itojun    426:                free(s);
1.4       cgd       427:                return NULL;
1.18      blymn     428:        }
                    429: }
                    430:
                    431: /*
                    432:  * Get a string valued option.
                    433:  * These are given as
                    434:  *     cl=^Z
                    435:  * Much decoding is done on the strings, and the strings are
                    436:  * placed in area, which is a ref parameter which is updated.
                    437:  * No checking on area overflow.
                    438:  */
                    439: char *
                    440: tgetstr(id, area)
                    441:        const char *id;
                    442:        char **area;
                    443: {
                    444:        struct tinfo dummy;
1.28      christos  445:        char ids[3];
                    446:
                    447:        _DIAGASSERT(id != NULL);
1.43.2.1! lukem     448:
        !           449:        if (fbuf == NULL)
        !           450:                return NULL;
        !           451:
1.28      christos  452:        /*
                    453:         * XXX
                    454:         * This is for all the boneheaded programs that relied on tgetstr
                    455:         * to look only at the first 2 characters of the string passed...
                    456:         */
                    457:        ids[0] = id[0];
                    458:        ids[1] = id[1];
                    459:        ids[2] = '\0';
1.18      blymn     460:
                    461:        if ((id[0] == 'Z') && (id[1] == 'Z')) {
                    462:                dummy.info = tbuf;
1.28      christos  463:                return t_getstr(&dummy, ids, area, NULL);
1.18      blymn     464:        }
                    465:        else
1.28      christos  466:                return t_getstr(fbuf, ids, area, NULL);
1.18      blymn     467: }
                    468:
1.30      blymn     469: /*
1.41      christos  470:  * Return a string valued option specified by id, allocating memory to
                    471:  * an internal buffer as necessary. The memory allocated can be
                    472:  * free'd by a call to t_freent().
1.39      christos  473:  *
1.41      christos  474:  * If the string is not found or memory allocation fails then NULL
                    475:  * is returned.
1.30      blymn     476:  */
1.40      christos  477: #define BSIZE 256
1.30      blymn     478: char *
1.40      christos  479: t_agetstr(struct tinfo *info, const char *id)
1.30      blymn     480: {
1.39      christos  481:        size_t new_size;
1.40      christos  482:        struct tbuf *tb;
1.30      blymn     483:
                    484:        _DIAGASSERT(info != NULL);
                    485:        _DIAGASSERT(id != NULL);
                    486:
                    487:        t_getstr(info, id, NULL, &new_size);
                    488:
1.40      christos  489:        /* either the string is empty or the capability does not exist. */
                    490:        if (new_size == 0)
1.30      blymn     491:                return NULL;
                    492:
1.43      blymn     493:        if ((tb = info->tbuf) == NULL || (tb->eptr - tb->ptr) < (new_size + 1)) {
1.40      christos  494:                if (new_size < BSIZE)
                    495:                        new_size = BSIZE;
                    496:                else
                    497:                        new_size++;
                    498:
                    499:                if ((tb = malloc(sizeof(*info->tbuf))) == NULL)
                    500:                        return NULL;
                    501:
                    502:                if ((tb->data = tb->ptr = tb->eptr = malloc(new_size)) == NULL)
1.30      blymn     503:                        return NULL;
1.40      christos  504:
                    505:                tb->eptr += new_size;
                    506:
                    507:                if (info->tbuf != NULL)
                    508:                        tb->next = info->tbuf;
                    509:                else
                    510:                        tb->next = NULL;
                    511:
                    512:                info->tbuf = tb;
1.30      blymn     513:        }
1.40      christos  514:        return t_getstr(info, id, &tb->ptr, NULL);
1.30      blymn     515: }
                    516:
1.18      blymn     517: /*
                    518:  * Free the buffer allocated by t_getent
                    519:  *
                    520:  */
                    521: void
                    522: t_freent(info)
                    523:        struct tinfo *info;
                    524: {
1.42      blymn     525:        struct tbuf *tb, *wb;
1.28      christos  526:        _DIAGASSERT(info != NULL);
1.18      blymn     527:        free(info->info);
1.36      blymn     528:        if (info->up != NULL)
                    529:                free(info->up);
                    530:        if (info->bc != NULL)
                    531:                free(info->bc);
1.40      christos  532:        for (tb = info->tbuf; tb;) {
1.42      blymn     533:                wb = tb;
                    534:                tb = tb->next;
                    535:                free(wb->data);
                    536:                free(wb);
1.40      christos  537:        }
1.18      blymn     538:        free(info);
1.1       cgd       539: }
1.24      blymn     540:
                    541: /*
                    542:  * Get the terminal name string from the termcap entry.
                    543:  *
                    544:  */
                    545: int
1.28      christos  546: t_getterm(info, area, limit)
                    547:        struct tinfo *info;
                    548:        char **area;
                    549:        size_t *limit;
1.24      blymn     550: {
                    551:        char *endp;
                    552:        size_t count;
                    553:
1.28      christos  554:        _DIAGASSERT(info != NULL);
                    555:        if ((endp = strchr(info->info, ':')) == NULL) {
1.24      blymn     556:                errno = EINVAL;
                    557:                return -1;
                    558:        }
                    559:
                    560:
                    561:        count = endp - info->info + 1;
                    562:        if (area == NULL) {
1.28      christos  563:                _DIAGASSERT(limit != NULL);
1.24      blymn     564:                *limit = count;
                    565:                return 0;
                    566:        } else {
                    567:                if ((limit != NULL) && (count > *limit)) {
                    568:                        errno = E2BIG;
                    569:                        return -1;
                    570:                }
                    571:
1.38      christos  572:                (void)strlcpy(*area, info->info, count);
1.24      blymn     573:                if (limit != NULL)
                    574:                        *limit -= count;
                    575:        }
                    576:
                    577:        return 0;
                    578: }

CVSweb <webmaster@jp.NetBSD.org>