150276Speter/**************************************************************************** 2176187Srafan * Copyright (c) 1998-2007,2008 Free Software Foundation, Inc. * 350276Speter * * 450276Speter * Permission is hereby granted, free of charge, to any person obtaining a * 550276Speter * copy of this software and associated documentation files (the * 650276Speter * "Software"), to deal in the Software without restriction, including * 750276Speter * without limitation the rights to use, copy, modify, merge, publish, * 850276Speter * distribute, distribute with modifications, sublicense, and/or sell * 950276Speter * copies of the Software, and to permit persons to whom the Software is * 1050276Speter * furnished to do so, subject to the following conditions: * 1150276Speter * * 1250276Speter * The above copyright notice and this permission notice shall be included * 1350276Speter * in all copies or substantial portions of the Software. * 1450276Speter * * 1550276Speter * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * 1650276Speter * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * 1750276Speter * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * 1850276Speter * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * 1950276Speter * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * 2050276Speter * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * 2150276Speter * THE USE OR OTHER DEALINGS IN THE SOFTWARE. * 2250276Speter * * 2350276Speter * Except as contained in this notice, the name(s) of the above copyright * 2450276Speter * holders shall not be used in advertising or otherwise to promote the * 2550276Speter * sale, use or other dealings in this Software without prior written * 2650276Speter * authorization. * 2750276Speter ****************************************************************************/ 2850276Speter 2950276Speter/**************************************************************************** 3050276Speter * Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 * 3150276Speter * and: Eric S. Raymond <esr@snark.thyrsus.com> * 32166124Srafan * and: Thomas E. Dickey 1996-on * 3350276Speter ****************************************************************************/ 3450276Speter 3550276Speter/* 3650276Speter * toe.c --- table of entries report generator 3750276Speter */ 3850276Speter 3950276Speter#include <progs.priv.h> 4050276Speter 4150276Speter#include <sys/stat.h> 4250276Speter 43166124Srafan#if USE_HASHED_DB 44166124Srafan#include <hashed_db.h> 45166124Srafan#endif 4650276Speter 47184989SrafanMODULE_ID("$Id: toe.c,v 1.51 2008/08/16 21:53:25 tom Exp $") 48166124Srafan 4962449Speter#define isDotname(name) (!strcmp(name, ".") || !strcmp(name, "..")) 5062449Speter 5150276Speterconst char *_nc_progname; 5250276Speter 5350276Speter#if NO_LEAKS 5450276Speter#undef ExitProgram 55166124Srafanstatic void ExitProgram(int code) GCC_NORETURN; 5662449Speterstatic void 57166124SrafanExitProgram(int code) 5850276Speter{ 5962449Speter _nc_free_entries(_nc_head); 60174993Srafan _nc_free_tic(code); 6150276Speter} 6250276Speter#endif 6350276Speter 64166124Srafan#if USE_HASHED_DB 6597049Speterstatic bool 66166124Srafanmake_db_name(char *dst, const char *src, unsigned limit) 6797049Speter{ 68166124Srafan static const char suffix[] = DBM_SUFFIX; 69166124Srafan 70166124Srafan bool result = FALSE; 71166124Srafan unsigned lens = sizeof(suffix) - 1; 72166124Srafan unsigned size = strlen(src); 73166124Srafan unsigned need = lens + size; 74166124Srafan 75166124Srafan if (need <= limit) { 76166124Srafan if (size >= lens 77166124Srafan && !strcmp(src + size - lens, suffix)) 78166124Srafan (void) strcpy(dst, src); 79166124Srafan else 80166124Srafan (void) sprintf(dst, "%s%s", src, suffix); 81166124Srafan result = TRUE; 82166124Srafan } 83166124Srafan return result; 8497049Speter} 85166124Srafan#endif 8697049Speter 8797049Speterstatic bool 88166124Srafanis_database(const char *path) 8997049Speter{ 90166124Srafan bool result = FALSE; 91166124Srafan#if USE_DATABASE 92166124Srafan if (_nc_is_dir_path(path) && access(path, R_OK | X_OK) == 0) { 93166124Srafan result = TRUE; 94166124Srafan } 95166124Srafan#endif 96166124Srafan#if USE_TERMCAP 97166124Srafan if (_nc_is_file_path(path) && access(path, R_OK) == 0) { 98166124Srafan result = TRUE; 99166124Srafan } 100166124Srafan#endif 101166124Srafan#if USE_HASHED_DB 102166124Srafan if (!result) { 103166124Srafan char filename[PATH_MAX]; 104166124Srafan if (_nc_is_file_path(path) && access(path, R_OK) == 0) { 105166124Srafan result = TRUE; 106166124Srafan } else if (make_db_name(filename, path, sizeof(filename))) { 107166124Srafan if (_nc_is_file_path(filename) && access(filename, R_OK) == 0) { 108166124Srafan result = TRUE; 109166124Srafan } 110166124Srafan } 111166124Srafan } 112166124Srafan#endif 113166124Srafan return result; 11497049Speter} 11597049Speter 116166124Srafanstatic void 117166124Srafandeschook(const char *cn, TERMTYPE *tp) 118166124Srafan/* display a description for the type */ 11950276Speter{ 120166124Srafan const char *desc; 121166124Srafan 122166124Srafan if ((desc = strrchr(tp->term_names, '|')) == 0 || *++desc == '\0') 123166124Srafan desc = "(No description)"; 124166124Srafan 125166124Srafan (void) printf("%-10s\t%s\n", cn, desc); 126166124Srafan} 127166124Srafan 128166124Srafan#if USE_TERMCAP 129166124Srafanstatic void 130166124Srafanshow_termcap(char *buffer, 131166124Srafan void (*hook) (const char *, TERMTYPE *tp)) 132166124Srafan{ 133166124Srafan TERMTYPE data; 134166124Srafan char *next = strchr(buffer, ':'); 135166124Srafan char *last; 136166124Srafan char *list = buffer; 137166124Srafan 138166124Srafan if (next) 139166124Srafan *next = '\0'; 140166124Srafan 141166124Srafan last = strrchr(buffer, '|'); 142166124Srafan if (last) 143166124Srafan ++last; 144166124Srafan 145166124Srafan data.term_names = strdup(buffer); 146166124Srafan while ((next = strtok(list, "|")) != 0) { 147166124Srafan if (next != last) 148166124Srafan hook(next, &data); 149166124Srafan list = 0; 15062449Speter } 151166124Srafan free(data.term_names); 15262449Speter} 153166124Srafan#endif 15450276Speter 155166124Srafanstatic int 156166124Srafantypelist(int eargc, char *eargv[], 157166124Srafan bool verbosity, 158166124Srafan void (*hook) (const char *, TERMTYPE *tp)) 159166124Srafan/* apply a function to each entry in given terminfo directories */ 160166124Srafan{ 161166124Srafan int i; 162166124Srafan 163166124Srafan for (i = 0; i < eargc; i++) { 164166124Srafan#if USE_DATABASE 165166124Srafan if (_nc_is_dir_path(eargv[i])) { 166184989Srafan char *cwd_buf = 0; 167166124Srafan DIR *termdir; 168166124Srafan DIRENT *subdir; 169166124Srafan 170166124Srafan if ((termdir = opendir(eargv[i])) == 0) { 171166124Srafan (void) fflush(stdout); 172166124Srafan (void) fprintf(stderr, 173166124Srafan "%s: can't open terminfo directory %s\n", 174166124Srafan _nc_progname, eargv[i]); 175166124Srafan return (EXIT_FAILURE); 176166124Srafan } else if (verbosity) 177166124Srafan (void) printf("#\n#%s:\n#\n", eargv[i]); 178166124Srafan 179166124Srafan while ((subdir = readdir(termdir)) != 0) { 180166124Srafan size_t len = NAMLEN(subdir); 181184989Srafan size_t cwd_len = len + strlen(eargv[i]) + 3; 182166124Srafan char name_1[PATH_MAX]; 183166124Srafan DIR *entrydir; 184166124Srafan DIRENT *entry; 185166124Srafan 186184989Srafan cwd_buf = typeRealloc(char, cwd_len, cwd_buf); 187184989Srafan if (cwd_buf == 0) { 188184989Srafan perror("realloc cwd_buf"); 189184989Srafan continue; 190184989Srafan } 191184989Srafan 192166124Srafan strncpy(name_1, subdir->d_name, len)[len] = '\0'; 193166124Srafan if (isDotname(name_1)) 194166124Srafan continue; 195166124Srafan 196184989Srafan (void) sprintf(cwd_buf, "%s/%.*s/", eargv[i], (int) len, name_1); 197184989Srafan if (chdir(cwd_buf) != 0) 198166124Srafan continue; 199166124Srafan 200166124Srafan entrydir = opendir("."); 201184989Srafan if (entrydir == 0) { 202184989Srafan perror(cwd_buf); 203184989Srafan continue; 204184989Srafan } 205166124Srafan while ((entry = readdir(entrydir)) != 0) { 206166124Srafan char name_2[PATH_MAX]; 207166124Srafan TERMTYPE lterm; 208166124Srafan char *cn; 209166124Srafan int status; 210166124Srafan 211166124Srafan len = NAMLEN(entry); 212166124Srafan strncpy(name_2, entry->d_name, len)[len] = '\0'; 213166124Srafan if (isDotname(name_2) || !_nc_is_file_path(name_2)) 214166124Srafan continue; 215166124Srafan 216166124Srafan status = _nc_read_file_entry(name_2, <erm); 217166124Srafan if (status <= 0) { 218166124Srafan (void) fflush(stdout); 219166124Srafan (void) fprintf(stderr, 220166124Srafan "%s: couldn't open terminfo file %s.\n", 221166124Srafan _nc_progname, name_2); 222166124Srafan return (EXIT_FAILURE); 223166124Srafan } 224166124Srafan 225166124Srafan /* only visit things once, by primary name */ 226166124Srafan cn = _nc_first_name(lterm.term_names); 227166124Srafan if (!strcmp(cn, name_2)) { 228166124Srafan /* apply the selected hook function */ 229166124Srafan (*hook) (cn, <erm); 230166124Srafan } 231166124Srafan _nc_free_termtype(<erm); 232166124Srafan } 233166124Srafan closedir(entrydir); 234166124Srafan } 235166124Srafan closedir(termdir); 236184989Srafan if (cwd_buf != 0) 237184989Srafan free(cwd_buf); 238166124Srafan } 239166124Srafan#if USE_HASHED_DB 240166124Srafan else { 241166124Srafan DB *capdbp; 242166124Srafan char filename[PATH_MAX]; 243166124Srafan 244166124Srafan if (make_db_name(filename, eargv[i], sizeof(filename))) { 245166124Srafan if ((capdbp = _nc_db_open(filename, FALSE)) != 0) { 246166124Srafan DBT key, data; 247166124Srafan int code; 248166124Srafan 249166124Srafan code = _nc_db_first(capdbp, &key, &data); 250166124Srafan while (code == 0) { 251166124Srafan TERMTYPE lterm; 252166124Srafan int used; 253166124Srafan char *have; 254166124Srafan char *cn; 255166124Srafan 256166124Srafan if (_nc_db_have_data(&key, &data, &have, &used)) { 257166124Srafan if (_nc_read_termtype(<erm, have, used) > 0) { 258166124Srafan /* only visit things once, by primary name */ 259166124Srafan cn = _nc_first_name(lterm.term_names); 260166124Srafan /* apply the selected hook function */ 261166124Srafan (*hook) (cn, <erm); 262166124Srafan _nc_free_termtype(<erm); 263166124Srafan } 264166124Srafan } 265166124Srafan code = _nc_db_next(capdbp, &key, &data); 266166124Srafan } 267166124Srafan 268166124Srafan _nc_db_close(capdbp); 269166124Srafan } 270166124Srafan } 271166124Srafan } 272166124Srafan#endif 273166124Srafan#endif 274166124Srafan#if USE_TERMCAP 275166124Srafan#if HAVE_BSD_CGETENT 276166124Srafan char *db_array[2]; 277166124Srafan char *buffer = 0; 278166124Srafan 279166124Srafan if (verbosity) 280166124Srafan (void) printf("#\n#%s:\n#\n", eargv[i]); 281166124Srafan 282166124Srafan db_array[0] = eargv[i]; 283166124Srafan db_array[1] = 0; 284166124Srafan 285166124Srafan if (cgetfirst(&buffer, db_array)) { 286166124Srafan show_termcap(buffer, hook); 287166124Srafan free(buffer); 288166124Srafan while (cgetnext(&buffer, db_array)) { 289166124Srafan show_termcap(buffer, hook); 290166124Srafan free(buffer); 291166124Srafan } 292166124Srafan } 293166124Srafan cgetclose(); 294166124Srafan#else 295166124Srafan /* scan termcap text-file only */ 296166124Srafan if (_nc_is_file_path(eargv[i])) { 297166124Srafan char buffer[2048]; 298166124Srafan FILE *fp; 299166124Srafan 300166124Srafan if ((fp = fopen(eargv[i], "r")) != 0) { 301166124Srafan while (fgets(buffer, sizeof(buffer), fp) != 0) { 302166124Srafan if (*buffer == '#') 303166124Srafan continue; 304166124Srafan if (isspace(*buffer)) 305166124Srafan continue; 306166124Srafan show_termcap(buffer, hook); 307166124Srafan } 308166124Srafan fclose(fp); 309166124Srafan } 310166124Srafan } 311166124Srafan#endif 312166124Srafan#endif 313166124Srafan } 314166124Srafan 315166124Srafan return (EXIT_SUCCESS); 316166124Srafan} 317166124Srafan 318166124Srafanstatic void 319166124Srafanusage(void) 320166124Srafan{ 321166124Srafan (void) fprintf(stderr, "usage: %s [-ahuUV] [-v n] [file...]\n", _nc_progname); 322166124Srafan ExitProgram(EXIT_FAILURE); 323166124Srafan} 324166124Srafan 32562449Speterint 32662449Spetermain(int argc, char *argv[]) 32762449Speter{ 328166124Srafan bool all_dirs = FALSE; 32962449Speter bool direct_dependencies = FALSE; 33062449Speter bool invert_dependencies = FALSE; 33162449Speter bool header = FALSE; 332176187Srafan char *report_file = 0; 333184989Srafan unsigned i; 33462449Speter int code; 335166124Srafan int this_opt, last_opt = '?'; 336166124Srafan int v_opt = 0; 33762449Speter 33897049Speter _nc_progname = _nc_rootname(argv[0]); 33950276Speter 340176187Srafan while ((this_opt = getopt(argc, argv, "0123456789ahu:vU:V")) != -1) { 341166124Srafan /* handle optional parameter */ 342166124Srafan if (isdigit(this_opt)) { 343166124Srafan switch (last_opt) { 344166124Srafan case 'v': 345166124Srafan v_opt = (this_opt - '0'); 346166124Srafan break; 347166124Srafan default: 348166124Srafan if (isdigit(last_opt)) 349166124Srafan v_opt *= 10; 350166124Srafan else 351166124Srafan v_opt = 0; 352166124Srafan v_opt += (this_opt - '0'); 353166124Srafan last_opt = this_opt; 354166124Srafan } 355166124Srafan continue; 356166124Srafan } 357166124Srafan switch (this_opt) { 358166124Srafan case 'a': 359166124Srafan all_dirs = TRUE; 360166124Srafan break; 36150276Speter case 'h': 36250276Speter header = TRUE; 36350276Speter break; 36450276Speter case 'u': 36550276Speter direct_dependencies = TRUE; 366176187Srafan report_file = optarg; 36750276Speter break; 36850276Speter case 'v': 369166124Srafan v_opt = 1; 37050276Speter break; 37150276Speter case 'U': 37250276Speter invert_dependencies = TRUE; 373176187Srafan report_file = optarg; 37450276Speter break; 37550276Speter case 'V': 37666963Speter puts(curses_version()); 37750276Speter ExitProgram(EXIT_SUCCESS); 37850276Speter default: 379166124Srafan usage(); 38050276Speter } 381166124Srafan } 382166124Srafan set_trace_level(v_opt); 38350276Speter 384176187Srafan if (report_file != 0) { 385176187Srafan if (freopen(report_file, "r", stdin) == 0) { 38650276Speter (void) fflush(stdout); 387176187Srafan fprintf(stderr, "%s: can't open %s\n", _nc_progname, report_file); 38850276Speter ExitProgram(EXIT_FAILURE); 38950276Speter } 39050276Speter 39150276Speter /* parse entries out of the source file */ 392176187Srafan _nc_set_source(report_file); 39362449Speter _nc_read_entry_source(stdin, 0, FALSE, FALSE, NULLHOOK); 39450276Speter } 39550276Speter 39650276Speter /* maybe we want a direct-dependency listing? */ 39762449Speter if (direct_dependencies) { 39862449Speter ENTRY *qp; 39950276Speter 400166124Srafan for_entry_list(qp) { 40162449Speter if (qp->nuses) { 402184989Srafan unsigned j; 40350276Speter 404166124Srafan (void) printf("%s:", _nc_first_name(qp->tterm.term_names)); 405166124Srafan for (j = 0; j < qp->nuses; j++) 406166124Srafan (void) printf(" %s", qp->uses[j].name); 407166124Srafan putchar('\n'); 408166124Srafan } 40962449Speter } 41050276Speter 41150276Speter ExitProgram(EXIT_SUCCESS); 41250276Speter } 41350276Speter 41450276Speter /* maybe we want a reverse-dependency listing? */ 41562449Speter if (invert_dependencies) { 41662449Speter ENTRY *qp, *rp; 41762449Speter int matchcount; 41850276Speter 41962449Speter for_entry_list(qp) { 42050276Speter matchcount = 0; 42162449Speter for_entry_list(rp) { 42250276Speter if (rp->nuses == 0) 42350276Speter continue; 42450276Speter 42550276Speter for (i = 0; i < rp->nuses; i++) 42662449Speter if (_nc_name_match(qp->tterm.term_names, 42797049Speter rp->uses[i].name, "|")) { 42850276Speter if (matchcount++ == 0) 42950276Speter (void) printf("%s:", 43097049Speter _nc_first_name(qp->tterm.term_names)); 43150276Speter (void) printf(" %s", 43297049Speter _nc_first_name(rp->tterm.term_names)); 43350276Speter } 43450276Speter } 43550276Speter if (matchcount) 43650276Speter putchar('\n'); 43750276Speter } 43850276Speter 43950276Speter ExitProgram(EXIT_SUCCESS); 44050276Speter } 44150276Speter 44250276Speter /* 44350276Speter * If we get this far, user wants a simple terminal type listing. 44450276Speter */ 44550276Speter if (optind < argc) { 44662449Speter code = typelist(argc - optind, argv + optind, header, deschook); 447166124Srafan } else if (all_dirs) { 448166124Srafan DBDIRS state; 449166124Srafan int offset; 450166124Srafan int pass; 451166124Srafan const char *path; 452166124Srafan char **eargv = 0; 45350276Speter 454166124Srafan code = EXIT_FAILURE; 455166124Srafan for (pass = 0; pass < 2; ++pass) { 456166124Srafan unsigned count = 0; 45750276Speter 458166124Srafan _nc_first_db(&state, &offset); 459166124Srafan while ((path = _nc_next_db(&state, &offset)) != 0) { 460166124Srafan if (!is_database(path)) { 461166124Srafan ; 462166124Srafan } else if (eargv != 0) { 463166124Srafan unsigned n; 464166124Srafan int found = FALSE; 46550276Speter 466166124Srafan /* eliminate duplicates */ 467166124Srafan for (n = 0; n < count; ++n) { 468166124Srafan if (!strcmp(path, eargv[n])) { 469166124Srafan found = TRUE; 470166124Srafan break; 471166124Srafan } 472166124Srafan } 473166124Srafan if (!found) { 474166124Srafan eargv[count] = strdup(path); 475166124Srafan ++count; 476166124Srafan } 477166124Srafan } else { 478166124Srafan ++count; 47950276Speter } 480166124Srafan } 481166124Srafan if (!pass) { 482166124Srafan eargv = typeCalloc(char *, count + 1); 483166124Srafan } else { 484166124Srafan code = typelist((int) count, eargv, header, deschook); 485166124Srafan while (count-- > 0) 486166124Srafan free(eargv[count]); 487166124Srafan free(eargv); 488166124Srafan } 489166124Srafan } 490166124Srafan } else { 491166124Srafan DBDIRS state; 492166124Srafan int offset; 493166124Srafan const char *path; 494166124Srafan char *eargv[3]; 495166124Srafan int count = 0; 49650276Speter 497166124Srafan _nc_first_db(&state, &offset); 498166124Srafan while ((path = _nc_next_db(&state, &offset)) != 0) { 499166124Srafan if (is_database(path)) { 500166124Srafan eargv[count++] = strdup(path); 501166124Srafan break; 50250276Speter } 50350276Speter } 504166124Srafan eargv[count] = 0; 505166124Srafan 506166124Srafan code = typelist(count, eargv, header, deschook); 507166124Srafan 508166124Srafan while (count-- > 0) 509166124Srafan free(eargv[count]); 51050276Speter } 511166124Srafan _nc_last_db(); 51250276Speter 513166124Srafan ExitProgram(code); 51450276Speter} 515