Пример #1
0
int kill_child_and_collect(int pid)
{
	int status;

	status = kill_process(pid);
	if (status != -ESRCH)
		return status;

	if (collect_child(pid, &status, 0))
		return -ECHILD;

	return status;
}
Пример #2
0
static int
resolve_conflict(struct da *da, int parent, unsigned char c)
{
  int left;
  struct resolve_stat rs;
  /* collect */
  collect_child(da, &rs, parent, c);
  /* find */
  left = find_place(da, &rs);
  /*printf("left=%d\n", left);*/
  /* move */
  move_children(da, &rs, parent, left);
  return left + c;
}
Пример #3
0
/*
 * Bring the system up single user.
 */
static state_func_t
single_user(void)
{
	pid_t pid, wpid;
	int status;
	sigset_t mask;
	const char *shell;
	char *argv[2];
#ifdef SECURE
	struct ttyent *typ;
	struct passwd *pp;
	static const char banner[] =
		"Enter root password, or ^D to go multi-user\n";
	char *clear, *password;
#endif
#ifdef DEBUGSHELL
	char altshell[128];
#endif

	if (Reboot) {
		/* Instead of going single user, let's reboot the machine */
		sync();
		reboot(howto);
		_exit(0);
	}

	shell = get_shell();

	if ((pid = fork()) == 0) {
		/*
		 * Start the single user session.
		 */
		open_console();

#ifdef SECURE
		/*
		 * Check the root password.
		 * We don't care if the console is 'on' by default;
		 * it's the only tty that can be 'off' and 'secure'.
		 */
		typ = getttynam("console");
		pp = getpwnam("root");
		if (typ && (typ->ty_status & TTY_SECURE) == 0 &&
		    pp && *pp->pw_passwd) {
			write_stderr(banner);
			for (;;) {
				clear = getpass("Password:"******"single-user login failed\n");
			}
		}
		endttyent();
		endpwent();
#endif /* SECURE */

#ifdef DEBUGSHELL
		{
			char *cp = altshell;
			int num;

#define	SHREQUEST "Enter full pathname of shell or RETURN for "
			write_stderr(SHREQUEST);
			write_stderr(shell);
			write_stderr(": ");
			while ((num = read(STDIN_FILENO, cp, 1)) != -1 &&
			    num != 0 && *cp != '\n' && cp < &altshell[127])
				cp++;
			*cp = '\0';
			if (altshell[0] != '\0')
				shell = altshell;
		}
#endif /* DEBUGSHELL */

		/*
		 * Unblock signals.
		 * We catch all the interesting ones,
		 * and those are reset to SIG_DFL on exec.
		 */
		sigemptyset(&mask);
		sigprocmask(SIG_SETMASK, &mask, (sigset_t *) 0);

		/*
		 * Fire off a shell.
		 * If the default one doesn't work, try the Bourne shell.
		 */

		char name[] = "-sh";

		argv[0] = name;
		argv[1] = 0;
		execv(shell, argv);
		emergency("can't exec %s for single user: %m", shell);
		execv(_PATH_BSHELL, argv);
		emergency("can't exec %s for single user: %m", _PATH_BSHELL);
		sleep(STALL_TIMEOUT);
		_exit(1);
	}

	if (pid == -1) {
		/*
		 * We are seriously hosed.  Do our best.
		 */
		emergency("can't fork single-user shell, trying again");
		while (waitpid(-1, (int *) 0, WNOHANG) > 0)
			continue;
		return (state_func_t) single_user;
	}

	requested_transition = 0;
	do {
		if ((wpid = waitpid(-1, &status, WUNTRACED)) != -1)
			collect_child(wpid);
		if (wpid == -1) {
			if (errno == EINTR)
				continue;
			warning("wait for single-user shell failed: %m; restarting");
			return (state_func_t) single_user;
		}
		if (wpid == pid && WIFSTOPPED(status)) {
			warning("init: shell stopped, restarting\n");
			kill(pid, SIGCONT);
			wpid = -1;
		}
	} while (wpid != pid && !requested_transition);

	if (requested_transition)
		return (state_func_t) requested_transition;

	if (!WIFEXITED(status)) {
		if (WTERMSIG(status) == SIGKILL) {
			/*
			 *  reboot(8) killed shell?
			 */
			warning("single user shell terminated.");
			sleep(STALL_TIMEOUT);
			_exit(0);
		} else {
			warning("single user shell terminated, restarting");
			return (state_func_t) single_user;
		}
	}

	runcom_mode = FASTBOOT;
	return (state_func_t) runcom;
}
Пример #4
0
int main(int argc, char **argv)
{
	int fd = -1, fd_gate, fd_locked = false, fd_gate_locked = false;
	int exit_val = EXIT_SUCCESS, ret_val;
	pid_t c_pid = -1;

	if(3 > argc)
		exit(invokation(argv[0]));

	/* first lock the gate, may be the archive isn't created yet */
	if(-1 == (fd_gate = open(".arflockgate", O_WRONLY|O_CREAT, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)))
	{
		perror(__FILE__ ", " mkstr(__LINE__) ", open() gate" );
		exit(EXIT_FAILURE);
	}
	ret_val = sprintf(pid_buf, "%i\n", (int)getpid());
	if(ret_val != write(fd_gate, pid_buf, ret_val)) {
		/* nothing we can do about, it's only nice to put our pid inside */
	}

	/* register alarm handler for timeout */
	if(SIG_ERR == signal(SIGALRM, sig_alarm))
	{
		perror(__FILE__ ", " mkstr(__LINE__) ", signal()");
		exit(EXIT_FAILURE);
	}

	/* get lock on the gate */
	timeout = DEFAULT_TIMEOUT;
	if(!gime_lock(fd_gate))
	{
		exit_val = EXIT_FAILURE;
		goto BAIL_OUT;
	}
	fd_gate_locked = true;

	/* open the lib */
	fd = open(argv[1], O_WRONLY);
	if(fd != -1)
	{
		/* lock the lib */
		timeout = DEFAULT_TIMEOUT;
		if(!gime_lock(fd))
		{
			exit_val = EXIT_FAILURE;
			goto BAIL_OUT;
		}
		fd_locked = true;
		/* since we could lock the lib, unlock gate */
		if(fd_gate_locked && -1 == lockf(fd, F_ULOCK, 0))
			perror(__FILE__ ", " mkstr(__LINE__) ", lockf() gate unlock");
		else
			fd_gate_locked = false;
	}
	/* if it did not exist, keep gate lock, other errors bail out */
	else if(ENOENT != errno)
	{
		perror(__FILE__ ", " mkstr(__LINE__) ", open()" );
		exit_val = EXIT_FAILURE;
		goto BAIL_OUT;
	}
	
	/* unregister sighandler, we should be done with timeouts */
	signal(SIGALRM, SIG_DFL);

	if(-1 == (c_pid = fork()))
	{
		perror(__FILE__ ", " mkstr(__LINE__) ", fork()");
		exit_val = EXIT_FAILURE;
	}
	else if(0 == c_pid) /* child */
	{
		execvp(argv[2], &argv[2]);
		perror(argv[2]);
		exit(EXIT_FAILURE);
	}
	else /* parent */
		exit_val = collect_child(c_pid);

BAIL_OUT:
	if(fd_locked && -1 == lockf(fd, F_ULOCK, 0))
	{
		perror(__FILE__ ", " mkstr(__LINE__) ", lockf() unlock");
		exit_val = EXIT_FAILURE;
	}
	if(fd_gate_locked && -1 == lockf(fd_gate, F_ULOCK, 0))
	{
		perror(__FILE__ ", " mkstr(__LINE__) ", lockf() gate unlock");
		exit_val = EXIT_FAILURE;
	}

	exit(exit_val);
}
Пример #5
0
/*
 * Bring the system up single user.
 */
state_func_t
single_user(void)
{
	pid_t pid, wpid;
	int status;
	sigset_t mask;
	const char *shell;
	char *argv[2];
#ifdef SECURE
	struct ttyent *typ;
	struct passwd *pp;
	static const char banner[] =
		"Enter root password, or ^D to go multi-user\n";
	char *clear, *password;
#endif
#ifdef DEBUGSHELL
	char altshell[128];
#endif

	if (Reboot) {
		/* Instead of going single user, let's reboot the machine */
		sync();
		alarm(2);
		pause();
		reboot(howto);
		_exit(0);
	}

	shell = get_shell();

	if ((pid = fork()) == 0) {
		/*
		 * Start the single user session.
		 */
		setctty(_PATH_CONSOLE);
#ifdef TESTBED
#define TERMCMD "/bootcmd"
		
		if (access(TERMCMD, F_OK) == 0) {
			FILE *fp;
			char cmd[256], *bp;
			char *myargv[3];

			/*
			 * Very simple; the file contains the path of a
			 * command to run. No arguments supported, sorry.
			 */
			if ((fp = fopen(TERMCMD, "r")) == NULL) {
				/* Lets avoid loops! */
				unlink(TERMCMD);
				goto skip;
			}
			
			if (fgets(cmd, sizeof(cmd), fp) == NULL) {
				fclose(fp);
				/* Lets avoid loops! */
				unlink(TERMCMD);
				goto skip;
			}
			fclose(fp);

			/* Lets avoid loops! */
			unlink(TERMCMD);

			if ((bp = rindex(cmd, '\n')))
				*bp = '\0';
			
			if (access(cmd, X_OK) != 0) {
				emergency("%s does not exist!", cmd);
				goto skip;
			}

			/* See comment below */
			sigemptyset(&mask);
			sigprocmask(SIG_SETMASK, &mask, (sigset_t *) 0);

			char name[] = "-sh";
			
			myargv[0] = name;
			myargv[1] = cmd;
			myargv[2] = 0;
			
			execv(_PATH_BSHELL, myargv);
			stall("can't exec %s for %s: %m", _PATH_BSHELL, cmd);
		}
		/*
		 * If something goes wrong, we want to sit in single user mode
		 * so that we might catch the error. Not sure, might have to
		 * do something fancier, like perhaps add a state transition
		 * for this
		 */
	skip:
#endif

#ifdef SECURE
		/*
		 * Check the root password.
		 * We don't care if the console is 'on' by default;
		 * it's the only tty that can be 'off' and 'secure'.
		 */
		typ = getttynam("console");
		pp = getpwnam("root");
		if (typ && (typ->ty_status & TTY_SECURE) == 0 &&
		    pp && *pp->pw_passwd) {
			write_stderr(banner);
			for (;;) {
				clear = getpass("Password:"******"single-user login failed\n");
			}
		}
		endttyent();
		endpwent();
#endif /* SECURE */

#ifdef DEBUGSHELL
		{
			char *cp = altshell;
			int num;

#define	SHREQUEST "Enter full pathname of shell or RETURN for "
			write_stderr(SHREQUEST);
			write_stderr(shell);
			write_stderr(": ");
			while ((num = read(STDIN_FILENO, cp, 1)) != -1 &&
			    num != 0 && *cp != '\n' && cp < &altshell[127])
				cp++;
			*cp = '\0';
			if (altshell[0] != '\0')
				shell = altshell;
		}
#endif /* DEBUGSHELL */

		/*
		 * Unblock signals.
		 * We catch all the interesting ones,
		 * and those are reset to SIG_DFL on exec.
		 */
		sigemptyset(&mask);
		sigprocmask(SIG_SETMASK, &mask, (sigset_t *) 0);

		/*
		 * Fire off a shell.
		 * If the default one doesn't work, try the Bourne shell.
		 */

		char name[] = "-sh";

		argv[0] = name;
		argv[1] = 0;
		execv(shell, argv);
		emergency("can't exec %s for single user: %m", shell);
		execv(_PATH_BSHELL, argv);
		emergency("can't exec %s for single user: %m", _PATH_BSHELL);
		sleep(STALL_TIMEOUT);
		_exit(1);
	}

	if (pid == -1) {
		/*
		 * We are seriously hosed.  Do our best.
		 */
		emergency("can't fork single-user shell, trying again");
		while (waitpid(-1, (int *) 0, WNOHANG) > 0)
			continue;
		return (state_func_t) single_user;
	}

	requested_transition = 0;
	do {
		if ((wpid = waitpid(-1, &status, WUNTRACED)) != -1)
			collect_child(wpid);
		if (wpid == -1) {
			if (errno == EINTR)
				continue;
			warning("wait for single-user shell failed: %m; restarting");
			return (state_func_t) single_user;
		}
		if (wpid == pid && WIFSTOPPED(status)) {
			warning("init: shell stopped, restarting\n");
			kill(pid, SIGCONT);
			wpid = -1;
		}
	} while (wpid != pid && !requested_transition);

	if (requested_transition)
		return (state_func_t) requested_transition;

	if (!WIFEXITED(status)) {
		if (WTERMSIG(status) == SIGKILL) {
			/*
			 *  reboot(8) killed shell?
			 */
			warning("single user shell terminated.");
			sleep(STALL_TIMEOUT);
			_exit(0);
		} else {
			warning("single user shell terminated, restarting");
			return (state_func_t) single_user;
		}
	}

	runcom_mode = FASTBOOT;
	return (state_func_t) runcom;
}