X-Git-Url: http://ncurses.scripts.mit.edu/?p=ncurses.git;a=blobdiff_plain;f=ncurses%2Ftinfo%2Fread_termcap.c;h=c6e7e358ad911b56106ab2cbe9188f156864635a;hp=26e72d40326345c20f5c702cc5b1145b2c677c7c;hb=46722468f47c2b77b3987729b4bcf2321cccfd01;hpb=b1f61d9f3aa244512045a6b02e759825d7049d34 diff --git a/ncurses/tinfo/read_termcap.c b/ncurses/tinfo/read_termcap.c index 26e72d40..c6e7e358 100644 --- a/ncurses/tinfo/read_termcap.c +++ b/ncurses/tinfo/read_termcap.c @@ -1,5 +1,5 @@ /**************************************************************************** - * Copyright (c) 1998,1999,2000 Free Software Foundation, Inc. * + * Copyright (c) 1998,1999,2000,2001 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -52,12 +52,14 @@ #include #include +#include +#include #include #include -MODULE_ID("$Id: read_termcap.c,v 1.47 2000/04/15 16:53:19 Todd.C.Miller Exp $") +MODULE_ID("$Id: read_termcap.c,v 1.58 2001/10/28 01:11:34 tom Exp $") -#ifndef PURE_TERMINFO +#if !PURE_TERMINFO #ifdef __EMX__ #define is_pathname(s) ((((s) != 0) && ((s)[0] == '/')) \ @@ -72,6 +74,17 @@ MODULE_ID("$Id: read_termcap.c,v 1.47 2000/04/15 16:53:19 Todd.C.Miller Exp $") #define TC_SYS_ERR -3 #define TC_REF_LOOP -4 +static char * +get_termpath(void) +{ + char *result; + + if (!use_terminfo_vars() || (result = getenv("TERMPATH")) == 0) + result = TERMPATH; + T(("TERMPATH is %s", result)); + return result; +} + #if USE_GETCAP #if HAVE_BSD_CGETENT @@ -81,7 +94,8 @@ MODULE_ID("$Id: read_termcap.c,v 1.47 2000/04/15 16:53:19 Todd.C.Miller Exp $") #define _nc_cgetset cgetset #else static int _nc_cgetmatch(char *, const char *); -static int _nc_getent(char **, unsigned *, int *, int, char **, int, const char *, int, char *); +static int _nc_getent(char **, unsigned *, int *, int, char **, int, const char + *, int, char *); static int _nc_nfcmp(const char *, char *); /*- @@ -124,13 +138,7 @@ static int _nc_nfcmp(const char *, char *); #define BFRAG 1024 #define BSIZE 1024 -#define ESC ('[' & 037) /* ASCII ESC */ #define MAX_RECURSION 32 /* maximum getent recursion */ -#define SFRAG 100 /* cgetstr mallocs in SFRAG chunks */ - -#define RECOK (char)0 -#define TCERR (char)1 -#define SHADOW (char)2 static size_t topreclen; /* toprec length */ static char *toprec; /* Additional record specified by cgetset() */ @@ -257,15 +265,15 @@ _nc_cgetent(char **buf, int *oline, char **db_array, const char *name) #define DOALLOC(size) typeRealloc(char, size, record) static int _nc_getent( - char **cap, /* termcap-content */ - unsigned *len, /* length, needed for recursion */ - int *beginning, /* line-number at match */ - int in_array, /* index in 'db_array[] */ - char **db_array, /* list of files to search */ - int fd, - const char *name, - int depth, - char *nfield) + char **cap, /* termcap-content */ + unsigned *len, /* length, needed for recursion */ + int *beginning, /* line-number at match */ + int in_array, /* index in 'db_array[] */ + char **db_array, /* list of files to search */ + int fd, + const char *name, + int depth, + char *nfield) { register char *r_end, *rp; int myfd = FALSE; @@ -318,7 +326,7 @@ _nc_getent( if (fd >= 0) { (void) lseek(fd, (off_t) 0, SEEK_SET); } else if ((_nc_access(db_array[current], R_OK) < 0) - || (fd = open(db_array[current], O_RDONLY, 0)) < 0) { + || (fd = open(db_array[current], O_RDONLY, 0)) < 0) { /* No error on unfound file. */ if (errno == ENOENT) continue; @@ -481,7 +489,7 @@ _nc_getent( tcend = s; iret = _nc_getent(&icap, &ilen, &oline, current, db_array, fd, - tc, depth + 1, 0); + tc, depth + 1, 0); newicap = icap; /* Put into a register. */ newilen = ilen; if (iret != TC_SUCCESS) { @@ -769,7 +777,7 @@ _nc_tgetent(char *bp, char **sourcename, int *lineno, const char *name) register char *p; register char *cp; - char *dummy; + char *dummy = NULL; char **fname; char *home; int i; @@ -777,12 +785,13 @@ _nc_tgetent(char *bp, char **sourcename, int *lineno, const char *name) char *pathvec[PVECSIZ]; /* to point to names in pathbuf */ char **pvec; /* holds usable tail of path vector */ char *termpath; + string_desc desc; fname = pathvec; pvec = pathvec; tbuf = bp; p = pathbuf; - cp = getenv("TERMCAP"); + cp = use_terminfo_vars()? getenv("TERMCAP") : NULL; /* * TERMCAP can have one of two things in it. It can be the name of a file @@ -793,29 +802,36 @@ _nc_tgetent(char *bp, char **sourcename, int *lineno, const char *name) * instead. The path is found in the TERMPATH variable, or becomes * "$HOME/.termcap /etc/termcap" if no TERMPATH exists. */ - if (!is_pathname(cp)) { /* no TERMCAP or it holds an entry */ - if ((termpath = getenv("TERMPATH")) != 0) { - strncpy(pathbuf, termpath, PBUFSIZ - 1); + _nc_str_init(&desc, pathbuf, sizeof(pathbuf)); + if (cp == NULL) { + _nc_safe_strcpy(&desc, get_termpath()); + } else if (!is_pathname(cp)) { /* TERMCAP holds an entry */ + if ((termpath = get_termpath()) != 0) { + _nc_safe_strcat(&desc, termpath); } else { - if ((home = getenv("HOME")) != 0 && - strlen(home) < PBUFSIZ) { /* setup path */ - p += strlen(home); /* path, looking in */ - strcpy(pathbuf, home); /* $HOME first */ - *p++ = '/'; - } /* if no $HOME look in current directory */ -#define MY_PATH_DEF ".termcap /etc/termcap /usr/share/misc/termcap" - strncpy(p, MY_PATH_DEF, (size_t) (PBUFSIZ - (p - pathbuf) - 1)); + char temp[PBUFSIZ]; + temp[0] = 0; + if ((home = getenv("HOME")) != 0 && *home != '\0' + && strchr(home, ' ') == 0 + && strlen(home) < sizeof(temp) - 10) { /* setup path */ + sprintf(temp, "%s/", home); /* $HOME first */ + } + /* if no $HOME look in current directory */ + strcat(temp, ".termcap"); + _nc_safe_strcat(&desc, temp); + _nc_safe_strcat(&desc, " "); + _nc_safe_strcat(&desc, get_termpath()); } - } else /* user-defined name in TERMCAP */ - strncpy(pathbuf, cp, PBUFSIZ - 1); /* still can be tokenized */ - pathbuf[PBUFSIZ - 1] = '\0'; + } else { /* user-defined name in TERMCAP */ + _nc_safe_strcat(&desc, cp); /* still can be tokenized */ + } *fname++ = pathbuf; /* tokenize path into vector of names */ while (*++p) { - if (*p == ' ' || *p == ':') { + if (*p == ' ' || *p == NCURSES_PATHSEP) { *p = '\0'; while (*++p) - if (*p != ' ' && *p != ':') + if (*p != ' ' && *p != NCURSES_PATHSEP) break; if (*p == '\0') break; @@ -899,16 +915,23 @@ _nc_tgetent(char *bp, char **sourcename, int *lineno, const char *name) static int add_tc(char *termpaths[], char *path, int count) { + char *save = strchr(path, NCURSES_PATHSEP); + if (save != 0) + *save = '\0'; if (count < MAXPATHS - && _nc_access(path, R_OK) == 0) + && _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; } #define ADD_TC(path, count) filecount = add_tc(termpaths, path, count) #endif /* !USE_GETCAP */ -int +NCURSES_EXPORT(int) _nc_read_termcap_entry(const char *const tn, TERMTYPE * const tp) { int found = FALSE; @@ -921,7 +944,8 @@ _nc_read_termcap_entry(const char *const tn, TERMTYPE * const tp) static char *source; static int lineno; - if ((p = getenv("TERMCAP")) != 0 + T(("read termcap entry for %s", tn)); + 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); @@ -966,45 +990,42 @@ _nc_read_termcap_entry(const char *const tn, TERMTYPE * const tp) 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 ((tc = getenv("TERMCAP")) != 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); - } else if ((tc = getenv("TERMPATH")) != 0) { - char *cp; - - for (cp = tc; *cp; cp++) { - if (*cp == ':') - *cp = '\0'; - else if (cp == tc || cp[-1] == '\0') { - ADD_TC(cp, filecount); - } - } + normal = FALSE; } - } else { /* normal case */ - char envhome[PATH_MAX], *h; + } - filecount = 0; + if (normal) { /* normal case */ + char envhome[PATH_MAX], *h; - /* - * Probably /etc/termcap is a symlink to /usr/share/misc/termcap. - * Avoid reading the same file twice. - */ - if (_nc_access("/etc/termcap", F_OK) == 0) - ADD_TC("/etc/termcap", filecount); - else - ADD_TC("/usr/share/misc/termcap", filecount); + 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 ((h = getenv("HOME")) != NULL + 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); @@ -1013,6 +1034,37 @@ _nc_read_termcap_entry(const char *const tn, TERMTYPE * const tp) } } + /* + * Probably /etc/termcap is a symlink to /usr/share/misc/termcap. + * Avoid reading the same file twice. + */ +#ifdef 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"); @@ -1028,7 +1080,8 @@ _nc_read_termcap_entry(const char *const tn, TERMTYPE * const tp) for (i = 0; i < filecount; i++) { T(("Looking for %s in %s", tn, termpaths[i])); - if ((fp = fopen(termpaths[i], "r")) != (FILE *) 0) { + if (_nc_access(termpaths[i], R_OK) == 0 + && (fp = fopen(termpaths[i], "r")) != (FILE *) 0) { _nc_set_source(termpaths[i]); /* @@ -1042,6 +1095,8 @@ _nc_read_termcap_entry(const char *const tn, TERMTYPE * const tp) } } } + if (copied != 0) + free(copied); #endif /* USE_GETCAP */ if (_nc_head == 0) @@ -1094,8 +1149,10 @@ _nc_read_termcap_entry(const char *const tn, TERMTYPE * const tp) return (found); } #else -extern void _nc_read_termcap(void); -void +extern +NCURSES_EXPORT(void) +_nc_read_termcap(void); +NCURSES_EXPORT(void) _nc_read_termcap(void) { }