temp_init::temp_init() { // First, choose a location for creating temporary files... const char *tem; // using the first match for any of the environment specs in listed order. if ( (tem = getenv(GROFF_TMPDIR_ENVVAR)) == NULL && (tem = getenv(TMPDIR_ENVVAR)) == NULL #if defined(__MSDOS__) || defined(_WIN32) // If we didn't find a match for either of the above // (which are preferred, regardless of the host operating system), // and we are hosted on either MS-Windows or MS-DOS, // then try the Microsoft conventions. && (tem = getenv(WIN32_TMPDIR_ENVVAR)) == NULL && (tem = getenv(MSDOS_TMPDIR_ENVVAR)) == NULL #endif ) // If we didn't find an environment spec fall back to this default. tem = DEFAULT_TMPDIR; size_t tem_len = strlen(tem); const char *tem_end = tem + tem_len - 1; int need_slash = strchr(DIR_SEPS, *tem_end) == NULL ? 1 : 0; char *tem2 = new char[tem_len + need_slash + 1]; strcpy(tem2, tem); if (need_slash) strcat(tem2, "/"); const char *tem3 = TMPFILE_PREFIX_LONG; if (file_name_max(tem2) <= 14) { tem3 = TMPFILE_PREFIX_SHORT; use_short_postfix = 1; } tmpfile_prefix_len = tem_len + need_slash + strlen(tem3); tmpfile_prefix = new char[tmpfile_prefix_len + 1]; strcpy(tmpfile_prefix, tem2); strcat(tmpfile_prefix, tem3); a_delete tem2; }
int main(int argc, char **argv) { program_name = argv[0]; static char stderr_buf[BUFSIZ]; setbuf(stderr, stderr_buf); const char *base_name = 0; typedef int (*parser_t)(const char *); parser_t parser = do_file; const char *directory = 0; const char *foption = 0; int opt; static const struct option long_options[] = { { "help", no_argument, 0, CHAR_MAX + 1 }, { "version", no_argument, 0, 'v' }, { NULL, 0, 0, 0 } }; while ((opt = getopt_long(argc, argv, "c:o:h:i:k:l:t:n:c:d:f:vw", long_options, NULL)) != EOF) switch (opt) { case 'c': common_words_file = optarg; break; case 'd': directory = optarg; break; case 'f': foption = optarg; break; case 'h': check_integer_arg('h', optarg, 1, &hash_table_size); if (!is_prime(hash_table_size)) { while (!is_prime(++hash_table_size)) ; warning("%1 not prime: using %2 instead", optarg, hash_table_size); } break; case 'i': ignore_fields = optarg; break; case 'k': check_integer_arg('k', optarg, 1, &max_keys_per_item); break; case 'l': check_integer_arg('l', optarg, 0, &shortest_len); break; case 'n': check_integer_arg('n', optarg, 0, &n_ignore_words); break; case 'o': base_name = optarg; break; case 't': check_integer_arg('t', optarg, 1, &truncate_len); break; case 'w': parser = do_whole_file; break; case 'v': printf("GNU indxbib (groff) version %s\n", Version_string); exit(0); break; case CHAR_MAX + 1: // --help usage(stdout); exit(0); break; case '?': usage(stderr); exit(1); break; default: assert(0); break; } if (optind >= argc && foption == 0) fatal("no files and no -f option"); if (!directory) { char *path = get_cwd(); store_filename(path); a_delete path; } else store_filename(directory); init_hash_table(); store_filename(common_words_file); store_filename(ignore_fields); key_buffer = new char[truncate_len]; read_common_words_file(); if (!base_name) base_name = optind < argc ? argv[optind] : DEFAULT_INDEX_NAME; const char *p = strrchr(base_name, DIR_SEPS[0]), *p1; const char *sep = &DIR_SEPS[1]; while (*sep) { p1 = strrchr(base_name, *sep); if (p1 && (!p || p1 > p)) p = p1; sep++; } size_t name_max; if (p) { char *dir = strsave(base_name); dir[p - base_name] = '\0'; name_max = file_name_max(dir); a_delete dir; } else name_max = file_name_max("."); const char *filename = p ? p + 1 : base_name; if (strlen(filename) + sizeof(INDEX_SUFFIX) - 1 > name_max) fatal("`%1.%2' is too long for a filename", filename, INDEX_SUFFIX); if (p) { p++; temp_index_file = new char[p - base_name + sizeof(TEMP_INDEX_TEMPLATE)]; memcpy(temp_index_file, base_name, p - base_name); strcpy(temp_index_file + (p - base_name), TEMP_INDEX_TEMPLATE); } else { temp_index_file = strsave(TEMP_INDEX_TEMPLATE); } catch_fatal_signals(); int fd = mkstemp(temp_index_file); if (fd < 0) fatal("can't create temporary index file: %1", strerror(errno)); indxfp = fdopen(fd, FOPEN_WB); if (indxfp == 0) fatal("fdopen failed"); if (fseek(indxfp, sizeof(index_header), 0) < 0) fatal("can't seek past index header: %1", strerror(errno)); int failed = 0; if (foption) { FILE *fp = stdin; if (strcmp(foption, "-") != 0) { errno = 0; fp = fopen(foption, "r"); if (!fp) fatal("can't open `%1': %2", foption, strerror(errno)); } string path; int lineno = 1; for (;;) { int c; for (c = getc(fp); c != '\n' && c != EOF; c = getc(fp)) { if (c == '\0') error_with_file_and_line(foption, lineno, "nul character in pathname ignored"); else path += c; } if (path.length() > 0) { path += '\0'; if (!(*parser)(path.contents())) failed = 1; path.clear(); } if (c == EOF) break; lineno++; } if (fp != stdin) fclose(fp); } for (int i = optind; i < argc; i++) if (!(*parser)(argv[i])) failed = 1; write_hash_table(); if (fclose(indxfp) < 0) fatal("error closing temporary index file: %1", strerror(errno)); char *index_file = new char[strlen(base_name) + sizeof(INDEX_SUFFIX)]; strcpy(index_file, base_name); strcat(index_file, INDEX_SUFFIX); #ifdef HAVE_RENAME #ifdef __EMX__ if (access(index_file, R_OK) == 0) unlink(index_file); #endif /* __EMX__ */ if (rename(temp_index_file, index_file) < 0) { #ifdef __MSDOS__ // RENAME could fail on plain MSDOS filesystems because // INDEX_FILE is an invalid filename, e.g. it has multiple dots. char *fname = p ? index_file + (p - base_name) : 0; char *dot = 0; // Replace the dot with an underscore and try again. if (fname && (dot = strchr(fname, '.')) != 0 && strcmp(dot, INDEX_SUFFIX) != 0) *dot = '_'; if (rename(temp_index_file, index_file) < 0) #endif fatal("can't rename temporary index file: %1", strerror(errno)); } #else /* not HAVE_RENAME */ ignore_fatal_signals(); if (unlink(index_file) < 0) { if (errno != ENOENT) fatal("can't unlink `%1': %2", index_file, strerror(errno)); } if (link(temp_index_file, index_file) < 0) fatal("can't link temporary index file: %1", strerror(errno)); if (unlink(temp_index_file) < 0) fatal("can't unlink temporary index file: %1", strerror(errno)); #endif /* not HAVE_RENAME */ temp_index_file = 0; return failed; }