X-Git-Url: https://ncurses.scripts.mit.edu/?p=ncurses.git;a=blobdiff_plain;f=progs%2Ftic.c;h=53fa7225a65285cc6979c3037b08499fa4daccd1;hp=04ab3e528aba3ea7f971d08ceaa2eaf8e47092be;hb=ba39fbc2e0cee4681395df4079d9e61c27262132;hpb=292968cf29abc10835415a6352607b38ce7c9cbd diff --git a/progs/tic.c b/progs/tic.c index 04ab3e52..53fa7225 100644 --- a/progs/tic.c +++ b/progs/tic.c @@ -1,5 +1,5 @@ /**************************************************************************** - * Copyright (c) 1998-2010,2011 Free Software Foundation, Inc. * + * Copyright (c) 1998-2011,2012 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -43,9 +43,10 @@ #include #include +#include #include -MODULE_ID("$Id: tic.c,v 1.157 2011/12/31 21:11:59 tom Exp $") +MODULE_ID("$Id: tic.c,v 1.162 2012/02/22 23:59:45 tom Exp $") const char *_nc_progname = "tic"; @@ -221,7 +222,7 @@ write_it(ENTRY * ep) } *d = 0; if (strlen(result) < strlen(s)) - strcpy(s, result); + _nc_STRCPY(s, result, strlen(s) + 1); } } @@ -313,7 +314,7 @@ put_translate(int c) if ((up = strchr(namebuf, '#')) != 0 || (up = strchr(namebuf, '=')) != 0 || ((up = strchr(namebuf, '@')) != 0 && up[1] == '>')) { - (void) strcpy(suffix, up); + _nc_STRCPY(suffix, up, have); *up = '\0'; } @@ -476,25 +477,107 @@ open_tempfile(char *name) return result; } +static const char * +valid_db_path(const char *nominal) +{ + struct stat sb; +#if USE_HASHED_DB + char suffix[] = DBM_SUFFIX; + size_t need = strlen(nominal) + sizeof(suffix); + char *result = malloc(need); + + _nc_STRCPY(result, nominal, need); + if (strcmp(result + need - sizeof(suffix), suffix)) { + _nc_STRCAT(result, suffix, need); + } +#else + char *result = strdup(nominal); +#endif + + DEBUG(1, ("** stat(%s)", result)); + if (stat(result, &sb) >= 0) { +#if USE_HASHED_DB + if (!S_ISREG(sb.st_mode) + || access(result, R_OK | W_OK) != 0) { + DEBUG(1, ("...not a writable file")); + free(result); + result = 0; + } +#else + if (!S_ISDIR(sb.st_mode) + || access(result, R_OK | W_OK | X_OK) != 0) { + DEBUG(1, ("...not a writable directory")); + free(result); + result = 0; + } +#endif + } else { + /* check if parent is directory and is writable */ + unsigned leaf = _nc_pathlast(result); + + DEBUG(1, ("...not found")); + if (leaf) { + char save = result[leaf]; + result[leaf] = 0; + if (stat(result, &sb) >= 0 + && S_ISDIR(sb.st_mode) + && access(result, R_OK | W_OK | X_OK) == 0) { + result[leaf] = save; + } else { + DEBUG(1, ("...parent directory %s is not writable", result)); + free(result); + result = 0; + } + } else { + DEBUG(1, ("... no parent directory")); + free(result); + result = 0; + } + } + return result; +} + /* - * Show the databases that tic knows about. The location to which it writes is - * always the first one. If that is not writable, then tic errors out before - * reaching this function. + * Show the databases to which tic could write. The location to which it + * writes is always the first one. If none are writable, print an error + * message. */ static void -show_databases(void) +show_databases(const char *outdir) { - DBDIRS state; - int offset; - const char *path; + bool specific = (outdir != 0) || getenv("TERMINFO") != 0; + const char *result; + const char *tried = 0; + + if (outdir == 0) { + outdir = _nc_tic_dir(0); + } + if ((result = valid_db_path(outdir)) != 0) { + printf("%s\n", result); + } else { + tried = outdir; + } + + if ((outdir = _nc_home_terminfo())) { + if ((result = valid_db_path(outdir)) != 0) { + printf("%s\n", result); + } else if (!specific) { + tried = outdir; + } + } - _nc_first_db(&state, &offset); - while ((path = _nc_next_db(&state, &offset)) != 0) { - printf("%s\n", path); + /* + * If we can write in neither location, give an error message. + */ + if (tried) { + fflush(stdout); + fprintf(stderr, "%s: %s (no permission)\n", _nc_progname, tried); + ExitProgram(EXIT_FAILURE); } - _nc_last_db(); } +#define VtoTrace(opt) (unsigned) ((opt > 0) ? opt : (opt == 0)) + int main(int argc, char *argv[]) { @@ -586,8 +669,9 @@ main(int argc, char *argv[]) sortmode = S_TERMCAP; break; case 'D': - _nc_set_writedir(outdir); - show_databases(); + debug_level = VtoTrace(v_opt); + set_trace_level(debug_level); + show_databases(outdir); ExitProgram(EXIT_SUCCESS); break; case 'I': @@ -665,7 +749,7 @@ main(int argc, char *argv[]) last_opt = this_opt; } - debug_level = (unsigned) ((v_opt > 0) ? v_opt : (v_opt == 0)); + debug_level = VtoTrace(v_opt); set_trace_level(debug_level); if (_nc_tracing) { @@ -685,7 +769,8 @@ main(int argc, char *argv[]) */ if (namelst && (!infodump && !capdump)) { (void) fprintf(stderr, - "Sorry, -e can't be used without -I or -C\n"); + "%s: Sorry, -e can't be used without -I or -C\n", + _nc_progname); cleanup(namelst); ExitProgram(EXIT_FAILURE); } @@ -710,16 +795,19 @@ main(int argc, char *argv[]) if (access(termcap, F_OK) == 0) { /* file exists */ source_file = termcap; - } else if ((tmp_fp = open_tempfile(strcpy(my_tmpname, - "/tmp/XXXXXX"))) - != 0) { - source_file = my_tmpname; - fprintf(tmp_fp, "%s\n", termcap); - fclose(tmp_fp); - tmp_fp = open_input(source_file); - to_remove = source_file; } else { - failed("tmpnam"); + _nc_STRCPY(my_tmpname, + "/tmp/XXXXXX", + sizeof(my_tmpname)); + if ((tmp_fp = open_tempfile(my_tmpname)) != 0) { + source_file = my_tmpname; + fprintf(tmp_fp, "%s\n", termcap); + fclose(tmp_fp); + tmp_fp = open_input(source_file); + to_remove = source_file; + } else { + failed("tmpnam"); + } } } } else { @@ -1196,19 +1284,19 @@ check_keypad(TERMTYPE *tp) assert(strlen(show) < (MAX_KP * 4)); switch (kk) { case 0: - strcat(show, " ka1"); + _nc_STRCAT(show, " ka1", sizeof(show)); break; case 1: - strcat(show, " ka3"); + _nc_STRCAT(show, " ka3", sizeof(show)); break; case 2: - strcat(show, " kb2"); + _nc_STRCAT(show, " kb2", sizeof(show)); break; case 3: - strcat(show, " kc1"); + _nc_STRCAT(show, " kc1", sizeof(show)); break; case 4: - strcat(show, " kc3"); + _nc_STRCAT(show, " kc3", sizeof(show)); break; } } @@ -1223,15 +1311,15 @@ check_keypad(TERMTYPE *tp) VALID_STRING(key_c3)) { show[0] = '\0'; if (keypad_index(key_a1) >= 0) - strcat(show, " ka1"); + _nc_STRCAT(show, " ka1", sizeof(show)); if (keypad_index(key_a3) >= 0) - strcat(show, " ka3"); + _nc_STRCAT(show, " ka3", sizeof(show)); if (keypad_index(key_b2) >= 0) - strcat(show, " kb2"); + _nc_STRCAT(show, " kb2", sizeof(show)); if (keypad_index(key_c1) >= 0) - strcat(show, " kc1"); + _nc_STRCAT(show, " kc1", sizeof(show)); if (keypad_index(key_c3) >= 0) - strcat(show, " kc3"); + _nc_STRCAT(show, " kc3", sizeof(show)); if (*show != '\0') _nc_warning("vt100 keypad map incomplete:%s", show); }