libbb: two new functions: wait_for_exitstatus(pid), xfchdir(fd)

Bartosz Golaszewski proposed xfchdir()

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
diff --git a/archival/libarchive/data_extract_to_command.c b/archival/libarchive/data_extract_to_command.c
index 6f5317a..5d87693 100644
--- a/archival/libarchive/data_extract_to_command.c
+++ b/archival/libarchive/data_extract_to_command.c
@@ -112,8 +112,7 @@
 		bb_copyfd_exact_size(archive_handle->src_fd, p[1], -file_header->size);
 		close(p[1]);
 
-		if (safe_waitpid(pid, &status, 0) == -1)
-			bb_perror_msg_and_die("waitpid");
+		status = wait_for_exitstatus(pid);
 		if (WIFEXITED(status) && WEXITSTATUS(status))
 			bb_error_msg_and_die("'%s' returned status %d",
 				archive_handle->tar__to_command, WEXITSTATUS(status));
diff --git a/include/libbb.h b/include/libbb.h
index 98d7884..5b4280e 100644
--- a/include/libbb.h
+++ b/include/libbb.h
@@ -500,6 +500,7 @@
 void xsetegid(gid_t egid) FAST_FUNC;
 void xseteuid(uid_t euid) FAST_FUNC;
 void xchdir(const char *path) FAST_FUNC;
+void xfchdir(int fd) FAST_FUNC;
 void xchroot(const char *path) FAST_FUNC;
 void xsetenv(const char *key, const char *value) FAST_FUNC;
 void bb_unsetenv(const char *key) FAST_FUNC;
@@ -1021,6 +1022,7 @@
  *      if (rc > 0) bb_error_msg("exit code: %d", rc & 0xff);
  */
 int wait4pid(pid_t pid) FAST_FUNC;
+int wait_for_exitstatus(pid_t pid) FAST_FUNC;
 /* Same as wait4pid(spawn(argv)), but with NOFORK/NOEXEC if configured: */
 int spawn_and_wait(char **argv) FAST_FUNC;
 /* Does NOT check that applet is NOFORK, just blindly runs it */
diff --git a/libbb/xfuncs.c b/libbb/xfuncs.c
index 206edb4..3f9a84a 100644
--- a/libbb/xfuncs.c
+++ b/libbb/xfuncs.c
@@ -315,3 +315,15 @@
 		return WTERMSIG(status) + 0x180;
 	return 0;
 }
+
+// Useful when we do know that pid is valid, and we just want to wait
+// for it to exit. Not existing pid is fatal. waitpid() status is not returned.
+int FAST_FUNC wait_for_exitstatus(pid_t pid)
+{
+	int exit_status, n;
+
+	n = safe_waitpid(pid, &exit_status, 0);
+	if (n < 0)
+		bb_perror_msg_and_die("waitpid");
+	return exit_status;
+}
diff --git a/libbb/xfuncs_printf.c b/libbb/xfuncs_printf.c
index 7348890..4aa1b5c 100644
--- a/libbb/xfuncs_printf.c
+++ b/libbb/xfuncs_printf.c
@@ -390,6 +390,12 @@
 		bb_perror_msg_and_die("can't change directory to '%s'", path);
 }
 
+void FAST_FUNC xfchdir(int fd)
+{
+	if (fchdir(fd))
+		bb_perror_msg_and_die("fchdir");
+}
+
 void FAST_FUNC xchroot(const char *path)
 {
 	if (chroot(path))
diff --git a/runit/chpst.c b/runit/chpst.c
index 301cdd0..7fe5151 100644
--- a/runit/chpst.c
+++ b/runit/chpst.c
@@ -255,8 +255,7 @@
 		xsetenv(d->d_name, buf);
 	}
 	closedir(dir);
-	if (fchdir(wdir) == -1)
-		bb_perror_msg_and_die("fchdir");
+	xfchdir(wdir);
 	close(wdir);
 }
 
diff --git a/util-linux/unshare.c b/util-linux/unshare.c
index f1a9cdf..b8cd467 100644
--- a/util-linux/unshare.c
+++ b/util-linux/unshare.c
@@ -57,17 +57,6 @@
 	}
 }
 
-// TODO: move to libbb
-static int wait_for_exitstatus(pid_t pid)
-{
-	int exit_status, n;
-
-	n = safe_waitpid(pid, &exit_status, 0);
-	if (n < 0)
-		bb_perror_msg_and_die("waitpid");
-	return exit_status;
-}
-
 /*
  * Longest possible path to a procfs file used in unshare. Must be able to
  * contain the '/proc/' string, the '/ns/user' string which is the longest