Back to index

tetex-bin  3.0
Defines | Functions
read_termcap.c File Reference
#include <curses.priv.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <tic.h>
#include <term_entry.h>

Go to the source code of this file.

Defines

#define is_pathname(s)   ((s) != 0 && (s)[0] == '/')
#define TC_SUCCESS   0
#define TC_UNRESOLVED   -1
#define TC_NOT_FOUND   -2
#define TC_SYS_ERR   -3
#define TC_REF_LOOP   -4
#define MAXPATHS   32
#define ADD_TC(path, count)   filecount = add_tc(termpaths, path, count)
#define PRIVATE_CAP   "%s/.termcap"

Functions

static NCURSES_CONST char * get_termpath (void)
static int add_tc (char *termpaths[], char *path, int count)
 _nc_read_termcap_entry (const char *const tn, TERMTYPE *const tp)

Define Documentation

#define ADD_TC (   path,
  count 
)    filecount = add_tc(termpaths, path, count)

Definition at line 931 of file read_termcap.c.

#define is_pathname (   s)    ((s) != 0 && (s)[0] == '/')

Definition at line 68 of file read_termcap.c.

#define MAXPATHS   32

Definition at line 908 of file read_termcap.c.

#define PRIVATE_CAP   "%s/.termcap"
#define TC_NOT_FOUND   -2

Definition at line 73 of file read_termcap.c.

#define TC_REF_LOOP   -4

Definition at line 75 of file read_termcap.c.

#define TC_SUCCESS   0

Definition at line 71 of file read_termcap.c.

#define TC_SYS_ERR   -3

Definition at line 74 of file read_termcap.c.

#define TC_UNRESOLVED   -1

Definition at line 72 of file read_termcap.c.


Function Documentation

_nc_read_termcap_entry ( const char *const  tn,
TERMTYPE *const  tp 
)

Definition at line 935 of file read_termcap.c.

