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

Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.

Diff for /src/lib/libterm/Attic/termcap.c between version 1.3 and 1.54.18.1

version 1.3, 1994/01/13 22:24:06 version 1.54.18.1, 2009/08/04 20:04:39
Line 1 
Line 1 
   /*      $NetBSD$        */
   
 /*  /*
  * Copyright (c) 1980 The Regents of the University of California.   * Copyright (c) 1980, 1993
  * All rights reserved.   *      The Regents of the University of California.  All rights reserved.
  *   *
  * Redistribution and use in source and binary forms, with or without   * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions   * modification, are permitted provided that the following conditions
Line 10 
Line 12 
  * 2. Redistributions in binary form must reproduce the above copyright   * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the   *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.   *    documentation and/or other materials provided with the distribution.
  * 3. All advertising materials mentioning features or use of this software   * 3. Neither the name of the University nor the names of its contributors
  *    must display the following acknowledgement:  
  *      This product includes software developed by the University of  
  *      California, Berkeley and its contributors.  
  * 4. Neither the name of the University nor the names of its contributors  
  *    may be used to endorse or promote products derived from this software   *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.   *    without specific prior written permission.
  *   *
Line 31 
Line 29 
  * SUCH DAMAGE.   * SUCH DAMAGE.
  */   */
   
   #include <sys/cdefs.h>
 #ifndef lint  #ifndef lint
 /*static char sccsid[] = "from: @(#)termcap.c   5.5 (Berkeley) 6/1/90";*/  #if 0
 static char rcsid[] = "$Id$";  static char sccsid[] = "@(#)termcap.c   8.1 (Berkeley) 6/4/93";
   #else
   __RCSID("$NetBSD$");
   #endif
 #endif /* not lint */  #endif /* not lint */
   
 #define BUFSIZ          1024  #include <sys/types.h>
 #define MAXHOP          32      /* max number of tc= indirections */  #include <sys/param.h>
 #define PBUFSIZ         512     /* max length of filename path */  #include <assert.h>
 #define PVECSIZ         32      /* max number of names in path */  
   
 #include <ctype.h>  #include <ctype.h>
   #include <stdio.h>
   #include <stdlib.h>
   #include <string.h>
   #include <termcap.h>
   #include <errno.h>
 #include "pathnames.h"  #include "pathnames.h"
   #include "termcap_private.h"
   
   #define PBUFSIZ         MAXPATHLEN      /* max length of filename path */
   #define PVECSIZ         32              /* max number of names in path */
   #define CAPSIZ          256             /* max capability size */
   
 /*  /*
  * termcap - routines for dealing with the terminal capability data base   * termcap - routines for dealing with the terminal capability data base
Line 58  static char rcsid[] = "$Id$";
Line 68  static char rcsid[] = "$Id$";
  * doesn't, and because living w/o it is not hard.   * doesn't, and because living w/o it is not hard.
  */   */
   
 static  char *tbuf;  static char *tbuf = NULL;               /* termcap buffer */
 static  int hopcount;   /* detect infinite loops in termcap, init 0 */  static struct tinfo *fbuf = NULL;       /* untruncated termcap buffer */
 static  char pathbuf[PBUFSIZ];          /* holds raw path of filenames */  
 static  char *pathvec[PVECSIZ];         /* to point to names in pathbuf */  
 static  char **pvec;                    /* holds usable tail of path vector */  
 static  char *tskip();  
 static  char *tdecode();  
 char    *tgetstr();  
 char    *getenv();  
   
 /*  /*
  * Get an entry for terminal name in buffer bp from the termcap file.   * Set the termcap entry to the arbitrary string passed in, this can
    * be used to provide a "dummy" termcap entry if a real one does not
    * exist.  This function will malloc the buffer and space for the
    * string.  If an error occurs return -1 otherwise return 0.
  */   */
 tgetent(bp, name)  int
         char *bp, *name;  t_setinfo(struct tinfo **bp, const char *entry)
 {  {
         register char *p;          char capability[CAPSIZ], *cap_ptr;
         register char *cp;          size_t limit;
         register int c;  
         char *term, *home, *termpath;          _DIAGASSERT(bp != NULL);
         char **fname = pathvec;          _DIAGASSERT(entry != NULL);
   
           if ((*bp = malloc(sizeof(struct tinfo))) == NULL)
                   return -1;
   
           if (((*bp)->info = (char *) malloc(strlen(entry) + 1)) == NULL)
                   return -1;
   
           strcpy((*bp)->info, entry);
   
           cap_ptr = capability;
           limit = sizeof(capability) - 1;
           (*bp)->up = t_getstr(*bp, "up", &cap_ptr, &limit);
           if ((*bp)->up)
                   (*bp)->up = strdup((*bp)->up);
           cap_ptr = capability;
           limit = sizeof(capability) - 1;
           (*bp)->bc = t_getstr(*bp, "bc", &cap_ptr, &limit);
           if ((*bp)->bc)
                   (*bp)->bc = strdup((*bp)->bc);
           (*bp)->tbuf = NULL;
   
           return 0;
   }
   
   /*
    * Get an extended entry for the terminal name.  This differs from
    * tgetent only in a) the buffer is malloc'ed for the caller and
    * b) the termcap entry is not truncated to 1023 characters.
    */
   
   int
   t_getent(struct tinfo **bp, const char *name)
   {
           char  *p;
           char  *cp;
           char **fname;
           char  *home;
           int    i, did_getset;
           size_t limit;
           char   pathbuf[PBUFSIZ];        /* holds raw path of filenames */
           char  *pathvec[PVECSIZ];        /* to point to names in pathbuf */
           char  *termpath;
           char  capability[CAPSIZ], *cap_ptr;
           int error;
   
   
         pvec = pathvec;          _DIAGASSERT(bp != NULL);
         tbuf = bp;          _DIAGASSERT(name != NULL);
   
           if ((*bp = malloc(sizeof(struct tinfo))) == NULL)
                   return 0;
   
           fname = pathvec;
         p = pathbuf;          p = pathbuf;
         cp = getenv("TERMCAP");          cp = getenv("TERMCAP");
         /*          /*
          * TERMCAP can have one of two things in it. It can be the           * TERMCAP can have one of two things in it. It can be the
          * name of a file to use instead of /etc/termcap. In this           * name of a file to use instead of
          * case it better start with a "/". Or it can be an entry to           * /usr/share/misc/termcap. In this case it better start with
          * use so we don't have to read the file. In this case it           * a "/". Or it can be an entry to use so we don't have to
          * has to already have the newlines crunched out.  If TERMCAP           * read the file. In this case cgetset() withh crunch out the
          * does not hold a file name then a path of names is searched           * newlines.  If TERMCAP does not hold a file name then a path
          * instead.  The path is found in the TERMPATH variable, or           * of names is searched instead.  The path is found in the
          * becomes "$HOME/.termcap /etc/termcap" if no TERMPATH exists.           * TERMPATH variable, or becomes _PATH_DEF ("$HOME/.termcap
            * /usr/share/misc/termcap") if no TERMPATH exists.
          */           */
         if (!cp || *cp != '/') {        /* no TERMCAP or it holds an entry */          if (!cp || *cp != '/') {        /* no TERMCAP or it holds an entry */
                 if (termpath = getenv("TERMPATH"))                  if ((termpath = getenv("TERMPATH")) != NULL)
                         strncpy(pathbuf, termpath, PBUFSIZ);                          (void)strlcpy(pathbuf, termpath, sizeof(pathbuf));
                 else {                  else {
                         if (home = getenv("HOME")) {    /* set up default */                          if ((home = getenv("HOME")) != NULL) {
                                   /* set up default */
                                 p += strlen(home);      /* path, looking in */                                  p += strlen(home);      /* path, looking in */
                                 strcpy(pathbuf, home);  /* $HOME first */                                  (void)strlcpy(pathbuf, home,
                                 *p++ = '/';                                      sizeof(pathbuf)); /* $HOME first */
                                   if ((size_t)(p - pathbuf) < sizeof(pathbuf) - 1)
                                       *p++ = '/';
                         }       /* if no $HOME look in current directory */                          }       /* if no $HOME look in current directory */
                         strncpy(p, _PATH_DEF, PBUFSIZ - (p - pathbuf));                          if ((size_t)(p - pathbuf) < sizeof(pathbuf) - 1) {
                               (void)strlcpy(p, _PATH_DEF,
                                   sizeof(pathbuf) - (p - pathbuf));
                           }
                 }                  }
         }          }
         else                            /* user-defined name in TERMCAP */          else {
                 strncpy(pathbuf, cp, PBUFSIZ);  /* still can be tokenized */                  /* user-defined name in TERMCAP; still can be tokenized */
                   (void)strlcpy(pathbuf, cp, sizeof(pathbuf));
           }
   
         *fname++ = pathbuf;     /* tokenize path into vector of names */          *fname++ = pathbuf;     /* tokenize path into vector of names */
         while (*++p)          while (*++p)
Line 124  tgetent(bp, name)
Line 189  tgetent(bp, name)
                                 break;                                  break;
                         }                          }
                 }                  }
         *fname = (char *) 0;                    /* mark end of vector */          *fname = NULL;                  /* mark end of vector */
         if (cp && *cp && *cp != '/') {  
                 tbuf = cp;          /*
                 c = tnamatch(name);           * try ignoring TERMCAP if it has a ZZ in it, we do this
                 tbuf = bp;           * because a TERMCAP with ZZ in it indicates the entry has been
                 if (c) {           * exported by another program using the "old" interface, the
                         strcpy(bp,cp);           * termcap entry has been truncated and ZZ points to an address
                         return (tnchktc());           * in the exporting programs memory space which is of no use
            * here - anyone who is exporting the termcap entry and then
            * reading it back again in the same program deserves to be
            * taken out, beaten up, dragged about, shot and then hurt some
            * more.
            */
           did_getset = 0;
           if (cp && *cp && *cp != '/' && strstr(cp, ":ZZ") == NULL) {
                   did_getset = 1;
                   if (cgetset(cp) < 0) {
                           error = -2;
                           goto out;
                 }                  }
         }          }
         return (tfindent(bp, name));    /* find terminal entry in path */  
           /*
            * XXX potential security hole here in a set-id program if the
            * user had setup name to be built from a path they can not
            * normally read.
            */
           (*bp)->info = NULL;
           i = cgetent(&((*bp)->info), (const char *const *)pathvec, name);
   
           /*
            * if we get an error and we skipped doing the cgetset before
            * we try with TERMCAP in place - we may be using a truncated
            * termcap entry but what else can one do?
            */
           if ((i < 0) && (did_getset == 0)) {
                   if (cp && *cp && *cp != '/')
                           if (cgetset(cp) < 0) {
                                   error = -2;
                                   goto out;
                           }
                   i = cgetent(&((*bp)->info), (const char *const *)pathvec, name);
           }
   
           /* no tc reference loop return code in libterm XXX */
           if (i == -3) {
                   error = -1;
                   goto out;
           }
   
           /*
            * fill in t_goto capabilities - this prevents memory leaks
            * and is more efficient than fetching these capabilities
            * every time t_goto is called.
            */
           if (i >= 0) {
                   cap_ptr = capability;
                   limit = sizeof(capability) - 1;
                   (*bp)->up = t_getstr(*bp, "up", &cap_ptr, &limit);
                   if ((*bp)->up)
                           (*bp)->up = strdup((*bp)->up);
                   cap_ptr = capability;
                   limit = sizeof(capability) - 1;
                   (*bp)->bc = t_getstr(*bp, "bc", &cap_ptr, &limit);
                   if ((*bp)->bc)
                           (*bp)->bc = strdup((*bp)->bc);
                   (*bp)->tbuf = NULL;
           } else {
                   error = i + 1;
                   goto out;
           }
   
           return (i + 1);
   out:
           free(*bp);
           *bp = NULL;
           return error;
 }  }
   
 /*  /*
  * tfindent - reads through the list of files in pathvec as if they were one   * Get an entry for terminal name in buffer bp from the termcap file.
  * continuous file searching for terminal entries along the way.  It will   */
  * participate in indirect recursion if the call to tnchktc() finds a tc=  int
  * field, which is only searched for in the current file and files ocurring  tgetent(char *bp, const char *name)
  * after it in pathvec.  The usable part of this vector is kept in the global  {
  * variable pvec.  Terminal entries may not be broken across files.  Parse is          int i, plen, elen, c;
  * very rudimentary; we just notice escaped newlines.          char *ptrbuf = NULL;
  */  
 tfindent(bp, name)  
         char *bp, *name;  
 {  
         register char *cp;  
         register int c;  
         register int i, cnt;  
         char ibuf[BUFSIZ];  
         int opencnt = 0;  
         int tf;  
   
         tbuf = bp;  
 nextfile:  
         i = cnt = 0;  
         while (*pvec && (tf = open(*pvec, 0)) < 0)  
                 pvec++;  
         if (!*pvec)  
                 return (opencnt ? 0 : -1);  
         opencnt++;  
         for (;;) {  
                 cp = bp;  
                 for (;;) {  
                         if (i == cnt) {  
                                 cnt = read(tf, ibuf, BUFSIZ);  
                                 if (cnt <= 0) {  
                                         close(tf);  
                                         pvec++;  
                                         goto nextfile;  
                                 }  
                                 i = 0;  
                         }  
                         c = ibuf[i++];  
                         if (c == '\n') {  
                                 if (cp > bp && cp[-1] == '\\'){  
                                         cp--;  
                                         continue;  
                                 }  
                                 break;  
                         }  
                         if (cp >= bp+BUFSIZ) {  
                                 write(2,"Termcap entry too long\n", 23);  
                                 break;  
                         } else  
                                 *cp++ = c;  
                 }  
                 *cp = 0;  
   
           i = t_getent(&fbuf, name);
   
           if (i == 1) {
                 /*                  /*
                  * The real work for the match.                   * if the termcap entry is larger than 1023 bytes,
                    * stash the full buffer pointer as the ZZ capability
                    * in the termcap buffer passed.
                  */                   */
                 if (tnamatch(name)) {                  if (strlcpy(bp, fbuf->info, 1024) >= 1024) {
                         close(tf);                          plen = asprintf(&ptrbuf, ":ZZ=%p", fbuf->info);
                         return(tnchktc());                          (void)strlcpy(bp, fbuf->info, 1024);
                           elen = strlen(bp);
                           /*
                            * backup over the entry if the addition of the full
                            * buffer pointer will overflow the buffer passed.  We
                            * want to truncate the termcap entry on a capability
                            * boundary.
                            */
                           if ((elen + plen) > 1023) {
                                   bp[1023 - plen] = '\0';
                                   for (c = (elen - plen); c > 0; c--) {
                                           if (bp[c] == ':') {
                                                   bp[c] = '\0';
                                                   break;
                                           }
                                   }
   
                           }
                           strcat(bp, ptrbuf);
                 }                  }
                   tbuf = bp;
         }          }
 }  
   
 /*          return i;
  * tnchktc: check the last entry, see if it's tc=xxx. If so,  
  * recursively find xxx and append that entry (minus the names)  
  * to take the place of the tc=xxx entry. This allows termcap  
  * entries to say "like an HP2621 but doesn't turn on the labels".  
  * Note that this works because of the left to right scan.  
  */  
 tnchktc()  
 {  
         register char *p, *q;  
         char tcname[16];        /* name of similar terminal */  
         char tcbuf[BUFSIZ];  
         char *holdtbuf = tbuf;  
         int l;  
   
         p = tbuf + strlen(tbuf) - 2;    /* before the last colon */  
         while (*--p != ':')  
                 if (p<tbuf) {  
                         write(2, "Bad termcap entry\n", 18);  
                         return (0);  
                 }  
         p++;  
         /* p now points to beginning of last field */  
         if (p[0] != 't' || p[1] != 'c')  
                 return(1);  
         strcpy(tcname,p+3);  
         q = tcname;  
         while (*q && *q != ':')  
                 q++;  
         *q = 0;  
         if (++hopcount > MAXHOP) {  
                 write(2, "Infinite tc= loop\n", 18);  
                 return (0);  
         }  
         if (tfindent(tcbuf, tcname) != 1) {  
                 hopcount = 0;           /* unwind recursion */  
                 return(0);  
         }  
         for (q=tcbuf; *q != ':'; q++)  
                 ;  
         l = p - holdtbuf + strlen(q);  
         if (l > BUFSIZ) {  
                 write(2, "Termcap entry too long\n", 23);  
                 q[BUFSIZ - (p-tbuf)] = 0;  
         }  
         strcpy(p, q+1);  
         tbuf = holdtbuf;  
         hopcount = 0;                   /* unwind recursion */  
         return(1);  
 }  
   
 /*  
  * Tnamatch deals with name matching.  The first field of the termcap  
  * entry is a sequence of names separated by |'s, so we compare  
  * against each such name.  The normal : terminator after the last  
  * name (before the first field) stops us.  
  */  
 tnamatch(np)  
         char *np;  
 {  
         register char *Np, *Bp;  
   
         Bp = tbuf;  
         if (*Bp == '#')  
                 return(0);  
         for (;;) {  
                 for (Np = np; *Np && *Bp == *Np; Bp++, Np++)  
                         continue;  
                 if (*Np == 0 && (*Bp == '|' || *Bp == ':' || *Bp == 0))  
                         return (1);  
                 while (*Bp && *Bp != ':' && *Bp != '|')  
                         Bp++;  
                 if (*Bp == 0 || *Bp == ':')  
                         return (0);  
                 Bp++;  
         }  
 }  
   
 /*  
  * Skip to the next field.  Notice that this is very dumb, not  
  * knowing about \: escapes or any such.  If necessary, :'s can be put  
  * into the termcap file in octal.  
  */  
 static char *  
 tskip(bp)  
         register char *bp;  
 {  
   
         while (*bp && *bp != ':')  
                 bp++;  
         if (*bp == ':')  
                 bp++;  
         return (bp);  
 }  }
   
 /*  /*
Line 305  tskip(bp)
Line 321  tskip(bp)
  * a # character.  If the option is not found we return -1.   * a # character.  If the option is not found we return -1.
  * Note that we handle octal numbers beginning with 0.   * Note that we handle octal numbers beginning with 0.
  */   */
 tgetnum(id)  int
         char *id;  t_getnum(struct tinfo *info, const char *id)
 {  {
         register int i, base;          long num;
         register char *bp = tbuf;  
   
         for (;;) {          _DIAGASSERT(info != NULL);
                 bp = tskip(bp);          _DIAGASSERT(id != NULL);
                 if (*bp == 0)  
                         return (-1);          if (cgetnum(info->info, id, &num) == 0)
                 if (*bp++ != id[0] || *bp == 0 || *bp++ != id[1])                  return (int)(num);
                         continue;          else
                 if (*bp == '@')                  return (-1);
                         return(-1);  }
                 if (*bp != '#')  
                         continue;  int
                 bp++;  tgetnum(const char *id)
                 base = 10;  {
                 if (*bp == '0')          return fbuf ? t_getnum(fbuf, id) : -1;
                         base = 8;  
                 i = 0;  
                 while (isdigit(*bp))  
                         i *= base, i += *bp++ - '0';  
                 return (i);  
         }  
 }  }
   
 /*  /*
Line 338  tgetnum(id)
Line 347  tgetnum(id)
  * of the buffer.  Return 1 if we find the option, or 0 if it is   * of the buffer.  Return 1 if we find the option, or 0 if it is
  * not given.   * not given.
  */   */
 tgetflag(id)  int t_getflag(struct tinfo *info, const char *id)
         char *id;  
 {  {
         register char *bp = tbuf;          _DIAGASSERT(info != NULL);
           _DIAGASSERT(id != NULL);
   
           return (cgetcap(info->info, id, ':') != NULL);
   }
   
         for (;;) {  int
                 bp = tskip(bp);  tgetflag(const char *id)
                 if (!*bp)  {
                         return (0);          return fbuf ? t_getflag(fbuf, id) : 0;
                 if (*bp++ == id[0] && *bp != 0 && *bp++ == id[1]) {  }
                         if (!*bp || *bp == ':')  
                                 return (1);  /*
                         else if (*bp == '@')   * Get a string valued option.
                                 return(0);   * These are given as
    *      cl=^Z
    * Much decoding is done on the strings, and the strings are
    * placed in area, which is a ref parameter which is updated.
    * limit is the number of characters allowed to be put into
    * area, this is updated.
    */
   char *
   t_getstr(struct tinfo *info, const char *id, char **area, size_t *limit)
   {
           char *s;
           int i;
   
           _DIAGASSERT(info != NULL);
           _DIAGASSERT(id != NULL);
           /* area may be NULL */
   
   
           if ((i = cgetstr(info->info, id, &s)) < 0) {
                   errno = ENOENT;
                   if ((area == NULL) && (limit != NULL))
                           *limit = 0;
                   return NULL;
           }
   
           if (area != NULL) {
                   /*
                    * check if there is room for the new entry to be put into
                    * area
                    */
                   if (limit != NULL && (*limit < (size_t) i)) {
                           errno = E2BIG;
                           free(s);
                           return NULL;
                 }                  }
   
                   (void)strcpy(*area, s);
                   free(s);
                   s = *area;
                   *area += i + 1;
                   if (limit != NULL)
                           *limit -= i;
                   return (s);
           } else {
                   _DIAGASSERT(limit != NULL);
                   *limit = i;
                   free(s);
                   return NULL;
         }          }
 }  }
   
