10e3d5408SPeter Wemm /****************************************************************************
2*21817992SBaptiste Daroussin * Copyright 2018-2022,2023 Thomas E. Dickey *
3e1865124SBaptiste Daroussin * Copyright 1998-2013,2017 Free Software Foundation, Inc. *
40e3d5408SPeter Wemm * *
50e3d5408SPeter Wemm * Permission is hereby granted, free of charge, to any person obtaining a *
60e3d5408SPeter Wemm * copy of this software and associated documentation files (the *
70e3d5408SPeter Wemm * "Software"), to deal in the Software without restriction, including *
80e3d5408SPeter Wemm * without limitation the rights to use, copy, modify, merge, publish, *
90e3d5408SPeter Wemm * distribute, distribute with modifications, sublicense, and/or sell *
100e3d5408SPeter Wemm * copies of the Software, and to permit persons to whom the Software is *
110e3d5408SPeter Wemm * furnished to do so, subject to the following conditions: *
120e3d5408SPeter Wemm * *
130e3d5408SPeter Wemm * The above copyright notice and this permission notice shall be included *
140e3d5408SPeter Wemm * in all copies or substantial portions of the Software. *
150e3d5408SPeter Wemm * *
160e3d5408SPeter Wemm * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
170e3d5408SPeter Wemm * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF *
180e3d5408SPeter Wemm * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. *
190e3d5408SPeter Wemm * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, *
200e3d5408SPeter Wemm * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR *
210e3d5408SPeter Wemm * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR *
220e3d5408SPeter Wemm * THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
230e3d5408SPeter Wemm * *
240e3d5408SPeter Wemm * Except as contained in this notice, the name(s) of the above copyright *
250e3d5408SPeter Wemm * holders shall not be used in advertising or otherwise to promote the *
260e3d5408SPeter Wemm * sale, use or other dealings in this Software without prior written *
270e3d5408SPeter Wemm * authorization. *
280e3d5408SPeter Wemm ****************************************************************************/
290e3d5408SPeter Wemm
300e3d5408SPeter Wemm /****************************************************************************
310e3d5408SPeter Wemm * Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 *
320e3d5408SPeter Wemm * and: Eric S. Raymond <esr@snark.thyrsus.com> *
334a1a9510SRong-En Fan * and: Thomas E. Dickey 1996-on *
340e3d5408SPeter Wemm ****************************************************************************/
350e3d5408SPeter Wemm
360e3d5408SPeter Wemm /*
370e3d5408SPeter Wemm * toe.c --- table of entries report generator
380e3d5408SPeter Wemm */
390e3d5408SPeter Wemm
400e3d5408SPeter Wemm #include <progs.priv.h>
410e3d5408SPeter Wemm
420e3d5408SPeter Wemm #include <sys/stat.h>
430e3d5408SPeter Wemm
444a1a9510SRong-En Fan #if USE_HASHED_DB
454a1a9510SRong-En Fan #include <hashed_db.h>
464a1a9510SRong-En Fan #endif
474a1a9510SRong-En Fan
48*21817992SBaptiste Daroussin MODULE_ID("$Id: toe.c,v 1.89 2023/07/01 17:04:46 tom Exp $")
4915589c42SPeter Wemm
5015589c42SPeter Wemm #define isDotname(name) (!strcmp(name, ".") || !strcmp(name, ".."))
510e3d5408SPeter Wemm
5273f0a83dSXin LI typedef struct {
5373f0a83dSXin LI int db_index;
5473f0a83dSXin LI unsigned long checksum;
5573f0a83dSXin LI char *term_name;
5673f0a83dSXin LI char *description;
5773f0a83dSXin LI } TERMDATA;
5873f0a83dSXin LI
590e3d5408SPeter Wemm const char *_nc_progname;
600e3d5408SPeter Wemm
6173f0a83dSXin LI static TERMDATA *ptr_termdata; /* array of terminal data */
6273f0a83dSXin LI static size_t use_termdata; /* actual usage in ptr_termdata[] */
6373f0a83dSXin LI static size_t len_termdata; /* allocated size of ptr_termdata[] */
6473f0a83dSXin LI
650e3d5408SPeter Wemm #if NO_LEAKS
660e3d5408SPeter Wemm #undef ExitProgram
67*21817992SBaptiste Daroussin static GCC_NORETURN void ExitProgram(int code);
6815589c42SPeter Wemm static void
ExitProgram(int code)694a1a9510SRong-En Fan ExitProgram(int code)
700e3d5408SPeter Wemm {
710e3d5408SPeter Wemm _nc_free_entries(_nc_head);
725ca44d1cSRong-En Fan _nc_free_tic(code);
730e3d5408SPeter Wemm }
740e3d5408SPeter Wemm #endif
750e3d5408SPeter Wemm
76*21817992SBaptiste Daroussin static GCC_NORETURN void failed(const char *);
7773f0a83dSXin LI
7806bfebdeSXin LI static void
failed(const char * msg)7906bfebdeSXin LI failed(const char *msg)
8006bfebdeSXin LI {
8106bfebdeSXin LI perror(msg);
8206bfebdeSXin LI ExitProgram(EXIT_FAILURE);
8306bfebdeSXin LI }
8406bfebdeSXin LI
8573f0a83dSXin LI static char *
strmalloc(const char * value)8673f0a83dSXin LI strmalloc(const char *value)
8773f0a83dSXin LI {
8873f0a83dSXin LI char *result = strdup(value);
8973f0a83dSXin LI if (result == 0) {
9073f0a83dSXin LI failed("strmalloc");
9173f0a83dSXin LI }
9273f0a83dSXin LI return result;
9373f0a83dSXin LI }
9473f0a83dSXin LI
9573f0a83dSXin LI static TERMDATA *
new_termdata(void)9673f0a83dSXin LI new_termdata(void)
9773f0a83dSXin LI {
9873f0a83dSXin LI size_t want = use_termdata + 1;
9973f0a83dSXin LI
10073f0a83dSXin LI if (want >= len_termdata) {
10173f0a83dSXin LI len_termdata = (2 * want) + 10;
10273f0a83dSXin LI ptr_termdata = typeRealloc(TERMDATA, len_termdata, ptr_termdata);
10373f0a83dSXin LI if (ptr_termdata == 0)
10473f0a83dSXin LI failed("ptr_termdata");
10573f0a83dSXin LI }
10673f0a83dSXin LI
10773f0a83dSXin LI return ptr_termdata + use_termdata++;
10873f0a83dSXin LI }
10973f0a83dSXin LI
11073f0a83dSXin LI static int
compare_termdata(const void * a,const void * b)11173f0a83dSXin LI compare_termdata(const void *a, const void *b)
11273f0a83dSXin LI {
11373f0a83dSXin LI const TERMDATA *p = (const TERMDATA *) a;
11473f0a83dSXin LI const TERMDATA *q = (const TERMDATA *) b;
11573f0a83dSXin LI int result = strcmp(p->term_name, q->term_name);
11673f0a83dSXin LI
11773f0a83dSXin LI if (result == 0) {
11873f0a83dSXin LI result = (p->db_index - q->db_index);
11973f0a83dSXin LI }
12073f0a83dSXin LI return result;
12173f0a83dSXin LI }
12273f0a83dSXin LI
12373f0a83dSXin LI /*
12473f0a83dSXin LI * Sort the array of TERMDATA and print it. If more than one database is being
12573f0a83dSXin LI * reported, add a column to show which database has a given entry.
12673f0a83dSXin LI */
12773f0a83dSXin LI static void
show_termdata(int eargc,char ** eargv)12873f0a83dSXin LI show_termdata(int eargc, char **eargv)
12973f0a83dSXin LI {
130*21817992SBaptiste Daroussin if (use_termdata) {
13173f0a83dSXin LI size_t n;
13273f0a83dSXin LI
13373f0a83dSXin LI if (eargc > 1) {
134*21817992SBaptiste Daroussin int j;
135*21817992SBaptiste Daroussin
13673f0a83dSXin LI for (j = 0; j < eargc; ++j) {
137*21817992SBaptiste Daroussin int k;
138*21817992SBaptiste Daroussin
13973f0a83dSXin LI for (k = 0; k <= j; ++k) {
14073f0a83dSXin LI printf("--");
14173f0a83dSXin LI }
14273f0a83dSXin LI printf("> ");
14373f0a83dSXin LI printf("%s\n", eargv[j]);
14473f0a83dSXin LI }
14573f0a83dSXin LI }
14673f0a83dSXin LI if (use_termdata > 1)
14773f0a83dSXin LI qsort(ptr_termdata, use_termdata, sizeof(TERMDATA), compare_termdata);
14873f0a83dSXin LI for (n = 0; n < use_termdata; ++n) {
149*21817992SBaptiste Daroussin int nk = -1;
15073f0a83dSXin LI
15173f0a83dSXin LI /*
15273f0a83dSXin LI * If there is more than one database, show how they differ.
15373f0a83dSXin LI */
15473f0a83dSXin LI if (eargc > 1) {
15573f0a83dSXin LI unsigned long check = 0;
156*21817992SBaptiste Daroussin int k = 0;
15773f0a83dSXin LI for (;;) {
158*21817992SBaptiste Daroussin char mark = ((check == 0
159*21817992SBaptiste Daroussin || (check != ptr_termdata[n].checksum))
160*21817992SBaptiste Daroussin ? '*'
161*21817992SBaptiste Daroussin : '+');
162*21817992SBaptiste Daroussin
16373f0a83dSXin LI for (; k < ptr_termdata[n].db_index; ++k) {
16473f0a83dSXin LI printf("--");
16573f0a83dSXin LI }
16673f0a83dSXin LI
16773f0a83dSXin LI /*
16873f0a83dSXin LI * If this is the first entry, or its checksum differs
16973f0a83dSXin LI * from the first entry's checksum, print "*". Otherwise
17073f0a83dSXin LI * it looks enough like a duplicate to print "+".
17173f0a83dSXin LI */
172*21817992SBaptiste Daroussin printf("%c-", mark);
17373f0a83dSXin LI check = ptr_termdata[n].checksum;
174*21817992SBaptiste Daroussin if (mark == '*' && nk < 0)
175*21817992SBaptiste Daroussin nk = (int) n;
17673f0a83dSXin LI
17773f0a83dSXin LI ++k;
17873f0a83dSXin LI if ((n + 1) >= use_termdata
17973f0a83dSXin LI || strcmp(ptr_termdata[n].term_name,
18073f0a83dSXin LI ptr_termdata[n + 1].term_name)) {
18173f0a83dSXin LI break;
18273f0a83dSXin LI }
18373f0a83dSXin LI ++n;
18473f0a83dSXin LI }
18573f0a83dSXin LI for (; k < eargc; ++k) {
18673f0a83dSXin LI printf("--");
18773f0a83dSXin LI }
18873f0a83dSXin LI printf(":\t");
18973f0a83dSXin LI }
190*21817992SBaptiste Daroussin if (nk < 0)
191*21817992SBaptiste Daroussin nk = (int) n;
19273f0a83dSXin LI
19373f0a83dSXin LI (void) printf("%-10s\t%s\n",
19473f0a83dSXin LI ptr_termdata[n].term_name,
195*21817992SBaptiste Daroussin ptr_termdata[nk].description);
19673f0a83dSXin LI }
19773f0a83dSXin LI }
19873f0a83dSXin LI }
19973f0a83dSXin LI
20073f0a83dSXin LI static void
free_termdata(void)20173f0a83dSXin LI free_termdata(void)
20273f0a83dSXin LI {
20373f0a83dSXin LI if (ptr_termdata != 0) {
20473f0a83dSXin LI while (use_termdata != 0) {
20573f0a83dSXin LI --use_termdata;
20673f0a83dSXin LI free(ptr_termdata[use_termdata].term_name);
20773f0a83dSXin LI free(ptr_termdata[use_termdata].description);
20873f0a83dSXin LI }
20973f0a83dSXin LI free(ptr_termdata);
21073f0a83dSXin LI ptr_termdata = 0;
21173f0a83dSXin LI }
21273f0a83dSXin LI use_termdata = 0;
21373f0a83dSXin LI len_termdata = 0;
21473f0a83dSXin LI }
21573f0a83dSXin LI
21673f0a83dSXin LI static char **
allocArgv(size_t count)21773f0a83dSXin LI allocArgv(size_t count)
21873f0a83dSXin LI {
21973f0a83dSXin LI char **result = typeCalloc(char *, count + 1);
22073f0a83dSXin LI if (result == 0)
22173f0a83dSXin LI failed("realloc eargv");
22273f0a83dSXin LI
22373f0a83dSXin LI assert(result != 0);
22473f0a83dSXin LI return result;
22573f0a83dSXin LI }
22673f0a83dSXin LI
22773f0a83dSXin LI static void
freeArgv(char ** argv)22873f0a83dSXin LI freeArgv(char **argv)
22973f0a83dSXin LI {
23073f0a83dSXin LI if (argv) {
23173f0a83dSXin LI int count = 0;
23273f0a83dSXin LI while (argv[count]) {
23373f0a83dSXin LI free(argv[count++]);
23473f0a83dSXin LI }
23573f0a83dSXin LI free(argv);
23673f0a83dSXin LI }
23773f0a83dSXin LI }
23873f0a83dSXin LI
2394a1a9510SRong-En Fan #if USE_HASHED_DB
24039f2269fSPeter Wemm static bool
make_db_name(char * dst,const char * src,unsigned limit)2414a1a9510SRong-En Fan make_db_name(char *dst, const char *src, unsigned limit)
24239f2269fSPeter Wemm {
2434a1a9510SRong-En Fan static const char suffix[] = DBM_SUFFIX;
2444a1a9510SRong-En Fan
2454a1a9510SRong-En Fan bool result = FALSE;
24673f0a83dSXin LI size_t lens = sizeof(suffix) - 1;
24773f0a83dSXin LI size_t size = strlen(src);
24873f0a83dSXin LI size_t need = lens + size;
2494a1a9510SRong-En Fan
2504a1a9510SRong-En Fan if (need <= limit) {
2514a1a9510SRong-En Fan if (size >= lens
25273f0a83dSXin LI && !strcmp(src + size - lens, suffix)) {
25373f0a83dSXin LI _nc_STRCPY(dst, src, PATH_MAX);
25473f0a83dSXin LI } else {
255*21817992SBaptiste Daroussin _nc_SPRINTF(dst, _nc_SLIMIT(PATH_MAX) "%.*s%s",
256*21817992SBaptiste Daroussin (int) (PATH_MAX - sizeof(suffix)),
257*21817992SBaptiste Daroussin src, suffix);
25873f0a83dSXin LI }
2594a1a9510SRong-En Fan result = TRUE;
26039f2269fSPeter Wemm }
2614a1a9510SRong-En Fan return result;
2624a1a9510SRong-En Fan }
2634a1a9510SRong-En Fan #endif
26439f2269fSPeter Wemm
26573f0a83dSXin LI typedef void (DescHook) (int /* db_index */ ,
26673f0a83dSXin LI int /* db_limit */ ,
26773f0a83dSXin LI const char * /* term_name */ ,
268aae38d10SBaptiste Daroussin TERMTYPE2 * /* term */ );
26939f2269fSPeter Wemm
27073f0a83dSXin LI static const char *
term_description(TERMTYPE2 * tp)271aae38d10SBaptiste Daroussin term_description(TERMTYPE2 *tp)
27215589c42SPeter Wemm {
2734a1a9510SRong-En Fan const char *desc;
2744a1a9510SRong-En Fan
27573f0a83dSXin LI if (tp->term_names == 0
27673f0a83dSXin LI || (desc = strrchr(tp->term_names, '|')) == 0
27773f0a83dSXin LI || (*++desc == '\0')) {
2784a1a9510SRong-En Fan desc = "(No description)";
27915589c42SPeter Wemm }
2804a1a9510SRong-En Fan
28173f0a83dSXin LI return desc;
28273f0a83dSXin LI }
28373f0a83dSXin LI
28473f0a83dSXin LI /* display a description for the type */
2854a1a9510SRong-En Fan static void
deschook(int db_index,int db_limit,const char * term_name,TERMTYPE2 * tp)286aae38d10SBaptiste Daroussin deschook(int db_index, int db_limit, const char *term_name, TERMTYPE2 *tp)
28773f0a83dSXin LI {
28873f0a83dSXin LI (void) db_index;
28973f0a83dSXin LI (void) db_limit;
29073f0a83dSXin LI (void) printf("%-10s\t%s\n", term_name, term_description(tp));
29173f0a83dSXin LI }
29273f0a83dSXin LI
29373f0a83dSXin LI static unsigned long
string_sum(const char * value)29473f0a83dSXin LI string_sum(const char *value)
29573f0a83dSXin LI {
29673f0a83dSXin LI unsigned long result = 0;
29773f0a83dSXin LI
29873f0a83dSXin LI if ((intptr_t) value == (intptr_t) (-1)) {
29973f0a83dSXin LI result = ~result;
30073f0a83dSXin LI } else if (value) {
30173f0a83dSXin LI while (*value) {
30273f0a83dSXin LI result += UChar(*value);
30373f0a83dSXin LI ++value;
30473f0a83dSXin LI }
30573f0a83dSXin LI }
30673f0a83dSXin LI return result;
30773f0a83dSXin LI }
30873f0a83dSXin LI
30973f0a83dSXin LI static unsigned long
checksum_of(TERMTYPE2 * tp)310aae38d10SBaptiste Daroussin checksum_of(TERMTYPE2 *tp)
31173f0a83dSXin LI {
31273f0a83dSXin LI unsigned long result = string_sum(tp->term_names);
31373f0a83dSXin LI unsigned i;
31473f0a83dSXin LI
31573f0a83dSXin LI for (i = 0; i < NUM_BOOLEANS(tp); i++) {
31673f0a83dSXin LI result += (unsigned long) (tp->Booleans[i]);
31773f0a83dSXin LI }
31873f0a83dSXin LI for (i = 0; i < NUM_NUMBERS(tp); i++) {
31973f0a83dSXin LI result += (unsigned long) (tp->Numbers[i]);
32073f0a83dSXin LI }
32173f0a83dSXin LI for (i = 0; i < NUM_STRINGS(tp); i++) {
32273f0a83dSXin LI result += string_sum(tp->Strings[i]);
32373f0a83dSXin LI }
32473f0a83dSXin LI return result;
32573f0a83dSXin LI }
32673f0a83dSXin LI
32773f0a83dSXin LI /* collect data, to sort before display */
32873f0a83dSXin LI static void
sorthook(int db_index,int db_limit,const char * term_name,TERMTYPE2 * tp)329aae38d10SBaptiste Daroussin sorthook(int db_index, int db_limit, const char *term_name, TERMTYPE2 *tp)
33073f0a83dSXin LI {
33173f0a83dSXin LI TERMDATA *data = new_termdata();
33273f0a83dSXin LI
33373f0a83dSXin LI data->db_index = db_index;
33473f0a83dSXin LI data->checksum = ((db_limit > 1) ? checksum_of(tp) : 0);
33573f0a83dSXin LI data->term_name = strmalloc(term_name);
33673f0a83dSXin LI data->description = strmalloc(term_description(tp));
33773f0a83dSXin LI }
33873f0a83dSXin LI
33973f0a83dSXin LI #if NCURSES_USE_TERMCAP
340*21817992SBaptiste Daroussin /*
341*21817992SBaptiste Daroussin * Check if the buffer contents are printable ASCII, ensuring that we do not
342*21817992SBaptiste Daroussin * accidentally pick up incompatible binary content from a hashed database.
343*21817992SBaptiste Daroussin */
344*21817992SBaptiste Daroussin static bool
is_termcap(char * buffer)345*21817992SBaptiste Daroussin is_termcap(char *buffer)
346*21817992SBaptiste Daroussin {
347*21817992SBaptiste Daroussin bool result = TRUE;
348*21817992SBaptiste Daroussin while (*buffer != '\0') {
349*21817992SBaptiste Daroussin int ch = UChar(*buffer++);
350*21817992SBaptiste Daroussin if (ch == '\t')
351*21817992SBaptiste Daroussin continue;
352*21817992SBaptiste Daroussin if (ch < ' ' || ch > '~') {
353*21817992SBaptiste Daroussin result = FALSE;
354*21817992SBaptiste Daroussin break;
355*21817992SBaptiste Daroussin }
356*21817992SBaptiste Daroussin }
357*21817992SBaptiste Daroussin return result;
358*21817992SBaptiste Daroussin }
359*21817992SBaptiste Daroussin
36073f0a83dSXin LI static void
show_termcap(int db_index,int db_limit,char * buffer,DescHook hook)36173f0a83dSXin LI show_termcap(int db_index, int db_limit, char *buffer, DescHook hook)
3624a1a9510SRong-En Fan {
363aae38d10SBaptiste Daroussin TERMTYPE2 data;
3644a1a9510SRong-En Fan char *next = strchr(buffer, ':');
3654a1a9510SRong-En Fan char *last;
3664a1a9510SRong-En Fan char *list = buffer;
3674a1a9510SRong-En Fan
3684a1a9510SRong-En Fan if (next)
3694a1a9510SRong-En Fan *next = '\0';
3704a1a9510SRong-En Fan
3714a1a9510SRong-En Fan last = strrchr(buffer, '|');
3724a1a9510SRong-En Fan if (last)
3734a1a9510SRong-En Fan ++last;
3744a1a9510SRong-En Fan
37573f0a83dSXin LI memset(&data, 0, sizeof(data));
37673f0a83dSXin LI data.term_names = strmalloc(buffer);
3774a1a9510SRong-En Fan while ((next = strtok(list, "|")) != 0) {
3784a1a9510SRong-En Fan if (next != last)
37973f0a83dSXin LI hook(db_index, db_limit, next, &data);
3804a1a9510SRong-En Fan list = 0;
3814a1a9510SRong-En Fan }
3824a1a9510SRong-En Fan free(data.term_names);
3834a1a9510SRong-En Fan }
3844a1a9510SRong-En Fan #endif
3854a1a9510SRong-En Fan
38673f0a83dSXin LI #if NCURSES_USE_DATABASE
38773f0a83dSXin LI static char *
copy_entryname(DIRENT * src)38873f0a83dSXin LI copy_entryname(DIRENT * src)
38973f0a83dSXin LI {
39073f0a83dSXin LI size_t len = NAMLEN(src);
39173f0a83dSXin LI char *result = malloc(len + 1);
39273f0a83dSXin LI if (result == 0)
39373f0a83dSXin LI failed("copy entryname");
39473f0a83dSXin LI memcpy(result, src->d_name, len);
39573f0a83dSXin LI result[len] = '\0';
39673f0a83dSXin LI
39773f0a83dSXin LI return result;
39873f0a83dSXin LI }
39973f0a83dSXin LI #endif
40073f0a83dSXin LI
4014a1a9510SRong-En Fan static int
typelist(int eargc,char * eargv[],int verbosity,DescHook hook)4024a1a9510SRong-En Fan typelist(int eargc, char *eargv[],
40373f0a83dSXin LI int verbosity,
40473f0a83dSXin LI DescHook hook)
4054a1a9510SRong-En Fan /* apply a function to each entry in given terminfo directories */
4064a1a9510SRong-En Fan {
4074a1a9510SRong-En Fan int i;
4084a1a9510SRong-En Fan
4094a1a9510SRong-En Fan for (i = 0; i < eargc; i++) {
41073f0a83dSXin LI #if NCURSES_USE_DATABASE
4114a1a9510SRong-En Fan if (_nc_is_dir_path(eargv[i])) {
4125d08fb1fSRong-En Fan char *cwd_buf = 0;
4134a1a9510SRong-En Fan DIR *termdir;
4144a1a9510SRong-En Fan DIRENT *subdir;
4154a1a9510SRong-En Fan
4164a1a9510SRong-En Fan if ((termdir = opendir(eargv[i])) == 0) {
4174a1a9510SRong-En Fan (void) fflush(stdout);
4184a1a9510SRong-En Fan (void) fprintf(stderr,
4194a1a9510SRong-En Fan "%s: can't open terminfo directory %s\n",
4204a1a9510SRong-En Fan _nc_progname, eargv[i]);
42173f0a83dSXin LI continue;
42273f0a83dSXin LI }
42373f0a83dSXin LI
42473f0a83dSXin LI if (verbosity)
4254a1a9510SRong-En Fan (void) printf("#\n#%s:\n#\n", eargv[i]);
4264a1a9510SRong-En Fan
4274a1a9510SRong-En Fan while ((subdir = readdir(termdir)) != 0) {
42873f0a83dSXin LI size_t cwd_len;
42973f0a83dSXin LI char *name_1;
4304a1a9510SRong-En Fan DIR *entrydir;
4314a1a9510SRong-En Fan DIRENT *entry;
4324a1a9510SRong-En Fan
43373f0a83dSXin LI name_1 = copy_entryname(subdir);
43473f0a83dSXin LI if (isDotname(name_1)) {
43573f0a83dSXin LI free(name_1);
43673f0a83dSXin LI continue;
43773f0a83dSXin LI }
43873f0a83dSXin LI
43973f0a83dSXin LI cwd_len = NAMLEN(subdir) + strlen(eargv[i]) + 3;
4405d08fb1fSRong-En Fan cwd_buf = typeRealloc(char, cwd_len, cwd_buf);
44106bfebdeSXin LI if (cwd_buf == 0)
44206bfebdeSXin LI failed("realloc cwd_buf");
44306bfebdeSXin LI
44406bfebdeSXin LI assert(cwd_buf != 0);
4455d08fb1fSRong-En Fan
44673f0a83dSXin LI _nc_SPRINTF(cwd_buf, _nc_SLIMIT(cwd_len)
44773f0a83dSXin LI "%s/%s/", eargv[i], name_1);
44873f0a83dSXin LI free(name_1);
4494a1a9510SRong-En Fan
4505d08fb1fSRong-En Fan if (chdir(cwd_buf) != 0)
4514a1a9510SRong-En Fan continue;
4524a1a9510SRong-En Fan
4534a1a9510SRong-En Fan entrydir = opendir(".");
4545d08fb1fSRong-En Fan if (entrydir == 0) {
4555d08fb1fSRong-En Fan perror(cwd_buf);
4565d08fb1fSRong-En Fan continue;
4575d08fb1fSRong-En Fan }
4584a1a9510SRong-En Fan while ((entry = readdir(entrydir)) != 0) {
45973f0a83dSXin LI char *name_2;
460aae38d10SBaptiste Daroussin TERMTYPE2 lterm;
4614a1a9510SRong-En Fan char *cn;
4624a1a9510SRong-En Fan int status;
4634a1a9510SRong-En Fan
46473f0a83dSXin LI name_2 = copy_entryname(entry);
46573f0a83dSXin LI if (isDotname(name_2) || !_nc_is_file_path(name_2)) {
46673f0a83dSXin LI free(name_2);
4674a1a9510SRong-En Fan continue;
46873f0a83dSXin LI }
4694a1a9510SRong-En Fan
4704a1a9510SRong-En Fan status = _nc_read_file_entry(name_2, <erm);
4714a1a9510SRong-En Fan if (status <= 0) {
4724a1a9510SRong-En Fan (void) fflush(stdout);
4734a1a9510SRong-En Fan (void) fprintf(stderr,
4744a1a9510SRong-En Fan "%s: couldn't open terminfo file %s.\n",
4754a1a9510SRong-En Fan _nc_progname, name_2);
47673f0a83dSXin LI free(name_2);
477aae38d10SBaptiste Daroussin continue;
4784a1a9510SRong-En Fan }
4794a1a9510SRong-En Fan
4804a1a9510SRong-En Fan /* only visit things once, by primary name */
4814a1a9510SRong-En Fan cn = _nc_first_name(lterm.term_names);
4824a1a9510SRong-En Fan if (!strcmp(cn, name_2)) {
4834a1a9510SRong-En Fan /* apply the selected hook function */
48473f0a83dSXin LI hook(i, eargc, cn, <erm);
4854a1a9510SRong-En Fan }
486aae38d10SBaptiste Daroussin _nc_free_termtype2(<erm);
48773f0a83dSXin LI free(name_2);
4884a1a9510SRong-En Fan }
4894a1a9510SRong-En Fan closedir(entrydir);
4904a1a9510SRong-En Fan }
4914a1a9510SRong-En Fan closedir(termdir);
4925d08fb1fSRong-En Fan if (cwd_buf != 0)
4935d08fb1fSRong-En Fan free(cwd_buf);
49473f0a83dSXin LI continue;
4954a1a9510SRong-En Fan }
4964a1a9510SRong-En Fan #if USE_HASHED_DB
4974a1a9510SRong-En Fan else {
4984a1a9510SRong-En Fan DB *capdbp;
4994a1a9510SRong-En Fan char filename[PATH_MAX];
5004a1a9510SRong-En Fan
50173f0a83dSXin LI if (verbosity)
50273f0a83dSXin LI (void) printf("#\n#%s:\n#\n", eargv[i]);
50373f0a83dSXin LI
5044a1a9510SRong-En Fan if (make_db_name(filename, eargv[i], sizeof(filename))) {
5054a1a9510SRong-En Fan if ((capdbp = _nc_db_open(filename, FALSE)) != 0) {
5064a1a9510SRong-En Fan DBT key, data;
5074a1a9510SRong-En Fan int code;
5084a1a9510SRong-En Fan
5094a1a9510SRong-En Fan code = _nc_db_first(capdbp, &key, &data);
5104a1a9510SRong-En Fan while (code == 0) {
511aae38d10SBaptiste Daroussin TERMTYPE2 lterm;
5124a1a9510SRong-En Fan int used;
5134a1a9510SRong-En Fan char *have;
5144a1a9510SRong-En Fan char *cn;
5154a1a9510SRong-En Fan
5164a1a9510SRong-En Fan if (_nc_db_have_data(&key, &data, &have, &used)) {
5174a1a9510SRong-En Fan if (_nc_read_termtype(<erm, have, used) > 0) {
5184a1a9510SRong-En Fan /* only visit things once, by primary name */
5194a1a9510SRong-En Fan cn = _nc_first_name(lterm.term_names);
5204a1a9510SRong-En Fan /* apply the selected hook function */
52173f0a83dSXin LI hook(i, eargc, cn, <erm);
522aae38d10SBaptiste Daroussin _nc_free_termtype2(<erm);
5234a1a9510SRong-En Fan }
5244a1a9510SRong-En Fan }
5254a1a9510SRong-En Fan code = _nc_db_next(capdbp, &key, &data);
5264a1a9510SRong-En Fan }
5274a1a9510SRong-En Fan
5284a1a9510SRong-En Fan _nc_db_close(capdbp);
52973f0a83dSXin LI continue;
5304a1a9510SRong-En Fan }
5314a1a9510SRong-En Fan }
5324a1a9510SRong-En Fan }
533aae38d10SBaptiste Daroussin #endif /* USE_HASHED_DB */
534aae38d10SBaptiste Daroussin #endif /* NCURSES_USE_DATABASE */
53573f0a83dSXin LI #if NCURSES_USE_TERMCAP
5364a1a9510SRong-En Fan #if HAVE_BSD_CGETENT
53773f0a83dSXin LI {
53873f0a83dSXin LI CGETENT_CONST char *db_array[2];
5394a1a9510SRong-En Fan char *buffer = 0;
5404a1a9510SRong-En Fan
5414a1a9510SRong-En Fan if (verbosity)
5424a1a9510SRong-En Fan (void) printf("#\n#%s:\n#\n", eargv[i]);
5434a1a9510SRong-En Fan
5444a1a9510SRong-En Fan db_array[0] = eargv[i];
5454a1a9510SRong-En Fan db_array[1] = 0;
5464a1a9510SRong-En Fan
54773f0a83dSXin LI if (cgetfirst(&buffer, db_array) > 0) {
548*21817992SBaptiste Daroussin if (is_termcap(buffer)) {
54973f0a83dSXin LI show_termcap(i, eargc, buffer, hook);
5504a1a9510SRong-En Fan free(buffer);
55173f0a83dSXin LI while (cgetnext(&buffer, db_array) > 0) {
55273f0a83dSXin LI show_termcap(i, eargc, buffer, hook);
5534a1a9510SRong-En Fan free(buffer);
5544a1a9510SRong-En Fan }
555*21817992SBaptiste Daroussin }
5564a1a9510SRong-En Fan cgetclose();
55773f0a83dSXin LI continue;
55873f0a83dSXin LI }
55973f0a83dSXin LI }
5604a1a9510SRong-En Fan #else
5614a1a9510SRong-En Fan /* scan termcap text-file only */
5624a1a9510SRong-En Fan if (_nc_is_file_path(eargv[i])) {
5634a1a9510SRong-En Fan char buffer[2048];
5644a1a9510SRong-En Fan FILE *fp;
5654a1a9510SRong-En Fan
56673f0a83dSXin LI if (verbosity)
56773f0a83dSXin LI (void) printf("#\n#%s:\n#\n", eargv[i]);
56873f0a83dSXin LI
569*21817992SBaptiste Daroussin if ((fp = safe_fopen(eargv[i], "r")) != 0) {
5704a1a9510SRong-En Fan while (fgets(buffer, sizeof(buffer), fp) != 0) {
571*21817992SBaptiste Daroussin if (!is_termcap(buffer))
572*21817992SBaptiste Daroussin break;
5734a1a9510SRong-En Fan if (*buffer == '#')
5744a1a9510SRong-En Fan continue;
575*21817992SBaptiste Daroussin if (isspace(UChar(*buffer)))
5764a1a9510SRong-En Fan continue;
57773f0a83dSXin LI show_termcap(i, eargc, buffer, hook);
5784a1a9510SRong-En Fan }
5794a1a9510SRong-En Fan fclose(fp);
5804a1a9510SRong-En Fan }
5814a1a9510SRong-En Fan }
5824a1a9510SRong-En Fan #endif
5834a1a9510SRong-En Fan #endif
5844a1a9510SRong-En Fan }
5854a1a9510SRong-En Fan
58673f0a83dSXin LI if (hook == sorthook) {
58773f0a83dSXin LI show_termdata(eargc, eargv);
58873f0a83dSXin LI free_termdata();
58973f0a83dSXin LI }
59073f0a83dSXin LI
5914a1a9510SRong-En Fan return (EXIT_SUCCESS);
5924a1a9510SRong-En Fan }
5934a1a9510SRong-En Fan
5944a1a9510SRong-En Fan static void
usage(void)5954a1a9510SRong-En Fan usage(void)
5964a1a9510SRong-En Fan {
59773f0a83dSXin LI (void) fprintf(stderr, "usage: %s [-ahsuUV] [-v n] [file...]\n", _nc_progname);
5984a1a9510SRong-En Fan ExitProgram(EXIT_FAILURE);
59915589c42SPeter Wemm }
60015589c42SPeter Wemm
60115589c42SPeter Wemm int
main(int argc,char * argv[])60215589c42SPeter Wemm main(int argc, char *argv[])
6030e3d5408SPeter Wemm {
6044a1a9510SRong-En Fan bool all_dirs = FALSE;
6050e3d5408SPeter Wemm bool direct_dependencies = FALSE;
6060e3d5408SPeter Wemm bool invert_dependencies = FALSE;
6070e3d5408SPeter Wemm bool header = FALSE;
608d8977eafSRong-En Fan char *report_file = 0;
6090e3d5408SPeter Wemm int code;
6104a1a9510SRong-En Fan int this_opt, last_opt = '?';
61173f0a83dSXin LI unsigned v_opt = 0;
61273f0a83dSXin LI DescHook *hook = deschook;
6130e3d5408SPeter Wemm
61439f2269fSPeter Wemm _nc_progname = _nc_rootname(argv[0]);
6150e3d5408SPeter Wemm
61673f0a83dSXin LI while ((this_opt = getopt(argc, argv, "0123456789ahsu:vU:V")) != -1) {
6174a1a9510SRong-En Fan /* handle optional parameter */
6184a1a9510SRong-En Fan if (isdigit(this_opt)) {
6194a1a9510SRong-En Fan switch (last_opt) {
6204a1a9510SRong-En Fan case 'v':
62173f0a83dSXin LI v_opt = (unsigned) (this_opt - '0');
6224a1a9510SRong-En Fan break;
6234a1a9510SRong-En Fan default:
6244a1a9510SRong-En Fan if (isdigit(last_opt))
6254a1a9510SRong-En Fan v_opt *= 10;
6264a1a9510SRong-En Fan else
6274a1a9510SRong-En Fan v_opt = 0;
62873f0a83dSXin LI v_opt += (unsigned) (this_opt - '0');
6294a1a9510SRong-En Fan last_opt = this_opt;
6304a1a9510SRong-En Fan }
6314a1a9510SRong-En Fan continue;
6324a1a9510SRong-En Fan }
6334a1a9510SRong-En Fan switch (this_opt) {
6344a1a9510SRong-En Fan case 'a':
6354a1a9510SRong-En Fan all_dirs = TRUE;
6364a1a9510SRong-En Fan break;
6370e3d5408SPeter Wemm case 'h':
6380e3d5408SPeter Wemm header = TRUE;
6390e3d5408SPeter Wemm break;
64073f0a83dSXin LI case 's':
64173f0a83dSXin LI hook = sorthook;
64273f0a83dSXin LI break;
6430e3d5408SPeter Wemm case 'u':
6440e3d5408SPeter Wemm direct_dependencies = TRUE;
645d8977eafSRong-En Fan report_file = optarg;
6460e3d5408SPeter Wemm break;
6470e3d5408SPeter Wemm case 'v':
6484a1a9510SRong-En Fan v_opt = 1;
6490e3d5408SPeter Wemm break;
6500e3d5408SPeter Wemm case 'U':
6510e3d5408SPeter Wemm invert_dependencies = TRUE;
652d8977eafSRong-En Fan report_file = optarg;
6530e3d5408SPeter Wemm break;
6540e3d5408SPeter Wemm case 'V':
65518259542SPeter Wemm puts(curses_version());
6560e3d5408SPeter Wemm ExitProgram(EXIT_SUCCESS);
6570e3d5408SPeter Wemm default:
6584a1a9510SRong-En Fan usage();
6590e3d5408SPeter Wemm }
6604a1a9510SRong-En Fan }
661*21817992SBaptiste Daroussin use_verbosity(v_opt);
6620e3d5408SPeter Wemm
663d8977eafSRong-En Fan if (report_file != 0) {
664d8977eafSRong-En Fan if (freopen(report_file, "r", stdin) == 0) {
6650e3d5408SPeter Wemm (void) fflush(stdout);
666d8977eafSRong-En Fan fprintf(stderr, "%s: can't open %s\n", _nc_progname, report_file);
6670e3d5408SPeter Wemm ExitProgram(EXIT_FAILURE);
6680e3d5408SPeter Wemm }
6690e3d5408SPeter Wemm
6700e3d5408SPeter Wemm /* parse entries out of the source file */
671d8977eafSRong-En Fan _nc_set_source(report_file);
67215589c42SPeter Wemm _nc_read_entry_source(stdin, 0, FALSE, FALSE, NULLHOOK);
6730e3d5408SPeter Wemm }
6740e3d5408SPeter Wemm
6750e3d5408SPeter Wemm /* maybe we want a direct-dependency listing? */
67615589c42SPeter Wemm if (direct_dependencies) {
6770e3d5408SPeter Wemm ENTRY *qp;
6780e3d5408SPeter Wemm
6794a1a9510SRong-En Fan for_entry_list(qp) {
68015589c42SPeter Wemm if (qp->nuses) {
6815d08fb1fSRong-En Fan unsigned j;
6820e3d5408SPeter Wemm
6830e3d5408SPeter Wemm (void) printf("%s:", _nc_first_name(qp->tterm.term_names));
6840e3d5408SPeter Wemm for (j = 0; j < qp->nuses; j++)
68515589c42SPeter Wemm (void) printf(" %s", qp->uses[j].name);
6860e3d5408SPeter Wemm putchar('\n');
6870e3d5408SPeter Wemm }
6884a1a9510SRong-En Fan }
6890e3d5408SPeter Wemm
6900e3d5408SPeter Wemm ExitProgram(EXIT_SUCCESS);
6910e3d5408SPeter Wemm }
6920e3d5408SPeter Wemm
6930e3d5408SPeter Wemm /* maybe we want a reverse-dependency listing? */
69415589c42SPeter Wemm if (invert_dependencies) {
6950e3d5408SPeter Wemm ENTRY *qp, *rp;
6960e3d5408SPeter Wemm
69715589c42SPeter Wemm for_entry_list(qp) {
698*21817992SBaptiste Daroussin int matchcount = 0;
699*21817992SBaptiste Daroussin
70015589c42SPeter Wemm for_entry_list(rp) {
701*21817992SBaptiste Daroussin unsigned i;
702*21817992SBaptiste Daroussin
7030e3d5408SPeter Wemm if (rp->nuses == 0)
7040e3d5408SPeter Wemm continue;
7050e3d5408SPeter Wemm
7060e3d5408SPeter Wemm for (i = 0; i < rp->nuses; i++)
70715589c42SPeter Wemm if (_nc_name_match(qp->tterm.term_names,
70815589c42SPeter Wemm rp->uses[i].name, "|")) {
7090e3d5408SPeter Wemm if (matchcount++ == 0)
7100e3d5408SPeter Wemm (void) printf("%s:",
7110e3d5408SPeter Wemm _nc_first_name(qp->tterm.term_names));
7120e3d5408SPeter Wemm (void) printf(" %s",
7130e3d5408SPeter Wemm _nc_first_name(rp->tterm.term_names));
7140e3d5408SPeter Wemm }
7150e3d5408SPeter Wemm }
7160e3d5408SPeter Wemm if (matchcount)
7170e3d5408SPeter Wemm putchar('\n');
7180e3d5408SPeter Wemm }
7190e3d5408SPeter Wemm
7200e3d5408SPeter Wemm ExitProgram(EXIT_SUCCESS);
7210e3d5408SPeter Wemm }
7220e3d5408SPeter Wemm
7230e3d5408SPeter Wemm /*
7240e3d5408SPeter Wemm * If we get this far, user wants a simple terminal type listing.
7250e3d5408SPeter Wemm */
7260e3d5408SPeter Wemm if (optind < argc) {
72773f0a83dSXin LI code = typelist(argc - optind, argv + optind, header, hook);
7284a1a9510SRong-En Fan } else if (all_dirs) {
7294a1a9510SRong-En Fan DBDIRS state;
7304a1a9510SRong-En Fan int offset;
7314a1a9510SRong-En Fan int pass;
7324a1a9510SRong-En Fan char **eargv = 0;
7330e3d5408SPeter Wemm
7344a1a9510SRong-En Fan code = EXIT_FAILURE;
7354a1a9510SRong-En Fan for (pass = 0; pass < 2; ++pass) {
73673f0a83dSXin LI size_t count = 0;
737*21817992SBaptiste Daroussin const char *path;
7380e3d5408SPeter Wemm
7394a1a9510SRong-En Fan _nc_first_db(&state, &offset);
7404a1a9510SRong-En Fan while ((path = _nc_next_db(&state, &offset)) != 0) {
741aae38d10SBaptiste Daroussin if (quick_prefix(path))
742aae38d10SBaptiste Daroussin continue;
74373f0a83dSXin LI if (pass) {
74473f0a83dSXin LI eargv[count] = strmalloc(path);
7450e3d5408SPeter Wemm }
7464a1a9510SRong-En Fan ++count;
7474a1a9510SRong-En Fan }
7484a1a9510SRong-En Fan if (!pass) {
74973f0a83dSXin LI eargv = allocArgv(count);
75006bfebdeSXin LI if (eargv == 0)
75173f0a83dSXin LI failed("eargv");
7524a1a9510SRong-En Fan } else {
75373f0a83dSXin LI code = typelist((int) count, eargv, header, hook);
75473f0a83dSXin LI freeArgv(eargv);
7554a1a9510SRong-En Fan }
7564a1a9510SRong-En Fan }
7574a1a9510SRong-En Fan } else {
7584a1a9510SRong-En Fan DBDIRS state;
7594a1a9510SRong-En Fan int offset;
7604a1a9510SRong-En Fan const char *path;
76173f0a83dSXin LI char **eargv = allocArgv((size_t) 2);
76273f0a83dSXin LI size_t count = 0;
7634a1a9510SRong-En Fan
76473f0a83dSXin LI if (eargv == 0)
76573f0a83dSXin LI failed("eargv");
7664a1a9510SRong-En Fan _nc_first_db(&state, &offset);
76773f0a83dSXin LI if ((path = _nc_next_db(&state, &offset)) != 0) {
768aae38d10SBaptiste Daroussin if (!quick_prefix(path))
76973f0a83dSXin LI eargv[count++] = strmalloc(path);
7704a1a9510SRong-En Fan }
7714a1a9510SRong-En Fan
77273f0a83dSXin LI code = typelist((int) count, eargv, header, hook);
7734a1a9510SRong-En Fan
77473f0a83dSXin LI freeArgv(eargv);
7754a1a9510SRong-En Fan }
7764a1a9510SRong-En Fan _nc_last_db();
7770e3d5408SPeter Wemm
7780e3d5408SPeter Wemm ExitProgram(code);
7790e3d5408SPeter Wemm }
780