if (cmd->dir && chdir(cmd->dir))
die("exec %s: cd to %s failed (%s)", cmd->argv[0],
cmd->dir, str_error_r(errno, sbuf, sizeof(sbuf))); if (cmd->env) { for (; *cmd->env; cmd->env++) { if (strchr(*cmd->env, '='))
putenv((char*)*cmd->env); else
unsetenv(*cmd->env);
}
} if (cmd->preexec_cb)
cmd->preexec_cb(); if (cmd->no_exec_cmd) exit(cmd->no_exec_cmd(cmd)); if (cmd->exec_cmd) {
execv_cmd(cmd->argv);
} else {
execvp(cmd->argv[0], (char *const*) cmd->argv);
} exit(127);
}
if (cmd->pid < 0) { int err = errno; if (need_in)
close_pair(fdin); elseif (cmd->in)
close(cmd->in); if (need_out)
close_pair(fdout); elseif (cmd->out)
close(cmd->out); if (need_err)
close_pair(fderr); return err == ENOENT ?
-ERR_RUN_COMMAND_EXEC :
-ERR_RUN_COMMAND_FORK;
}
if (need_in)
close(fdin[0]); elseif (cmd->in)
close(cmd->in);
if (need_out)
close(fdout[1]); elseif (cmd->out)
close(cmd->out);
if (need_err)
close(fderr[1]);
return 0;
}
staticint wait_or_whine(struct child_process *cmd, bool block)
{ bool finished = cmd->finished; int result = cmd->finish_result;
while (!finished) { int status, code;
pid_t waiting = waitpid(cmd->pid, &status, block ? 0 : WNOHANG);
if (!block && waiting == 0) break;
if (waiting < 0 && errno == EINTR) continue;
finished = true; if (waiting < 0) { char sbuf[STRERR_BUFSIZE];
fprintf(stderr, " Error: waitpid failed (%s)",
str_error_r(errno, sbuf, sizeof(sbuf)));
result = -ERR_RUN_COMMAND_WAITPID;
} elseif (waiting != cmd->pid) {
result = -ERR_RUN_COMMAND_WAITPID_WRONG_PID;
} elseif (WIFSIGNALED(status)) {
result = -ERR_RUN_COMMAND_WAITPID_SIGNAL;
} elseif (!WIFEXITED(status)) {
result = -ERR_RUN_COMMAND_WAITPID_NOEXIT;
} else {
code = WEXITSTATUS(status); switch (code) { case 127:
result = -ERR_RUN_COMMAND_EXEC; break; case 0:
result = 0; break; default:
result = -code; break;
}
}
} if (finished) {
cmd->finished = 1;
cmd->finish_result = result;
} return result;
}
/* * Conservative estimate of number of characaters needed to hold an a decoded * integer, assume each 3 bits needs a character byte and plus a possible sign * character.
*/ #ifndef is_signed_type #define is_signed_type(type) (((type)(-1)) < (type)1) #endif #define MAX_STRLEN_TYPE(type) (sizeof(type) * 8 / 3 + (is_signed_type(type) ? 1 : 0))
/* * Check by reading /proc/<pid>/status as calling waitpid causes * stdout/stderr to be closed and data lost.
*/
sprintf(filename, "/proc/%u/status", cmd->pid);
status_file = fopen(filename, "r"); if (status_file == NULL) { /* Open failed assume finish_command was called. */ returntrue;
} while (fgets(status_line, sizeof(status_line), status_file) != NULL) { char *p;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.