?? read_termcap.c
字號:
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 */ char *termpath; string_desc desc; fname = pathvec; pvec = pathvec; tbuf = bp; p = pathbuf; cp = use_terminfo_vars()? getenv("TERMCAP") : NULL; /* * 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 case it better start with a * "/". Or it can be an entry to use so we don't have to read the file. * In this case it has to already have the newlines crunched out. If * TERMCAP does not hold a file name then a path of names is searched * instead. The path is found in the TERMPATH variable, or becomes * "$HOME/.termcap /etc/termcap" if no TERMPATH exists. */ _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 { 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 */ _nc_safe_strcat(&desc, cp); /* still can be tokenized */ } *fname++ = pathbuf; /* tokenize path into vector of names */ while (*++p) { if (*p == ' ' || *p == NCURSES_PATHSEP) { *p = '\0'; while (*++p) if (*p != ' ' && *p != NCURSES_PATHSEP) break; if (*p == '\0') break; *fname++ = p; if (fname >= pathvec + PVECSIZ) { fname--; break; } } } *fname = 0; /* mark end of vector */ if (is_pathname(cp)) { if (_nc_cgetset(cp) < 0) { return (TC_SYS_ERR); } } i = _nc_cgetent(&dummy, lineno, pathvec, name); /* ncurses' termcap-parsing routines cannot handle multiple adjacent * empty fields, and mistakenly use the last valid cap entry instead of * the first (breaks tc= includes) */ if (i >= 0) { char *pd, *ps, *tok; int endflag = FALSE; char *list[1023]; size_t n, count = 0; pd = bp; ps = dummy; while (!endflag && (tok = get_tc_token(&ps, &endflag)) != 0) { bool ignore = FALSE; for (n = 1; n < count; n++) { char *s = list[n]; if (s[0] == tok[0] && s[1] == tok[1]) { ignore = TRUE; break; } } if (ignore != TRUE) { list[count++] = tok; pd = copy_tc_token(pd, tok, TBUFSIZ - (2 + pd - bp)); if (pd == 0) { i = -1; break; } *pd++ = ':'; *pd = '\0'; } } } FreeIfNeeded(dummy); FreeIfNeeded(the_source); the_source = 0; /* This is not related to the BSD cgetent(), but to fake up a suitable * filename for ncurses' error reporting. (If we are not using BSD * cgetent, then it is the actual filename). */ if (i >= 0) { if ((the_source = strdup(pathvec[i])) != 0) *sourcename = the_source; } return (i);}#endif /* USE_BSD_TGETENT */#endif /* USE_GETCAP */#define MAXPATHS 32/* * Add a filename to the list in 'termpaths[]', checking that we really have * a right to open the file. */#if !USE_GETCAPstatic intadd_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) { 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 */NCURSES_EXPORT(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 *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. */#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"); /* * 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_uses(TRUE); /* 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);}#elseexternNCURSES_EXPORT(void)_nc_read_termcap(void);NCURSES_EXPORT(void)_nc_read_termcap(void){}#endif /* PURE_TERMINFO */
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -