Exemple #1
0
static void edit_file(const struct passwd *pas, const char *file)
{
	const char *ptr;
	pid_t pid;

	pid = xvfork();
	if (pid) { /* parent */
		wait4pid(pid);
		return;
	}

	/* CHILD - change user and run editor */
	/* initgroups, setgid, setuid */
	change_identity(pas);
	setup_environment(pas->pw_shell,
			SETUP_ENV_CHANGEENV | SETUP_ENV_TO_TMP,
			pas);
	ptr = getenv("VISUAL");
	if (!ptr) {
		ptr = getenv("EDITOR");
		if (!ptr)
			ptr = "vi";
	}

	BB_EXECLP(ptr, ptr, file, NULL);
	bb_perror_msg_and_die("can't execute '%s'", ptr);
}
static void passwd_wrapper(const char *login)
{
	static const char prog[] ALIGN1 = "passwd";

	BB_EXECLP(prog, prog, login, NULL);
	bb_error_msg_and_die("cannot execute %s, you must set password manually", prog);
}
Exemple #3
0
static void edit_file(const struct passwd *pas, const char *file)
{
	const char *ptr;
	int pid = vfork();

	if (pid < 0) /* failure */
		bb_perror_msg_and_die("vfork");
	if (pid) { /* parent */
		wait4pid(pid);
		return;
	}

	/* CHILD - change user and run editor */
	change_user(pas);
	ptr = getenv("VISUAL");
	if (!ptr) {
		ptr = getenv("EDITOR");
		if (!ptr)
			ptr = "vi";
	}

	BB_EXECLP(ptr, ptr, file, NULL);
	bb_perror_msg_and_die("exec %s", ptr);
}
Exemple #4
0
static void passwd_wrapper(const char *login_name)
{
	BB_EXECLP("passwd", "passwd", "--", login_name, NULL);
	bb_error_msg_and_die("can't execute passwd, you must set password manually");
}
Exemple #5
0
/* Don't inline: vfork scares gcc and pessimizes code */
static void NOINLINE vfork_compressor(int tar_fd, int gzip)
{
	pid_t gzipPid;
#if ENABLE_FEATURE_SEAMLESS_GZ && ENABLE_FEATURE_SEAMLESS_BZ2
	const char *zip_exec = (gzip == 1) ? "gzip" : "bzip2";
#elif ENABLE_FEATURE_SEAMLESS_GZ
	const char *zip_exec = "gzip";
#else /* only ENABLE_FEATURE_SEAMLESS_BZ2 */
	const char *zip_exec = "bzip2";
#endif
	// On Linux, vfork never unpauses parent early, although standard
	// allows for that. Do we want to waste bytes checking for it?
#define WAIT_FOR_CHILD 0
	volatile int vfork_exec_errno = 0;
	struct fd_pair gzipDataPipe;
#if WAIT_FOR_CHILD
	struct fd_pair gzipStatusPipe;
	xpiped_pair(gzipStatusPipe);
#endif
	xpiped_pair(gzipDataPipe);

	signal(SIGPIPE, SIG_IGN); /* we only want EPIPE on errors */

#if defined(__GNUC__) && __GNUC__
	/* Avoid vfork clobbering */
	(void) &zip_exec;
#endif

	gzipPid = vfork();
	if (gzipPid < 0)
		bb_perror_msg_and_die("vfork");

	if (gzipPid == 0) {
		/* child */
		/* NB: close _first_, then move fds! */
		close(gzipDataPipe.wr);
#if WAIT_FOR_CHILD
		close(gzipStatusPipe.rd);
		/* gzipStatusPipe.wr will close only on exec -
		 * parent waits for this close to happen */
		fcntl(gzipStatusPipe.wr, F_SETFD, FD_CLOEXEC);
#endif
		xmove_fd(gzipDataPipe.rd, 0);
		xmove_fd(tar_fd, 1);
		/* exec gzip/bzip2 program/applet */
		BB_EXECLP(zip_exec, zip_exec, "-f", NULL);
		vfork_exec_errno = errno;
		_exit(EXIT_FAILURE);
	}

	/* parent */
	xmove_fd(gzipDataPipe.wr, tar_fd);
	close(gzipDataPipe.rd);
#if WAIT_FOR_CHILD
	close(gzipStatusPipe.wr);
	while (1) {
		char buf;
		int n;

		/* Wait until child execs (or fails to) */
		n = full_read(gzipStatusPipe.rd, &buf, 1);
		if (n < 0 /* && errno == EAGAIN */)
			continue;	/* try it again */
	}
	close(gzipStatusPipe.rd);
#endif
	if (vfork_exec_errno) {
		errno = vfork_exec_errno;
		bb_perror_msg_and_die("can't execute '%s'", zip_exec);
	}
}
Exemple #6
0
static int writeTarFile(const int tar_fd, const int verboseFlag,
	const unsigned long dereferenceFlag, const llist_t *include,
	const llist_t *exclude, const int gzip)
{
	pid_t gzipPid = 0;
	int errorFlag = FALSE;
	struct TarBallInfo tbInfo;

	tbInfo.hlInfoHead = NULL;

	fchmod(tar_fd, 0644);
	tbInfo.tarFd = tar_fd;
	tbInfo.verboseFlag = verboseFlag;

	/* Store the stat info for the tarball's file, so
	 * can avoid including the tarball into itself....  */
	if (fstat(tbInfo.tarFd, &tbInfo.statBuf) < 0)
		bb_perror_msg_and_die("cannot stat tar file");

#if ENABLE_FEATURE_TAR_GZIP || ENABLE_FEATURE_TAR_BZIP2
	if (gzip) {
#if ENABLE_FEATURE_TAR_GZIP && ENABLE_FEATURE_TAR_BZIP2
		const char *zip_exec = (gzip == 1) ? "gzip" : "bzip2";
#elif ENABLE_FEATURE_TAR_GZIP
		const char *zip_exec = "gzip";
#else /* only ENABLE_FEATURE_TAR_BZIP2 */
		const char *zip_exec = "bzip2";
#endif
	// On Linux, vfork never unpauses parent early, although standard
	// allows for that. Do we want to waste bytes checking for it?
#define WAIT_FOR_CHILD 0
		volatile int vfork_exec_errno = 0;
#if WAIT_FOR_CHILD
		struct fd_pair gzipStatusPipe;
#endif
		struct fd_pair gzipDataPipe;
		xpiped_pair(gzipDataPipe);
#if WAIT_FOR_CHILD
		xpiped_pair(gzipStatusPipe);
#endif

		signal(SIGPIPE, SIG_IGN); /* we only want EPIPE on errors */

#if defined(__GNUC__) && __GNUC__
		/* Avoid vfork clobbering */
		(void) &include;
		(void) &errorFlag;
		(void) &zip_exec;
#endif

		gzipPid = vfork();
		if (gzipPid < 0)
			bb_perror_msg_and_die("vfork gzip");

		if (gzipPid == 0) {
			/* child */
			/* NB: close _first_, then move fds! */
			close(gzipDataPipe.wr);
#if WAIT_FOR_CHILD
			close(gzipStatusPipe.rd);
			/* gzipStatusPipe.wr will close only on exec -
			 * parent waits for this close to happen */
			fcntl(gzipStatusPipe.wr, F_SETFD, FD_CLOEXEC);
#endif
			xmove_fd(gzipDataPipe.rd, 0);
			xmove_fd(tbInfo.tarFd, 1);
			/* exec gzip/bzip2 program/applet */
			BB_EXECLP(zip_exec, zip_exec, "-f", NULL);
			vfork_exec_errno = errno;
			_exit(1);
		}

		/* parent */
		xmove_fd(gzipDataPipe.wr, tbInfo.tarFd);
		close(gzipDataPipe.rd);
#if WAIT_FOR_CHILD
		close(gzipStatusPipe.wr);
		while (1) {
			char buf;
			int n;

			/* Wait until child execs (or fails to) */
			n = full_read(gzipStatusPipe.rd, &buf, 1);
			if (n < 0 /* && errno == EAGAIN */)
				continue;	/* try it again */

		}
		close(gzipStatusPipe.rd);
#endif
		if (vfork_exec_errno) {
			errno = vfork_exec_errno;
			bb_perror_msg_and_die("cannot exec %s", zip_exec);
		}
	}
#endif

	tbInfo.excludeList = exclude;

	/* Read the directory/files and iterate over them one at a time */
	while (include) {
		if (!recursive_action(include->data, ACTION_RECURSE |
				(dereferenceFlag ? ACTION_FOLLOWLINKS : 0),
				writeFileToTarball, writeFileToTarball, &tbInfo, 0))
		{
			errorFlag = TRUE;
		}
		include = include->link;
	}
	/* Write two empty blocks to the end of the archive */
	memset(block_buf, 0, 2*TAR_BLOCK_SIZE);
	xwrite(tbInfo.tarFd, block_buf, 2*TAR_BLOCK_SIZE);

	/* To be pedantically correct, we would check if the tarball
	 * is smaller than 20 tar blocks, and pad it if it was smaller,
	 * but that isn't necessary for GNU tar interoperability, and
	 * so is considered a waste of space */

	/* Close so the child process (if any) will exit */
	close(tbInfo.tarFd);

	/* Hang up the tools, close up shop, head home */
	if (ENABLE_FEATURE_CLEAN_UP)
		freeHardLinkInfo(&tbInfo.hlInfoHead);

	if (errorFlag)
		bb_error_msg("error exit delayed from previous errors");

	if (gzipPid) {
#if ENABLE_FEATURE_TAR_GZIP || ENABLE_FEATURE_TAR_BZIP2
		int status;
		if (safe_waitpid(gzipPid, &status, 0) == -1)
			bb_perror_msg("waitpid");
		else if (!WIFEXITED(status) || WEXITSTATUS(status))
			/* gzip was killed or has exited with nonzero! */
			errorFlag = TRUE;
#endif
	}
	return errorFlag;
}
Exemple #7
0
static int writeTarFile(const int tar_fd, const int verboseFlag,
	const unsigned long dereferenceFlag, const llist_t *include,
	const llist_t *exclude, const int gzip)
{
	pid_t gzipPid = 0;
	int errorFlag = FALSE;
	struct TarBallInfo tbInfo;

	tbInfo.hlInfoHead = NULL;

	fchmod(tar_fd, 0644);
	tbInfo.tarFd = tar_fd;
	tbInfo.verboseFlag = verboseFlag;

	/* Store the stat info for the tarball's file, so
	 * can avoid including the tarball into itself....  */
	if (fstat(tbInfo.tarFd, &tbInfo.statBuf) < 0)
		bb_perror_msg_and_die("cannot stat tar file");

	if ((ENABLE_FEATURE_TAR_GZIP || ENABLE_FEATURE_TAR_BZIP2) && gzip) {
		int gzipDataPipe[2] = { -1, -1 };
		int gzipStatusPipe[2] = { -1, -1 };
		volatile int vfork_exec_errno = 0;
		const char *zip_exec = (gzip == 1) ? "gzip" : "bzip2";

		if (pipe(gzipDataPipe) < 0 || pipe(gzipStatusPipe) < 0)
			bb_perror_msg_and_die("pipe");

		signal(SIGPIPE, SIG_IGN); /* we only want EPIPE on errors */

#if defined(__GNUC__) && __GNUC__
		/* Avoid vfork clobbering */
		(void) &include;
		(void) &errorFlag;
		(void) &zip_exec;
#endif

		gzipPid = vfork();

		if (gzipPid == 0) {
			dup2(gzipDataPipe[0], 0);
			close(gzipDataPipe[1]);

			dup2(tbInfo.tarFd, 1);

			close(gzipStatusPipe[0]);
			fcntl(gzipStatusPipe[1], F_SETFD, FD_CLOEXEC);	/* close on exec shows success */

			BB_EXECLP(zip_exec, zip_exec, "-f", NULL);
			vfork_exec_errno = errno;

			close(gzipStatusPipe[1]);
			exit(-1);
		} else if (gzipPid > 0) {
			close(gzipDataPipe[0]);
			close(gzipStatusPipe[1]);

			while (1) {
				char buf;

				int n = full_read(gzipStatusPipe[0], &buf, 1);

				if (n == 0 && vfork_exec_errno != 0) {
					errno = vfork_exec_errno;
					bb_perror_msg_and_die("cannot exec %s", zip_exec);
				} else if ((n < 0) && (errno == EAGAIN || errno == EINTR))
					continue;	/* try it again */
				break;
			}
			close(gzipStatusPipe[0]);

			tbInfo.tarFd = gzipDataPipe[1];
		} else bb_perror_msg_and_die("vfork gzip");
	}

	tbInfo.excludeList = exclude;

	/* Read the directory/files and iterate over them one at a time */
	while (include) {
		if (!recursive_action(include->data, TRUE, dereferenceFlag,
				FALSE, writeFileToTarball, writeFileToTarball, &tbInfo, 0))
		{
			errorFlag = TRUE;
		}
		include = include->link;
	}
	/* Write two empty blocks to the end of the archive */
	memset(bb_common_bufsiz1, 0, 2*TAR_BLOCK_SIZE);
	xwrite(tbInfo.tarFd, bb_common_bufsiz1, 2*TAR_BLOCK_SIZE);

	/* To be pedantically correct, we would check if the tarball
	 * is smaller than 20 tar blocks, and pad it if it was smaller,
	 * but that isn't necessary for GNU tar interoperability, and
	 * so is considered a waste of space */

	/* Close so the child process (if any) will exit */
	close(tbInfo.tarFd);

	/* Hang up the tools, close up shop, head home */
	if (ENABLE_FEATURE_CLEAN_UP)
		freeHardLinkInfo(&tbInfo.hlInfoHead);

	if (errorFlag)
		bb_error_msg("error exit delayed from previous errors");

	if (gzipPid) {
		int status;
		if (waitpid(gzipPid, &status, 0) == -1)
			bb_perror_msg("waitpid");
		else if (!WIFEXITED(status) || WEXITSTATUS(status))
			/* gzip was killed or has exited with nonzero! */
			errorFlag = TRUE;
	}
	return errorFlag;
}