authdismissed = (pkout && strstr(pkout, "dismissed=true"));
if (status != 0) {
- char *tmp = virProcessTranslateStatus(status);
- VIR_ERROR(_("Policy kit denied action %s from pid %lld, uid %d: %s"),
- action, (long long) callerPid, callerUid, NULLSTR(tmp));
- VIR_FREE(tmp);
+ VIR_ERROR(_("Policy kit denied action %s from pid %lld, uid %d "
+ "with status %d"),
+ action, (long long) callerPid, callerUid, status);
goto authdeny;
}
PROBE(RPC_SERVER_CLIENT_AUTH_ALLOW,
if (string)
VIR_DEBUG("about to run %s", string);
VIR_FREE(string);
- if (virCommandRun(cmd) < 0)
+ if (virCommandRun(cmd, NULL) < 0)
return -1;
</pre>
non-zero exit status can represent a success condition,
it is possible to request the exit status and perform
that check manually instead of letting <code>virCommandRun</code>
- raise the error
+ raise the error. By default, the captured status is only
+ for a normal exit (death from a signal is treated as an error),
+ but a caller can use <code>virCommandRawStatus</code> to get
+ encoded status that includes any terminating signals.
</p>
<pre>
int status;
if (virCommandRun(cmd, &status) < 0)
- return -1;
+ return -1;
+ if (status == 1) {
+ ...do stuff...
+ }
- if (WEXITSTATUS(status) ...) {
+ virCommandRawStatus(cmd2);
+ if (virCommandRun(cmd2, &status) < 0)
+ return -1;
+ if (WIFEXITED(status) && WEXITSTATUS(status) == 1) {
...do stuff...
}
</pre>
/*
* viraccessdriverpolkit.c: polkited access control driver
*
- * Copyright (C) 2012 Red Hat, Inc.
+ * Copyright (C) 2012, 2014 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
ret = 0; /* Denied */
} else {
ret = -1; /* Error */
- char *tmp = virProcessTranslateStatus(status);
virAccessError(VIR_ERR_ACCESS_DENIED,
- _("Policy kit denied action %s from %s: %s"),
- actionid, process, NULLSTR(tmp));
- VIR_FREE(tmp);
+ _("Policy kit denied action %s from %s: "
+ "exit status %d"),
+ actionid, process, status);
}
goto cleanup;
}
virCommandPtr cmd = NULL;
virCommandPtr load_cmd = NULL;
bhyveConnPtr privconn = conn->privateData;
- int ret = -1, status;
+ int ret = -1;
if (virAsprintf(&logfile, "%s/%s.log",
BHYVE_LOG_DIR, vm->def->name) < 0)
virStrerror(errno, ebuf, sizeof(ebuf)));
VIR_DEBUG("Loading domain '%s'", vm->def->name);
- if (virCommandRun(load_cmd, &status) < 0)
+ if (virCommandRun(load_cmd, NULL) < 0)
goto cleanup;
- if (status != 0) {
- virReportError(VIR_ERR_INTERNAL_ERROR,
- _("Guest failed to load: %d"), status);
- goto cleanup;
- }
-
/* Now we can start the domain */
VIR_DEBUG("Starting domain '%s'", vm->def->name);
ret = virCommandRun(cmd, NULL);
{
size_t i;
int ret = -1;
- int status;
virCommandPtr cmd = NULL;
if (!virDomainObjIsActive(vm)) {
if (!(cmd = virBhyveProcessBuildDestroyCmd(driver, vm)))
goto cleanup;
- if (virCommandRun(cmd, &status) < 0)
+ if (virCommandRun(cmd, NULL) < 0)
goto cleanup;
- if (status != 0) {
- virReportError(VIR_ERR_INTERNAL_ERROR,
- _("Guest failed to stop: %d"), status);
- goto cleanup;
- }
-
ret = 0;
virDomainObjSetState(vm, VIR_DOMAIN_SHUTOFF, reason);
/*
* fdstream.c: generic streams impl for file descriptors
*
- * Copyright (C) 2009-2012 Red Hat, Inc.
+ * Copyright (C) 2009-2012, 2014 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
else
buf[len] = '\0';
+ virCommandRawStatus(fdst->cmd);
if (virCommandWait(fdst->cmd, &status) < 0) {
ret = -1;
} else if (status != 0) {
virConnectAuthGainPolkit(const char *privilege)
{
virCommandPtr cmd;
- int status;
int ret = -1;
if (geteuid() == 0)
return 0;
cmd = virCommandNewArgList(POLKIT_AUTH, "--obtain", privilege, NULL);
- if (virCommandRun(cmd, &status) < 0 ||
- status > 0)
+ if (virCommandRun(cmd, NULL) < 0)
goto cleanup;
ret = 0;
virCommandNewArgs;
virCommandNonblockingFDs;
virCommandPassFD;
+virCommandRawStatus;
virCommandRequireHandshake;
virCommandRun;
virCommandRunAsync;
VIR_WARN("Unable to seek to end of logfile: %s",
virStrerror(errno, ebuf, sizeof(ebuf)));
+ virCommandRawStatus(cmd);
if (virCommandRun(cmd, &status) < 0)
goto cleanup;
if (status != 0) {
- if (virLXCProcessReadLogOutput(vm, logfile, pos, ebuf, sizeof(ebuf)) <= 0)
- snprintf(ebuf, sizeof(ebuf), "unexpected exit status %d", status);
+ if (virLXCProcessReadLogOutput(vm, logfile, pos, ebuf,
+ sizeof(ebuf)) <= 0) {
+ if (WIFEXITED(status))
+ snprintf(ebuf, sizeof(ebuf), _("unexpected exit status %d"),
+ WEXITSTATUS(status));
+ else
+ snprintf(ebuf, sizeof(ebuf), "%s", _("terminated abnormally"));
+ }
virReportError(VIR_ERR_INTERNAL_ERROR,
_("guest failed to start: %s"), ebuf);
goto cleanup;
/*
* openvz_driver.c: core driver methods for managing OpenVZ VEs
*
- * Copyright (C) 2010-2013 Red Hat, Inc.
+ * Copyright (C) 2010-2014 Red Hat, Inc.
* Copyright (C) 2006, 2007 Binary Karma
* Copyright (C) 2006 Shuveb Hussain
* Copyright (C) 2007 Anoop Joe Cyriac
unsigned long long *barrier,
unsigned long long *limit)
{
- int status, ret = -1;
+ int ret = -1;
char *endp, *output = NULL;
const char *tmp;
virCommandPtr cmd = virCommandNewArgList(VZLIST, "--no-header", NULL);
virCommandSetOutputBuffer(cmd, &output);
virCommandAddArgFormat(cmd, "-o%s.b,%s.l", param, param);
virCommandAddArg(cmd, domain->name);
- if (virCommandRun(cmd, &status) < 0 || status != 0) {
- virReportError(VIR_ERR_OPERATION_FAILED,
- _("Failed to get %s for %s: %d"), param, domain->name,
- status);
+ if (virCommandRun(cmd, NULL) < 0)
goto cleanup;
- }
tmp = output;
virSkipSpaces(&tmp);
unsigned long long barrier,
unsigned long long limit)
{
- int status, ret = -1;
+ int ret = -1;
virCommandPtr cmd = virCommandNewArgList(VZCTL, "--quiet", "set", NULL);
/* LONG_MAX indicates unlimited so reject larger values */
virCommandAddArgFormat(cmd, "--%s", param);
virCommandAddArgFormat(cmd, "%llu:%llu", barrier, limit);
virCommandAddArg(cmd, "--save");
- if (virCommandRun(cmd, &status) < 0 || status != 0) {
- virReportError(VIR_ERR_OPERATION_FAILED,
- _("Failed to set %s for %s: %d"), param, domain->name,
- status);
+ if (virCommandRun(cmd, NULL) < 0)
goto cleanup;
- }
ret = 0;
cleanup:
virCommandSetGID(cmd, runGid);
virCommandSetUID(cmd, runUid);
+ /* Log, but otherwise ignore, non-zero status. */
if (virCommandRun(cmd, &status) < 0)
goto cleanup;
unsigned int flags)
{
virCommandPtr cmd;
- int status;
int pair[2] = { -1, -1 };
if ((flags & ~VIR_NETDEV_TAP_CREATE_VNET_HDR) != VIR_NETDEV_TAP_CREATE_IFUP)
}
if (virNetDevTapGetName(*tapfd, ifname) < 0 ||
- virCommandWait(cmd, &status) < 0) {
+ virCommandWait(cmd, NULL) < 0) {
VIR_FORCE_CLOSE(*tapfd);
*tapfd = -1;
}
/*
* storage_backend_iscsi.c: storage backend for iSCSI handling
*
- * Copyright (C) 2007-2008, 2010-2012 Red Hat, Inc.
+ * Copyright (C) 2007-2014 Red Hat, Inc.
* Copyright (C) 2007-2008 Daniel P. Berrange
*
* This library is free software; you can redistribute it and/or
virCommandPtr cmd = virCommandNewArgList(ISCSIADM, "--mode", "session", NULL);
- /* Note that we ignore the exitstatus. Older versions of iscsiadm tools
- * returned an exit status of > 0, even if they succeeded. We will just
- * rely on whether session got filled in properly.
- */
if (virStorageBackendRunProgRegex(pool,
cmd,
1,
"--value", value,
NULL);
+ /* Ignore non-zero status. */
if (virCommandRun(cmd, &status) < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("Failed to update '%s' of node mode for target '%s'"),
pid_t pid;
char *pidfile;
bool reap;
+ bool rawStatus;
unsigned long long maxMemLock;
unsigned int maxProcesses;
cmd->flags |= VIR_EXEC_NONBLOCK;
}
+/**
+ * virCommandRawStatus:
+ * @cmd: the command to modify
+ *
+ * Mark this command as returning raw exit status via virCommandRun() or
+ * virCommandWait() (caller must use WIFEXITED() and friends, and can
+ * detect death from signals) instead of the default of only allowing
+ * normal exit status (caller must not use WEXITSTATUS(), and death from
+ * signals returns -1).
+ */
+void
+virCommandRawStatus(virCommandPtr cmd)
+{
+ if (!cmd || cmd->has_error)
+ return;
+
+ cmd->rawStatus = true;
+}
+
/* Add an environment variable to the cmd->env list. 'env' is a
* string like "name=value". If the named environment variable is
* already set, then it is replaced in the list.
* Returns -1 on any error executing the
* command. Returns 0 if the command executed,
* with the exit status set. If @exitstatus is NULL, then the
- * child must exit with status 0 for this to succeed.
+ * child must exit with status 0 for this to succeed. By default,
+ * a non-NULL @exitstatus contains the normal exit status of the child
+ * (death from a signal is treated as execution error); but if
+ * virCommandRawStatus() was used, it instead contains the raw exit
+ * status that the caller must then decipher using WIFEXITED() and friends.
*/
int
virCommandRun(virCommandPtr cmd, int *exitstatus)
* to complete. Return -1 on any error waiting for
* completion. Returns 0 if the command
* finished with the exit status set. If @exitstatus is NULL, then the
- * child must exit with status 0 for this to succeed.
+ * child must exit with status 0 for this to succeed. By default,
+ * a non-NULL @exitstatus contains the normal exit status of the child
+ * (death from a signal is treated as execution error); but if
+ * virCommandRawStatus() was used, it instead contains the raw exit
+ * status that the caller must then decipher using WIFEXITED() and friends.
*/
int
virCommandWait(virCommandPtr cmd, int *exitstatus)
* message is not as detailed as what we can provide. So, we
* guarantee that virProcessWait only fails due to failure to wait,
* and repeat the exitstatus check code ourselves. */
- ret = virProcessWait(cmd->pid, exitstatus ? exitstatus : &status, true);
+ ret = virProcessWait(cmd->pid, &status, true);
if (cmd->flags & VIR_EXEC_ASYNC_IO) {
cmd->flags &= ~VIR_EXEC_ASYNC_IO;
virThreadJoin(cmd->asyncioThread);
if (ret == 0) {
cmd->pid = -1;
cmd->reap = false;
- if (status) {
+ if (exitstatus && (cmd->rawStatus || WIFEXITED(status))) {
+ *exitstatus = cmd->rawStatus ? status : WEXITSTATUS(status);
+ } else if (status) {
char *str = virCommandToString(cmd);
char *st = virProcessTranslateStatus(status);
bool haveErrMsg = cmd->errbuf && *cmd->errbuf && (*cmd->errbuf)[0];
void virCommandNonblockingFDs(virCommandPtr cmd);
+void virCommandRawStatus(virCommandPtr cmd);
+
void virCommandAddEnvFormat(virCommandPtr cmd, const char *format, ...)
ATTRIBUTE_NONNULL(2) ATTRIBUTE_FMT_PRINTF(2, 3);
/*
* virebtables.c: Helper APIs for managing ebtables
*
- * Copyright (C) 2007-2013 Red Hat, Inc.
+ * Copyright (C) 2007-2014 Red Hat, Inc.
* Copyright (C) 2009 IBM Corp.
*
* This library is free software; you can redistribute it and/or
"firewalld support disabled for ebtables.");
} else {
virCommandPtr cmd = virCommandNew(firewall_cmd_path);
- int status;
virCommandAddArgList(cmd, "--state", NULL);
- if (virCommandRun(cmd, &status) < 0 || status != 0) {
+ if (virCommandRun(cmd, NULL) < 0) {
VIR_INFO("firewall-cmd found but disabled for ebtables");
VIR_FREE(firewall_cmd_path);
firewall_cmd_path = NULL;
/*
* viriptables.c: helper APIs for managing iptables
*
- * Copyright (C) 2007-2013 Red Hat, Inc.
+ * Copyright (C) 2007-2014 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
virIpTablesOnceInit(void)
{
virCommandPtr cmd;
- int status;
#if HAVE_FIREWALLD
firewall_cmd_path = virFindFileInPath("firewall-cmd");
cmd = virCommandNew(firewall_cmd_path);
virCommandAddArgList(cmd, "--state", NULL);
- if (virCommandRun(cmd, &status) < 0 || status != 0) {
+ if (virCommandRun(cmd, NULL) < 0) {
VIR_INFO("firewall-cmd found but disabled for iptables");
VIR_FREE(firewall_cmd_path);
firewall_cmd_path = NULL;
cmd = virCommandNew(IPTABLES_PATH);
virCommandAddArgList(cmd, "-w", "-L", "-n", NULL);
- if (virCommandRun(cmd, &status) < 0 || status != 0) {
+ if (virCommandRun(cmd, NULL) < 0) {
VIR_INFO("xtables locking not supported by your iptables");
} else {
VIR_INFO("using xtables locking for iptables");
/*
- * Copyright (C) 2010-2013 Red Hat, Inc.
+ * Copyright (C) 2010-2014 Red Hat, Inc.
* Copyright IBM Corp. 2008
*
* This library is free software; you can redistribute it and/or
VIR_DEBUG("Failed to create veth host: %s guest: %s: %d",
*veth1 ? *veth1 : veth1auto,
- *veth1 ? *veth1 : veth1auto,
+ *veth2 ? *veth2 : veth2auto,
status);
VIR_FREE(veth1auto);
VIR_FREE(veth2auto);
}
#ifdef WITH_LIBXL
-static int
+static bool
xenUnifiedXendProbe(void)
{
virCommandPtr cmd;
- int status;
- int ret = 0;
+ bool ret = false;
cmd = virCommandNewArgList("/usr/sbin/xend", "status", NULL);
- if (virCommandRun(cmd, &status) == 0 && status == 0)
- ret = 1;
+ if (virCommandRun(cmd, NULL) == 0)
+ ret = true;
virCommandFree(cmd);
return ret;
int status;
cmd = virCommandNew(abs_builddir "/commandhelper-doesnotexist");
+ if (virCommandRun(cmd, &status) < 0)
+ goto cleanup;
+ if (status != EXIT_ENOENT)
+ goto cleanup;
+
+ virCommandRawStatus(cmd);
if (virCommandRun(cmd, &status) < 0)
goto cleanup;
if (!WIFEXITED(status) || WEXITSTATUS(status) != EXIT_ENOENT)
cmd = virCommandNewArgList("/bin/sh", "-c", "exit 3", NULL);
+ if (virCommandRun(cmd, &status) < 0) {
+ virErrorPtr err = virGetLastError();
+ printf("Cannot run child %s\n", err->message);
+ goto cleanup;
+ }
+ if (status != 3) {
+ printf("Unexpected status %d\n", status);
+ goto cleanup;
+ }
+
+ virCommandRawStatus(cmd);
if (virCommandRun(cmd, &status) < 0) {
virErrorPtr err = virGetLastError();
printf("Cannot run child %s\n", err->message);
virCommandFree(cmd);
cmd = virCommandNewArgList("/bin/sh", "-c", "kill -9 $$", NULL);
+ if (virCommandRun(cmd, &status) == 0) {
+ printf("Death by signal not detected, status %d\n", status);
+ goto cleanup;
+ }
+
+ virCommandRawStatus(cmd);
if (virCommandRun(cmd, &status) < 0) {
virErrorPtr err = virGetLastError();
printf("Cannot run child %s\n", err->message);
bool ro = false;
virConnectPtr conn;
virDomainPtr dom;
- int status;
virCommandPtr cmd;
struct utsname ut;
if (strstr(ut.release, "xen") == NULL)
return EXIT_AM_SKIP;
cmd = virCommandNewArgList("/usr/sbin/xend", "status", NULL);
- if (virCommandRun(cmd, &status) != 0 || status != 0) {
+ if (virCommandRun(cmd, NULL) < 0) {
virCommandFree(cmd);
return EXIT_AM_SKIP;
}
mymain(void)
{
int ret = 0;
- int status;
virCommandPtr cmd;
struct utsname ut;
if (strstr(ut.release, "xen") == NULL)
return EXIT_AM_SKIP;
cmd = virCommandNewArgList("/usr/sbin/xend", "status", NULL);
- if (virCommandRun(cmd, &status) != 0 || status != 0) {
+ if (virCommandRun(cmd, NULL) < 0) {
virCommandFree(cmd);
return EXIT_AM_SKIP;
}