1/**************************************************************************** 2 * Copyright (c) 1998-2002,2005 Free Software Foundation, Inc. * 3 * * 4 * Permission is hereby granted, free of charge, to any person obtaining a * 5 * copy of this software and associated documentation files (the * 6 * "Software"), to deal in the Software without restriction, including * 7 * without limitation the rights to use, copy, modify, merge, publish, * 8 * distribute, distribute with modifications, sublicense, and/or sell * 9 * copies of the Software, and to permit persons to whom the Software is * 10 * furnished to do so, subject to the following conditions: * 11 * * 12 * The above copyright notice and this permission notice shall be included * 13 * in all copies or substantial portions of the Software. * 14 * * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * 16 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * 17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * 18 * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * 19 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * 20 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * 21 * THE USE OR OTHER DEALINGS IN THE SOFTWARE. * 22 * * 23 * Except as contained in this notice, the name(s) of the above copyright * 24 * holders shall not be used in advertising or otherwise to promote the * 25 * sale, use or other dealings in this Software without prior written * 26 * authorization. * 27 ****************************************************************************/ 28 29/**************************************************************************** 30 * Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 * 31 * and: Eric S. Raymond <esr@snark.thyrsus.com> * 32 * and: Thomas E. Dickey 1996-on * 33 ****************************************************************************/ 34 35/* 36 * toe.c --- table of entries report generator 37 * 38 */ 39 40#include <progs.priv.h> 41 42#include <sys/stat.h> 43 44#include <dump_entry.h> 45 46MODULE_ID("$Id: toe.c,v 1.29 2005/09/25 00:39:43 tom Exp $") 47 48#define isDotname(name) (!strcmp(name, ".") || !strcmp(name, "..")) 49 50const char *_nc_progname; 51 52static int typelist(int eargc, char *eargv[], bool, 53 void (*)(const char *, TERMTYPE *)); 54static void deschook(const char *, TERMTYPE *); 55 56#if NO_LEAKS 57#undef ExitProgram 58static void 59ExitProgram(int code) GCC_NORETURN; 60 static void ExitProgram(int code) 61{ 62 _nc_free_entries(_nc_head); 63 _nc_leaks_dump_entry(); 64 _nc_free_and_exit(code); 65} 66#endif 67 68static bool 69is_a_file(char *path) 70{ 71 struct stat sb; 72 return (stat(path, &sb) == 0 73 && (sb.st_mode & S_IFMT) == S_IFREG); 74} 75 76static bool 77is_a_directory(char *path) 78{ 79 struct stat sb; 80 return (stat(path, &sb) == 0 81 && (sb.st_mode & S_IFMT) == S_IFDIR); 82} 83 84static char * 85get_directory(char *path) 86{ 87 if (path != 0) { 88 if (!is_a_directory(path) 89 || access(path, R_OK | X_OK) != 0) 90 path = 0; 91 } 92 return path; 93} 94 95int 96main(int argc, char *argv[]) 97{ 98 bool direct_dependencies = FALSE; 99 bool invert_dependencies = FALSE; 100 bool header = FALSE; 101 int i, c; 102 int code; 103 104 _nc_progname = _nc_rootname(argv[0]); 105 106 while ((c = getopt(argc, argv, "huv:UV")) != EOF) 107 switch (c) { 108 case 'h': 109 header = TRUE; 110 break; 111 case 'u': 112 direct_dependencies = TRUE; 113 break; 114 case 'v': 115 set_trace_level(atoi(optarg)); 116 break; 117 case 'U': 118 invert_dependencies = TRUE; 119 break; 120 case 'V': 121 puts(curses_version()); 122 ExitProgram(EXIT_SUCCESS); 123 default: 124 (void) fprintf(stderr, "usage: toe [-huUV] [-v n] [file...]\n"); 125 ExitProgram(EXIT_FAILURE); 126 } 127 128 if (direct_dependencies || invert_dependencies) { 129 if (freopen(argv[optind], "r", stdin) == 0) { 130 (void) fflush(stdout); 131 fprintf(stderr, "%s: can't open %s\n", _nc_progname, argv[optind]); 132 ExitProgram(EXIT_FAILURE); 133 } 134 135 /* parse entries out of the source file */ 136 _nc_set_source(argv[optind]); 137 _nc_read_entry_source(stdin, 0, FALSE, FALSE, NULLHOOK); 138 } 139 140 /* maybe we want a direct-dependency listing? */ 141 if (direct_dependencies) { 142 ENTRY *qp; 143 144 for_entry_list(qp) { 145 if (qp->nuses) { 146 int j; 147 148 (void) printf("%s:", _nc_first_name(qp->tterm.term_names)); 149 for (j = 0; j < qp->nuses; j++) 150 (void) printf(" %s", qp->uses[j].name); 151 putchar('\n'); 152 } 153 } 154 155 ExitProgram(EXIT_SUCCESS); 156 } 157 158 /* maybe we want a reverse-dependency listing? */ 159 if (invert_dependencies) { 160 ENTRY *qp, *rp; 161 int matchcount; 162 163 for_entry_list(qp) { 164 matchcount = 0; 165 for_entry_list(rp) { 166 if (rp->nuses == 0) 167 continue; 168 169 for (i = 0; i < rp->nuses; i++) 170 if (_nc_name_match(qp->tterm.term_names, 171 rp->uses[i].name, "|")) { 172 if (matchcount++ == 0) 173 (void) printf("%s:", 174 _nc_first_name(qp->tterm.term_names)); 175 (void) printf(" %s", 176 _nc_first_name(rp->tterm.term_names)); 177 } 178 } 179 if (matchcount) 180 putchar('\n'); 181 } 182 183 ExitProgram(EXIT_SUCCESS); 184 } 185 186 /* 187 * If we get this far, user wants a simple terminal type listing. 188 */ 189 if (optind < argc) { 190 code = typelist(argc - optind, argv + optind, header, deschook); 191 } else { 192 char *home, *eargv[3]; 193 char personal[PATH_MAX]; 194 int j; 195 196 j = 0; 197 if ((eargv[j] = get_directory(getenv("TERMINFO"))) != 0) { 198 j++; 199 } else { 200 if ((home = getenv("HOME")) != 0) { 201 (void) sprintf(personal, PRIVATE_INFO, home); 202 if ((eargv[j] = get_directory(personal)) != 0) 203 j++; 204 } 205 if ((eargv[j] = get_directory(strcpy(personal, TERMINFO))) != 0) 206 j++; 207 } 208 eargv[j] = 0; 209 210 code = typelist(j, eargv, header, deschook); 211 } 212 213 ExitProgram(code); 214} 215 216static void 217deschook(const char *cn, TERMTYPE * tp) 218/* display a description for the type */ 219{ 220 const char *desc; 221 222 if ((desc = strrchr(tp->term_names, '|')) == 0) 223 desc = "(No description)"; 224 else 225 ++desc; 226 227 (void) printf("%-10s\t%s\n", cn, desc); 228} 229 230static int 231typelist(int eargc, char *eargv[], 232 bool verbosity, 233 void (*hook) (const char *, TERMTYPE * tp)) 234/* apply a function to each entry in given terminfo directories */ 235{ 236 int i; 237 238 for (i = 0; i < eargc; i++) { 239 DIR *termdir; 240 DIRENT *subdir; 241 242 if ((termdir = opendir(eargv[i])) == 0) { 243 (void) fflush(stdout); 244 (void) fprintf(stderr, 245 "%s: can't open terminfo directory %s\n", 246 _nc_progname, eargv[i]); 247 return (EXIT_FAILURE); 248 } else if (verbosity) 249 (void) printf("#\n#%s:\n#\n", eargv[i]); 250 251 while ((subdir = readdir(termdir)) != 0) { 252 size_t len = NAMLEN(subdir); 253 char buf[PATH_MAX]; 254 char name_1[PATH_MAX]; 255 DIR *entrydir; 256 DIRENT *entry; 257 258 strncpy(name_1, subdir->d_name, len)[len] = '\0'; 259 if (isDotname(name_1)) 260 continue; 261 262 (void) sprintf(buf, "%s/%s/", eargv[i], name_1); 263 if (chdir(buf) != 0) 264 continue; 265 266 entrydir = opendir("."); 267 while ((entry = readdir(entrydir)) != 0) { 268 char name_2[PATH_MAX]; 269 TERMTYPE lterm; 270 char *cn; 271 int status; 272 273 len = NAMLEN(entry); 274 strncpy(name_2, entry->d_name, len)[len] = '\0'; 275 if (isDotname(name_2) || !is_a_file(name_2)) 276 continue; 277 278 status = _nc_read_file_entry(name_2, <erm); 279 if (status <= 0) { 280 (void) fflush(stdout); 281 (void) fprintf(stderr, 282 "toe: couldn't open terminfo file %s.\n", 283 name_2); 284 return (EXIT_FAILURE); 285 } 286 287 /* only visit things once, by primary name */ 288 cn = _nc_first_name(lterm.term_names); 289 if (!strcmp(cn, name_2)) { 290 /* apply the selected hook function */ 291 (*hook) (cn, <erm); 292 } 293 if (lterm.term_names) { 294 free(lterm.term_names); 295 lterm.term_names = 0; 296 } 297 if (lterm.str_table) { 298 free(lterm.str_table); 299 lterm.str_table = 0; 300 } 301 } 302 closedir(entrydir); 303 } 304 closedir(termdir); 305 } 306 307 return (EXIT_SUCCESS); 308} 309