xref: /freebsd/contrib/ncurses/progs/toe.c (revision d8977eaf361f5fdc1261c3f3524988f661ed926e)
10e3d5408SPeter Wemm /****************************************************************************
2d8977eafSRong-En Fan  * Copyright (c) 1998-2007,2008 Free Software Foundation, Inc.              *
30e3d5408SPeter Wemm  *                                                                          *
40e3d5408SPeter Wemm  * Permission is hereby granted, free of charge, to any person obtaining a  *
50e3d5408SPeter Wemm  * copy of this software and associated documentation files (the            *
60e3d5408SPeter Wemm  * "Software"), to deal in the Software without restriction, including      *
70e3d5408SPeter Wemm  * without limitation the rights to use, copy, modify, merge, publish,      *
80e3d5408SPeter Wemm  * distribute, distribute with modifications, sublicense, and/or sell       *
90e3d5408SPeter Wemm  * copies of the Software, and to permit persons to whom the Software is    *
100e3d5408SPeter Wemm  * furnished to do so, subject to the following conditions:                 *
110e3d5408SPeter Wemm  *                                                                          *
120e3d5408SPeter Wemm  * The above copyright notice and this permission notice shall be included  *
130e3d5408SPeter Wemm  * in all copies or substantial portions of the Software.                   *
140e3d5408SPeter Wemm  *                                                                          *
150e3d5408SPeter Wemm  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
160e3d5408SPeter Wemm  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
170e3d5408SPeter Wemm  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
180e3d5408SPeter Wemm  * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,   *
190e3d5408SPeter Wemm  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR    *
200e3d5408SPeter Wemm  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR    *
210e3d5408SPeter Wemm  * THE USE OR OTHER DEALINGS IN THE SOFTWARE.                               *
220e3d5408SPeter Wemm  *                                                                          *
230e3d5408SPeter Wemm  * Except as contained in this notice, the name(s) of the above copyright   *
240e3d5408SPeter Wemm  * holders shall not be used in advertising or otherwise to promote the     *
250e3d5408SPeter Wemm  * sale, use or other dealings in this Software without prior written       *
260e3d5408SPeter Wemm  * authorization.                                                           *
270e3d5408SPeter Wemm  ****************************************************************************/
280e3d5408SPeter Wemm 
290e3d5408SPeter Wemm /****************************************************************************
300e3d5408SPeter Wemm  *  Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995               *
310e3d5408SPeter Wemm  *     and: Eric S. Raymond <esr@snark.thyrsus.com>                         *
324a1a9510SRong-En Fan  *     and: Thomas E. Dickey                        1996-on                 *
330e3d5408SPeter Wemm  ****************************************************************************/
340e3d5408SPeter Wemm 
350e3d5408SPeter Wemm /*
360e3d5408SPeter Wemm  *	toe.c --- table of entries report generator
370e3d5408SPeter Wemm  */
380e3d5408SPeter Wemm 
390e3d5408SPeter Wemm #include <progs.priv.h>
400e3d5408SPeter Wemm 
410e3d5408SPeter Wemm #include <sys/stat.h>
420e3d5408SPeter Wemm 
434a1a9510SRong-En Fan #if USE_HASHED_DB
444a1a9510SRong-En Fan #include <hashed_db.h>
454a1a9510SRong-En Fan #endif
464a1a9510SRong-En Fan 
47d8977eafSRong-En Fan MODULE_ID("$Id: toe.c,v 1.48 2008/01/05 20:41:26 tom Exp $")
4815589c42SPeter Wemm 
4915589c42SPeter Wemm #define isDotname(name) (!strcmp(name, ".") || !strcmp(name, ".."))
500e3d5408SPeter Wemm 
510e3d5408SPeter Wemm const char *_nc_progname;
520e3d5408SPeter Wemm 
530e3d5408SPeter Wemm #if NO_LEAKS
540e3d5408SPeter Wemm #undef ExitProgram
554a1a9510SRong-En Fan static void ExitProgram(int code) GCC_NORETURN;
5615589c42SPeter Wemm static void
574a1a9510SRong-En Fan ExitProgram(int code)
580e3d5408SPeter Wemm {
590e3d5408SPeter Wemm     _nc_free_entries(_nc_head);
605ca44d1cSRong-En Fan     _nc_free_tic(code);
610e3d5408SPeter Wemm }
620e3d5408SPeter Wemm #endif
630e3d5408SPeter Wemm 
644a1a9510SRong-En Fan #if USE_HASHED_DB
6539f2269fSPeter Wemm static bool
664a1a9510SRong-En Fan make_db_name(char *dst, const char *src, unsigned limit)
6739f2269fSPeter Wemm {
684a1a9510SRong-En Fan     static const char suffix[] = DBM_SUFFIX;
694a1a9510SRong-En Fan 
704a1a9510SRong-En Fan     bool result = FALSE;
714a1a9510SRong-En Fan     unsigned lens = sizeof(suffix) - 1;
724a1a9510SRong-En Fan     unsigned size = strlen(src);
734a1a9510SRong-En Fan     unsigned need = lens + size;
744a1a9510SRong-En Fan 
754a1a9510SRong-En Fan     if (need <= limit) {
764a1a9510SRong-En Fan 	if (size >= lens
774a1a9510SRong-En Fan 	    && !strcmp(src + size - lens, suffix))
784a1a9510SRong-En Fan 	    (void) strcpy(dst, src);
794a1a9510SRong-En Fan 	else
804a1a9510SRong-En Fan 	    (void) sprintf(dst, "%s%s", src, suffix);
814a1a9510SRong-En Fan 	result = TRUE;
8239f2269fSPeter Wemm     }
834a1a9510SRong-En Fan     return result;
844a1a9510SRong-En Fan }
854a1a9510SRong-En Fan #endif
8639f2269fSPeter Wemm 
8739f2269fSPeter Wemm static bool
884a1a9510SRong-En Fan is_database(const char *path)
8939f2269fSPeter Wemm {
904a1a9510SRong-En Fan     bool result = FALSE;
914a1a9510SRong-En Fan #if USE_DATABASE
924a1a9510SRong-En Fan     if (_nc_is_dir_path(path) && access(path, R_OK | X_OK) == 0) {
934a1a9510SRong-En Fan 	result = TRUE;
944a1a9510SRong-En Fan     }
954a1a9510SRong-En Fan #endif
964a1a9510SRong-En Fan #if USE_TERMCAP
974a1a9510SRong-En Fan     if (_nc_is_file_path(path) && access(path, R_OK) == 0) {
984a1a9510SRong-En Fan 	result = TRUE;
994a1a9510SRong-En Fan     }
1004a1a9510SRong-En Fan #endif
1014a1a9510SRong-En Fan #if USE_HASHED_DB
1024a1a9510SRong-En Fan     if (!result) {
1034a1a9510SRong-En Fan 	char filename[PATH_MAX];
1044a1a9510SRong-En Fan 	if (_nc_is_file_path(path) && access(path, R_OK) == 0) {
1054a1a9510SRong-En Fan 	    result = TRUE;
1064a1a9510SRong-En Fan 	} else if (make_db_name(filename, path, sizeof(filename))) {
1074a1a9510SRong-En Fan 	    if (_nc_is_file_path(filename) && access(filename, R_OK) == 0) {
1084a1a9510SRong-En Fan 		result = TRUE;
1094a1a9510SRong-En Fan 	    }
1104a1a9510SRong-En Fan 	}
1114a1a9510SRong-En Fan     }
1124a1a9510SRong-En Fan #endif
1134a1a9510SRong-En Fan     return result;
11439f2269fSPeter Wemm }
11539f2269fSPeter Wemm 
1164a1a9510SRong-En Fan static void
1174a1a9510SRong-En Fan deschook(const char *cn, TERMTYPE *tp)
1184a1a9510SRong-En Fan /* display a description for the type */
11915589c42SPeter Wemm {
1204a1a9510SRong-En Fan     const char *desc;
1214a1a9510SRong-En Fan 
1224a1a9510SRong-En Fan     if ((desc = strrchr(tp->term_names, '|')) == 0 || *++desc == '\0')
1234a1a9510SRong-En Fan 	desc = "(No description)";
1244a1a9510SRong-En Fan 
1254a1a9510SRong-En Fan     (void) printf("%-10s\t%s\n", cn, desc);
12615589c42SPeter Wemm }
1274a1a9510SRong-En Fan 
1284a1a9510SRong-En Fan #if USE_TERMCAP
1294a1a9510SRong-En Fan static void
1304a1a9510SRong-En Fan show_termcap(char *buffer,
1314a1a9510SRong-En Fan 	     void (*hook) (const char *, TERMTYPE *tp))
1324a1a9510SRong-En Fan {
1334a1a9510SRong-En Fan     TERMTYPE data;
1344a1a9510SRong-En Fan     char *next = strchr(buffer, ':');
1354a1a9510SRong-En Fan     char *last;
1364a1a9510SRong-En Fan     char *list = buffer;
1374a1a9510SRong-En Fan 
1384a1a9510SRong-En Fan     if (next)
1394a1a9510SRong-En Fan 	*next = '\0';
1404a1a9510SRong-En Fan 
1414a1a9510SRong-En Fan     last = strrchr(buffer, '|');
1424a1a9510SRong-En Fan     if (last)
1434a1a9510SRong-En Fan 	++last;
1444a1a9510SRong-En Fan 
1454a1a9510SRong-En Fan     data.term_names = strdup(buffer);
1464a1a9510SRong-En Fan     while ((next = strtok(list, "|")) != 0) {
1474a1a9510SRong-En Fan 	if (next != last)
1484a1a9510SRong-En Fan 	    hook(next, &data);
1494a1a9510SRong-En Fan 	list = 0;
1504a1a9510SRong-En Fan     }
1514a1a9510SRong-En Fan     free(data.term_names);
1524a1a9510SRong-En Fan }
1534a1a9510SRong-En Fan #endif
1544a1a9510SRong-En Fan 
1554a1a9510SRong-En Fan static int
1564a1a9510SRong-En Fan typelist(int eargc, char *eargv[],
1574a1a9510SRong-En Fan 	 bool verbosity,
1584a1a9510SRong-En Fan 	 void (*hook) (const char *, TERMTYPE *tp))
1594a1a9510SRong-En Fan /* apply a function to each entry in given terminfo directories */
1604a1a9510SRong-En Fan {
1614a1a9510SRong-En Fan     int i;
1624a1a9510SRong-En Fan 
1634a1a9510SRong-En Fan     for (i = 0; i < eargc; i++) {
1644a1a9510SRong-En Fan #if USE_DATABASE
1654a1a9510SRong-En Fan 	if (_nc_is_dir_path(eargv[i])) {
1664a1a9510SRong-En Fan 	    DIR *termdir;
1674a1a9510SRong-En Fan 	    DIRENT *subdir;
1684a1a9510SRong-En Fan 
1694a1a9510SRong-En Fan 	    if ((termdir = opendir(eargv[i])) == 0) {
1704a1a9510SRong-En Fan 		(void) fflush(stdout);
1714a1a9510SRong-En Fan 		(void) fprintf(stderr,
1724a1a9510SRong-En Fan 			       "%s: can't open terminfo directory %s\n",
1734a1a9510SRong-En Fan 			       _nc_progname, eargv[i]);
1744a1a9510SRong-En Fan 		return (EXIT_FAILURE);
1754a1a9510SRong-En Fan 	    } else if (verbosity)
1764a1a9510SRong-En Fan 		(void) printf("#\n#%s:\n#\n", eargv[i]);
1774a1a9510SRong-En Fan 
1784a1a9510SRong-En Fan 	    while ((subdir = readdir(termdir)) != 0) {
1794a1a9510SRong-En Fan 		size_t len = NAMLEN(subdir);
1804a1a9510SRong-En Fan 		char buf[PATH_MAX];
1814a1a9510SRong-En Fan 		char name_1[PATH_MAX];
1824a1a9510SRong-En Fan 		DIR *entrydir;
1834a1a9510SRong-En Fan 		DIRENT *entry;
1844a1a9510SRong-En Fan 
1854a1a9510SRong-En Fan 		strncpy(name_1, subdir->d_name, len)[len] = '\0';
1864a1a9510SRong-En Fan 		if (isDotname(name_1))
1874a1a9510SRong-En Fan 		    continue;
1884a1a9510SRong-En Fan 
1894a1a9510SRong-En Fan 		(void) sprintf(buf, "%s/%s/", eargv[i], name_1);
1904a1a9510SRong-En Fan 		if (chdir(buf) != 0)
1914a1a9510SRong-En Fan 		    continue;
1924a1a9510SRong-En Fan 
1934a1a9510SRong-En Fan 		entrydir = opendir(".");
1944a1a9510SRong-En Fan 		while ((entry = readdir(entrydir)) != 0) {
1954a1a9510SRong-En Fan 		    char name_2[PATH_MAX];
1964a1a9510SRong-En Fan 		    TERMTYPE lterm;
1974a1a9510SRong-En Fan 		    char *cn;
1984a1a9510SRong-En Fan 		    int status;
1994a1a9510SRong-En Fan 
2004a1a9510SRong-En Fan 		    len = NAMLEN(entry);
2014a1a9510SRong-En Fan 		    strncpy(name_2, entry->d_name, len)[len] = '\0';
2024a1a9510SRong-En Fan 		    if (isDotname(name_2) || !_nc_is_file_path(name_2))
2034a1a9510SRong-En Fan 			continue;
2044a1a9510SRong-En Fan 
2054a1a9510SRong-En Fan 		    status = _nc_read_file_entry(name_2, &lterm);
2064a1a9510SRong-En Fan 		    if (status <= 0) {
2074a1a9510SRong-En Fan 			(void) fflush(stdout);
2084a1a9510SRong-En Fan 			(void) fprintf(stderr,
2094a1a9510SRong-En Fan 				       "%s: couldn't open terminfo file %s.\n",
2104a1a9510SRong-En Fan 				       _nc_progname, name_2);
2114a1a9510SRong-En Fan 			return (EXIT_FAILURE);
2124a1a9510SRong-En Fan 		    }
2134a1a9510SRong-En Fan 
2144a1a9510SRong-En Fan 		    /* only visit things once, by primary name */
2154a1a9510SRong-En Fan 		    cn = _nc_first_name(lterm.term_names);
2164a1a9510SRong-En Fan 		    if (!strcmp(cn, name_2)) {
2174a1a9510SRong-En Fan 			/* apply the selected hook function */
2184a1a9510SRong-En Fan 			(*hook) (cn, &lterm);
2194a1a9510SRong-En Fan 		    }
2204a1a9510SRong-En Fan 		    _nc_free_termtype(&lterm);
2214a1a9510SRong-En Fan 		}
2224a1a9510SRong-En Fan 		closedir(entrydir);
2234a1a9510SRong-En Fan 	    }
2244a1a9510SRong-En Fan 	    closedir(termdir);
2254a1a9510SRong-En Fan 	}
2264a1a9510SRong-En Fan #if USE_HASHED_DB
2274a1a9510SRong-En Fan 	else {
2284a1a9510SRong-En Fan 	    DB *capdbp;
2294a1a9510SRong-En Fan 	    char filename[PATH_MAX];
2304a1a9510SRong-En Fan 
2314a1a9510SRong-En Fan 	    if (make_db_name(filename, eargv[i], sizeof(filename))) {
2324a1a9510SRong-En Fan 		if ((capdbp = _nc_db_open(filename, FALSE)) != 0) {
2334a1a9510SRong-En Fan 		    DBT key, data;
2344a1a9510SRong-En Fan 		    int code;
2354a1a9510SRong-En Fan 
2364a1a9510SRong-En Fan 		    code = _nc_db_first(capdbp, &key, &data);
2374a1a9510SRong-En Fan 		    while (code == 0) {
2384a1a9510SRong-En Fan 			TERMTYPE lterm;
2394a1a9510SRong-En Fan 			int used;
2404a1a9510SRong-En Fan 			char *have;
2414a1a9510SRong-En Fan 			char *cn;
2424a1a9510SRong-En Fan 
2434a1a9510SRong-En Fan 			if (_nc_db_have_data(&key, &data, &have, &used)) {
2444a1a9510SRong-En Fan 			    if (_nc_read_termtype(&lterm, have, used) > 0) {
2454a1a9510SRong-En Fan 				/* only visit things once, by primary name */
2464a1a9510SRong-En Fan 				cn = _nc_first_name(lterm.term_names);
2474a1a9510SRong-En Fan 				/* apply the selected hook function */
2484a1a9510SRong-En Fan 				(*hook) (cn, &lterm);
2494a1a9510SRong-En Fan 				_nc_free_termtype(&lterm);
2504a1a9510SRong-En Fan 			    }
2514a1a9510SRong-En Fan 			}
2524a1a9510SRong-En Fan 			code = _nc_db_next(capdbp, &key, &data);
2534a1a9510SRong-En Fan 		    }
2544a1a9510SRong-En Fan 
2554a1a9510SRong-En Fan 		    _nc_db_close(capdbp);
2564a1a9510SRong-En Fan 		}
2574a1a9510SRong-En Fan 	    }
2584a1a9510SRong-En Fan 	}
2594a1a9510SRong-En Fan #endif
2604a1a9510SRong-En Fan #endif
2614a1a9510SRong-En Fan #if USE_TERMCAP
2624a1a9510SRong-En Fan #if HAVE_BSD_CGETENT
2634a1a9510SRong-En Fan 	char *db_array[2];
2644a1a9510SRong-En Fan 	char *buffer = 0;
2654a1a9510SRong-En Fan 
2664a1a9510SRong-En Fan 	if (verbosity)
2674a1a9510SRong-En Fan 	    (void) printf("#\n#%s:\n#\n", eargv[i]);
2684a1a9510SRong-En Fan 
2694a1a9510SRong-En Fan 	db_array[0] = eargv[i];
2704a1a9510SRong-En Fan 	db_array[1] = 0;
2714a1a9510SRong-En Fan 
2724a1a9510SRong-En Fan 	if (cgetfirst(&buffer, db_array)) {
2734a1a9510SRong-En Fan 	    show_termcap(buffer, hook);
2744a1a9510SRong-En Fan 	    free(buffer);
2754a1a9510SRong-En Fan 	    while (cgetnext(&buffer, db_array)) {
2764a1a9510SRong-En Fan 		show_termcap(buffer, hook);
2774a1a9510SRong-En Fan 		free(buffer);
2784a1a9510SRong-En Fan 	    }
2794a1a9510SRong-En Fan 	}
2804a1a9510SRong-En Fan 	cgetclose();
2814a1a9510SRong-En Fan #else
2824a1a9510SRong-En Fan 	/* scan termcap text-file only */
2834a1a9510SRong-En Fan 	if (_nc_is_file_path(eargv[i])) {
2844a1a9510SRong-En Fan 	    char buffer[2048];
2854a1a9510SRong-En Fan 	    FILE *fp;
2864a1a9510SRong-En Fan 
2874a1a9510SRong-En Fan 	    if ((fp = fopen(eargv[i], "r")) != 0) {
2884a1a9510SRong-En Fan 		while (fgets(buffer, sizeof(buffer), fp) != 0) {
2894a1a9510SRong-En Fan 		    if (*buffer == '#')
2904a1a9510SRong-En Fan 			continue;
2914a1a9510SRong-En Fan 		    if (isspace(*buffer))
2924a1a9510SRong-En Fan 			continue;
2934a1a9510SRong-En Fan 		    show_termcap(buffer, hook);
2944a1a9510SRong-En Fan 		}
2954a1a9510SRong-En Fan 		fclose(fp);
2964a1a9510SRong-En Fan 	    }
2974a1a9510SRong-En Fan 	}
2984a1a9510SRong-En Fan #endif
2994a1a9510SRong-En Fan #endif
3004a1a9510SRong-En Fan     }
3014a1a9510SRong-En Fan 
3024a1a9510SRong-En Fan     return (EXIT_SUCCESS);
3034a1a9510SRong-En Fan }
3044a1a9510SRong-En Fan 
3054a1a9510SRong-En Fan static void
3064a1a9510SRong-En Fan usage(void)
3074a1a9510SRong-En Fan {
3084a1a9510SRong-En Fan     (void) fprintf(stderr, "usage: %s [-ahuUV] [-v n] [file...]\n", _nc_progname);
3094a1a9510SRong-En Fan     ExitProgram(EXIT_FAILURE);
31015589c42SPeter Wemm }
31115589c42SPeter Wemm 
31215589c42SPeter Wemm int
31315589c42SPeter Wemm main(int argc, char *argv[])
3140e3d5408SPeter Wemm {
3154a1a9510SRong-En Fan     bool all_dirs = FALSE;
3160e3d5408SPeter Wemm     bool direct_dependencies = FALSE;
3170e3d5408SPeter Wemm     bool invert_dependencies = FALSE;
3180e3d5408SPeter Wemm     bool header = FALSE;
319d8977eafSRong-En Fan     char *report_file = 0;
3204a1a9510SRong-En Fan     int i;
3210e3d5408SPeter Wemm     int code;
3224a1a9510SRong-En Fan     int this_opt, last_opt = '?';
3234a1a9510SRong-En Fan     int v_opt = 0;
3240e3d5408SPeter Wemm 
32539f2269fSPeter Wemm     _nc_progname = _nc_rootname(argv[0]);
3260e3d5408SPeter Wemm 
327d8977eafSRong-En Fan     while ((this_opt = getopt(argc, argv, "0123456789ahu:vU:V")) != -1) {
3284a1a9510SRong-En Fan 	/* handle optional parameter */
3294a1a9510SRong-En Fan 	if (isdigit(this_opt)) {
3304a1a9510SRong-En Fan 	    switch (last_opt) {
3314a1a9510SRong-En Fan 	    case 'v':
3324a1a9510SRong-En Fan 		v_opt = (this_opt - '0');
3334a1a9510SRong-En Fan 		break;
3344a1a9510SRong-En Fan 	    default:
3354a1a9510SRong-En Fan 		if (isdigit(last_opt))
3364a1a9510SRong-En Fan 		    v_opt *= 10;
3374a1a9510SRong-En Fan 		else
3384a1a9510SRong-En Fan 		    v_opt = 0;
3394a1a9510SRong-En Fan 		v_opt += (this_opt - '0');
3404a1a9510SRong-En Fan 		last_opt = this_opt;
3414a1a9510SRong-En Fan 	    }
3424a1a9510SRong-En Fan 	    continue;
3434a1a9510SRong-En Fan 	}
3444a1a9510SRong-En Fan 	switch (this_opt) {
3454a1a9510SRong-En Fan 	case 'a':
3464a1a9510SRong-En Fan 	    all_dirs = TRUE;
3474a1a9510SRong-En Fan 	    break;
3480e3d5408SPeter Wemm 	case 'h':
3490e3d5408SPeter Wemm 	    header = TRUE;
3500e3d5408SPeter Wemm 	    break;
3510e3d5408SPeter Wemm 	case 'u':
3520e3d5408SPeter Wemm 	    direct_dependencies = TRUE;
353d8977eafSRong-En Fan 	    report_file = optarg;
3540e3d5408SPeter Wemm 	    break;
3550e3d5408SPeter Wemm 	case 'v':
3564a1a9510SRong-En Fan 	    v_opt = 1;
3570e3d5408SPeter Wemm 	    break;
3580e3d5408SPeter Wemm 	case 'U':
3590e3d5408SPeter Wemm 	    invert_dependencies = TRUE;
360d8977eafSRong-En Fan 	    report_file = optarg;
3610e3d5408SPeter Wemm 	    break;
3620e3d5408SPeter Wemm 	case 'V':
36318259542SPeter Wemm 	    puts(curses_version());
3640e3d5408SPeter Wemm 	    ExitProgram(EXIT_SUCCESS);
3650e3d5408SPeter Wemm 	default:
3664a1a9510SRong-En Fan 	    usage();
3670e3d5408SPeter Wemm 	}
3684a1a9510SRong-En Fan     }
3694a1a9510SRong-En Fan     set_trace_level(v_opt);
3700e3d5408SPeter Wemm 
371d8977eafSRong-En Fan     if (report_file != 0) {
372d8977eafSRong-En Fan 	if (freopen(report_file, "r", stdin) == 0) {
3730e3d5408SPeter Wemm 	    (void) fflush(stdout);
374d8977eafSRong-En Fan 	    fprintf(stderr, "%s: can't open %s\n", _nc_progname, report_file);
3750e3d5408SPeter Wemm 	    ExitProgram(EXIT_FAILURE);
3760e3d5408SPeter Wemm 	}
3770e3d5408SPeter Wemm 
3780e3d5408SPeter Wemm 	/* parse entries out of the source file */
379d8977eafSRong-En Fan 	_nc_set_source(report_file);
38015589c42SPeter Wemm 	_nc_read_entry_source(stdin, 0, FALSE, FALSE, NULLHOOK);
3810e3d5408SPeter Wemm     }
3820e3d5408SPeter Wemm 
3830e3d5408SPeter Wemm     /* maybe we want a direct-dependency listing? */
38415589c42SPeter Wemm     if (direct_dependencies) {
3850e3d5408SPeter Wemm 	ENTRY *qp;
3860e3d5408SPeter Wemm 
3874a1a9510SRong-En Fan 	for_entry_list(qp) {
38815589c42SPeter Wemm 	    if (qp->nuses) {
3890e3d5408SPeter Wemm 		int j;
3900e3d5408SPeter Wemm 
3910e3d5408SPeter Wemm 		(void) printf("%s:", _nc_first_name(qp->tterm.term_names));
3920e3d5408SPeter Wemm 		for (j = 0; j < qp->nuses; j++)
39315589c42SPeter Wemm 		    (void) printf(" %s", qp->uses[j].name);
3940e3d5408SPeter Wemm 		putchar('\n');
3950e3d5408SPeter Wemm 	    }
3964a1a9510SRong-En Fan 	}
3970e3d5408SPeter Wemm 
3980e3d5408SPeter Wemm 	ExitProgram(EXIT_SUCCESS);
3990e3d5408SPeter Wemm     }
4000e3d5408SPeter Wemm 
4010e3d5408SPeter Wemm     /* maybe we want a reverse-dependency listing? */
40215589c42SPeter Wemm     if (invert_dependencies) {
4030e3d5408SPeter Wemm 	ENTRY *qp, *rp;
4040e3d5408SPeter Wemm 	int matchcount;
4050e3d5408SPeter Wemm 
40615589c42SPeter Wemm 	for_entry_list(qp) {
4070e3d5408SPeter Wemm 	    matchcount = 0;
40815589c42SPeter Wemm 	    for_entry_list(rp) {
4090e3d5408SPeter Wemm 		if (rp->nuses == 0)
4100e3d5408SPeter Wemm 		    continue;
4110e3d5408SPeter Wemm 
4120e3d5408SPeter Wemm 		for (i = 0; i < rp->nuses; i++)
41315589c42SPeter Wemm 		    if (_nc_name_match(qp->tterm.term_names,
41415589c42SPeter Wemm 				       rp->uses[i].name, "|")) {
4150e3d5408SPeter Wemm 			if (matchcount++ == 0)
4160e3d5408SPeter Wemm 			    (void) printf("%s:",
4170e3d5408SPeter Wemm 					  _nc_first_name(qp->tterm.term_names));
4180e3d5408SPeter Wemm 			(void) printf(" %s",
4190e3d5408SPeter Wemm 				      _nc_first_name(rp->tterm.term_names));
4200e3d5408SPeter Wemm 		    }
4210e3d5408SPeter Wemm 	    }
4220e3d5408SPeter Wemm 	    if (matchcount)
4230e3d5408SPeter Wemm 		putchar('\n');
4240e3d5408SPeter Wemm 	}
4250e3d5408SPeter Wemm 
4260e3d5408SPeter Wemm 	ExitProgram(EXIT_SUCCESS);
4270e3d5408SPeter Wemm     }
4280e3d5408SPeter Wemm 
4290e3d5408SPeter Wemm     /*
4300e3d5408SPeter Wemm      * If we get this far, user wants a simple terminal type listing.
4310e3d5408SPeter Wemm      */
4320e3d5408SPeter Wemm     if (optind < argc) {
4330e3d5408SPeter Wemm 	code = typelist(argc - optind, argv + optind, header, deschook);
4344a1a9510SRong-En Fan     } else if (all_dirs) {
4354a1a9510SRong-En Fan 	DBDIRS state;
4364a1a9510SRong-En Fan 	int offset;
4374a1a9510SRong-En Fan 	int pass;
4384a1a9510SRong-En Fan 	const char *path;
4394a1a9510SRong-En Fan 	char **eargv = 0;
4400e3d5408SPeter Wemm 
4414a1a9510SRong-En Fan 	code = EXIT_FAILURE;
4424a1a9510SRong-En Fan 	for (pass = 0; pass < 2; ++pass) {
4434a1a9510SRong-En Fan 	    unsigned count = 0;
4440e3d5408SPeter Wemm 
4454a1a9510SRong-En Fan 	    _nc_first_db(&state, &offset);
4464a1a9510SRong-En Fan 	    while ((path = _nc_next_db(&state, &offset)) != 0) {
4474a1a9510SRong-En Fan 		if (!is_database(path)) {
4484a1a9510SRong-En Fan 		    ;
4494a1a9510SRong-En Fan 		} else if (eargv != 0) {
4504a1a9510SRong-En Fan 		    unsigned n;
4514a1a9510SRong-En Fan 		    int found = FALSE;
4524a1a9510SRong-En Fan 
4534a1a9510SRong-En Fan 		    /* eliminate duplicates */
4544a1a9510SRong-En Fan 		    for (n = 0; n < count; ++n) {
4554a1a9510SRong-En Fan 			if (!strcmp(path, eargv[n])) {
4564a1a9510SRong-En Fan 			    found = TRUE;
4574a1a9510SRong-En Fan 			    break;
4580e3d5408SPeter Wemm 			}
4594a1a9510SRong-En Fan 		    }
4604a1a9510SRong-En Fan 		    if (!found) {
4614a1a9510SRong-En Fan 			eargv[count] = strdup(path);
4624a1a9510SRong-En Fan 			++count;
4634a1a9510SRong-En Fan 		    }
4644a1a9510SRong-En Fan 		} else {
4654a1a9510SRong-En Fan 		    ++count;
4664a1a9510SRong-En Fan 		}
4674a1a9510SRong-En Fan 	    }
4684a1a9510SRong-En Fan 	    if (!pass) {
4694a1a9510SRong-En Fan 		eargv = typeCalloc(char *, count + 1);
4704a1a9510SRong-En Fan 	    } else {
4714a1a9510SRong-En Fan 		code = typelist((int) count, eargv, header, deschook);
4724a1a9510SRong-En Fan 		while (count-- > 0)
4734a1a9510SRong-En Fan 		    free(eargv[count]);
4744a1a9510SRong-En Fan 		free(eargv);
4754a1a9510SRong-En Fan 	    }
4764a1a9510SRong-En Fan 	}
4774a1a9510SRong-En Fan     } else {
4784a1a9510SRong-En Fan 	DBDIRS state;
4794a1a9510SRong-En Fan 	int offset;
4804a1a9510SRong-En Fan 	const char *path;
4814a1a9510SRong-En Fan 	char *eargv[3];
4824a1a9510SRong-En Fan 	int count = 0;
4834a1a9510SRong-En Fan 
4844a1a9510SRong-En Fan 	_nc_first_db(&state, &offset);
4854a1a9510SRong-En Fan 	while ((path = _nc_next_db(&state, &offset)) != 0) {
4864a1a9510SRong-En Fan 	    if (is_database(path)) {
4874a1a9510SRong-En Fan 		eargv[count++] = strdup(path);
4884a1a9510SRong-En Fan 		break;
4894a1a9510SRong-En Fan 	    }
4904a1a9510SRong-En Fan 	}
4914a1a9510SRong-En Fan 	eargv[count] = 0;
4924a1a9510SRong-En Fan 
4934a1a9510SRong-En Fan 	code = typelist(count, eargv, header, deschook);
4944a1a9510SRong-En Fan 
4954a1a9510SRong-En Fan 	while (count-- > 0)
4964a1a9510SRong-En Fan 	    free(eargv[count]);
4974a1a9510SRong-En Fan     }
4984a1a9510SRong-En Fan     _nc_last_db();
4990e3d5408SPeter Wemm 
5000e3d5408SPeter Wemm     ExitProgram(code);
5010e3d5408SPeter Wemm }
502