/* * Wait for one child process to exit; when it does, unlink it from * the list of executing child processes, and return it. */ static struct fsck_instance *wait_one(int flags) { int status; int sig; struct fsck_instance *inst, *inst2, *prev; pid_t pid; if (!instance_list) return NULL; if (noexecute) { inst = instance_list; prev = 0; #ifdef RANDOM_DEBUG while (inst->next && (random() & 1)) { prev = inst; inst = inst->next; } #endif inst->exit_status = 0; goto ret_inst; } /* * gcc -Wall fails saving throw against stupidity * (inst and prev are thought to be uninitialized variables) */ inst = prev = NULL; do { pid = waitpid(-1, &status, flags); if (cancel_requested && !kill_sent) { kill_all(SIGTERM); kill_sent++; } if ((pid == 0) && (flags & WNOHANG)) return NULL; if (pid < 0) { if ((errno == EINTR) || (errno == EAGAIN)) continue; if (errno == ECHILD) { bb_error_msg("wait: no more child process?!?"); return NULL; } perror("wait"); continue; } for (prev = 0, inst = instance_list; inst; prev = inst, inst = inst->next) { if (inst->pid == pid) break; } } while (!inst); if (WIFEXITED(status)) status = WEXITSTATUS(status); else if (WIFSIGNALED(status)) { sig = WTERMSIG(status); if (sig == SIGINT) { status = EXIT_UNCORRECTED; } else { printf("Warning... %s for device %s exited " "with signal %d.\n", inst->prog, inst->device, sig); status = EXIT_ERROR; } } else { printf("%s %s: status is %x, should never happen.\n", inst->prog, inst->device, status); status = EXIT_ERROR; } inst->exit_status = status; if (progress && (inst->flags & FLAG_PROGRESS) && !progress_active()) { for (inst2 = instance_list; inst2; inst2 = inst2->next) { if (inst2->flags & FLAG_DONE) continue; if (strcmp(inst2->type, "ext2") && strcmp(inst2->type, "ext3")) continue; /* * If we've just started the fsck, wait a tiny * bit before sending the kill, to give it * time to set up the signal handler */ if (inst2->start_time < time(0)+2) { if (fork() == 0) { sleep(1); kill(inst2->pid, SIGUSR1); exit(0); } } else kill(inst2->pid, SIGUSR1); inst2->flags |= FLAG_PROGRESS; break; } } ret_inst: if (prev) prev->next = inst->next; else instance_list = inst->next; if (verbose > 1) printf("Finished with %s (exit status %d)\n", inst->device, inst->exit_status); num_running--; return inst; }
/* * Execute a particular fsck program, and link it into the list of * child processes we are waiting for. */ static int execute(const char *type, const char *device, const char *mntpt, int interactive) { char *s, *argv[80]; char *prog; int argc, i; struct fsck_instance *inst, *p; pid_t pid; inst = malloc(sizeof(struct fsck_instance)); if (!inst) return ENOMEM; memset(inst, 0, sizeof(struct fsck_instance)); prog = xasprintf("fsck.%s", type); argv[0] = prog; argc = 1; for (i=0; i <num_args; i++) argv[argc++] = string_copy(args[i]); if (progress && !progress_active()) { if ((strcmp(type, "ext2") == 0) || (strcmp(type, "ext3") == 0)) { char tmp[80]; snprintf(tmp, 80, "-C%d", progress_fd); argv[argc++] = string_copy(tmp); inst->flags |= FLAG_PROGRESS; } } argv[argc++] = string_copy(device); argv[argc] = 0; s = find_fsck(prog); if (s == NULL) { bb_error_msg("%s: not found", prog); return ENOENT; } if (verbose || noexecute) { printf("[%s (%d) -- %s] ", s, num_running, mntpt ? mntpt : device); for (i=0; i < argc; i++) printf("%s ", argv[i]); puts(""); } /* Fork and execute the correct program. */ if (noexecute) pid = -1; else if ((pid = fork()) < 0) { perror("fork"); return errno; } else if (pid == 0) { if (!interactive) close(0); (void) execv(s, argv); bb_perror_msg_and_die("%s", argv[0]); } for (i = 1; i < argc; i++) free(argv[i]); free(s); inst->pid = pid; inst->prog = prog; inst->type = string_copy(type); inst->device = string_copy(device); inst->base_device = base_device(device); inst->start_time = time(0); inst->next = NULL; /* * Find the end of the list, so we add the instance on at the end. */ for (p = instance_list; p && p->next; p = p->next); if (p) p->next = inst; else instance_list = inst; return 0; }
static int execute(const char *type, const char *device, const char *mntpt, int interactive) { char *s, *argv[80], prog[80]; int argc, i; struct fsck_instance *inst, *p; pid_t pid; inst = malloc(sizeof(struct fsck_instance)); if (!inst) return ENOMEM; memset(inst, 0, sizeof(struct fsck_instance)); sprintf(prog, "fsck.%s", type); argv[0] = string_copy(prog); argc = 1; for (i=0; i <num_args; i++) argv[argc++] = string_copy(args[i]); if (progress) { if ((strcmp(type, "ext2") == 0) || (strcmp(type, "ext3") == 0) || (strcmp(type, "ext4") == 0) || (strcmp(type, "ext4dev") == 0)) { char tmp[80]; tmp[0] = 0; if (!progress_active()) { snprintf(tmp, 80, "-C%d", progress_fd); inst->flags |= FLAG_PROGRESS; } else if (progress_fd) snprintf(tmp, 80, "-C%d", progress_fd * -1); if (tmp[0]) argv[argc++] = string_copy(tmp); } } argv[argc++] = string_copy(device); argv[argc] = 0; s = find_fsck(prog); if (s == NULL) { fprintf(stderr, _("fsck: %s: not found\n"), prog); free(inst); return ENOENT; } if (verbose || noexecute) { printf("[%s (%d) -- %s] ", s, num_running, mntpt ? mntpt : device); for (i=0; i < argc; i++) printf("%s ", argv[i]); printf("\n"); } if (noexecute) pid = -1; else if ((pid = fork()) < 0) { perror("fork"); free(inst); return errno; } else if (pid == 0) { if (!interactive) close(0); (void) execv(s, argv); perror(argv[0]); free(inst); exit(EXIT_ERROR); } for (i=0; i < argc; i++) free(argv[i]); inst->pid = pid; inst->prog = string_copy(prog); inst->type = string_copy(type); inst->device = string_copy(device); inst->base_device = base_device(device); inst->start_time = time(0); inst->next = NULL; for (p = instance_list; p && p->next; p = p->next); if (p) p->next = inst; else instance_list = inst; return 0; }
static struct fsck_instance *wait_one(int flags) { int status; int sig; struct fsck_instance *inst, *inst2, *prev; pid_t pid; if (!instance_list) return NULL; if (noexecute) { inst = instance_list; prev = 0; #ifdef RANDOM_DEBUG while (inst->next && (random() & 1)) { prev = inst; inst = inst->next; } #endif inst->exit_status = 0; goto ret_inst; } inst = prev = NULL; do { pid = waitpid(-1, &status, flags); if (cancel_requested && !kill_sent) { kill_all(SIGTERM); kill_sent++; } if ((pid == 0) && (flags & WNOHANG)) return NULL; if (pid < 0) { if ((errno == EINTR) || (errno == EAGAIN)) continue; if (errno == ECHILD) { fprintf(stderr, _("%s: wait: No more child process?!?\n"), progname); return NULL; } perror("wait"); continue; } for (prev = 0, inst = instance_list; inst; prev = inst, inst = inst->next) { if (inst->pid == pid) break; } } while (!inst); if (WIFEXITED(status)) status = WEXITSTATUS(status); else if (WIFSIGNALED(status)) { sig = WTERMSIG(status); if (sig == SIGINT) { status = EXIT_UNCORRECTED; } else { printf(_("Warning... %s for device %s exited " "with signal %d.\n"), inst->prog, inst->device, sig); status = EXIT_ERROR; } } else { printf(_("%s %s: status is %x, should never happen.\n"), inst->prog, inst->device, status); status = EXIT_ERROR; } inst->exit_status = status; inst->flags |= FLAG_DONE; if (progress && (inst->flags & FLAG_PROGRESS) && !progress_active()) { for (inst2 = instance_list; inst2; inst2 = inst2->next) { if (inst2->flags & FLAG_DONE) continue; if (strcmp(inst2->type, "ext2") && strcmp(inst2->type, "ext3") && strcmp(inst2->type, "ext4") && strcmp(inst2->type, "ext4dev")) continue; if (inst2->start_time < time(0)+2) { if (fork() == 0) { sleep(1); kill(inst2->pid, SIGUSR1); exit(0); } } else kill(inst2->pid, SIGUSR1); inst2->flags |= FLAG_PROGRESS; break; } } ret_inst: if (prev) prev->next = inst->next; else instance_list = inst->next; if (verbose > 1) printf(_("Finished with %s (exit status %d)\n"), inst->device, inst->exit_status); num_running--; return inst; }
/* * Wait for one child process to exit; when it does, unlink it from * the list of executing child processes, and return it. */ static struct fsck_instance *wait_one(NOARGS) { int status; int sig; struct fsck_instance *inst, *inst2, *prev; pid_t pid; if (!instance_list) return NULL; if (noexecute) { inst = instance_list; instance_list = inst->next; inst->exit_status = 0; return(inst); } /* * gcc -Wall fails saving throw against stupidity * (inst and prev are thought to be uninitialized variables) */ inst = prev = NULL; do { pid = wait(&status); if (pid < 0) { if ((errno == EINTR) || (errno == EAGAIN)) continue; if (errno == ECHILD) { fprintf(stderr, _("%s: wait: No more child process?!?\n"), progname); return NULL; } perror("wait"); continue; } for (prev = 0, inst = instance_list; inst; prev = inst, inst = inst->next) { if (inst->pid == pid) break; } } while (!inst); if (WIFEXITED(status)) status = WEXITSTATUS(status); else if (WIFSIGNALED(status)) { sig = WTERMSIG(status); if (sig == SIGINT) { status = EXIT_UNCORRECTED; } else { printf(_("Warning... %s for device %s exited " "with signal %d.\n"), inst->prog, inst->device, sig); status = EXIT_ERROR; } } else { printf(_("%s %s: status is %x, should never happen.\n"), inst->prog, inst->device, status); status = EXIT_ERROR; } inst->exit_status = status; if (prev) prev->next = inst->next; else instance_list = inst->next; if (progress && (inst->flags & FLAG_PROGRESS) && !progress_active()) { for (inst2 = instance_list; inst2; inst2 = inst2->next) { if (inst2->flags & FLAG_DONE) continue; if (strcmp(inst2->type, "ext2") && strcmp(inst2->type, "ext3")) continue; /* * If we've just started the fsck, wait a tiny * bit before sending the kill, to give it * time to set up the signal handler */ if (inst2->start_time < time(0)+2) { if (fork() == 0) { sleep(1); kill(inst2->pid, SIGUSR1); exit(0); } } else kill(inst2->pid, SIGUSR1); inst2->flags |= FLAG_PROGRESS; break; } } return inst; }