#include #include #include #include #include #include #include int main(int argc, char *argv[]) { if (argc < 4) { fprintf(stderr, "Usage: parent [ ...]\n" " max_replacements: maximum number of replacements\n" " input/output: pairs of input and output files\n"); return -1; } if ((argc - 2) % 2 != 0) { fprintf(stderr, "Error: number of input/output files must be even (pairs of input/output)\n"); return -1; } const char *max_replacements_arg = argv[1]; int num_pairs = (argc - 2) / 2; pid_t *child_pids = malloc(num_pairs * sizeof(pid_t)); if (!child_pids) { perror("malloc failed"); return -1; } for (int i = 0; i < num_pairs; i++) { const char *input_file = argv[2 + i * 2]; const char *output_file = argv[2 + i * 2 + 1]; pid_t pid = fork(); if (pid < 0) { perror("fork failed"); // Wait for already started children for (int j = 0; j < i; j++) { waitpid(child_pids[j], NULL, 0); } free(child_pids); return -1; } if (pid == 0) { // Child process printf("Child %d (PID=%d) processing %s -> %s\n", i + 1, getpid(), input_file, output_file); execl("./task11", "task11", input_file, output_file, max_replacements_arg, (char *) NULL); // If exec returns, error happened fprintf(stderr, "Child %d: execl failed for %s: %s\n", i + 1, input_file, strerror(errno)); _exit(-1); } // Parent process child_pids[i] = pid; } printf("Parent process waiting for children...\n"); int ret_code = 0; for (int i = 0; i < num_pairs; i++) { int status; pid_t pid = waitpid(child_pids[i], &status, 0); if (pid < 0) { perror("waitpid failed"); continue; } if (WIFEXITED(status)) { int code = WEXITSTATUS(status); printf("Child %d (PID=%d) exited with code %d\n", i + 1, pid, code); if (code != 0) { ret_code = code; } } else if (WIFSIGNALED(status)) { printf("Child %d (PID=%d) terminated by signal %d\n", i + 1, pid, WTERMSIG(status)); } else { printf("Child %d (PID=%d) ended abnormally\n", i + 1, pid); } } free(child_pids); printf("All children finished\n"); return ret_code; }