10e3d5408SPeter Wemm /**************************************************************************** 2*aae38d10SBaptiste Daroussin * Copyright (c) 1998-2017,2018 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 47*aae38d10SBaptiste Daroussin MODULE_ID("$Id: toe.c,v 1.78 2018/11/17 22:41:46 tom Exp $") 4815589c42SPeter Wemm 4915589c42SPeter Wemm #define isDotname(name) (!strcmp(name, ".") || !strcmp(name, "..")) 500e3d5408SPeter Wemm 5173f0a83dSXin LI typedef struct { 5273f0a83dSXin LI int db_index; 5373f0a83dSXin LI unsigned long checksum; 5473f0a83dSXin LI char *term_name; 5573f0a83dSXin LI char *description; 5673f0a83dSXin LI } TERMDATA; 5773f0a83dSXin LI 580e3d5408SPeter Wemm const char *_nc_progname; 590e3d5408SPeter Wemm 6073f0a83dSXin LI static TERMDATA *ptr_termdata; /* array of terminal data */ 6173f0a83dSXin LI static size_t use_termdata; /* actual usage in ptr_termdata[] */ 6273f0a83dSXin LI static size_t len_termdata; /* allocated size of ptr_termdata[] */ 6373f0a83dSXin LI 640e3d5408SPeter Wemm #if NO_LEAKS 650e3d5408SPeter Wemm #undef ExitProgram 664a1a9510SRong-En Fan static void ExitProgram(int code) GCC_NORETURN; 6715589c42SPeter Wemm static void 684a1a9510SRong-En Fan ExitProgram(int code) 690e3d5408SPeter Wemm { 700e3d5408SPeter Wemm _nc_free_entries(_nc_head); 715ca44d1cSRong-En Fan _nc_free_tic(code); 720e3d5408SPeter Wemm } 730e3d5408SPeter Wemm #endif 740e3d5408SPeter Wemm 7573f0a83dSXin LI static void failed(const char *) GCC_NORETURN; 7673f0a83dSXin LI 7706bfebdeSXin LI static void 7806bfebdeSXin LI failed(const char *msg) 7906bfebdeSXin LI { 8006bfebdeSXin LI perror(msg); 8106bfebdeSXin LI ExitProgram(EXIT_FAILURE); 8206bfebdeSXin LI } 8306bfebdeSXin LI 8473f0a83dSXin LI static char * 8573f0a83dSXin LI strmalloc(const char *value) 8673f0a83dSXin LI { 8773f0a83dSXin LI char *result = strdup(value); 8873f0a83dSXin LI if (result == 0) { 8973f0a83dSXin LI failed("strmalloc"); 9073f0a83dSXin LI } 9173f0a83dSXin LI return result; 9273f0a83dSXin LI } 9373f0a83dSXin LI 9473f0a83dSXin LI static TERMDATA * 9573f0a83dSXin LI new_termdata(void) 9673f0a83dSXin LI { 9773f0a83dSXin LI size_t want = use_termdata + 1; 9873f0a83dSXin LI 9973f0a83dSXin LI if (want >= len_termdata) { 10073f0a83dSXin LI len_termdata = (2 * want) + 10; 10173f0a83dSXin LI ptr_termdata = typeRealloc(TERMDATA, len_termdata, ptr_termdata); 10273f0a83dSXin LI if (ptr_termdata == 0) 10373f0a83dSXin LI failed("ptr_termdata"); 10473f0a83dSXin LI } 10573f0a83dSXin LI 10673f0a83dSXin LI return ptr_termdata + use_termdata++; 10773f0a83dSXin LI } 10873f0a83dSXin LI 10973f0a83dSXin LI static int 11073f0a83dSXin LI compare_termdata(const void *a, const void *b) 11173f0a83dSXin LI { 11273f0a83dSXin LI const TERMDATA *p = (const TERMDATA *) a; 11373f0a83dSXin LI const TERMDATA *q = (const TERMDATA *) b; 11473f0a83dSXin LI int result = strcmp(p->term_name, q->term_name); 11573f0a83dSXin LI 11673f0a83dSXin LI if (result == 0) { 11773f0a83dSXin LI result = (p->db_index - q->db_index); 11873f0a83dSXin LI } 11973f0a83dSXin LI return result; 12073f0a83dSXin LI } 12173f0a83dSXin LI 12273f0a83dSXin LI /* 12373f0a83dSXin LI * Sort the array of TERMDATA and print it. If more than one database is being 12473f0a83dSXin LI * reported, add a column to show which database has a given entry. 12573f0a83dSXin LI */ 12673f0a83dSXin LI static void 12773f0a83dSXin LI show_termdata(int eargc, char **eargv) 12873f0a83dSXin LI { 12973f0a83dSXin LI int j, k; 13073f0a83dSXin LI size_t n; 13173f0a83dSXin LI 13273f0a83dSXin LI if (use_termdata) { 13373f0a83dSXin LI if (eargc > 1) { 13473f0a83dSXin LI for (j = 0; j < eargc; ++j) { 13573f0a83dSXin LI for (k = 0; k <= j; ++k) { 13673f0a83dSXin LI printf("--"); 13773f0a83dSXin LI } 13873f0a83dSXin LI printf("> "); 13973f0a83dSXin LI printf("%s\n", eargv[j]); 14073f0a83dSXin LI } 14173f0a83dSXin LI } 14273f0a83dSXin LI if (use_termdata > 1) 14373f0a83dSXin LI qsort(ptr_termdata, use_termdata, sizeof(TERMDATA), compare_termdata); 14473f0a83dSXin LI for (n = 0; n < use_termdata; ++n) { 14573f0a83dSXin LI 14673f0a83dSXin LI /* 14773f0a83dSXin LI * If there is more than one database, show how they differ. 14873f0a83dSXin LI */ 14973f0a83dSXin LI if (eargc > 1) { 15073f0a83dSXin LI unsigned long check = 0; 15173f0a83dSXin LI k = 0; 15273f0a83dSXin LI for (;;) { 15373f0a83dSXin LI for (; k < ptr_termdata[n].db_index; ++k) { 15473f0a83dSXin LI printf("--"); 15573f0a83dSXin LI } 15673f0a83dSXin LI 15773f0a83dSXin LI /* 15873f0a83dSXin LI * If this is the first entry, or its checksum differs 15973f0a83dSXin LI * from the first entry's checksum, print "*". Otherwise 16073f0a83dSXin LI * it looks enough like a duplicate to print "+". 16173f0a83dSXin LI */ 16273f0a83dSXin LI printf("%c-", ((check == 0 16373f0a83dSXin LI || (check != ptr_termdata[n].checksum)) 16473f0a83dSXin LI ? '*' 16573f0a83dSXin LI : '+')); 16673f0a83dSXin LI check = ptr_termdata[n].checksum; 16773f0a83dSXin LI 16873f0a83dSXin LI ++k; 16973f0a83dSXin LI if ((n + 1) >= use_termdata 17073f0a83dSXin LI || strcmp(ptr_termdata[n].term_name, 17173f0a83dSXin LI ptr_termdata[n + 1].term_name)) { 17273f0a83dSXin LI break; 17373f0a83dSXin LI } 17473f0a83dSXin LI ++n; 17573f0a83dSXin LI } 17673f0a83dSXin LI for (; k < eargc; ++k) { 17773f0a83dSXin LI printf("--"); 17873f0a83dSXin LI } 17973f0a83dSXin LI printf(":\t"); 18073f0a83dSXin LI } 18173f0a83dSXin LI 18273f0a83dSXin LI (void) printf("%-10s\t%s\n", 18373f0a83dSXin LI ptr_termdata[n].term_name, 18473f0a83dSXin LI ptr_termdata[n].description); 18573f0a83dSXin LI } 18673f0a83dSXin LI } 18773f0a83dSXin LI } 18873f0a83dSXin LI 18973f0a83dSXin LI static void 19073f0a83dSXin LI free_termdata(void) 19173f0a83dSXin LI { 19273f0a83dSXin LI if (ptr_termdata != 0) { 19373f0a83dSXin LI while (use_termdata != 0) { 19473f0a83dSXin LI --use_termdata; 19573f0a83dSXin LI free(ptr_termdata[use_termdata].term_name); 19673f0a83dSXin LI free(ptr_termdata[use_termdata].description); 19773f0a83dSXin LI } 19873f0a83dSXin LI free(ptr_termdata); 19973f0a83dSXin LI ptr_termdata = 0; 20073f0a83dSXin LI } 20173f0a83dSXin LI use_termdata = 0; 20273f0a83dSXin LI len_termdata = 0; 20373f0a83dSXin LI } 20473f0a83dSXin LI 20573f0a83dSXin LI static char ** 20673f0a83dSXin LI allocArgv(size_t count) 20773f0a83dSXin LI { 20873f0a83dSXin LI char **result = typeCalloc(char *, count + 1); 20973f0a83dSXin LI if (result == 0) 21073f0a83dSXin LI failed("realloc eargv"); 21173f0a83dSXin LI 21273f0a83dSXin LI assert(result != 0); 21373f0a83dSXin LI return result; 21473f0a83dSXin LI } 21573f0a83dSXin LI 21673f0a83dSXin LI static void 21773f0a83dSXin LI freeArgv(char **argv) 21873f0a83dSXin LI { 21973f0a83dSXin LI if (argv) { 22073f0a83dSXin LI int count = 0; 22173f0a83dSXin LI while (argv[count]) { 22273f0a83dSXin LI free(argv[count++]); 22373f0a83dSXin LI } 22473f0a83dSXin LI free(argv); 22573f0a83dSXin LI } 22673f0a83dSXin LI } 22773f0a83dSXin LI 2284a1a9510SRong-En Fan #if USE_HASHED_DB 22939f2269fSPeter Wemm static bool 2304a1a9510SRong-En Fan make_db_name(char *dst, const char *src, unsigned limit) 23139f2269fSPeter Wemm { 2324a1a9510SRong-En Fan static const char suffix[] = DBM_SUFFIX; 2334a1a9510SRong-En Fan 2344a1a9510SRong-En Fan bool result = FALSE; 23573f0a83dSXin LI size_t lens = sizeof(suffix) - 1; 23673f0a83dSXin LI size_t size = strlen(src); 23773f0a83dSXin LI size_t need = lens + size; 2384a1a9510SRong-En Fan 2394a1a9510SRong-En Fan if (need <= limit) { 2404a1a9510SRong-En Fan if (size >= lens 24173f0a83dSXin LI && !strcmp(src + size - lens, suffix)) { 24273f0a83dSXin LI _nc_STRCPY(dst, src, PATH_MAX); 24373f0a83dSXin LI } else { 24473f0a83dSXin LI _nc_SPRINTF(dst, _nc_SLIMIT(PATH_MAX) "%s%s", src, suffix); 24573f0a83dSXin LI } 2464a1a9510SRong-En Fan result = TRUE; 24739f2269fSPeter Wemm } 2484a1a9510SRong-En Fan return result; 2494a1a9510SRong-En Fan } 2504a1a9510SRong-En Fan #endif 25139f2269fSPeter Wemm 25273f0a83dSXin LI typedef void (DescHook) (int /* db_index */ , 25373f0a83dSXin LI int /* db_limit */ , 25473f0a83dSXin LI const char * /* term_name */ , 255*aae38d10SBaptiste Daroussin TERMTYPE2 * /* term */ ); 25639f2269fSPeter Wemm 25773f0a83dSXin LI static const char * 258*aae38d10SBaptiste Daroussin term_description(TERMTYPE2 *tp) 25915589c42SPeter Wemm { 2604a1a9510SRong-En Fan const char *desc; 2614a1a9510SRong-En Fan 26273f0a83dSXin LI if (tp->term_names == 0 26373f0a83dSXin LI || (desc = strrchr(tp->term_names, '|')) == 0 26473f0a83dSXin LI || (*++desc == '\0')) { 2654a1a9510SRong-En Fan desc = "(No description)"; 26615589c42SPeter Wemm } 2674a1a9510SRong-En Fan 26873f0a83dSXin LI return desc; 26973f0a83dSXin LI } 27073f0a83dSXin LI 27173f0a83dSXin LI /* display a description for the type */ 2724a1a9510SRong-En Fan static void 273*aae38d10SBaptiste Daroussin deschook(int db_index, int db_limit, const char *term_name, TERMTYPE2 *tp) 27473f0a83dSXin LI { 27573f0a83dSXin LI (void) db_index; 27673f0a83dSXin LI (void) db_limit; 27773f0a83dSXin LI (void) printf("%-10s\t%s\n", term_name, term_description(tp)); 27873f0a83dSXin LI } 27973f0a83dSXin LI 28073f0a83dSXin LI static unsigned long 28173f0a83dSXin LI string_sum(const char *value) 28273f0a83dSXin LI { 28373f0a83dSXin LI unsigned long result = 0; 28473f0a83dSXin LI 28573f0a83dSXin LI if ((intptr_t) value == (intptr_t) (-1)) { 28673f0a83dSXin LI result = ~result; 28773f0a83dSXin LI } else if (value) { 28873f0a83dSXin LI while (*value) { 28973f0a83dSXin LI result += UChar(*value); 29073f0a83dSXin LI ++value; 29173f0a83dSXin LI } 29273f0a83dSXin LI } 29373f0a83dSXin LI return result; 29473f0a83dSXin LI } 29573f0a83dSXin LI 29673f0a83dSXin LI static unsigned long 297*aae38d10SBaptiste Daroussin checksum_of(TERMTYPE2 *tp) 29873f0a83dSXin LI { 29973f0a83dSXin LI unsigned long result = string_sum(tp->term_names); 30073f0a83dSXin LI unsigned i; 30173f0a83dSXin LI 30273f0a83dSXin LI for (i = 0; i < NUM_BOOLEANS(tp); i++) { 30373f0a83dSXin LI result += (unsigned long) (tp->Booleans[i]); 30473f0a83dSXin LI } 30573f0a83dSXin LI for (i = 0; i < NUM_NUMBERS(tp); i++) { 30673f0a83dSXin LI result += (unsigned long) (tp->Numbers[i]); 30773f0a83dSXin LI } 30873f0a83dSXin LI for (i = 0; i < NUM_STRINGS(tp); i++) { 30973f0a83dSXin LI result += string_sum(tp->Strings[i]); 31073f0a83dSXin LI } 31173f0a83dSXin LI return result; 31273f0a83dSXin LI } 31373f0a83dSXin LI 31473f0a83dSXin LI /* collect data, to sort before display */ 31573f0a83dSXin LI static void 316*aae38d10SBaptiste Daroussin sorthook(int db_index, int db_limit, const char *term_name, TERMTYPE2 *tp) 31773f0a83dSXin LI { 31873f0a83dSXin LI TERMDATA *data = new_termdata(); 31973f0a83dSXin LI 32073f0a83dSXin LI data->db_index = db_index; 32173f0a83dSXin LI data->checksum = ((db_limit > 1) ? checksum_of(tp) : 0); 32273f0a83dSXin LI data->term_name = strmalloc(term_name); 32373f0a83dSXin LI data->description = strmalloc(term_description(tp)); 32473f0a83dSXin LI } 32573f0a83dSXin LI 32673f0a83dSXin LI #if NCURSES_USE_TERMCAP 32773f0a83dSXin LI static void 32873f0a83dSXin LI show_termcap(int db_index, int db_limit, char *buffer, DescHook hook) 3294a1a9510SRong-En Fan { 330*aae38d10SBaptiste Daroussin TERMTYPE2 data; 3314a1a9510SRong-En Fan char *next = strchr(buffer, ':'); 3324a1a9510SRong-En Fan char *last; 3334a1a9510SRong-En Fan char *list = buffer; 3344a1a9510SRong-En Fan 3354a1a9510SRong-En Fan if (next) 3364a1a9510SRong-En Fan *next = '\0'; 3374a1a9510SRong-En Fan 3384a1a9510SRong-En Fan last = strrchr(buffer, '|'); 3394a1a9510SRong-En Fan if (last) 3404a1a9510SRong-En Fan ++last; 3414a1a9510SRong-En Fan 34273f0a83dSXin LI memset(&data, 0, sizeof(data)); 34373f0a83dSXin LI data.term_names = strmalloc(buffer); 3444a1a9510SRong-En Fan while ((next = strtok(list, "|")) != 0) { 3454a1a9510SRong-En Fan if (next != last) 34673f0a83dSXin LI hook(db_index, db_limit, next, &data); 3474a1a9510SRong-En Fan list = 0; 3484a1a9510SRong-En Fan } 3494a1a9510SRong-En Fan free(data.term_names); 3504a1a9510SRong-En Fan } 3514a1a9510SRong-En Fan #endif 3524a1a9510SRong-En Fan 35373f0a83dSXin LI #if NCURSES_USE_DATABASE 35473f0a83dSXin LI static char * 35573f0a83dSXin LI copy_entryname(DIRENT * src) 35673f0a83dSXin LI { 35773f0a83dSXin LI size_t len = NAMLEN(src); 35873f0a83dSXin LI char *result = malloc(len + 1); 35973f0a83dSXin LI if (result == 0) 36073f0a83dSXin LI failed("copy entryname"); 36173f0a83dSXin LI memcpy(result, src->d_name, len); 36273f0a83dSXin LI result[len] = '\0'; 36373f0a83dSXin LI 36473f0a83dSXin LI return result; 36573f0a83dSXin LI } 36673f0a83dSXin LI #endif 36773f0a83dSXin LI 3684a1a9510SRong-En Fan static int 3694a1a9510SRong-En Fan typelist(int eargc, char *eargv[], 37073f0a83dSXin LI int verbosity, 37173f0a83dSXin LI DescHook hook) 3724a1a9510SRong-En Fan /* apply a function to each entry in given terminfo directories */ 3734a1a9510SRong-En Fan { 3744a1a9510SRong-En Fan int i; 3754a1a9510SRong-En Fan 3764a1a9510SRong-En Fan for (i = 0; i < eargc; i++) { 37773f0a83dSXin LI #if NCURSES_USE_DATABASE 3784a1a9510SRong-En Fan if (_nc_is_dir_path(eargv[i])) { 3795d08fb1fSRong-En Fan char *cwd_buf = 0; 3804a1a9510SRong-En Fan DIR *termdir; 3814a1a9510SRong-En Fan DIRENT *subdir; 3824a1a9510SRong-En Fan 3834a1a9510SRong-En Fan if ((termdir = opendir(eargv[i])) == 0) { 3844a1a9510SRong-En Fan (void) fflush(stdout); 3854a1a9510SRong-En Fan (void) fprintf(stderr, 3864a1a9510SRong-En Fan "%s: can't open terminfo directory %s\n", 3874a1a9510SRong-En Fan _nc_progname, eargv[i]); 38873f0a83dSXin LI continue; 38973f0a83dSXin LI } 39073f0a83dSXin LI 39173f0a83dSXin LI if (verbosity) 3924a1a9510SRong-En Fan (void) printf("#\n#%s:\n#\n", eargv[i]); 3934a1a9510SRong-En Fan 3944a1a9510SRong-En Fan while ((subdir = readdir(termdir)) != 0) { 39573f0a83dSXin LI size_t cwd_len; 39673f0a83dSXin LI char *name_1; 3974a1a9510SRong-En Fan DIR *entrydir; 3984a1a9510SRong-En Fan DIRENT *entry; 3994a1a9510SRong-En Fan 40073f0a83dSXin LI name_1 = copy_entryname(subdir); 40173f0a83dSXin LI if (isDotname(name_1)) { 40273f0a83dSXin LI free(name_1); 40373f0a83dSXin LI continue; 40473f0a83dSXin LI } 40573f0a83dSXin LI 40673f0a83dSXin LI cwd_len = NAMLEN(subdir) + strlen(eargv[i]) + 3; 4075d08fb1fSRong-En Fan cwd_buf = typeRealloc(char, cwd_len, cwd_buf); 40806bfebdeSXin LI if (cwd_buf == 0) 40906bfebdeSXin LI failed("realloc cwd_buf"); 41006bfebdeSXin LI 41106bfebdeSXin LI assert(cwd_buf != 0); 4125d08fb1fSRong-En Fan 41373f0a83dSXin LI _nc_SPRINTF(cwd_buf, _nc_SLIMIT(cwd_len) 41473f0a83dSXin LI "%s/%s/", eargv[i], name_1); 41573f0a83dSXin LI free(name_1); 4164a1a9510SRong-En Fan 4175d08fb1fSRong-En Fan if (chdir(cwd_buf) != 0) 4184a1a9510SRong-En Fan continue; 4194a1a9510SRong-En Fan 4204a1a9510SRong-En Fan entrydir = opendir("."); 4215d08fb1fSRong-En Fan if (entrydir == 0) { 4225d08fb1fSRong-En Fan perror(cwd_buf); 4235d08fb1fSRong-En Fan continue; 4245d08fb1fSRong-En Fan } 4254a1a9510SRong-En Fan while ((entry = readdir(entrydir)) != 0) { 42673f0a83dSXin LI char *name_2; 427*aae38d10SBaptiste Daroussin TERMTYPE2 lterm; 4284a1a9510SRong-En Fan char *cn; 4294a1a9510SRong-En Fan int status; 4304a1a9510SRong-En Fan 43173f0a83dSXin LI name_2 = copy_entryname(entry); 43273f0a83dSXin LI if (isDotname(name_2) || !_nc_is_file_path(name_2)) { 43373f0a83dSXin LI free(name_2); 4344a1a9510SRong-En Fan continue; 43573f0a83dSXin LI } 4364a1a9510SRong-En Fan 4374a1a9510SRong-En Fan status = _nc_read_file_entry(name_2, <erm); 4384a1a9510SRong-En Fan if (status <= 0) { 4394a1a9510SRong-En Fan (void) fflush(stdout); 4404a1a9510SRong-En Fan (void) fprintf(stderr, 4414a1a9510SRong-En Fan "%s: couldn't open terminfo file %s.\n", 4424a1a9510SRong-En Fan _nc_progname, name_2); 44373f0a83dSXin LI free(name_2); 444*aae38d10SBaptiste Daroussin continue; 4454a1a9510SRong-En Fan } 4464a1a9510SRong-En Fan 4474a1a9510SRong-En Fan /* only visit things once, by primary name */ 4484a1a9510SRong-En Fan cn = _nc_first_name(lterm.term_names); 4494a1a9510SRong-En Fan if (!strcmp(cn, name_2)) { 4504a1a9510SRong-En Fan /* apply the selected hook function */ 45173f0a83dSXin LI hook(i, eargc, cn, <erm); 4524a1a9510SRong-En Fan } 453*aae38d10SBaptiste Daroussin _nc_free_termtype2(<erm); 45473f0a83dSXin LI free(name_2); 4554a1a9510SRong-En Fan } 4564a1a9510SRong-En Fan closedir(entrydir); 4574a1a9510SRong-En Fan } 4584a1a9510SRong-En Fan closedir(termdir); 4595d08fb1fSRong-En Fan if (cwd_buf != 0) 4605d08fb1fSRong-En Fan free(cwd_buf); 46173f0a83dSXin LI continue; 4624a1a9510SRong-En Fan } 4634a1a9510SRong-En Fan #if USE_HASHED_DB 4644a1a9510SRong-En Fan else { 4654a1a9510SRong-En Fan DB *capdbp; 4664a1a9510SRong-En Fan char filename[PATH_MAX]; 4674a1a9510SRong-En Fan 46873f0a83dSXin LI if (verbosity) 46973f0a83dSXin LI (void) printf("#\n#%s:\n#\n", eargv[i]); 47073f0a83dSXin LI 4714a1a9510SRong-En Fan if (make_db_name(filename, eargv[i], sizeof(filename))) { 4724a1a9510SRong-En Fan if ((capdbp = _nc_db_open(filename, FALSE)) != 0) { 4734a1a9510SRong-En Fan DBT key, data; 4744a1a9510SRong-En Fan int code; 4754a1a9510SRong-En Fan 4764a1a9510SRong-En Fan code = _nc_db_first(capdbp, &key, &data); 4774a1a9510SRong-En Fan while (code == 0) { 478*aae38d10SBaptiste Daroussin TERMTYPE2 lterm; 4794a1a9510SRong-En Fan int used; 4804a1a9510SRong-En Fan char *have; 4814a1a9510SRong-En Fan char *cn; 4824a1a9510SRong-En Fan 4834a1a9510SRong-En Fan if (_nc_db_have_data(&key, &data, &have, &used)) { 4844a1a9510SRong-En Fan if (_nc_read_termtype(<erm, have, used) > 0) { 4854a1a9510SRong-En Fan /* only visit things once, by primary name */ 4864a1a9510SRong-En Fan cn = _nc_first_name(lterm.term_names); 4874a1a9510SRong-En Fan /* apply the selected hook function */ 48873f0a83dSXin LI hook(i, eargc, cn, <erm); 489*aae38d10SBaptiste Daroussin _nc_free_termtype2(<erm); 4904a1a9510SRong-En Fan } 4914a1a9510SRong-En Fan } 4924a1a9510SRong-En Fan code = _nc_db_next(capdbp, &key, &data); 4934a1a9510SRong-En Fan } 4944a1a9510SRong-En Fan 4954a1a9510SRong-En Fan _nc_db_close(capdbp); 49673f0a83dSXin LI continue; 4974a1a9510SRong-En Fan } 4984a1a9510SRong-En Fan } 4994a1a9510SRong-En Fan } 500*aae38d10SBaptiste Daroussin #endif /* USE_HASHED_DB */ 501*aae38d10SBaptiste Daroussin #endif /* NCURSES_USE_DATABASE */ 50273f0a83dSXin LI #if NCURSES_USE_TERMCAP 5034a1a9510SRong-En Fan #if HAVE_BSD_CGETENT 50473f0a83dSXin LI { 50573f0a83dSXin LI CGETENT_CONST char *db_array[2]; 5064a1a9510SRong-En Fan char *buffer = 0; 5074a1a9510SRong-En Fan 5084a1a9510SRong-En Fan if (verbosity) 5094a1a9510SRong-En Fan (void) printf("#\n#%s:\n#\n", eargv[i]); 5104a1a9510SRong-En Fan 5114a1a9510SRong-En Fan db_array[0] = eargv[i]; 5124a1a9510SRong-En Fan db_array[1] = 0; 5134a1a9510SRong-En Fan 51473f0a83dSXin LI if (cgetfirst(&buffer, db_array) > 0) { 51573f0a83dSXin LI show_termcap(i, eargc, buffer, hook); 5164a1a9510SRong-En Fan free(buffer); 51773f0a83dSXin LI while (cgetnext(&buffer, db_array) > 0) { 51873f0a83dSXin LI show_termcap(i, eargc, buffer, hook); 5194a1a9510SRong-En Fan free(buffer); 5204a1a9510SRong-En Fan } 5214a1a9510SRong-En Fan cgetclose(); 52273f0a83dSXin LI continue; 52373f0a83dSXin LI } 52473f0a83dSXin LI } 5254a1a9510SRong-En Fan #else 5264a1a9510SRong-En Fan /* scan termcap text-file only */ 5274a1a9510SRong-En Fan if (_nc_is_file_path(eargv[i])) { 5284a1a9510SRong-En Fan char buffer[2048]; 5294a1a9510SRong-En Fan FILE *fp; 5304a1a9510SRong-En Fan 53173f0a83dSXin LI if (verbosity) 53273f0a83dSXin LI (void) printf("#\n#%s:\n#\n", eargv[i]); 53373f0a83dSXin LI 5344a1a9510SRong-En Fan if ((fp = fopen(eargv[i], "r")) != 0) { 5354a1a9510SRong-En Fan while (fgets(buffer, sizeof(buffer), fp) != 0) { 5364a1a9510SRong-En Fan if (*buffer == '#') 5374a1a9510SRong-En Fan continue; 5384a1a9510SRong-En Fan if (isspace(*buffer)) 5394a1a9510SRong-En Fan continue; 54073f0a83dSXin LI show_termcap(i, eargc, buffer, hook); 5414a1a9510SRong-En Fan } 5424a1a9510SRong-En Fan fclose(fp); 5434a1a9510SRong-En Fan } 5444a1a9510SRong-En Fan } 5454a1a9510SRong-En Fan #endif 5464a1a9510SRong-En Fan #endif 5474a1a9510SRong-En Fan } 5484a1a9510SRong-En Fan 54973f0a83dSXin LI if (hook == sorthook) { 55073f0a83dSXin LI show_termdata(eargc, eargv); 55173f0a83dSXin LI free_termdata(); 55273f0a83dSXin LI } 55373f0a83dSXin LI 5544a1a9510SRong-En Fan return (EXIT_SUCCESS); 5554a1a9510SRong-En Fan } 5564a1a9510SRong-En Fan 5574a1a9510SRong-En Fan static void 5584a1a9510SRong-En Fan usage(void) 5594a1a9510SRong-En Fan { 56073f0a83dSXin LI (void) fprintf(stderr, "usage: %s [-ahsuUV] [-v n] [file...]\n", _nc_progname); 5614a1a9510SRong-En Fan ExitProgram(EXIT_FAILURE); 56215589c42SPeter Wemm } 56315589c42SPeter Wemm 56415589c42SPeter Wemm int 56515589c42SPeter Wemm main(int argc, char *argv[]) 5660e3d5408SPeter Wemm { 5674a1a9510SRong-En Fan bool all_dirs = FALSE; 5680e3d5408SPeter Wemm bool direct_dependencies = FALSE; 5690e3d5408SPeter Wemm bool invert_dependencies = FALSE; 5700e3d5408SPeter Wemm bool header = FALSE; 571d8977eafSRong-En Fan char *report_file = 0; 5725d08fb1fSRong-En Fan unsigned i; 5730e3d5408SPeter Wemm int code; 5744a1a9510SRong-En Fan int this_opt, last_opt = '?'; 57573f0a83dSXin LI unsigned v_opt = 0; 57673f0a83dSXin LI DescHook *hook = deschook; 5770e3d5408SPeter Wemm 57839f2269fSPeter Wemm _nc_progname = _nc_rootname(argv[0]); 5790e3d5408SPeter Wemm 58073f0a83dSXin LI while ((this_opt = getopt(argc, argv, "0123456789ahsu:vU:V")) != -1) { 5814a1a9510SRong-En Fan /* handle optional parameter */ 5824a1a9510SRong-En Fan if (isdigit(this_opt)) { 5834a1a9510SRong-En Fan switch (last_opt) { 5844a1a9510SRong-En Fan case 'v': 58573f0a83dSXin LI v_opt = (unsigned) (this_opt - '0'); 5864a1a9510SRong-En Fan break; 5874a1a9510SRong-En Fan default: 5884a1a9510SRong-En Fan if (isdigit(last_opt)) 5894a1a9510SRong-En Fan v_opt *= 10; 5904a1a9510SRong-En Fan else 5914a1a9510SRong-En Fan v_opt = 0; 59273f0a83dSXin LI v_opt += (unsigned) (this_opt - '0'); 5934a1a9510SRong-En Fan last_opt = this_opt; 5944a1a9510SRong-En Fan } 5954a1a9510SRong-En Fan continue; 5964a1a9510SRong-En Fan } 5974a1a9510SRong-En Fan switch (this_opt) { 5984a1a9510SRong-En Fan case 'a': 5994a1a9510SRong-En Fan all_dirs = TRUE; 6004a1a9510SRong-En Fan break; 6010e3d5408SPeter Wemm case 'h': 6020e3d5408SPeter Wemm header = TRUE; 6030e3d5408SPeter Wemm break; 60473f0a83dSXin LI case 's': 60573f0a83dSXin LI hook = sorthook; 60673f0a83dSXin LI break; 6070e3d5408SPeter Wemm case 'u': 6080e3d5408SPeter Wemm direct_dependencies = TRUE; 609d8977eafSRong-En Fan report_file = optarg; 6100e3d5408SPeter Wemm break; 6110e3d5408SPeter Wemm case 'v': 6124a1a9510SRong-En Fan v_opt = 1; 6130e3d5408SPeter Wemm break; 6140e3d5408SPeter Wemm case 'U': 6150e3d5408SPeter Wemm invert_dependencies = TRUE; 616d8977eafSRong-En Fan report_file = optarg; 6170e3d5408SPeter Wemm break; 6180e3d5408SPeter Wemm case 'V': 61918259542SPeter Wemm puts(curses_version()); 6200e3d5408SPeter Wemm ExitProgram(EXIT_SUCCESS); 6210e3d5408SPeter Wemm default: 6224a1a9510SRong-En Fan usage(); 6230e3d5408SPeter Wemm } 6244a1a9510SRong-En Fan } 6254a1a9510SRong-En Fan set_trace_level(v_opt); 6260e3d5408SPeter Wemm 627d8977eafSRong-En Fan if (report_file != 0) { 628d8977eafSRong-En Fan if (freopen(report_file, "r", stdin) == 0) { 6290e3d5408SPeter Wemm (void) fflush(stdout); 630d8977eafSRong-En Fan fprintf(stderr, "%s: can't open %s\n", _nc_progname, report_file); 6310e3d5408SPeter Wemm ExitProgram(EXIT_FAILURE); 6320e3d5408SPeter Wemm } 6330e3d5408SPeter Wemm 6340e3d5408SPeter Wemm /* parse entries out of the source file */ 635d8977eafSRong-En Fan _nc_set_source(report_file); 63615589c42SPeter Wemm _nc_read_entry_source(stdin, 0, FALSE, FALSE, NULLHOOK); 6370e3d5408SPeter Wemm } 6380e3d5408SPeter Wemm 6390e3d5408SPeter Wemm /* maybe we want a direct-dependency listing? */ 64015589c42SPeter Wemm if (direct_dependencies) { 6410e3d5408SPeter Wemm ENTRY *qp; 6420e3d5408SPeter Wemm 6434a1a9510SRong-En Fan for_entry_list(qp) { 64415589c42SPeter Wemm if (qp->nuses) { 6455d08fb1fSRong-En Fan unsigned j; 6460e3d5408SPeter Wemm 6470e3d5408SPeter Wemm (void) printf("%s:", _nc_first_name(qp->tterm.term_names)); 6480e3d5408SPeter Wemm for (j = 0; j < qp->nuses; j++) 64915589c42SPeter Wemm (void) printf(" %s", qp->uses[j].name); 6500e3d5408SPeter Wemm putchar('\n'); 6510e3d5408SPeter Wemm } 6524a1a9510SRong-En Fan } 6530e3d5408SPeter Wemm 6540e3d5408SPeter Wemm ExitProgram(EXIT_SUCCESS); 6550e3d5408SPeter Wemm } 6560e3d5408SPeter Wemm 6570e3d5408SPeter Wemm /* maybe we want a reverse-dependency listing? */ 65815589c42SPeter Wemm if (invert_dependencies) { 6590e3d5408SPeter Wemm ENTRY *qp, *rp; 6600e3d5408SPeter Wemm int matchcount; 6610e3d5408SPeter Wemm 66215589c42SPeter Wemm for_entry_list(qp) { 6630e3d5408SPeter Wemm matchcount = 0; 66415589c42SPeter Wemm for_entry_list(rp) { 6650e3d5408SPeter Wemm if (rp->nuses == 0) 6660e3d5408SPeter Wemm continue; 6670e3d5408SPeter Wemm 6680e3d5408SPeter Wemm for (i = 0; i < rp->nuses; i++) 66915589c42SPeter Wemm if (_nc_name_match(qp->tterm.term_names, 67015589c42SPeter Wemm rp->uses[i].name, "|")) { 6710e3d5408SPeter Wemm if (matchcount++ == 0) 6720e3d5408SPeter Wemm (void) printf("%s:", 6730e3d5408SPeter Wemm _nc_first_name(qp->tterm.term_names)); 6740e3d5408SPeter Wemm (void) printf(" %s", 6750e3d5408SPeter Wemm _nc_first_name(rp->tterm.term_names)); 6760e3d5408SPeter Wemm } 6770e3d5408SPeter Wemm } 6780e3d5408SPeter Wemm if (matchcount) 6790e3d5408SPeter Wemm putchar('\n'); 6800e3d5408SPeter Wemm } 6810e3d5408SPeter Wemm 6820e3d5408SPeter Wemm ExitProgram(EXIT_SUCCESS); 6830e3d5408SPeter Wemm } 6840e3d5408SPeter Wemm 6850e3d5408SPeter Wemm /* 6860e3d5408SPeter Wemm * If we get this far, user wants a simple terminal type listing. 6870e3d5408SPeter Wemm */ 6880e3d5408SPeter Wemm if (optind < argc) { 68973f0a83dSXin LI code = typelist(argc - optind, argv + optind, header, hook); 6904a1a9510SRong-En Fan } else if (all_dirs) { 6914a1a9510SRong-En Fan DBDIRS state; 6924a1a9510SRong-En Fan int offset; 6934a1a9510SRong-En Fan int pass; 6944a1a9510SRong-En Fan const char *path; 6954a1a9510SRong-En Fan char **eargv = 0; 6960e3d5408SPeter Wemm 6974a1a9510SRong-En Fan code = EXIT_FAILURE; 6984a1a9510SRong-En Fan for (pass = 0; pass < 2; ++pass) { 69973f0a83dSXin LI size_t count = 0; 7000e3d5408SPeter Wemm 7014a1a9510SRong-En Fan _nc_first_db(&state, &offset); 7024a1a9510SRong-En Fan while ((path = _nc_next_db(&state, &offset)) != 0) { 703*aae38d10SBaptiste Daroussin if (quick_prefix(path)) 704*aae38d10SBaptiste Daroussin continue; 70573f0a83dSXin LI if (pass) { 70673f0a83dSXin LI eargv[count] = strmalloc(path); 7070e3d5408SPeter Wemm } 7084a1a9510SRong-En Fan ++count; 7094a1a9510SRong-En Fan } 7104a1a9510SRong-En Fan if (!pass) { 71173f0a83dSXin LI eargv = allocArgv(count); 71206bfebdeSXin LI if (eargv == 0) 71373f0a83dSXin LI failed("eargv"); 7144a1a9510SRong-En Fan } else { 71573f0a83dSXin LI code = typelist((int) count, eargv, header, hook); 71673f0a83dSXin LI freeArgv(eargv); 7174a1a9510SRong-En Fan } 7184a1a9510SRong-En Fan } 7194a1a9510SRong-En Fan } else { 7204a1a9510SRong-En Fan DBDIRS state; 7214a1a9510SRong-En Fan int offset; 7224a1a9510SRong-En Fan const char *path; 72373f0a83dSXin LI char **eargv = allocArgv((size_t) 2); 72473f0a83dSXin LI size_t count = 0; 7254a1a9510SRong-En Fan 72673f0a83dSXin LI if (eargv == 0) 72773f0a83dSXin LI failed("eargv"); 7284a1a9510SRong-En Fan _nc_first_db(&state, &offset); 72973f0a83dSXin LI if ((path = _nc_next_db(&state, &offset)) != 0) { 730*aae38d10SBaptiste Daroussin if (!quick_prefix(path)) 73173f0a83dSXin LI eargv[count++] = strmalloc(path); 7324a1a9510SRong-En Fan } 7334a1a9510SRong-En Fan 73473f0a83dSXin LI code = typelist((int) count, eargv, header, hook); 7354a1a9510SRong-En Fan 73673f0a83dSXin LI freeArgv(eargv); 7374a1a9510SRong-En Fan } 7384a1a9510SRong-En Fan _nc_last_db(); 7390e3d5408SPeter Wemm 7400e3d5408SPeter Wemm ExitProgram(code); 7410e3d5408SPeter Wemm } 742