{
    int found = FALSE;
    ENTRY *ep;
#if USE_GETCAP_CACHE
    char cwd_buf[PATH_MAX];
#endif
#if USE_GETCAP
    char *p, tc[TBUFSIZ];
    static char *source;
    static int lineno;

    T(("read termcap entry for %s", tn));

    if (strlen(tn) == 0
       || strcmp(tn, ".") == 0
       || strcmp(tn, "..") == 0
       || _nc_pathlast(tn) != 0) {
       T(("illegal or missing entry name '%s'", tn));
       return 0;
    }

    if (use_terminfo_vars() && (p = getenv("TERMCAP")) != 0
       && !is_pathname(p) && _nc_name_match(p, tn, "|:")) {
       /* TERMCAP holds a termcap entry */
       strncpy(tc, p, sizeof(tc) - 1);
       tc[sizeof(tc) - 1] = '\0';
       _nc_set_source("TERMCAP");
    } else {
       /* we're using getcap(3) */
       if (_nc_tgetent(tc, &source, &lineno, tn) < 0)
           return (ERR);

       _nc_curr_line = lineno;
       _nc_set_source(source);
    }
    _nc_read_entry_source((FILE *) 0, tc, FALSE, FALSE, NULLHOOK);
#else
    /*
     * Here is what the 4.4BSD termcap(3) page prescribes:
     *
     * It will look in the environment for a TERMCAP variable.  If found, and
     * the value does not begin with a slash, and the terminal type name is the
     * same as the environment string TERM, the TERMCAP string is used instead
     * of reading a termcap file.  If it does begin with a slash, the string is
     * used as a path name of the termcap file to search.  If TERMCAP does not
     * begin with a slash and name is different from TERM, tgetent() searches
     * the files $HOME/.termcap and /usr/share/misc/termcap, in that order,
     * unless the environment variable TERMPATH exists, in which case it
     * specifies a list of file pathnames (separated by spaces or colons) to be
     * searched instead.
     *
     * It goes on to state:
     *
     * Whenever multiple files are searched and a tc field occurs in the
     * requested entry, the entry it names must be found in the same file or
     * one of the succeeding files.
     *
     * However, this restriction is relaxed in ncurses; tc references to
     * previous files are permitted.
     *
     * This routine returns 1 if an entry is found, 0 if not found, and -1 if
     * the database is not accessible.
     */
    FILE *fp;
    char *tc, *termpaths[MAXPATHS];
    int filecount = 0;
    int j, k;
    bool use_buffer = FALSE;
    bool normal = TRUE;
    char tc_buf[1024];
    char pathbuf[PATH_MAX];
    char *copied = 0;
    char *cp;
    struct stat test_stat[MAXPATHS];

    termpaths[filecount] = 0;
    if (use_terminfo_vars() && (tc = getenv("TERMCAP")) != 0) {
       if (is_pathname(tc)) {      /* interpret as a filename */
           ADD_TC(tc, 0);
           normal = FALSE;
       } else if (_nc_name_match(tc, tn, "|:")) {       /* treat as a capability file */
           use_buffer = TRUE;
           (void) sprintf(tc_buf, "%.*s\n", (int) sizeof(tc_buf) - 2, tc);
           normal = FALSE;
       }
    }

    if (normal) {           /* normal case */
       char envhome[PATH_MAX], *h;

       copied = strdup(get_termpath());
       for (cp = copied; *cp; cp++) {
           if (*cp == NCURSES_PATHSEP)
              *cp = '\0';
           else if (cp == copied || cp[-1] == '\0') {
              ADD_TC(cp, filecount);
           }
       }

#define PRIVATE_CAP "%s/.termcap"

       if (use_terminfo_vars() && (h = getenv("HOME")) != NULL && *h != '\0'
           && (strlen(h) + sizeof(PRIVATE_CAP)) < PATH_MAX) {
           /* user's .termcap, if any, should override it */
           (void) strcpy(envhome, h);
           (void) sprintf(pathbuf, PRIVATE_CAP, envhome);
           ADD_TC(pathbuf, filecount);
       }
    }

    /*
     * Probably /etc/termcap is a symlink to /usr/share/misc/termcap.
     * Avoid reading the same file twice.
     */
#if HAVE_LINK
    for (j = 0; j < filecount; j++) {
       bool omit = FALSE;
       if (stat(termpaths[j], &test_stat[j]) != 0
           || (test_stat[j].st_mode & S_IFMT) != S_IFREG) {
           omit = TRUE;
       } else {
           for (k = 0; k < j; k++) {
              if (test_stat[k].st_dev == test_stat[j].st_dev
                  && test_stat[k].st_ino == test_stat[j].st_ino) {
                  omit = TRUE;
                  break;
              }
           }
       }
       if (omit) {
           T(("Path %s is a duplicate", termpaths[j]));
           for (k = j + 1; k < filecount; k++) {
              termpaths[k - 1] = termpaths[k];
              test_stat[k - 1] = test_stat[k];
           }
           --filecount;
           --j;
       }
    }
#endif

    /* parse the sources */
    if (use_buffer) {
       _nc_set_source("TERMCAP");

       /*
        * We don't suppress warning messages here.  The presumption is
        * that since it's just a single entry, they won't be a pain.
        */
       _nc_read_entry_source((FILE *) 0, tc_buf, FALSE, FALSE, NULLHOOK);
    } else {
       int i;

       for (i = 0; i < filecount; i++) {

           T(("Looking for %s in %s", tn, termpaths[i]));
           if (_nc_access(termpaths[i], R_OK) == 0
              && (fp = fopen(termpaths[i], "r")) != (FILE *) 0) {
              _nc_set_source(termpaths[i]);

              /*
               * Suppress warning messages.  Otherwise you get 400 lines of
               * crap from archaic termcap files as ncurses complains about
               * all the obsolete capabilities.
               */
              _nc_read_entry_source(fp, (char *) 0, FALSE, TRUE, NULLHOOK);

              (void) fclose(fp);
           }
       }
    }
    if (copied != 0)
       free(copied);
#endif /* USE_GETCAP */

    if (_nc_head == 0)
       return (ERR);

    /* resolve all use references */
    _nc_resolve_uses2(TRUE, FALSE);

    /* find a terminal matching tn, if we can */
#if USE_GETCAP_CACHE
    if (getcwd(cwd_buf, sizeof(cwd_buf)) != 0) {
       _nc_set_writedir((char *) 0);      /* note: this does a chdir */
#endif
       for_entry_list(ep) {
           if (_nc_name_match(ep->tterm.term_names, tn, "|:")) {
              /*
               * Make a local copy of the terminal capabilities.  Free all
               * entry storage except the string table for the loaded type
               * (which we disconnected from the list by NULLing out
               * ep->tterm.str_table above).
               */
              *tp = ep->tterm;
              ep->tterm.str_table = (char *) 0;

              /*
               * OK, now try to write the type to user's terminfo directory. 
               * Next time he loads this, it will come through terminfo.
               *
               * Advantage:  Second and subsequent fetches of this entry will
               * be very fast.
               *
               * Disadvantage:  After the first time a termcap type is loaded
               * by its user, editing it in the /etc/termcap file, or in
               * TERMCAP, or in a local ~/.termcap, will be ineffective
               * unless the terminfo entry is explicitly removed.
               */
#if USE_GETCAP_CACHE
              (void) _nc_write_entry(tp);
#endif
              found = TRUE;
              break;
           }
       }
#if USE_GETCAP_CACHE
       chdir(cwd_buf);
    }
#endif

    _nc_free_entries(_nc_head);
    return (found);
}

Here is the call graph for this function:

static int add_tc ( char *  termpaths[],
char *  path,
int  count 
) [static]

Definition at line 916 of file read_termcap.c.

{
    char *save = strchr(path, NCURSES_PATHSEP);
    if (save != 0)
       *save = '\0';
    if (count < MAXPATHS
       && _nc_access(path, R_OK) == 0) {
       termpaths[count++] = path;
       T(("Adding termpath %s", path));
    }
    termpaths[count] = 0;
    if (save != 0)
       *save = NCURSES_PATHSEP;
    return count;
}

Here is the call graph for this function:

static NCURSES_CONST char* get_termpath ( void  ) [static]

Definition at line 78 of file read_termcap.c.

{
    NCURSES_CONST char *result;

    if (!use_terminfo_vars() || (result = getenv("TERMPATH")) == 0)
       result = TERMPATH;
    T(("TERMPATH is %s", result));
    return result;
}

Here is the caller graph for this function: