2 * This file is in the public domain.
3 * You may freely use, modify, distribute, and relicense it.
6 #include "bash.preinst.h"
12 #include <sys/types.h>
19 extern char **environ;
21 __attribute__((format(printf, 1, 0)))
22 static void vreportf(const char *err, va_list params, int errnum)
24 fprintf(stderr, "bash.preinst: ");
25 vfprintf(stderr, err, params);
27 fprintf(stderr, ": %s", strerror(errnum));
28 fprintf(stderr, "\n");
31 __attribute__((format(printf, 1, 2)))
32 NORETURN void die_errno(const char *fmt, ...)
35 va_start(params, fmt);
36 vreportf(fmt, params, errno);
41 __attribute__((format(printf, 1, 2)))
42 NORETURN void die(const char *fmt, ...)
45 va_start(params, fmt);
46 vreportf(fmt, params, 0);
51 int exists(const char *file)
54 if (!lstat(file, &sb))
58 die_errno("cannot get status of %s", file);
61 void set_cloexec(int fd)
63 int flags = fcntl(fd, F_GETFD);
64 if (flags < 0 || fcntl(fd, F_SETFD, flags | FD_CLOEXEC))
65 die_errno("cannot set close-on-exec flag");
68 void xpipe(int pipefd[2])
71 die_errno("cannot create pipe");
72 set_cloexec(pipefd[0]);
73 set_cloexec(pipefd[1]);
76 void wait_or_die(pid_t child, const char *name, int flags)
79 if (waitpid(child, &status, 0) != child)
80 die_errno("cannot wait for %s", name);
81 if ((WIFEXITED(status) && WEXITSTATUS(status) == 0) ||
82 ((flags & ERROR_OK) && WIFEXITED(status)) ||
83 ((flags & SIGPIPE_OK) &&
84 WIFSIGNALED(status) && WTERMSIG(status) == SIGPIPE))
87 if (WIFEXITED(status))
88 die("%s exited with status %d", name, WEXITSTATUS(status));
89 if (WIFSIGNALED(status))
90 die("%s killed by signal %d", name, WTERMSIG(status));
91 if (WIFSTOPPED(status))
92 die("%s stopped by signal %d", name, WSTOPSIG(status));
93 die("waitpid is confused (status=%d)", status);
96 pid_t spawn(const char * const cmd[], int out, int err)
99 posix_spawn_file_actions_t redir;
101 if (posix_spawn_file_actions_init(&redir) ||
102 (out >= 0 && posix_spawn_file_actions_adddup2(&redir, out, 1)) ||
103 (err >= 0 && posix_spawn_file_actions_adddup2(&redir, err, 2)) ||
104 posix_spawnp(&child, cmd[0], &redir, NULL,
105 (char **) cmd, environ) ||
106 posix_spawn_file_actions_destroy(&redir))
107 die_errno("cannot run %s", cmd[0]);
111 void run(const char * const cmd[])
113 pid_t child = spawn(cmd, -1, -1);
114 wait_or_die(child, cmd[0], 0);
117 FILE *spawn_pipe(pid_t *pid, const char * const cmd[], int errfd)
123 *pid = spawn(cmd, pipefd[1], errfd);
124 if (close(pipefd[1]) || (errfd != -1 && close(errfd)))
125 die_errno("cannot close unneeded fd");
127 f = fdopen(pipefd[0], "r");
129 die_errno("cannot stream read end of pipe");