Line 365  tgetflag(id)
Line 423  tgetflag(id)
  * No checking on area overflow.   * No checking on area overflow.
  */   */
 char *  char *
 tgetstr(id, area)  tgetstr(const char *id, char **area)
         char *id, **area;  {
           struct tinfo dummy, *ti;
           char ids[3];
   
           _DIAGASSERT(id != NULL);
   
           if (fbuf == NULL)
                   return NULL;
   
           /*
            * XXX
            * This is for all the boneheaded programs that relied on tgetstr
            * to look only at the first 2 characters of the string passed...
            */
           ids[0] = id[0];
           ids[1] = id[1];
           ids[2] = '\0';
   
           if ((id[0] == 'Z') && (id[1] == 'Z')) {
                   ti = &dummy;
                   dummy.info = tbuf;
           } else
                   ti = fbuf;
   
           if (area == NULL || *area == NULL) {
                   static char capability[CAPSIZ];
                   size_t limit = sizeof(capability) - 1;
                   char *ptr;
   
                   ptr = capability;
                   return t_getstr(ti, ids, &ptr, &limit);
           } else
                   return t_getstr(ti, ids, area, NULL);
   }
   
   /*
    * Return a string valued option specified by id, allocating memory to
    * an internal buffer as necessary. The memory allocated can be
    * free'd by a call to t_freent().
    *
    * If the string is not found or memory allocation fails then NULL
    * is returned.
    */
   char *
   t_agetstr(struct tinfo *info, const char *id)
 {  {
         register char *bp = tbuf;          size_t new_size;
           struct tbuf *tb;
   
           _DIAGASSERT(info != NULL);
           _DIAGASSERT(id != NULL);
   
           t_getstr(info, id, NULL, &new_size);
   
           /* either the string is empty or the capability does not exist. */
           if (new_size == 0)
                   return NULL;
   
           if ((tb = info->tbuf) == NULL ||
               (size_t) (tb->eptr - tb->ptr) < (new_size + 1)) {
                   if (new_size < CAPSIZ)
                           new_size = CAPSIZ;
                   else
                           new_size++;
   
                   if ((tb = malloc(sizeof(*info->tbuf))) == NULL)
                           return NULL;
   
                   if ((tb->data = tb->ptr = tb->eptr = malloc(new_size))
                       == NULL) {
                           free(tb);
                           return NULL;
                   }
   
         for (;;) {                  tb->eptr += new_size;
                 bp = tskip(bp);  
                 if (!*bp)                  if (info->tbuf != NULL)
                         return (0);                          tb->next = info->tbuf;
                 if (*bp++ != id[0] || *bp == 0 || *bp++ != id[1])                  else
                         continue;                          tb->next = NULL;
                 if (*bp == '@')  
                         return(0);                  info->tbuf = tb;
                 if (*bp != '=')  
                         continue;  
                 bp++;  
                 return (tdecode(bp, area));  
         }          }
           return t_getstr(info, id, &tb->ptr, NULL);
 }  }
   
 /*  /*
  * Tdecode does the grung work to decode the   * Free the buffer allocated by t_getent
  * string capability escapes.   *
  */   */
 static char *  void
 tdecode(str, area)  t_freent(struct tinfo *info)
         register char *str;  {
         char **area;          struct tbuf *tb, *wb;
 {          _DIAGASSERT(info != NULL);
         register char *cp;          free(info->info);
         register int c;          if (info->up != NULL)
         register char *dp;                  free(info->up);
         int i;          if (info->bc != NULL)
                   free(info->bc);
           for (tb = info->tbuf; tb;) {
                   wb = tb;
                   tb = tb->next;
                   free(wb->data);
                   free(wb);
           }
           free(info);
   }
   
         cp = *area;  /*
         while ((c = *str++) && c != ':') {   * Get the terminal name string from the termcap entry.
                 switch (c) {   *
    */
                 case '^':  int
                         c = *str++ & 037;  t_getterm(struct tinfo *info, char **area, size_t *limit)
                         break;  {
           char *endp;
                 case '\\':          size_t count;
                         dp = "E\033^^\\\\::n\nr\rt\tb\bf\f";  
                         c = *str++;          _DIAGASSERT(info != NULL);
 nextc:          if ((endp = strchr(info->info, ':')) == NULL) {
                         if (*dp++ == c) {                  errno = EINVAL;
                                 c = *dp++;                  return -1;
                                 break;          }
                         }  
                         dp++;  
                         if (*dp)          count = endp - info->info + 1;
                                 goto nextc;          if (area == NULL) {
                         if (isdigit(c)) {                  _DIAGASSERT(limit != NULL);
                                 c -= '0', i = 2;                  *limit = count;
                                 do                  return 0;
                                         c <<= 3, c |= *str++ - '0';          } else {
                                 while (--i && isdigit(*str));                  if ((limit != NULL) && (count > *limit)) {
                         }                          errno = E2BIG;
                         break;                          return -1;
                 }                  }
                 *cp++ = c;  
                   (void)strlcpy(*area, info->info, count);
                   if (limit != NULL)
                           *limit -= count;
         }          }
         *cp++ = 0;  
         str = *area;          return 0;
         *area = cp;  
         return (str);  
 }  }

Legend:
Removed from v.1.3  
changed lines
  Added in v.1.54.18.1

CVSweb <webmaster@jp.NetBSD.org>