xref: /dragonfly/contrib/ncurses/progs/toe.c (revision 32bb5217)
15f4613f2SJohn Marino /****************************************************************************
2*32bb5217SDaniel Fojt  * Copyright 2018,2020 Thomas E. Dickey                                     *
3*32bb5217SDaniel Fojt  * Copyright 1998-2013,2017 Free Software Foundation, Inc.                  *
45f4613f2SJohn Marino  *                                                                          *
55f4613f2SJohn Marino  * Permission is hereby granted, free of charge, to any person obtaining a  *
65f4613f2SJohn Marino  * copy of this software and associated documentation files (the            *
75f4613f2SJohn Marino  * "Software"), to deal in the Software without restriction, including      *
85f4613f2SJohn Marino  * without limitation the rights to use, copy, modify, merge, publish,      *
95f4613f2SJohn Marino  * distribute, distribute with modifications, sublicense, and/or sell       *
105f4613f2SJohn Marino  * copies of the Software, and to permit persons to whom the Software is    *
115f4613f2SJohn Marino  * furnished to do so, subject to the following conditions:                 *
125f4613f2SJohn Marino  *                                                                          *
135f4613f2SJohn Marino  * The above copyright notice and this permission notice shall be included  *
145f4613f2SJohn Marino  * in all copies or substantial portions of the Software.                   *
155f4613f2SJohn Marino  *                                                                          *
165f4613f2SJohn Marino  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
175f4613f2SJohn Marino  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
185f4613f2SJohn Marino  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
195f4613f2SJohn Marino  * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,   *
205f4613f2SJohn Marino  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR    *
215f4613f2SJohn Marino  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR    *
225f4613f2SJohn Marino  * THE USE OR OTHER DEALINGS IN THE SOFTWARE.                               *
235f4613f2SJohn Marino  *                                                                          *
245f4613f2SJohn Marino  * Except as contained in this notice, the name(s) of the above copyright   *
255f4613f2SJohn Marino  * holders shall not be used in advertising or otherwise to promote the     *
265f4613f2SJohn Marino  * sale, use or other dealings in this Software without prior written       *
275f4613f2SJohn Marino  * authorization.                                                           *
285f4613f2SJohn Marino  ****************************************************************************/
295f4613f2SJohn Marino 
305f4613f2SJohn Marino /****************************************************************************
315f4613f2SJohn Marino  *  Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995               *
325f4613f2SJohn Marino  *     and: Eric S. Raymond <esr@snark.thyrsus.com>                         *
335f4613f2SJohn Marino  *     and: Thomas E. Dickey                        1996-on                 *
345f4613f2SJohn Marino  ****************************************************************************/
355f4613f2SJohn Marino 
365f4613f2SJohn Marino /*
375f4613f2SJohn Marino  *	toe.c --- table of entries report generator
385f4613f2SJohn Marino  */
395f4613f2SJohn Marino 
405f4613f2SJohn Marino #include <progs.priv.h>
415f4613f2SJohn Marino 
425f4613f2SJohn Marino #include <sys/stat.h>
435f4613f2SJohn Marino 
445f4613f2SJohn Marino #if USE_HASHED_DB
455f4613f2SJohn Marino #include <hashed_db.h>
465f4613f2SJohn Marino #endif
475f4613f2SJohn Marino 
48*32bb5217SDaniel Fojt MODULE_ID("$Id: toe.c,v 1.79 2020/02/02 23:34:34 tom Exp $")
495f4613f2SJohn Marino 
505f4613f2SJohn Marino #define isDotname(name) (!strcmp(name, ".") || !strcmp(name, ".."))
515f4613f2SJohn Marino 
523468e90cSJohn Marino typedef struct {
533468e90cSJohn Marino     int db_index;
543468e90cSJohn Marino     unsigned long checksum;
553468e90cSJohn Marino     char *term_name;
563468e90cSJohn Marino     char *description;
573468e90cSJohn Marino } TERMDATA;
583468e90cSJohn Marino 
595f4613f2SJohn Marino const char *_nc_progname;
605f4613f2SJohn Marino 
613468e90cSJohn Marino static TERMDATA *ptr_termdata;	/* array of terminal data */
623468e90cSJohn Marino static size_t use_termdata;	/* actual usage in ptr_termdata[] */
633468e90cSJohn Marino static size_t len_termdata;	/* allocated size of ptr_termdata[] */
643468e90cSJohn Marino 
655f4613f2SJohn Marino #if NO_LEAKS
665f4613f2SJohn Marino #undef ExitProgram
675f4613f2SJohn Marino static void ExitProgram(int code) GCC_NORETURN;
685f4613f2SJohn Marino static void
ExitProgram(int code)695f4613f2SJohn Marino ExitProgram(int code)
705f4613f2SJohn Marino {
715f4613f2SJohn Marino     _nc_free_entries(_nc_head);
725f4613f2SJohn Marino     _nc_free_tic(code);
735f4613f2SJohn Marino }
745f4613f2SJohn Marino #endif
755f4613f2SJohn Marino 
763468e90cSJohn Marino static void failed(const char *) GCC_NORETURN;
773468e90cSJohn Marino 
785f4613f2SJohn Marino static void
failed(const char * msg)795f4613f2SJohn Marino failed(const char *msg)
805f4613f2SJohn Marino {
815f4613f2SJohn Marino     perror(msg);
825f4613f2SJohn Marino     ExitProgram(EXIT_FAILURE);
835f4613f2SJohn Marino }
845f4613f2SJohn Marino 
853468e90cSJohn Marino static char *
strmalloc(const char * value)863468e90cSJohn Marino strmalloc(const char *value)
873468e90cSJohn Marino {
883468e90cSJohn Marino     char *result = strdup(value);
893468e90cSJohn Marino     if (result == 0) {
903468e90cSJohn Marino 	failed("strmalloc");
913468e90cSJohn Marino     }
923468e90cSJohn Marino     return result;
933468e90cSJohn Marino }
943468e90cSJohn Marino 
953468e90cSJohn Marino static TERMDATA *
new_termdata(void)963468e90cSJohn Marino new_termdata(void)
973468e90cSJohn Marino {
983468e90cSJohn Marino     size_t want = use_termdata + 1;
993468e90cSJohn Marino 
1003468e90cSJohn Marino     if (want >= len_termdata) {
1013468e90cSJohn Marino 	len_termdata = (2 * want) + 10;
1023468e90cSJohn Marino 	ptr_termdata = typeRealloc(TERMDATA, len_termdata, ptr_termdata);
1033468e90cSJohn Marino 	if (ptr_termdata == 0)
1043468e90cSJohn Marino 	    failed("ptr_termdata");
1053468e90cSJohn Marino     }
1063468e90cSJohn Marino 
1073468e90cSJohn Marino     return ptr_termdata + use_termdata++;
1083468e90cSJohn Marino }
1093468e90cSJohn Marino 
1103468e90cSJohn Marino static int
compare_termdata(const void * a,const void * b)1113468e90cSJohn Marino compare_termdata(const void *a, const void *b)
1123468e90cSJohn Marino {
1133468e90cSJohn Marino     const TERMDATA *p = (const TERMDATA *) a;
1143468e90cSJohn Marino     const TERMDATA *q = (const TERMDATA *) b;
1153468e90cSJohn Marino     int result = strcmp(p->term_name, q->term_name);
1163468e90cSJohn Marino 
1173468e90cSJohn Marino     if (result == 0) {
1183468e90cSJohn Marino 	result = (p->db_index - q->db_index);
1193468e90cSJohn Marino     }
1203468e90cSJohn Marino     return result;
1213468e90cSJohn Marino }
1223468e90cSJohn Marino 
1233468e90cSJohn Marino /*
1243468e90cSJohn Marino  * Sort the array of TERMDATA and print it.  If more than one database is being
1253468e90cSJohn Marino  * reported, add a column to show which database has a given entry.
1263468e90cSJohn Marino  */
1273468e90cSJohn Marino static void
show_termdata(int eargc,char ** eargv)1283468e90cSJohn Marino show_termdata(int eargc, char **eargv)
1293468e90cSJohn Marino {
1303468e90cSJohn Marino     int j, k;
1313468e90cSJohn Marino     size_t n;
1323468e90cSJohn Marino 
1333468e90cSJohn Marino     if (use_termdata) {
1343468e90cSJohn Marino 	if (eargc > 1) {
1353468e90cSJohn Marino 	    for (j = 0; j < eargc; ++j) {
1363468e90cSJohn Marino 		for (k = 0; k <= j; ++k) {
1373468e90cSJohn Marino 		    printf("--");
1383468e90cSJohn Marino 		}
1393468e90cSJohn Marino 		printf("> ");
1403468e90cSJohn Marino 		printf("%s\n", eargv[j]);
1413468e90cSJohn Marino 	    }
1423468e90cSJohn Marino 	}
1433468e90cSJohn Marino 	if (use_termdata > 1)
1443468e90cSJohn Marino 	    qsort(ptr_termdata, use_termdata, sizeof(TERMDATA), compare_termdata);
1453468e90cSJohn Marino 	for (n = 0; n < use_termdata; ++n) {
1463468e90cSJohn Marino 
1473468e90cSJohn Marino 	    /*
1483468e90cSJohn Marino 	     * If there is more than one database, show how they differ.
1493468e90cSJohn Marino 	     */
1503468e90cSJohn Marino 	    if (eargc > 1) {
1513468e90cSJohn Marino 		unsigned long check = 0;
1523468e90cSJohn Marino 		k = 0;
1533468e90cSJohn Marino 		for (;;) {
1543468e90cSJohn Marino 		    for (; k < ptr_termdata[n].db_index; ++k) {
1553468e90cSJohn Marino 			printf("--");
1563468e90cSJohn Marino 		    }
1573468e90cSJohn Marino 
1583468e90cSJohn Marino 		    /*
1593468e90cSJohn Marino 		     * If this is the first entry, or its checksum differs
1603468e90cSJohn Marino 		     * from the first entry's checksum, print "*". Otherwise
1613468e90cSJohn Marino 		     * it looks enough like a duplicate to print "+".
1623468e90cSJohn Marino 		     */
1633468e90cSJohn Marino 		    printf("%c-", ((check == 0
1643468e90cSJohn Marino 				    || (check != ptr_termdata[n].checksum))
1653468e90cSJohn Marino 				   ? '*'
1663468e90cSJohn Marino 				   : '+'));
1673468e90cSJohn Marino 		    check = ptr_termdata[n].checksum;
1683468e90cSJohn Marino 
1693468e90cSJohn Marino 		    ++k;
1703468e90cSJohn Marino 		    if ((n + 1) >= use_termdata
1713468e90cSJohn Marino 			|| strcmp(ptr_termdata[n].term_name,
1723468e90cSJohn Marino 				  ptr_termdata[n + 1].term_name)) {
1733468e90cSJohn Marino 			break;
1743468e90cSJohn Marino 		    }
1753468e90cSJohn Marino 		    ++n;
1763468e90cSJohn Marino 		}
1773468e90cSJohn Marino 		for (; k < eargc; ++k) {
1783468e90cSJohn Marino 		    printf("--");
1793468e90cSJohn Marino 		}
1803468e90cSJohn Marino 		printf(":\t");
1813468e90cSJohn Marino 	    }
1823468e90cSJohn Marino 
1833468e90cSJohn Marino 	    (void) printf("%-10s\t%s\n",
1843468e90cSJohn Marino 			  ptr_termdata[n].term_name,
1853468e90cSJohn Marino 			  ptr_termdata[n].description);
1863468e90cSJohn Marino 	}
1873468e90cSJohn Marino     }
1883468e90cSJohn Marino }
1893468e90cSJohn Marino 
1903468e90cSJohn Marino static void
free_termdata(void)1913468e90cSJohn Marino free_termdata(void)
1923468e90cSJohn Marino {
1933468e90cSJohn Marino     if (ptr_termdata != 0) {
1943468e90cSJohn Marino 	while (use_termdata != 0) {
1953468e90cSJohn Marino 	    --use_termdata;
1963468e90cSJohn Marino 	    free(ptr_termdata[use_termdata].term_name);
1973468e90cSJohn Marino 	    free(ptr_termdata[use_termdata].description);
1983468e90cSJohn Marino 	}
1993468e90cSJohn Marino 	free(ptr_termdata);
2003468e90cSJohn Marino 	ptr_termdata = 0;
2013468e90cSJohn Marino     }
2023468e90cSJohn Marino     use_termdata = 0;
2033468e90cSJohn Marino     len_termdata = 0;
2043468e90cSJohn Marino }
2053468e90cSJohn Marino 
2063468e90cSJohn Marino static char **
allocArgv(size_t count)2073468e90cSJohn Marino allocArgv(size_t count)
2083468e90cSJohn Marino {
2093468e90cSJohn Marino     char **result = typeCalloc(char *, count + 1);
2103468e90cSJohn Marino     if (result == 0)
2113468e90cSJohn Marino 	failed("realloc eargv");
2123468e90cSJohn Marino 
2133468e90cSJohn Marino     assert(result != 0);
2143468e90cSJohn Marino     return result;
2153468e90cSJohn Marino }
2163468e90cSJohn Marino 
2173468e90cSJohn Marino static void
freeArgv(char ** argv)2183468e90cSJohn Marino freeArgv(char **argv)
2193468e90cSJohn Marino {
2203468e90cSJohn Marino     if (argv) {
2213468e90cSJohn Marino 	int count = 0;
2223468e90cSJohn Marino 	while (argv[count]) {
2233468e90cSJohn Marino 	    free(argv[count++]);
2243468e90cSJohn Marino 	}
2253468e90cSJohn Marino 	free(argv);
2263468e90cSJohn Marino     }
2273468e90cSJohn Marino }
2283468e90cSJohn Marino 
2295f4613f2SJohn Marino #if USE_HASHED_DB
2305f4613f2SJohn Marino static bool
make_db_name(char * dst,const char * src,unsigned limit)2315f4613f2SJohn Marino make_db_name(char *dst, const char *src, unsigned limit)
2325f4613f2SJohn Marino {
2335f4613f2SJohn Marino     static const char suffix[] = DBM_SUFFIX;
2345f4613f2SJohn Marino 
2355f4613f2SJohn Marino     bool result = FALSE;
2363468e90cSJohn Marino     size_t lens = sizeof(suffix) - 1;
2373468e90cSJohn Marino     size_t size = strlen(src);
2383468e90cSJohn Marino     size_t need = lens + size;
2395f4613f2SJohn Marino 
2405f4613f2SJohn Marino     if (need <= limit) {
2415f4613f2SJohn Marino 	if (size >= lens
2423468e90cSJohn Marino 	    && !strcmp(src + size - lens, suffix)) {
2433468e90cSJohn Marino 	    _nc_STRCPY(dst, src, PATH_MAX);
2443468e90cSJohn Marino 	} else {
2453468e90cSJohn Marino 	    _nc_SPRINTF(dst, _nc_SLIMIT(PATH_MAX) "%s%s", src, suffix);
2463468e90cSJohn Marino 	}
2475f4613f2SJohn Marino 	result = TRUE;
2485f4613f2SJohn Marino     }
2495f4613f2SJohn Marino     return result;
2505f4613f2SJohn Marino }
2515f4613f2SJohn Marino #endif
2525f4613f2SJohn Marino 
2533468e90cSJohn Marino typedef void (DescHook) (int /* db_index */ ,
2543468e90cSJohn Marino 			 int /* db_limit */ ,
2553468e90cSJohn Marino 			 const char * /* term_name */ ,
256*32bb5217SDaniel Fojt 			 TERMTYPE2 * /* term */ );
2575f4613f2SJohn Marino 
2583468e90cSJohn Marino static const char *
term_description(TERMTYPE2 * tp)259*32bb5217SDaniel Fojt term_description(TERMTYPE2 *tp)
2605f4613f2SJohn Marino {
2615f4613f2SJohn Marino     const char *desc;
2625f4613f2SJohn Marino 
2633468e90cSJohn Marino     if (tp->term_names == 0
2643468e90cSJohn Marino 	|| (desc = strrchr(tp->term_names, '|')) == 0
2653468e90cSJohn Marino 	|| (*++desc == '\0')) {
2665f4613f2SJohn Marino 	desc = "(No description)";
2675f4613f2SJohn Marino     }
2685f4613f2SJohn Marino 
2693468e90cSJohn Marino     return desc;
2703468e90cSJohn Marino }
2713468e90cSJohn Marino 
2723468e90cSJohn Marino /* display a description for the type */
2735f4613f2SJohn Marino static void
deschook(int db_index,int db_limit,const char * term_name,TERMTYPE2 * tp)274*32bb5217SDaniel Fojt deschook(int db_index, int db_limit, const char *term_name, TERMTYPE2 *tp)
2753468e90cSJohn Marino {
2763468e90cSJohn Marino     (void) db_index;
2773468e90cSJohn Marino     (void) db_limit;
2783468e90cSJohn Marino     (void) printf("%-10s\t%s\n", term_name, term_description(tp));
2793468e90cSJohn Marino }
2803468e90cSJohn Marino 
2813468e90cSJohn Marino static unsigned long
string_sum(const char * value)2823468e90cSJohn Marino string_sum(const char *value)
2833468e90cSJohn Marino {
2843468e90cSJohn Marino     unsigned long result = 0;
2853468e90cSJohn Marino 
2863468e90cSJohn Marino     if ((intptr_t) value == (intptr_t) (-1)) {
2873468e90cSJohn Marino 	result = ~result;
2883468e90cSJohn Marino     } else if (value) {
2893468e90cSJohn Marino 	while (*value) {
2903468e90cSJohn Marino 	    result += UChar(*value);
2913468e90cSJohn Marino 	    ++value;
2923468e90cSJohn Marino 	}
2933468e90cSJohn Marino     }
2943468e90cSJohn Marino     return result;
2953468e90cSJohn Marino }
2963468e90cSJohn Marino 
2973468e90cSJohn Marino static unsigned long
checksum_of(TERMTYPE2 * tp)298*32bb5217SDaniel Fojt checksum_of(TERMTYPE2 *tp)
2993468e90cSJohn Marino {
3003468e90cSJohn Marino     unsigned long result = string_sum(tp->term_names);
3013468e90cSJohn Marino     unsigned i;
3023468e90cSJohn Marino 
3033468e90cSJohn Marino     for (i = 0; i < NUM_BOOLEANS(tp); i++) {
3043468e90cSJohn Marino 	result += (unsigned long) (tp->Booleans[i]);
3053468e90cSJohn Marino     }
3063468e90cSJohn Marino     for (i = 0; i < NUM_NUMBERS(tp); i++) {
3073468e90cSJohn Marino 	result += (unsigned long) (tp->Numbers[i]);
3083468e90cSJohn Marino     }
3093468e90cSJohn Marino     for (i = 0; i < NUM_STRINGS(tp); i++) {
3103468e90cSJohn Marino 	result += string_sum(tp->Strings[i]);
3113468e90cSJohn Marino     }
3123468e90cSJohn Marino     return result;
3133468e90cSJohn Marino }
3143468e90cSJohn Marino 
3153468e90cSJohn Marino /* collect data, to sort before display */
3163468e90cSJohn Marino static void
sorthook(int db_index,int db_limit,const char * term_name,TERMTYPE2 * tp)317*32bb5217SDaniel Fojt sorthook(int db_index, int db_limit, const char *term_name, TERMTYPE2 *tp)
3183468e90cSJohn Marino {
3193468e90cSJohn Marino     TERMDATA *data = new_termdata();
3203468e90cSJohn Marino 
3213468e90cSJohn Marino     data->db_index = db_index;
3223468e90cSJohn Marino     data->checksum = ((db_limit > 1) ? checksum_of(tp) : 0);
3233468e90cSJohn Marino     data->term_name = strmalloc(term_name);
3243468e90cSJohn Marino     data->description = strmalloc(term_description(tp));
3253468e90cSJohn Marino }
3263468e90cSJohn Marino 
3273468e90cSJohn Marino #if NCURSES_USE_TERMCAP
3283468e90cSJohn Marino static void
show_termcap(int db_index,int db_limit,char * buffer,DescHook hook)3293468e90cSJohn Marino show_termcap(int db_index, int db_limit, char *buffer, DescHook hook)
3305f4613f2SJohn Marino {
331*32bb5217SDaniel Fojt     TERMTYPE2 data;
3325f4613f2SJohn Marino     char *next = strchr(buffer, ':');
3335f4613f2SJohn Marino     char *last;
3345f4613f2SJohn Marino     char *list = buffer;
3355f4613f2SJohn Marino 
3365f4613f2SJohn Marino     if (next)
3375f4613f2SJohn Marino 	*next = '\0';
3385f4613f2SJohn Marino 
3395f4613f2SJohn Marino     last = strrchr(buffer, '|');
3405f4613f2SJohn Marino     if (last)
3415f4613f2SJohn Marino 	++last;
3425f4613f2SJohn Marino 
3433468e90cSJohn Marino     memset(&data, 0, sizeof(data));
3443468e90cSJohn Marino     data.term_names = strmalloc(buffer);
3455f4613f2SJohn Marino     while ((next = strtok(list, "|")) != 0) {
3465f4613f2SJohn Marino 	if (next != last)
3473468e90cSJohn Marino 	    hook(db_index, db_limit, next, &data);
3485f4613f2SJohn Marino 	list = 0;
3495f4613f2SJohn Marino     }
3505f4613f2SJohn Marino     free(data.term_names);
3515f4613f2SJohn Marino }
3525f4613f2SJohn Marino #endif
3535f4613f2SJohn Marino 
3543468e90cSJohn Marino #if NCURSES_USE_DATABASE
3553468e90cSJohn Marino static char *
copy_entryname(DIRENT * src)3563468e90cSJohn Marino copy_entryname(DIRENT * src)
3573468e90cSJohn Marino {
3583468e90cSJohn Marino     size_t len = NAMLEN(src);
3593468e90cSJohn Marino     char *result = malloc(len + 1);
3603468e90cSJohn Marino     if (result == 0)
3613468e90cSJohn Marino 	failed("copy entryname");
3623468e90cSJohn Marino     memcpy(result, src->d_name, len);
3633468e90cSJohn Marino     result[len] = '\0';
3643468e90cSJohn Marino 
3653468e90cSJohn Marino     return result;
3663468e90cSJohn Marino }
3673468e90cSJohn Marino #endif
3683468e90cSJohn Marino 
3695f4613f2SJohn Marino static int
typelist(int eargc,char * eargv[],int verbosity,DescHook hook)3705f4613f2SJohn Marino typelist(int eargc, char *eargv[],
3713468e90cSJohn Marino 	 int verbosity,
3723468e90cSJohn Marino 	 DescHook hook)
3735f4613f2SJohn Marino /* apply a function to each entry in given terminfo directories */
3745f4613f2SJohn Marino {
3755f4613f2SJohn Marino     int i;
3765f4613f2SJohn Marino 
3775f4613f2SJohn Marino     for (i = 0; i < eargc; i++) {
3783468e90cSJohn Marino #if NCURSES_USE_DATABASE
3795f4613f2SJohn Marino 	if (_nc_is_dir_path(eargv[i])) {
3805f4613f2SJohn Marino 	    char *cwd_buf = 0;
3815f4613f2SJohn Marino 	    DIR *termdir;
3825f4613f2SJohn Marino 	    DIRENT *subdir;
3835f4613f2SJohn Marino 
3845f4613f2SJohn Marino 	    if ((termdir = opendir(eargv[i])) == 0) {
3855f4613f2SJohn Marino 		(void) fflush(stdout);
3865f4613f2SJohn Marino 		(void) fprintf(stderr,
3875f4613f2SJohn Marino 			       "%s: can't open terminfo directory %s\n",
3885f4613f2SJohn Marino 			       _nc_progname, eargv[i]);
3893468e90cSJohn Marino 		continue;
3903468e90cSJohn Marino 	    }
3913468e90cSJohn Marino 
3923468e90cSJohn Marino 	    if (verbosity)
3935f4613f2SJohn Marino 		(void) printf("#\n#%s:\n#\n", eargv[i]);
3945f4613f2SJohn Marino 
3955f4613f2SJohn Marino 	    while ((subdir = readdir(termdir)) != 0) {
3963468e90cSJohn Marino 		size_t cwd_len;
3973468e90cSJohn Marino 		char *name_1;
3985f4613f2SJohn Marino 		DIR *entrydir;
3995f4613f2SJohn Marino 		DIRENT *entry;
4005f4613f2SJohn Marino 
4013468e90cSJohn Marino 		name_1 = copy_entryname(subdir);
4023468e90cSJohn Marino 		if (isDotname(name_1)) {
4033468e90cSJohn Marino 		    free(name_1);
4043468e90cSJohn Marino 		    continue;
4053468e90cSJohn Marino 		}
4063468e90cSJohn Marino 
4073468e90cSJohn Marino 		cwd_len = NAMLEN(subdir) + strlen(eargv[i]) + 3;
4085f4613f2SJohn Marino 		cwd_buf = typeRealloc(char, cwd_len, cwd_buf);
4095f4613f2SJohn Marino 		if (cwd_buf == 0)
4105f4613f2SJohn Marino 		    failed("realloc cwd_buf");
4115f4613f2SJohn Marino 
4125f4613f2SJohn Marino 		assert(cwd_buf != 0);
4135f4613f2SJohn Marino 
4143468e90cSJohn Marino 		_nc_SPRINTF(cwd_buf, _nc_SLIMIT(cwd_len)
4153468e90cSJohn Marino 			    "%s/%s/", eargv[i], name_1);
4163468e90cSJohn Marino 		free(name_1);
4175f4613f2SJohn Marino 
4185f4613f2SJohn Marino 		if (chdir(cwd_buf) != 0)
4195f4613f2SJohn Marino 		    continue;
4205f4613f2SJohn Marino 
4215f4613f2SJohn Marino 		entrydir = opendir(".");
4225f4613f2SJohn Marino 		if (entrydir == 0) {
4235f4613f2SJohn Marino 		    perror(cwd_buf);
4245f4613f2SJohn Marino 		    continue;
4255f4613f2SJohn Marino 		}
4265f4613f2SJohn Marino 		while ((entry = readdir(entrydir)) != 0) {
4273468e90cSJohn Marino 		    char *name_2;
428*32bb5217SDaniel Fojt 		    TERMTYPE2 lterm;
4295f4613f2SJohn Marino 		    char *cn;
4305f4613f2SJohn Marino 		    int status;
4315f4613f2SJohn Marino 
4323468e90cSJohn Marino 		    name_2 = copy_entryname(entry);
4333468e90cSJohn Marino 		    if (isDotname(name_2) || !_nc_is_file_path(name_2)) {
4343468e90cSJohn Marino 			free(name_2);
4355f4613f2SJohn Marino 			continue;
4363468e90cSJohn Marino 		    }
4375f4613f2SJohn Marino 
4385f4613f2SJohn Marino 		    status = _nc_read_file_entry(name_2, &lterm);
4395f4613f2SJohn Marino 		    if (status <= 0) {
4405f4613f2SJohn Marino 			(void) fflush(stdout);
4415f4613f2SJohn Marino 			(void) fprintf(stderr,
4425f4613f2SJohn Marino 				       "%s: couldn't open terminfo file %s.\n",
4435f4613f2SJohn Marino 				       _nc_progname, name_2);
4443468e90cSJohn Marino 			free(name_2);
445*32bb5217SDaniel Fojt 			continue;
4465f4613f2SJohn Marino 		    }
4475f4613f2SJohn Marino 
4485f4613f2SJohn Marino 		    /* only visit things once, by primary name */
4495f4613f2SJohn Marino 		    cn = _nc_first_name(lterm.term_names);
4505f4613f2SJohn Marino 		    if (!strcmp(cn, name_2)) {
4515f4613f2SJohn Marino 			/* apply the selected hook function */
4523468e90cSJohn Marino 			hook(i, eargc, cn, &lterm);
4535f4613f2SJohn Marino 		    }
454*32bb5217SDaniel Fojt 		    _nc_free_termtype2(&lterm);
4553468e90cSJohn Marino 		    free(name_2);
4565f4613f2SJohn Marino 		}
4575f4613f2SJohn Marino 		closedir(entrydir);
4585f4613f2SJohn Marino 	    }
4595f4613f2SJohn Marino 	    closedir(termdir);
4605f4613f2SJohn Marino 	    if (cwd_buf != 0)
4615f4613f2SJohn Marino 		free(cwd_buf);
4623468e90cSJohn Marino 	    continue;
4635f4613f2SJohn Marino 	}
4645f4613f2SJohn Marino #if USE_HASHED_DB
4655f4613f2SJohn Marino 	else {
4665f4613f2SJohn Marino 	    DB *capdbp;
4675f4613f2SJohn Marino 	    char filename[PATH_MAX];
4685f4613f2SJohn Marino 
4693468e90cSJohn Marino 	    if (verbosity)
4703468e90cSJohn Marino 		(void) printf("#\n#%s:\n#\n", eargv[i]);
4713468e90cSJohn Marino 
4725f4613f2SJohn Marino 	    if (make_db_name(filename, eargv[i], sizeof(filename))) {
4735f4613f2SJohn Marino 		if ((capdbp = _nc_db_open(filename, FALSE)) != 0) {
4745f4613f2SJohn Marino 		    DBT key, data;
4755f4613f2SJohn Marino 		    int code;
4765f4613f2SJohn Marino 
4775f4613f2SJohn Marino 		    code = _nc_db_first(capdbp, &key, &data);
4785f4613f2SJohn Marino 		    while (code == 0) {
479*32bb5217SDaniel Fojt 			TERMTYPE2 lterm;
4805f4613f2SJohn Marino 			int used;
4815f4613f2SJohn Marino 			char *have;
4825f4613f2SJohn Marino 			char *cn;
4835f4613f2SJohn Marino 
4845f4613f2SJohn Marino 			if (_nc_db_have_data(&key, &data, &have, &used)) {
4855f4613f2SJohn Marino 			    if (_nc_read_termtype(&lterm, have, used) > 0) {
4865f4613f2SJohn Marino 				/* only visit things once, by primary name */
4875f4613f2SJohn Marino 				cn = _nc_first_name(lterm.term_names);
4885f4613f2SJohn Marino 				/* apply the selected hook function */
4893468e90cSJohn Marino 				hook(i, eargc, cn, &lterm);
490*32bb5217SDaniel Fojt 				_nc_free_termtype2(&lterm);
4915f4613f2SJohn Marino 			    }
4925f4613f2SJohn Marino 			}
4935f4613f2SJohn Marino 			code = _nc_db_next(capdbp, &key, &data);
4945f4613f2SJohn Marino 		    }
4955f4613f2SJohn Marino 
4965f4613f2SJohn Marino 		    _nc_db_close(capdbp);
4973468e90cSJohn Marino 		    continue;
4985f4613f2SJohn Marino 		}
4995f4613f2SJohn Marino 	    }
5005f4613f2SJohn Marino 	}
501*32bb5217SDaniel Fojt #endif /* USE_HASHED_DB */
502*32bb5217SDaniel Fojt #endif /* NCURSES_USE_DATABASE */
5033468e90cSJohn Marino #if NCURSES_USE_TERMCAP
5045f4613f2SJohn Marino #if HAVE_BSD_CGETENT
5053468e90cSJohn Marino 	{
5063468e90cSJohn Marino 	    CGETENT_CONST char *db_array[2];
5075f4613f2SJohn Marino 	    char *buffer = 0;
5085f4613f2SJohn Marino 
5095f4613f2SJohn Marino 	    if (verbosity)
5105f4613f2SJohn Marino 		(void) printf("#\n#%s:\n#\n", eargv[i]);
5115f4613f2SJohn Marino 
5125f4613f2SJohn Marino 	    db_array[0] = eargv[i];
5135f4613f2SJohn Marino 	    db_array[1] = 0;
5145f4613f2SJohn Marino 
5153468e90cSJohn Marino 	    if (cgetfirst(&buffer, db_array) > 0) {
5163468e90cSJohn Marino 		show_termcap(i, eargc, buffer, hook);
5175f4613f2SJohn Marino 		free(buffer);
5183468e90cSJohn Marino 		while (cgetnext(&buffer, db_array) > 0) {
5193468e90cSJohn Marino 		    show_termcap(i, eargc, buffer, hook);
5205f4613f2SJohn Marino 		    free(buffer);
5215f4613f2SJohn Marino 		}
5225f4613f2SJohn Marino 		cgetclose();
5233468e90cSJohn Marino 		continue;
5243468e90cSJohn Marino 	    }
5253468e90cSJohn Marino 	}
5265f4613f2SJohn Marino #else
5275f4613f2SJohn Marino 	/* scan termcap text-file only */
5285f4613f2SJohn Marino 	if (_nc_is_file_path(eargv[i])) {
5295f4613f2SJohn Marino 	    char buffer[2048];
5305f4613f2SJohn Marino 	    FILE *fp;
5315f4613f2SJohn Marino 
5323468e90cSJohn Marino 	    if (verbosity)
5333468e90cSJohn Marino 		(void) printf("#\n#%s:\n#\n", eargv[i]);
5343468e90cSJohn Marino 
5355f4613f2SJohn Marino 	    if ((fp = fopen(eargv[i], "r")) != 0) {
5365f4613f2SJohn Marino 		while (fgets(buffer, sizeof(buffer), fp) != 0) {
5375f4613f2SJohn Marino 		    if (*buffer == '#')
5385f4613f2SJohn Marino 			continue;
5395f4613f2SJohn Marino 		    if (isspace(*buffer))
5405f4613f2SJohn Marino 			continue;
5413468e90cSJohn Marino 		    show_termcap(i, eargc, buffer, hook);
5425f4613f2SJohn Marino 		}
5435f4613f2SJohn Marino 		fclose(fp);
5445f4613f2SJohn Marino 	    }
5455f4613f2SJohn Marino 	}
5465f4613f2SJohn Marino #endif
5475f4613f2SJohn Marino #endif
5485f4613f2SJohn Marino     }
5495f4613f2SJohn Marino 
5503468e90cSJohn Marino     if (hook == sorthook) {
5513468e90cSJohn Marino 	show_termdata(eargc, eargv);
5523468e90cSJohn Marino 	free_termdata();
5533468e90cSJohn Marino     }
5543468e90cSJohn Marino 
5555f4613f2SJohn Marino     return (EXIT_SUCCESS);
5565f4613f2SJohn Marino }
5575f4613f2SJohn Marino 
5585f4613f2SJohn Marino static void
usage(void)5595f4613f2SJohn Marino usage(void)
5605f4613f2SJohn Marino {
5613468e90cSJohn Marino     (void) fprintf(stderr, "usage: %s [-ahsuUV] [-v n] [file...]\n", _nc_progname);
5625f4613f2SJohn Marino     ExitProgram(EXIT_FAILURE);
5635f4613f2SJohn Marino }
5645f4613f2SJohn Marino 
5655f4613f2SJohn Marino int
main(int argc,char * argv[])5665f4613f2SJohn Marino main(int argc, char *argv[])
5675f4613f2SJohn Marino {
5685f4613f2SJohn Marino     bool all_dirs = FALSE;
5695f4613f2SJohn Marino     bool direct_dependencies = FALSE;
5705f4613f2SJohn Marino     bool invert_dependencies = FALSE;
5715f4613f2SJohn Marino     bool header = FALSE;
5725f4613f2SJohn Marino     char *report_file = 0;
5735f4613f2SJohn Marino     unsigned i;
5745f4613f2SJohn Marino     int code;
5755f4613f2SJohn Marino     int this_opt, last_opt = '?';
5763468e90cSJohn Marino     unsigned v_opt = 0;
5773468e90cSJohn Marino     DescHook *hook = deschook;
5785f4613f2SJohn Marino 
5795f4613f2SJohn Marino     _nc_progname = _nc_rootname(argv[0]);
5805f4613f2SJohn Marino 
5813468e90cSJohn Marino     while ((this_opt = getopt(argc, argv, "0123456789ahsu:vU:V")) != -1) {
5825f4613f2SJohn Marino 	/* handle optional parameter */
5835f4613f2SJohn Marino 	if (isdigit(this_opt)) {
5845f4613f2SJohn Marino 	    switch (last_opt) {
5855f4613f2SJohn Marino 	    case 'v':
5863468e90cSJohn Marino 		v_opt = (unsigned) (this_opt - '0');
5875f4613f2SJohn Marino 		break;
5885f4613f2SJohn Marino 	    default:
5895f4613f2SJohn Marino 		if (isdigit(last_opt))
5905f4613f2SJohn Marino 		    v_opt *= 10;
5915f4613f2SJohn Marino 		else
5925f4613f2SJohn Marino 		    v_opt = 0;
5933468e90cSJohn Marino 		v_opt += (unsigned) (this_opt - '0');
5945f4613f2SJohn Marino 		last_opt = this_opt;
5955f4613f2SJohn Marino 	    }
5965f4613f2SJohn Marino 	    continue;
5975f4613f2SJohn Marino 	}
5985f4613f2SJohn Marino 	switch (this_opt) {
5995f4613f2SJohn Marino 	case 'a':
6005f4613f2SJohn Marino 	    all_dirs = TRUE;
6015f4613f2SJohn Marino 	    break;
6025f4613f2SJohn Marino 	case 'h':
6035f4613f2SJohn Marino 	    header = TRUE;
6045f4613f2SJohn Marino 	    break;
6053468e90cSJohn Marino 	case 's':
6063468e90cSJohn Marino 	    hook = sorthook;
6073468e90cSJohn Marino 	    break;
6085f4613f2SJohn Marino 	case 'u':
6095f4613f2SJohn Marino 	    direct_dependencies = TRUE;
6105f4613f2SJohn Marino 	    report_file = optarg;
6115f4613f2SJohn Marino 	    break;
6125f4613f2SJohn Marino 	case 'v':
6135f4613f2SJohn Marino 	    v_opt = 1;
6145f4613f2SJohn Marino 	    break;
6155f4613f2SJohn Marino 	case 'U':
6165f4613f2SJohn Marino 	    invert_dependencies = TRUE;
6175f4613f2SJohn Marino 	    report_file = optarg;
6185f4613f2SJohn Marino 	    break;
6195f4613f2SJohn Marino 	case 'V':
6205f4613f2SJohn Marino 	    puts(curses_version());
6215f4613f2SJohn Marino 	    ExitProgram(EXIT_SUCCESS);
6225f4613f2SJohn Marino 	default:
6235f4613f2SJohn Marino 	    usage();
6245f4613f2SJohn Marino 	}
6255f4613f2SJohn Marino     }
6265f4613f2SJohn Marino     set_trace_level(v_opt);
6275f4613f2SJohn Marino 
6285f4613f2SJohn Marino     if (report_file != 0) {
6295f4613f2SJohn Marino 	if (freopen(report_file, "r", stdin) == 0) {
6305f4613f2SJohn Marino 	    (void) fflush(stdout);
6315f4613f2SJohn Marino 	    fprintf(stderr, "%s: can't open %s\n", _nc_progname, report_file);
6325f4613f2SJohn Marino 	    ExitProgram(EXIT_FAILURE);
6335f4613f2SJohn Marino 	}
6345f4613f2SJohn Marino 
6355f4613f2SJohn Marino 	/* parse entries out of the source file */
6365f4613f2SJohn Marino 	_nc_set_source(report_file);
6375f4613f2SJohn Marino 	_nc_read_entry_source(stdin, 0, FALSE, FALSE, NULLHOOK);
6385f4613f2SJohn Marino     }
6395f4613f2SJohn Marino 
6405f4613f2SJohn Marino     /* maybe we want a direct-dependency listing? */
6415f4613f2SJohn Marino     if (direct_dependencies) {
6425f4613f2SJohn Marino 	ENTRY *qp;
6435f4613f2SJohn Marino 
6445f4613f2SJohn Marino 	for_entry_list(qp) {
6455f4613f2SJohn Marino 	    if (qp->nuses) {
6465f4613f2SJohn Marino 		unsigned j;
6475f4613f2SJohn Marino 
6485f4613f2SJohn Marino 		(void) printf("%s:", _nc_first_name(qp->tterm.term_names));
6495f4613f2SJohn Marino 		for (j = 0; j < qp->nuses; j++)
6505f4613f2SJohn Marino 		    (void) printf(" %s", qp->uses[j].name);
6515f4613f2SJohn Marino 		putchar('\n');
6525f4613f2SJohn Marino 	    }
6535f4613f2SJohn Marino 	}
6545f4613f2SJohn Marino 
6555f4613f2SJohn Marino 	ExitProgram(EXIT_SUCCESS);
6565f4613f2SJohn Marino     }
6575f4613f2SJohn Marino 
6585f4613f2SJohn Marino     /* maybe we want a reverse-dependency listing? */
6595f4613f2SJohn Marino     if (invert_dependencies) {
6605f4613f2SJohn Marino 	ENTRY *qp, *rp;
6615f4613f2SJohn Marino 	int matchcount;
6625f4613f2SJohn Marino 
6635f4613f2SJohn Marino 	for_entry_list(qp) {
6645f4613f2SJohn Marino 	    matchcount = 0;
6655f4613f2SJohn Marino 	    for_entry_list(rp) {
6665f4613f2SJohn Marino 		if (rp->nuses == 0)
6675f4613f2SJohn Marino 		    continue;
6685f4613f2SJohn Marino 
6695f4613f2SJohn Marino 		for (i = 0; i < rp->nuses; i++)
6705f4613f2SJohn Marino 		    if (_nc_name_match(qp->tterm.term_names,
6715f4613f2SJohn Marino 				       rp->uses[i].name, "|")) {
6725f4613f2SJohn Marino 			if (matchcount++ == 0)
6735f4613f2SJohn Marino 			    (void) printf("%s:",
6745f4613f2SJohn Marino 					  _nc_first_name(qp->tterm.term_names));
6755f4613f2SJohn Marino 			(void) printf(" %s",
6765f4613f2SJohn Marino 				      _nc_first_name(rp->tterm.term_names));
6775f4613f2SJohn Marino 		    }
6785f4613f2SJohn Marino 	    }
6795f4613f2SJohn Marino 	    if (matchcount)
6805f4613f2SJohn Marino 		putchar('\n');
6815f4613f2SJohn Marino 	}
6825f4613f2SJohn Marino 
6835f4613f2SJohn Marino 	ExitProgram(EXIT_SUCCESS);
6845f4613f2SJohn Marino     }
6855f4613f2SJohn Marino 
6865f4613f2SJohn Marino     /*
6875f4613f2SJohn Marino      * If we get this far, user wants a simple terminal type listing.
6885f4613f2SJohn Marino      */
6895f4613f2SJohn Marino     if (optind < argc) {
6903468e90cSJohn Marino 	code = typelist(argc - optind, argv + optind, header, hook);
6915f4613f2SJohn Marino     } else if (all_dirs) {
6925f4613f2SJohn Marino 	DBDIRS state;
6935f4613f2SJohn Marino 	int offset;
6945f4613f2SJohn Marino 	int pass;
6955f4613f2SJohn Marino 	const char *path;
6965f4613f2SJohn Marino 	char **eargv = 0;
6975f4613f2SJohn Marino 
6985f4613f2SJohn Marino 	code = EXIT_FAILURE;
6995f4613f2SJohn Marino 	for (pass = 0; pass < 2; ++pass) {
7003468e90cSJohn Marino 	    size_t count = 0;
7015f4613f2SJohn Marino 
7025f4613f2SJohn Marino 	    _nc_first_db(&state, &offset);
7035f4613f2SJohn Marino 	    while ((path = _nc_next_db(&state, &offset)) != 0) {
704*32bb5217SDaniel Fojt 		if (quick_prefix(path))
705*32bb5217SDaniel Fojt 		    continue;
7063468e90cSJohn Marino 		if (pass) {
7073468e90cSJohn Marino 		    eargv[count] = strmalloc(path);
7085f4613f2SJohn Marino 		}
7095f4613f2SJohn Marino 		++count;
7105f4613f2SJohn Marino 	    }
7115f4613f2SJohn Marino 	    if (!pass) {
7123468e90cSJohn Marino 		eargv = allocArgv(count);
7135f4613f2SJohn Marino 		if (eargv == 0)
7143468e90cSJohn Marino 		    failed("eargv");
7155f4613f2SJohn Marino 	    } else {
7163468e90cSJohn Marino 		code = typelist((int) count, eargv, header, hook);
7173468e90cSJohn Marino 		freeArgv(eargv);
7185f4613f2SJohn Marino 	    }
7195f4613f2SJohn Marino 	}
7205f4613f2SJohn Marino     } else {
7215f4613f2SJohn Marino 	DBDIRS state;
7225f4613f2SJohn Marino 	int offset;
7235f4613f2SJohn Marino 	const char *path;
7243468e90cSJohn Marino 	char **eargv = allocArgv((size_t) 2);
7253468e90cSJohn Marino 	size_t count = 0;
7265f4613f2SJohn Marino 
7273468e90cSJohn Marino 	if (eargv == 0)
7283468e90cSJohn Marino 	    failed("eargv");
7295f4613f2SJohn Marino 	_nc_first_db(&state, &offset);
7303468e90cSJohn Marino 	if ((path = _nc_next_db(&state, &offset)) != 0) {
731*32bb5217SDaniel Fojt 	    if (!quick_prefix(path))
7323468e90cSJohn Marino 		eargv[count++] = strmalloc(path);
7335f4613f2SJohn Marino 	}
7345f4613f2SJohn Marino 
7353468e90cSJohn Marino 	code = typelist((int) count, eargv, header, hook);
7365f4613f2SJohn Marino 
7373468e90cSJohn Marino 	freeArgv(eargv);
7385f4613f2SJohn Marino     }
7395f4613f2SJohn Marino     _nc_last_db();
7405f4613f2SJohn Marino 
7415f4613f2SJohn Marino     ExitProgram(code);
7425f4613f2SJohn Marino }
743