2 #if defined(HAVE_CONFIG_H)
12 #include <sys/types.h>
16 #include <talloc/talloc.h>
19 const struct pb_system_apps pb_system_apps = {
22 .kexec = HOST_PROG_KEXEC,
23 .mount = HOST_PROG_MOUNT,
24 .shutdown = HOST_PROG_SHUTDOWN,
25 .sftp = HOST_PROG_SFTP,
26 .tftp = HOST_PROG_TFTP,
27 .umount = HOST_PROG_UMOUNT,
28 .wget = HOST_PROG_WGET,
30 .udhcpc = HOST_PROG_UDHCPC,
33 int pb_mkdir_recursive(const char *dir)
42 if (!stat(dir, &statbuf)) {
43 if (!S_ISDIR(statbuf.st_mode)) {
44 pb_log("%s: %s exists, but isn't a directory\n",
51 str = talloc_strdup(NULL, dir);
52 sep = strchr(*str == '/' ? str + 1 : str, '/');
56 /* terminate the path at sep */
60 if (mkdir(str, mode) && errno != EEXIST) {
61 pb_log("mkdir(%s): %s\n", str, strerror(errno));
68 /* reset dir to the full path */
70 sep = strchr(sep + 1, '/');
78 int pb_rmdir_recursive(const char *base, const char *dir)
82 /* sanity check: make sure that dir is within base */
83 if (strncmp(base, dir, strlen(base)))
86 cur = talloc_strdup(NULL, dir);
88 while (strcmp(base, dir)) {
92 /* null-terminate at the last slash */
93 pos = strrchr(dir, '/');
105 static int read_pipe(void *ctx, int fd, char **bufp, int *lenp)
107 int rc, len, alloc_len;
113 buf = talloc_array(ctx, char, alloc_len);
116 rc = read(fd, buf, alloc_len - len - 1);
121 if (len == alloc_len - 1) {
123 buf = talloc_realloc(ctx, buf, char, alloc_len);
140 * pb_run_cmd - Run the supplied command.
141 * @cmd_argv: An argument list array for execv.
142 * @wait: Wait for the child process to complete before returning.
143 * @dry_run: Don't actually fork and exec.
146 int pb_run_cmd(const char *const *cmd_argv, int wait, int dry_run)
148 return pb_run_cmd_pipe(cmd_argv, wait, dry_run, NULL, NULL, NULL);
151 int pb_run_cmd_pipe(const char *const *cmd_argv, int wait, int dry_run,
152 void *ctx, char **stdout_buf, int *stdout_buf_len)
159 int status, pipefd[2];
162 assert(!stdout_buf || wait);
163 assert(!stdout_buf || ctx);
164 assert(!stdout_buf || stdout_buf_len);
167 const char *const *p = cmd_argv;
169 pb_log("%s: %s", __func__, (dry_run ? "(dry-run) " : ""));
177 pb_log("%s: %s%s\n", __func__, (dry_run ? "(dry-run) " : ""),
189 status = pipe(pipefd);
191 pb_log("pipe failed");
199 pb_log("%s: fork failed: %s\n", __func__, strerror(errno));
205 int log = fileno(pb_log_get_stream());
207 /* Redirect child output to log. */
210 status = dup2(pipefd[1], STDOUT_FILENO);
212 status = dup2(log, STDOUT_FILENO);
214 assert(status != -1);
216 status = dup2(log, STDERR_FILENO);
217 assert(status != -1);
219 execvp(cmd_argv[0], (char *const *)cmd_argv);
220 pb_log("%s: exec failed: %s\n", __func__, strerror(errno));
224 if (!wait && !waitpid(pid, &status, WNOHANG))
229 status = read_pipe(ctx, pipefd[0], stdout_buf, stdout_buf_len);
234 if (waitpid(pid, &status, 0) == -1) {
235 pb_log("%s: waitpid failed: %s\n", __func__,
240 if (do_debug && WIFSIGNALED(status) && WTERMSIG(status) == SIGINT)
241 pb_log("%s: signaled\n", __func__);
243 if (!WIFEXITED(status)) {
244 pb_log("%s: %s failed\n", __func__, cmd_argv[0]);
248 if (WEXITSTATUS(status))
249 pb_log("%s: WEXITSTATUS %d\n", __func__, WEXITSTATUS(status));
251 return WEXITSTATUS(status);