/****************************************************************************
- * Copyright (c) 1998-2002,2005 Free Software Foundation, Inc. *
+ * Copyright (c) 1998-2010,2011 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 *
/*
* toe.c --- table of entries report generator
- *
*/
#include <progs.priv.h>
#include <sys/stat.h>
-#include <dump_entry.h>
+#if USE_HASHED_DB
+#include <hashed_db.h>
+#endif
-MODULE_ID("$Id: toe.c,v 1.29 2005/09/25 00:39:43 tom Exp $")
+MODULE_ID("$Id: toe.c,v 1.54 2011/05/21 18:32:13 tom Exp $")
#define isDotname(name) (!strcmp(name, ".") || !strcmp(name, ".."))
const char *_nc_progname;
-static int typelist(int eargc, char *eargv[], bool,
- void (*)(const char *, TERMTYPE *));
-static void deschook(const char *, TERMTYPE *);
-
#if NO_LEAKS
#undef ExitProgram
+static void ExitProgram(int code) GCC_NORETURN;
static void
-ExitProgram(int code) GCC_NORETURN;
- static void ExitProgram(int code)
+ExitProgram(int code)
{
_nc_free_entries(_nc_head);
- _nc_leaks_dump_entry();
- _nc_free_and_exit(code);
+ _nc_free_tic(code);
}
#endif
+static void failed(const char *) GCC_NORETURN;
+
+static void
+failed(const char *msg)
+{
+ perror(msg);
+ ExitProgram(EXIT_FAILURE);
+}
+
+#if USE_HASHED_DB
static bool
-is_a_file(char *path)
+make_db_name(char *dst, const char *src, unsigned limit)
{
- struct stat sb;
- return (stat(path, &sb) == 0
- && (sb.st_mode & S_IFMT) == S_IFREG);
+ static const char suffix[] = DBM_SUFFIX;
+
+ bool result = FALSE;
+ unsigned lens = sizeof(suffix) - 1;
+ unsigned size = strlen(src);
+ unsigned need = lens + size;
+
+ if (need <= limit) {
+ if (size >= lens
+ && !strcmp(src + size - lens, suffix))
+ (void) strcpy(dst, src);
+ else
+ (void) sprintf(dst, "%s%s", src, suffix);
+ result = TRUE;
+ }
+ return result;
}
+#endif
static bool
-is_a_directory(char *path)
+is_database(const char *path)
+{
+ bool result = FALSE;
+#if USE_DATABASE
+ if (_nc_is_dir_path(path) && access(path, R_OK | X_OK) == 0) {
+ result = TRUE;
+ }
+#endif
+#if USE_TERMCAP
+ if (_nc_is_file_path(path) && access(path, R_OK) == 0) {
+ result = TRUE;
+ }
+#endif
+#if USE_HASHED_DB
+ if (!result) {
+ char filename[PATH_MAX];
+ if (_nc_is_file_path(path) && access(path, R_OK) == 0) {
+ result = TRUE;
+ } else if (make_db_name(filename, path, sizeof(filename))) {
+ if (_nc_is_file_path(filename) && access(filename, R_OK) == 0) {
+ result = TRUE;
+ }
+ }
+ }
+#endif
+ return result;
+}
+
+static void
+deschook(const char *cn, TERMTYPE *tp)
+/* display a description for the type */
+{
+ const char *desc;
+
+ if ((desc = strrchr(tp->term_names, '|')) == 0 || *++desc == '\0')
+ desc = "(No description)";
+
+ (void) printf("%-10s\t%s\n", cn, desc);
+}
+
+#if USE_TERMCAP
+static void
+show_termcap(char *buffer,
+ void (*hook) (const char *, TERMTYPE *tp))
{
- struct stat sb;
- return (stat(path, &sb) == 0
- && (sb.st_mode & S_IFMT) == S_IFDIR);
+ TERMTYPE data;
+ char *next = strchr(buffer, ':');
+ char *last;
+ char *list = buffer;
+
+ if (next)
+ *next = '\0';
+
+ last = strrchr(buffer, '|');
+ if (last)
+ ++last;
+
+ data.term_names = strdup(buffer);
+ while ((next = strtok(list, "|")) != 0) {
+ if (next != last)
+ hook(next, &data);
+ list = 0;
+ }
+ free(data.term_names);
}
+#endif
-static char *
-get_directory(char *path)
+static int
+typelist(int eargc, char *eargv[],
+ bool verbosity,
+ void (*hook) (const char *, TERMTYPE *tp))
+/* apply a function to each entry in given terminfo directories */
{
- if (path != 0) {
- if (!is_a_directory(path)
- || access(path, R_OK | X_OK) != 0)
- path = 0;
+ int i;
+
+ for (i = 0; i < eargc; i++) {
+#if USE_DATABASE
+ if (_nc_is_dir_path(eargv[i])) {
+ char *cwd_buf = 0;
+ DIR *termdir;
+ DIRENT *subdir;
+
+ if ((termdir = opendir(eargv[i])) == 0) {
+ (void) fflush(stdout);
+ (void) fprintf(stderr,
+ "%s: can't open terminfo directory %s\n",
+ _nc_progname, eargv[i]);
+ return (EXIT_FAILURE);
+ } else if (verbosity)
+ (void) printf("#\n#%s:\n#\n", eargv[i]);
+
+ while ((subdir = readdir(termdir)) != 0) {
+ size_t len = NAMLEN(subdir);
+ size_t cwd_len = len + strlen(eargv[i]) + 3;
+ char name_1[PATH_MAX];
+ DIR *entrydir;
+ DIRENT *entry;
+
+ cwd_buf = typeRealloc(char, cwd_len, cwd_buf);
+ if (cwd_buf == 0)
+ failed("realloc cwd_buf");
+
+ assert(cwd_buf != 0);
+
+ strncpy(name_1, subdir->d_name, len)[len] = '\0';
+ if (isDotname(name_1))
+ continue;
+
+ (void) sprintf(cwd_buf, "%s/%.*s/", eargv[i], (int) len, name_1);
+ if (chdir(cwd_buf) != 0)
+ continue;
+
+ entrydir = opendir(".");
+ if (entrydir == 0) {
+ perror(cwd_buf);
+ continue;
+ }
+ while ((entry = readdir(entrydir)) != 0) {
+ char name_2[PATH_MAX];
+ TERMTYPE lterm;
+ char *cn;
+ int status;
+
+ len = NAMLEN(entry);
+ strncpy(name_2, entry->d_name, len)[len] = '\0';
+ if (isDotname(name_2) || !_nc_is_file_path(name_2))
+ continue;
+
+ status = _nc_read_file_entry(name_2, <erm);
+ if (status <= 0) {
+ (void) fflush(stdout);
+ (void) fprintf(stderr,
+ "%s: couldn't open terminfo file %s.\n",
+ _nc_progname, name_2);
+ return (EXIT_FAILURE);
+ }
+
+ /* only visit things once, by primary name */
+ cn = _nc_first_name(lterm.term_names);
+ if (!strcmp(cn, name_2)) {
+ /* apply the selected hook function */
+ (*hook) (cn, <erm);
+ }
+ _nc_free_termtype(<erm);
+ }
+ closedir(entrydir);
+ }
+ closedir(termdir);
+ if (cwd_buf != 0)
+ free(cwd_buf);
+ }
+#if USE_HASHED_DB
+ else {
+ DB *capdbp;
+ char filename[PATH_MAX];
+
+ if (make_db_name(filename, eargv[i], sizeof(filename))) {
+ if ((capdbp = _nc_db_open(filename, FALSE)) != 0) {
+ DBT key, data;
+ int code;
+
+ code = _nc_db_first(capdbp, &key, &data);
+ while (code == 0) {
+ TERMTYPE lterm;
+ int used;
+ char *have;
+ char *cn;
+
+ if (_nc_db_have_data(&key, &data, &have, &used)) {
+ if (_nc_read_termtype(<erm, have, used) > 0) {
+ /* only visit things once, by primary name */
+ cn = _nc_first_name(lterm.term_names);
+ /* apply the selected hook function */
+ (*hook) (cn, <erm);
+ _nc_free_termtype(<erm);
+ }
+ }
+ code = _nc_db_next(capdbp, &key, &data);
+ }
+
+ _nc_db_close(capdbp);
+ }
+ }
+ }
+#endif
+#endif
+#if USE_TERMCAP
+#if HAVE_BSD_CGETENT
+ char *db_array[2];
+ char *buffer = 0;
+
+ if (verbosity)
+ (void) printf("#\n#%s:\n#\n", eargv[i]);
+
+ db_array[0] = eargv[i];
+ db_array[1] = 0;
+
+ if (cgetfirst(&buffer, db_array)) {
+ show_termcap(buffer, hook);
+ free(buffer);
+ while (cgetnext(&buffer, db_array)) {
+ show_termcap(buffer, hook);
+ free(buffer);
+ }
+ }
+ cgetclose();
+#else
+ /* scan termcap text-file only */
+ if (_nc_is_file_path(eargv[i])) {
+ char buffer[2048];
+ FILE *fp;
+
+ if ((fp = fopen(eargv[i], "r")) != 0) {
+ while (fgets(buffer, sizeof(buffer), fp) != 0) {
+ if (*buffer == '#')
+ continue;
+ if (isspace(*buffer))
+ continue;
+ show_termcap(buffer, hook);
+ }
+ fclose(fp);
+ }
+ }
+#endif
+#endif
}
- return path;
+
+ return (EXIT_SUCCESS);
+}
+
+static void
+usage(void)
+{
+ (void) fprintf(stderr, "usage: %s [-ahuUV] [-v n] [file...]\n", _nc_progname);
+ ExitProgram(EXIT_FAILURE);
}
int
main(int argc, char *argv[])
{
+ bool all_dirs = FALSE;
bool direct_dependencies = FALSE;
bool invert_dependencies = FALSE;
bool header = FALSE;
- int i, c;
+ char *report_file = 0;
+ unsigned i;
int code;
+ int this_opt, last_opt = '?';
+ unsigned v_opt = 0;
_nc_progname = _nc_rootname(argv[0]);
- while ((c = getopt(argc, argv, "huv:UV")) != EOF)
- switch (c) {
+ while ((this_opt = getopt(argc, argv, "0123456789ahu:vU:V")) != -1) {
+ /* handle optional parameter */
+ if (isdigit(this_opt)) {
+ switch (last_opt) {
+ case 'v':
+ v_opt = (unsigned) (this_opt - '0');
+ break;
+ default:
+ if (isdigit(last_opt))
+ v_opt *= 10;
+ else
+ v_opt = 0;
+ v_opt += (unsigned) (this_opt - '0');
+ last_opt = this_opt;
+ }
+ continue;
+ }
+ switch (this_opt) {
+ case 'a':
+ all_dirs = TRUE;
+ break;
case 'h':
header = TRUE;
break;
case 'u':
direct_dependencies = TRUE;
+ report_file = optarg;
break;
case 'v':
- set_trace_level(atoi(optarg));
+ v_opt = 1;
break;
case 'U':
invert_dependencies = TRUE;
+ report_file = optarg;
break;
case 'V':
puts(curses_version());
ExitProgram(EXIT_SUCCESS);
default:
- (void) fprintf(stderr, "usage: toe [-huUV] [-v n] [file...]\n");
- ExitProgram(EXIT_FAILURE);
+ usage();
}
+ }
+ set_trace_level(v_opt);
- if (direct_dependencies || invert_dependencies) {
- if (freopen(argv[optind], "r", stdin) == 0) {
+ if (report_file != 0) {
+ if (freopen(report_file, "r", stdin) == 0) {
(void) fflush(stdout);
- fprintf(stderr, "%s: can't open %s\n", _nc_progname, argv[optind]);
+ fprintf(stderr, "%s: can't open %s\n", _nc_progname, report_file);
ExitProgram(EXIT_FAILURE);
}
/* parse entries out of the source file */
- _nc_set_source(argv[optind]);
+ _nc_set_source(report_file);
_nc_read_entry_source(stdin, 0, FALSE, FALSE, NULLHOOK);
}
for_entry_list(qp) {
if (qp->nuses) {
- int j;
+ unsigned j;
(void) printf("%s:", _nc_first_name(qp->tterm.term_names));
for (j = 0; j < qp->nuses; j++)
*/
if (optind < argc) {
code = typelist(argc - optind, argv + optind, header, deschook);
+ } else if (all_dirs) {
+ DBDIRS state;
+ int offset;
+ int pass;
+ const char *path;
+ char **eargv = 0;
+
+ code = EXIT_FAILURE;
+ for (pass = 0; pass < 2; ++pass) {
+ unsigned count = 0;
+
+ _nc_first_db(&state, &offset);
+ while ((path = _nc_next_db(&state, &offset)) != 0) {
+ if (!is_database(path)) {
+ ;
+ } else if (eargv != 0) {
+ unsigned n;
+ int found = FALSE;
+
+ /* eliminate duplicates */
+ for (n = 0; n < count; ++n) {
+ if (!strcmp(path, eargv[n])) {
+ found = TRUE;
+ break;
+ }
+ }
+ if (!found) {
+ eargv[count] = strdup(path);
+ ++count;
+ }
+ } else {
+ ++count;
+ }
+ }
+ if (!pass) {
+ eargv = typeCalloc(char *, count + 1);
+ if (eargv == 0)
+ failed("realloc eargv");
+
+ assert(eargv != 0);
+ } else {
+ code = typelist((int) count, eargv, header, deschook);
+ while (count-- > 0)
+ free(eargv[count]);
+ free(eargv);
+ }
+ }
} else {
- char *home, *eargv[3];
- char personal[PATH_MAX];
- int j;
-
- j = 0;
- if ((eargv[j] = get_directory(getenv("TERMINFO"))) != 0) {
- j++;
- } else {
- if ((home = getenv("HOME")) != 0) {
- (void) sprintf(personal, PRIVATE_INFO, home);
- if ((eargv[j] = get_directory(personal)) != 0)
- j++;
+ DBDIRS state;
+ int offset;
+ const char *path;
+ char *eargv[3];
+ int count = 0;
+
+ _nc_first_db(&state, &offset);
+ while ((path = _nc_next_db(&state, &offset)) != 0) {
+ if (is_database(path)) {
+ eargv[count++] = strdup(path);
+ break;
}
- if ((eargv[j] = get_directory(strcpy(personal, TERMINFO))) != 0)
- j++;
}
- eargv[j] = 0;
-
- code = typelist(j, eargv, header, deschook);
- }
-
- ExitProgram(code);
-}
-
-static void
-deschook(const char *cn, TERMTYPE * tp)
-/* display a description for the type */
-{
- const char *desc;
-
- if ((desc = strrchr(tp->term_names, '|')) == 0)
- desc = "(No description)";
- else
- ++desc;
-
- (void) printf("%-10s\t%s\n", cn, desc);
-}
+ eargv[count] = 0;
-static int
-typelist(int eargc, char *eargv[],
- bool verbosity,
- void (*hook) (const char *, TERMTYPE * tp))
-/* apply a function to each entry in given terminfo directories */
-{
- int i;
+ code = typelist(count, eargv, header, deschook);
- for (i = 0; i < eargc; i++) {
- DIR *termdir;
- DIRENT *subdir;
-
- if ((termdir = opendir(eargv[i])) == 0) {
- (void) fflush(stdout);
- (void) fprintf(stderr,
- "%s: can't open terminfo directory %s\n",
- _nc_progname, eargv[i]);
- return (EXIT_FAILURE);
- } else if (verbosity)
- (void) printf("#\n#%s:\n#\n", eargv[i]);
-
- while ((subdir = readdir(termdir)) != 0) {
- size_t len = NAMLEN(subdir);
- char buf[PATH_MAX];
- char name_1[PATH_MAX];
- DIR *entrydir;
- DIRENT *entry;
-
- strncpy(name_1, subdir->d_name, len)[len] = '\0';
- if (isDotname(name_1))
- continue;
-
- (void) sprintf(buf, "%s/%s/", eargv[i], name_1);
- if (chdir(buf) != 0)
- continue;
-
- entrydir = opendir(".");
- while ((entry = readdir(entrydir)) != 0) {
- char name_2[PATH_MAX];
- TERMTYPE lterm;
- char *cn;
- int status;
-
- len = NAMLEN(entry);
- strncpy(name_2, entry->d_name, len)[len] = '\0';
- if (isDotname(name_2) || !is_a_file(name_2))
- continue;
-
- status = _nc_read_file_entry(name_2, <erm);
- if (status <= 0) {
- (void) fflush(stdout);
- (void) fprintf(stderr,
- "toe: couldn't open terminfo file %s.\n",
- name_2);
- return (EXIT_FAILURE);
- }
-
- /* only visit things once, by primary name */
- cn = _nc_first_name(lterm.term_names);
- if (!strcmp(cn, name_2)) {
- /* apply the selected hook function */
- (*hook) (cn, <erm);
- }
- if (lterm.term_names) {
- free(lterm.term_names);
- lterm.term_names = 0;
- }
- if (lterm.str_table) {
- free(lterm.str_table);
- lterm.str_table = 0;
- }
- }
- closedir(entrydir);
- }
- closedir(termdir);
+ while (count-- > 0)
+ free(eargv[count]);
}
+ _nc_last_db();
- return (EXIT_SUCCESS);
+ ExitProgram(code);
}