static int do_start() { int sfd; int exit_status = EXIT_SUCCESS; catch_fatal_signals(); sfd = create_signal_fd(); for (int i = 0; i < num_processes; i++) { bench_process_t *p = processes + i; p->pid = ctrs_execvp_cb(&p->ctrs, -1 /* cpu */, 0 /* flags */, &setup_child, p, p->argv[0], p->argv); EXPECT(p->pid != -1); } run_state = RUN_STATE_RUNNING; while (run_state != RUN_STATE_EXIT) { struct pollfd pfd[] = { { sfd, POLLIN, 0 } }; EXPECT_ERRNO(poll(pfd, sizeof(pfd) / sizeof(*pfd), -1) != -1); if (pfd[0].revents & POLLIN) { struct signalfd_siginfo fdsi; EXPECT(read(sfd, &fdsi, sizeof(fdsi)) == sizeof(fdsi)); handle_signal(&fdsi); } } print_counters(stderr); for (int i = 0; i < num_processes; i++) { bench_process_t *p = processes + i; int status; EXPECT(waitpid(p->pid, &status, 0) != -1); if (WIFEXITED(status)) { if (WEXITSTATUS(status)) fprintf(stderr, "Child %i: Exit status %i\n", i, WEXITSTATUS(status)); exit_status = EXIT_FAILURE; } else if (WIFSIGNALED(status)) { if (WTERMSIG(status) != SIGTERM) fprintf(stderr, "Child %i: Unexpected exit signal: %i\n", i, WTERMSIG(status)); exit_status = EXIT_FAILURE; } else { fprintf(stderr, "Child %i: Unhandled exit status\n", i); exit_status = EXIT_FAILURE; } } return exit_status; }
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; }