/****************************************************************************
- * Copyright (c) 1998-2011,2012 Free Software Foundation, Inc. *
+ * Copyright 2018-2021,2022 Thomas E. Dickey *
+ * Copyright 1998-2013,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 *
#include <hashed_db.h>
#endif
-MODULE_ID("$Id: toe.c,v 1.68 2012/07/21 22:55:59 tom Exp $")
+MODULE_ID("$Id: toe.c,v 1.88 2022/09/03 23:29:32 tom Exp $")
#define isDotname(name) (!strcmp(name, ".") || !strcmp(name, ".."))
#if NO_LEAKS
#undef ExitProgram
-static void ExitProgram(int code) GCC_NORETURN;
+static GCC_NORETURN void ExitProgram(int code);
static void
ExitProgram(int code)
{
}
#endif
-static void failed(const char *) GCC_NORETURN;
+static GCC_NORETURN void failed(const char *);
static void
failed(const char *msg)
if (want >= len_termdata) {
len_termdata = (2 * want) + 10;
ptr_termdata = typeRealloc(TERMDATA, len_termdata, ptr_termdata);
+ if (ptr_termdata == 0)
+ failed("ptr_termdata");
}
return ptr_termdata + use_termdata++;
static void
show_termdata(int eargc, char **eargv)
{
- int j, k;
- size_t n;
-
if (use_termdata) {
+ size_t n;
+
if (eargc > 1) {
+ int j;
+
for (j = 0; j < eargc; ++j) {
+ int k;
+
for (k = 0; k <= j; ++k) {
printf("--");
}
if (use_termdata > 1)
qsort(ptr_termdata, use_termdata, sizeof(TERMDATA), compare_termdata);
for (n = 0; n < use_termdata; ++n) {
+ int nk = -1;
/*
* If there is more than one database, show how they differ.
*/
if (eargc > 1) {
unsigned long check = 0;
- k = 0;
+ int k = 0;
for (;;) {
+ char mark = ((check == 0
+ || (check != ptr_termdata[n].checksum))
+ ? '*'
+ : '+');
+
for (; k < ptr_termdata[n].db_index; ++k) {
printf("--");
}
* from the first entry's checksum, print "*". Otherwise
* it looks enough like a duplicate to print "+".
*/
- printf("%c-", ((check == 0
- || (check != ptr_termdata[n].checksum))
- ? '*'
- : '+'));
+ printf("%c-", mark);
check = ptr_termdata[n].checksum;
+ if (mark == '*' && nk < 0)
+ nk = (int) n;
++k;
if ((n + 1) >= use_termdata
}
printf(":\t");
}
+ if (nk < 0)
+ nk = (int) n;
(void) printf("%-10s\t%s\n",
ptr_termdata[n].term_name,
- ptr_termdata[n].description);
+ ptr_termdata[nk].description);
}
}
}
static const char suffix[] = DBM_SUFFIX;
bool result = FALSE;
- unsigned lens = sizeof(suffix) - 1;
- unsigned size = strlen(src);
- unsigned need = lens + size;
+ size_t lens = sizeof(suffix) - 1;
+ size_t size = strlen(src);
+ size_t need = lens + size;
if (need <= limit) {
if (size >= lens
&& !strcmp(src + size - lens, suffix)) {
_nc_STRCPY(dst, src, PATH_MAX);
} else {
- _nc_SPRINTF(dst, _nc_SLIMIT(PATH_MAX) "%s%s", src, suffix);
+ _nc_SPRINTF(dst, _nc_SLIMIT(PATH_MAX) "%.*s%s",
+ (int) (PATH_MAX - sizeof(suffix)),
+ src, suffix);
}
result = TRUE;
}
typedef void (DescHook) (int /* db_index */ ,
int /* db_limit */ ,
const char * /* term_name */ ,
- TERMTYPE * /* term */ );
+ TERMTYPE2 * /* term */ );
static const char *
-term_description(TERMTYPE *tp)
+term_description(TERMTYPE2 *tp)
{
const char *desc;
- if ((desc = strrchr(tp->term_names, '|')) == 0 || *++desc == '\0')
+ if (tp->term_names == 0
+ || (desc = strrchr(tp->term_names, '|')) == 0
+ || (*++desc == '\0')) {
desc = "(No description)";
+ }
return desc;
}
/* display a description for the type */
static void
-deschook(int db_index, int db_limit, const char *term_name, TERMTYPE *tp)
+deschook(int db_index, int db_limit, const char *term_name, TERMTYPE2 *tp)
{
(void) db_index;
(void) db_limit;
}
static unsigned long
-checksum_of(TERMTYPE *tp)
+checksum_of(TERMTYPE2 *tp)
{
unsigned long result = string_sum(tp->term_names);
unsigned i;
/* collect data, to sort before display */
static void
-sorthook(int db_index, int db_limit, const char *term_name, TERMTYPE *tp)
+sorthook(int db_index, int db_limit, const char *term_name, TERMTYPE2 *tp)
{
TERMDATA *data = new_termdata();
data->description = strmalloc(term_description(tp));
}
-#if USE_TERMCAP
+#if NCURSES_USE_TERMCAP
+/*
+ * Check if the buffer contents are printable ASCII, ensuring that we do not
+ * accidentally pick up incompatible binary content from a hashed database.
+ */
+static bool
+is_termcap(char *buffer)
+{
+ bool result = TRUE;
+ while (*buffer != '\0') {
+ int ch = UChar(*buffer++);
+ if (ch == '\t')
+ continue;
+ if (ch < ' ' || ch > '~') {
+ result = FALSE;
+ break;
+ }
+ }
+ return result;
+}
+
static void
show_termcap(int db_index, int db_limit, char *buffer, DescHook hook)
{
- TERMTYPE data;
+ TERMTYPE2 data;
char *next = strchr(buffer, ':');
char *last;
char *list = buffer;
}
#endif
-#if USE_DATABASE
+#if NCURSES_USE_DATABASE
static char *
copy_entryname(DIRENT * src)
{
static int
typelist(int eargc, char *eargv[],
- bool verbosity,
+ int verbosity,
DescHook hook)
/* apply a function to each entry in given terminfo directories */
{
int i;
for (i = 0; i < eargc; i++) {
-#if USE_DATABASE
+#if NCURSES_USE_DATABASE
if (_nc_is_dir_path(eargv[i])) {
char *cwd_buf = 0;
DIR *termdir;
}
while ((entry = readdir(entrydir)) != 0) {
char *name_2;
- TERMTYPE lterm;
+ TERMTYPE2 lterm;
char *cn;
int status;
"%s: couldn't open terminfo file %s.\n",
_nc_progname, name_2);
free(name_2);
- return (EXIT_FAILURE);
+ continue;
}
/* only visit things once, by primary name */
/* apply the selected hook function */
hook(i, eargc, cn, <erm);
}
- _nc_free_termtype(<erm);
+ _nc_free_termtype2(<erm);
free(name_2);
}
closedir(entrydir);
code = _nc_db_first(capdbp, &key, &data);
while (code == 0) {
- TERMTYPE lterm;
+ TERMTYPE2 lterm;
int used;
char *have;
char *cn;
cn = _nc_first_name(lterm.term_names);
/* apply the selected hook function */
hook(i, eargc, cn, <erm);
- _nc_free_termtype(<erm);
+ _nc_free_termtype2(<erm);
}
}
code = _nc_db_next(capdbp, &key, &data);
}
}
}
-#endif
-#endif
-#if USE_TERMCAP
+#endif /* USE_HASHED_DB */
+#endif /* NCURSES_USE_DATABASE */
+#if NCURSES_USE_TERMCAP
#if HAVE_BSD_CGETENT
{
CGETENT_CONST char *db_array[2];
db_array[1] = 0;
if (cgetfirst(&buffer, db_array) > 0) {
- show_termcap(i, eargc, buffer, hook);
- free(buffer);
- while (cgetnext(&buffer, db_array) > 0) {
+ if (is_termcap(buffer)) {
show_termcap(i, eargc, buffer, hook);
free(buffer);
+ while (cgetnext(&buffer, db_array) > 0) {
+ show_termcap(i, eargc, buffer, hook);
+ free(buffer);
+ }
}
cgetclose();
continue;
if (verbosity)
(void) printf("#\n#%s:\n#\n", eargv[i]);
- if ((fp = fopen(eargv[i], "r")) != 0) {
+ if ((fp = safe_fopen(eargv[i], "r")) != 0) {
while (fgets(buffer, sizeof(buffer), fp) != 0) {
+ if (!is_termcap(buffer))
+ break;
if (*buffer == '#')
continue;
if (isspace(*buffer))
bool invert_dependencies = FALSE;
bool header = FALSE;
char *report_file = 0;
- unsigned i;
int code;
int this_opt, last_opt = '?';
unsigned v_opt = 0;
usage();
}
}
- set_trace_level(v_opt);
+ use_verbosity(v_opt);
if (report_file != 0) {
if (freopen(report_file, "r", stdin) == 0) {
/* maybe we want a reverse-dependency listing? */
if (invert_dependencies) {
ENTRY *qp, *rp;
- int matchcount;
for_entry_list(qp) {
- matchcount = 0;
+ int matchcount = 0;
+
for_entry_list(rp) {
+ unsigned i;
+
if (rp->nuses == 0)
continue;
DBDIRS state;
int offset;
int pass;
- const char *path;
char **eargv = 0;
code = EXIT_FAILURE;
for (pass = 0; pass < 2; ++pass) {
size_t count = 0;
+ const char *path;
_nc_first_db(&state, &offset);
while ((path = _nc_next_db(&state, &offset)) != 0) {
+ if (quick_prefix(path))
+ continue;
if (pass) {
eargv[count] = strmalloc(path);
}
}
if (!pass) {
eargv = allocArgv(count);
+ if (eargv == 0)
+ failed("eargv");
} else {
code = typelist((int) count, eargv, header, hook);
freeArgv(eargv);
DBDIRS state;
int offset;
const char *path;
- char **eargv = allocArgv(2);
+ char **eargv = allocArgv((size_t) 2);
size_t count = 0;
+ if (eargv == 0)
+ failed("eargv");
_nc_first_db(&state, &offset);
if ((path = _nc_next_db(&state, &offset)) != 0) {
- eargv[count++] = strmalloc(path);
+ if (!quick_prefix(path))
+ eargv[count++] = strmalloc(path);
}
code = typelist((int) count, eargv, header, hook);