X-Git-Url: https://ncurses.scripts.mit.edu/?p=ncurses.git;a=blobdiff_plain;f=ncurses%2Ftinfo%2Fread_termcap.c;h=eb1c172d5af5fdf8f76da9a14f2cf17827977340;hp=4596be730a17e6dea667bac34691a290b7904010;hb=312665d3aaaf5d8e3ba34d80fdd650abf758272a;hpb=3996fe0bf797f113d6abc4329cc869951735a4d8 diff --git a/ncurses/tinfo/read_termcap.c b/ncurses/tinfo/read_termcap.c index 4596be73..eb1c172d 100644 --- a/ncurses/tinfo/read_termcap.c +++ b/ncurses/tinfo/read_termcap.c @@ -1,5 +1,6 @@ /**************************************************************************** - * Copyright (c) 1998-2006,2009 Free Software Foundation, Inc. * + * Copyright 2018-2020,2021 Thomas E. Dickey * + * Copyright 1998-2016,2017 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 * @@ -54,11 +55,9 @@ #include #include -#include #include -#include -MODULE_ID("$Id: read_termcap.c,v 1.73 2009/12/12 20:21:17 tom Exp $") +MODULE_ID("$Id: read_termcap.c,v 1.99 2021/04/18 11:43:38 tom Exp $") #if !PURE_TERMINFO @@ -68,14 +67,14 @@ MODULE_ID("$Id: read_termcap.c,v 1.73 2009/12/12 20:21:17 tom Exp $") #define TC_REF_LOOP -3 #define TC_UNRESOLVED -4 /* this is not returned by BSD cgetent */ -static NCURSES_CONST char * +static const char * get_termpath(void) { - NCURSES_CONST char *result; + const char *result; if (!use_terminfo_vars() || (result = getenv("TERMPATH")) == 0) result = TERMPATH; - T(("TERMPATH is %s", result)); + TR(TRACE_DATABASE, ("TERMPATH is %s", result)); return result; } @@ -163,7 +162,7 @@ _nc_cgetset(const char *ent) return (-1); } gottoprec = 0; - (void) strcpy(toprec, ent); + _nc_STRCPY(toprec, ent, topreclen); return (0); } @@ -296,7 +295,7 @@ _nc_getent( errno = ENOMEM; return (TC_SYS_ERR); } - (void) strcpy(record, toprec); + _nc_STRCPY(record, toprec, topreclen + BFRAG); rp = record + topreclen + 1; r_end = rp + BFRAG; current = in_array; @@ -366,7 +365,7 @@ _nc_getent( if (bp >= b_end) { int n; - n = read(fd, buf, sizeof(buf)); + n = (int) read(fd, buf, sizeof(buf)); if (n <= 0) { if (myfd) (void) close(fd); @@ -385,10 +384,17 @@ _nc_getent( c = *bp++; if (c == '\n') { lineno++; - if (rp == record || *(rp - 1) != '\\') + /* + * Unlike BSD 4.3, this ignores a backslash at the + * end of a comment-line. That makes it consistent + * with the rest of ncurses -TD + */ + if (rp == record + || *record == '#' + || *(rp - 1) != '\\') break; } - *rp++ = c; + *rp++ = (char) c; /* * Enforce loop invariant: if no room @@ -399,8 +405,8 @@ _nc_getent( unsigned pos; size_t newsize; - pos = rp - record; - newsize = r_end - record + BFRAG; + pos = (unsigned) (rp - record); + newsize = (size_t) (r_end - record + BFRAG); record = DOALLOC(newsize); if (record == 0) { if (myfd) @@ -443,8 +449,10 @@ _nc_getent( break; } - if (!foundit) + if (!foundit) { + free(record); return (TC_NOT_FOUND); + } } /* @@ -456,7 +464,7 @@ _nc_getent( register int newilen; unsigned ilen; int diff, iret, tclen, oline; - char *icap, *scan, *tc, *tcstart, *tcend; + char *icap = 0, *scan, *tc, *tcstart, *tcend; /* * Loop invariants: @@ -469,8 +477,9 @@ _nc_getent( scan = record; tc_not_resolved = FALSE; for (;;) { - if ((tc = _nc_cgetcap(scan, "tc", '=')) == 0) + if ((tc = _nc_cgetcap(scan, "tc", '=')) == 0) { break; + } /* * Find end of tc=name and stomp on the trailing `:' @@ -484,25 +493,27 @@ _nc_getent( } } tcstart = tc - 3; - tclen = s - tcstart; + tclen = (int) (s - tcstart); tcend = s; + icap = 0; iret = _nc_getent(&icap, &ilen, &oline, current, db_array, fd, tc, depth + 1, 0); newicap = icap; /* Put into a register. */ - newilen = ilen; + newilen = (int) ilen; if (iret != TC_SUCCESS) { /* an error */ if (iret < TC_NOT_FOUND) { if (myfd) (void) close(fd); free(record); + FreeIfNeeded(icap); return (iret); } - if (iret == TC_UNRESOLVED) + if (iret == TC_UNRESOLVED) { tc_not_resolved = TRUE; - /* couldn't resolve tc */ - if (iret == TC_NOT_FOUND) { + /* couldn't resolve tc */ + } else if (iret == TC_NOT_FOUND) { *(s - 1) = ':'; scan = s - 1; tc_not_resolved = TRUE; @@ -513,7 +524,7 @@ _nc_getent( /* not interested in name field of tc'ed record */ s = newicap; while (*s != '\0' && *s++ != ':') ; - newilen -= s - newicap; + newilen -= (int) (s - newicap); newicap = s; /* make sure interpolated record is `:'-terminated */ @@ -532,10 +543,10 @@ _nc_getent( unsigned pos, tcpos, tcposend; size_t newsize; - pos = rp - record; - newsize = r_end - record + diff + BFRAG; - tcpos = tcstart - record; - tcposend = tcend - record; + pos = (unsigned) (rp - record); + newsize = (size_t) (r_end - record + diff + BFRAG); + tcpos = (unsigned) (tcstart - record); + tcposend = (unsigned) (tcend - record); record = DOALLOC(newsize); if (record == 0) { if (myfd) @@ -573,7 +584,7 @@ _nc_getent( */ if (myfd) (void) close(fd); - *len = rp - record - 1; /* don't count NUL */ + *len = (unsigned) (rp - record - 1); /* don't count NUL */ if (r_end > rp) { if ((record = DOALLOC((size_t) (rp - record))) == 0) { errno = ENOMEM; @@ -582,8 +593,9 @@ _nc_getent( } *cap = record; - if (tc_not_resolved) + if (tc_not_resolved) { return (TC_UNRESOLVED); + } return (current); } @@ -698,8 +710,6 @@ _nc_nfcmp(const char *nf, char *rec) #define PVECSIZ 32 /* max number of names in path */ #define TBUFSIZ (2048*2) -static char *tbuf; - /* * On entry, srcp points to a non ':' character which is the beginning of the * token, if any. We'll try to return a string that doesn't end with a ':'. @@ -761,7 +771,7 @@ copy_tc_token(char *dst, const char *src, size_t len) dst = 0; break; } - *dst++ = ch; + *dst++ = (char) ch; } return dst; } @@ -777,18 +787,16 @@ _nc_tgetent(char *bp, char **sourcename, int *lineno, const char *name) register char *p; register char *cp; char *dummy = NULL; - char **fname; + CGETENT_CONST char **fname; char *home; int i; char pathbuf[PBUFSIZ]; /* holds raw path of filenames */ - char *pathvec[PVECSIZ]; /* to point to names in pathbuf */ - char **pvec; /* holds usable tail of path vector */ - NCURSES_CONST char *termpath; + CGETENT_CONST char *pathvec[PVECSIZ]; /* point to names in pathbuf */ + const char *termpath; string_desc desc; + *lineno = 1; fname = pathvec; - pvec = pathvec; - tbuf = bp; p = pathbuf; cp = use_terminfo_vars()? getenv("TERMCAP") : NULL; @@ -813,10 +821,11 @@ _nc_tgetent(char *bp, char **sourcename, int *lineno, const char *name) if ((home = getenv("HOME")) != 0 && *home != '\0' && strchr(home, ' ') == 0 && strlen(home) < sizeof(temp) - 10) { /* setup path */ - sprintf(temp, "%s/", home); /* $HOME first */ + _nc_SPRINTF(temp, _nc_SLIMIT(sizeof(temp)) + "%s/", home); /* $HOME first */ } /* if no $HOME look in current directory */ - strcat(temp, ".termcap"); + _nc_STRCAT(temp, ".termcap", sizeof(temp)); _nc_safe_strcat(&desc, temp); _nc_safe_strcat(&desc, " "); _nc_safe_strcat(&desc, get_termpath()); @@ -842,6 +851,9 @@ _nc_tgetent(char *bp, char **sourcename, int *lineno, const char *name) } } *fname = 0; /* mark end of vector */ +#if !HAVE_BSD_CGETENT + (void) _nc_cgetset(0); +#endif if (_nc_is_abs_path(cp)) { if (_nc_cgetset(cp) < 0) { return (TC_SYS_ERR); @@ -854,6 +866,7 @@ _nc_tgetent(char *bp, char **sourcename, int *lineno, const char *name) * empty fields, and mistakenly use the last valid cap entry instead of * the first (breaks tc= includes) */ + *bp = '\0'; if (i >= 0) { char *pd, *ps, *tok; int endflag = FALSE; @@ -875,7 +888,7 @@ _nc_tgetent(char *bp, char **sourcename, int *lineno, const char *name) } if (ignore != TRUE) { list[count++] = tok; - pd = copy_tc_token(pd, tok, TBUFSIZ - (2 + pd - bp)); + pd = copy_tc_token(pd, tok, (size_t) (TBUFSIZ - (2 + pd - bp))); if (pd == 0) { i = -1; break; @@ -933,7 +946,7 @@ add_tc(char *termpaths[], char *path, int count) if (count < MAXPATHS && _nc_access(path, R_OK) == 0) { termpaths[count++] = path; - T(("Adding termpath %s", path)); + TR(TRACE_DATABASE, ("Adding termpath %s", path)); } termpaths[count] = 0; if (save != 0) @@ -944,7 +957,7 @@ add_tc(char *termpaths[], char *path, int count) #endif /* !USE_GETCAP */ NCURSES_EXPORT(int) -_nc_read_termcap_entry(const char *const tn, TERMTYPE *const tp) +_nc_read_termcap_entry(const char *const tn, TERMTYPE2 *const tp) { int found = TGETENT_NO; ENTRY *ep; @@ -953,25 +966,26 @@ _nc_read_termcap_entry(const char *const tn, TERMTYPE *const tp) #endif #if USE_GETCAP char *p, tc[TBUFSIZ]; + char *tc_buf = 0; +#define MY_SIZE sizeof(tc) - 1 int status; static char *source; static int lineno; - T(("read termcap entry for %s", tn)); + TR(TRACE_DATABASE, ("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)); + TR(TRACE_DATABASE, ("illegal or missing entry name '%s'", tn)); return TGETENT_NO; } if (use_terminfo_vars() && (p = getenv("TERMCAP")) != 0 && !_nc_is_abs_path(p) && _nc_name_match(p, tn, "|:")) { /* TERMCAP holds a termcap entry */ - strncpy(tc, p, sizeof(tc) - 1); - tc[sizeof(tc) - 1] = '\0'; + tc_buf = strdup(p); _nc_set_source("TERMCAP"); } else { /* we're using getcap(3) */ @@ -980,8 +994,13 @@ _nc_read_termcap_entry(const char *const tn, TERMTYPE *const tp) _nc_curr_line = lineno; _nc_set_source(source); + tc_buf = tc; } - _nc_read_entry_source((FILE *) 0, tc, FALSE, FALSE, NULLHOOK); + if (tc_buf == 0) + return (TGETENT_ERR); + _nc_read_entry_source((FILE *) 0, tc_buf, FALSE, TRUE, NULLHOOK); + if (tc_buf != tc) + free(tc_buf); #else /* * Here is what the 4.4BSD termcap(3) page prescribes: @@ -1015,7 +1034,7 @@ _nc_read_termcap_entry(const char *const tn, TERMTYPE *const tp) int j, k; bool use_buffer = FALSE; bool normal = TRUE; - char tc_buf[1024]; + char *tc_buf = 0; char pathbuf[PATH_MAX]; char *copied = 0; char *cp; @@ -1027,8 +1046,8 @@ _nc_read_termcap_entry(const char *const tn, TERMTYPE *const tp) 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); + tc_buf = strdup(tc); + use_buffer = (tc_buf != 0); normal = FALSE; } } @@ -1045,13 +1064,16 @@ _nc_read_termcap_entry(const char *const tn, TERMTYPE *const tp) } } -#define PRIVATE_CAP "%s/.termcap" +#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); + _nc_STRCPY(envhome, h, sizeof(envhome)); + _nc_SPRINTF(pathbuf, _nc_SLIMIT(sizeof(pathbuf)) + PRIVATE_CAP, + (int) (sizeof(pathbuf) - sizeof(PRIVATE_CAP)), + envhome); ADD_TC(pathbuf, filecount); } } @@ -1064,7 +1086,7 @@ _nc_read_termcap_entry(const char *const tn, TERMTYPE *const tp) 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) { + || !S_ISREG(test_stat[j].st_mode)) { omit = TRUE; } else { for (k = 0; k < j; k++) { @@ -1076,7 +1098,7 @@ _nc_read_termcap_entry(const char *const tn, TERMTYPE *const tp) } } if (omit) { - T(("Path %s is a duplicate", termpaths[j])); + TR(TRACE_DATABASE, ("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]; @@ -1096,12 +1118,13 @@ _nc_read_termcap_entry(const char *const tn, TERMTYPE *const tp) * 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); + free(tc_buf); } else { int i; for (i = 0; i < filecount; i++) { - T(("Looking for %s in %s", tn, termpaths[i])); + TR(TRACE_DATABASE, ("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]); @@ -1125,7 +1148,8 @@ _nc_read_termcap_entry(const char *const tn, TERMTYPE *const tp) return (TGETENT_ERR); /* resolve all use references */ - _nc_resolve_uses2(TRUE, FALSE); + if (_nc_resolve_uses2(TRUE, FALSE) != TRUE) + return (TGETENT_ERR); /* find a terminal matching tn, if we can */ #if USE_GETCAP_CACHE @@ -1139,8 +1163,7 @@ _nc_read_termcap_entry(const char *const tn, TERMTYPE *const tp) * from the list. */ *tp = ep->tterm; - _nc_delink_entry(_nc_head, &(ep->tterm)); - free(ep); + _nc_free_entry(_nc_head, &(ep->tterm)); /* * OK, now try to write the type to user's terminfo directory.