Ejemplo n.º 1
0
/*
 * 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;
}
Ejemplo n.º 2
0
/*
 * 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;
}
Ejemplo n.º 3
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;
}
Ejemplo n.º 4
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;
}
Ejemplo n.º 5
0
/*
 * 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;
}