static void file_comparison(int argc, char *argv[]) { #define MAXCOMPARE 2 /* someday we may allow comparisons on more files */ int filecount = 0; ENTRY *heads[MAXCOMPARE]; ENTRY *tails[MAXCOMPARE]; ENTRY *qp, *rp; int i, n; dump_init((char *)NULL, F_LITERAL, S_TERMINFO, 0, itrace, FALSE); for (n = 0; n < argc && n < MAXCOMPARE; n++) { if (freopen(argv[n], "r", stdin) == NULL) _nc_err_abort("Can't open %s", argv[n]); _nc_head = _nc_tail = (ENTRY *)NULL; /* parse entries out of the source file */ _nc_set_source(argv[n]); _nc_read_entry_source(stdin, NULL, TRUE, FALSE, NULLHOOK); if (itrace) (void) fprintf(stderr, "Resolving file %d...\n", n-0); /* do use resolution */ if (!_nc_resolve_uses()) { (void) fprintf(stderr, "There are unresolved use entries in %s:\n", argv[n]); for_entry_list(qp) if (qp->nuses) { (void) fputs(qp->tterm.term_names, stderr); (void) fputc('\n', stderr); } exit(EXIT_FAILURE); } heads[filecount] = _nc_head; tails[filecount] = _nc_tail; filecount++; }
int _nc_read_termcap_entry(const char *const tn, TERMTYPE *const tp) { int found = FALSE; ENTRY *ep; #if USE_GETCAP_CACHE char cwd_buf[PATH_MAX]; #endif #if USE_GETCAP char tc[TBUFSIZ]; static char *source; static int lineno; /* 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; bool use_buffer = FALSE; char tc_buf[1024]; char pathbuf[PATH_MAX]; termpaths[filecount] = 0; if ((tc = getenv("TERMCAP")) != 0) { if (is_pathname(tc)) /* interpret as a filename */ { ADD_TC(tc, 0); } 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); } } } } else /* normal case */ { char envhome[PATH_MAX], *h; filecount = 0; /* * 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); if ((h = getenv("HOME")) != NULL && strlen(h) + 9 < PATH_MAX) { /* user's .termcap, if any, should override it */ (void) strcpy(envhome, h); (void) sprintf(pathbuf, "%s/.termcap", envhome); ADD_TC(pathbuf, filecount); } } /* 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 ((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); } } } #endif /* USE_GETCAP */ if (_nc_head == 0) return(ERR); /* resolve all use references */ _nc_resolve_uses(); /* 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). */ memcpy(tp, &ep->tterm, sizeof(TERMTYPE)); 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); }