]> xenbits.xensource.com Git - libvirt.git/commitdiff
* src/Makefile.am src/openvz_conf.c src/openvz_conf.h
authorDaniel Veillard <veillard@redhat.com>
Thu, 19 Jul 2007 16:22:40 +0000 (16:22 +0000)
committerDaniel Veillard <veillard@redhat.com>
Thu, 19 Jul 2007 16:22:40 +0000 (16:22 +0000)
  src/openvz_driver.c src/qemu_driver.c src/util.c src/util.h:
  cleanup patches from Shuveb Hussain, with new util module for
  common code shared between drivers.
Daniel

ChangeLog
include/libvirt/virterror.h
src/Makefile.am
src/openvz_conf.c
src/openvz_conf.h
src/openvz_driver.c
src/qemu_driver.c
src/util.c [new file with mode: 0644]
src/util.h [new file with mode: 0644]

index 884f4699b527e3fe1768aef9c0ecbf3b0ac955be..a6a1a1d7e2e78a9df5d1ecd795a3c5249d206605 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+Thu Jul 19 18:21:47 CEST 2007 Daniel Veillard <veillard@redhat.com>
+
+       * src/Makefile.am src/openvz_conf.c src/openvz_conf.h
+         src/openvz_driver.c src/qemu_driver.c src/util.c src/util.h:
+         cleanup patches from Shuveb Hussain, with new util module for
+         common code shared between drivers.
+
 Thu Jul 19 16:35:00 BST 2007 Richard W.M. Jones <rjones@redhat.com>
 
        * configure.in, src/xen_internal.c: Newer Xen uses
index da115cbbe1b82b310640e6bd59c9cb2a778b873f..8e2701f47eaac9e2845304e7ea55819193ebd559 100644 (file)
@@ -51,6 +51,7 @@ typedef enum {
     VIR_FROM_NET,       /* Error when operating on a network */
     VIR_FROM_TEST,     /* Error from test driver */
     VIR_FROM_REMOTE,   /* Error from remote driver */
+    VIR_FROM_OPENVZ,    /* Error from OpenVZ driver */
 } virErrorDomain;
 
 
index c4bf4a2ac8dabe2bd31ed8d220a303791d6ee5f9..ff8e86d94edeb9889bf332c6c779382252009de4 100644 (file)
@@ -49,7 +49,8 @@ CLIENT_SOURCES =                                              \
                qemu_driver.c qemu_driver.h                     \
                qemu_conf.c qemu_conf.h                                 \
                openvz_conf.c openvz_conf.h                             \
-               openvz_driver.c openvz_driver.h                         
+               openvz_driver.c openvz_driver.h                 \
+               util.c util.h
 
 SERVER_SOURCES =                                               \
                ../qemud/protocol.h ../qemud/protocol.c         \
index 3f57bdb1e7ba4b6fbbeb30a649039b6723d2b1c7..2dc3f6c0c0ba88d6fc815ee428a273ac72f8ddb4 100644 (file)
@@ -57,7 +57,8 @@ error (virConnectPtr conn, virErrorNumber code, const char *info)
                      errmsg, info);
 }
 
-struct openvz_vm *openvzFindVMByID(const struct openvz_driver *driver, int id) {
+struct openvz_vm 
+*openvzFindVMByID(const struct openvz_driver *driver, int id) {
     struct openvz_vm *vm = driver->vms;
 
     while (vm) {
@@ -69,7 +70,8 @@ struct openvz_vm *openvzFindVMByID(const struct openvz_driver *driver, int id) {
     return NULL;
 }
 
-struct openvz_vm *openvzFindVMByUUID(const struct openvz_driver *driver,
+struct openvz_vm 
+*openvzFindVMByUUID(const struct openvz_driver *driver,
                                    const unsigned char *uuid) {
     struct openvz_vm *vm = driver->vms;
 
@@ -82,7 +84,8 @@ struct openvz_vm *openvzFindVMByUUID(const struct openvz_driver *driver,
     return NULL;
 }
 
-struct openvz_vm *openvzFindVMByName(const struct openvz_driver *driver,
+struct openvz_vm 
+*openvzFindVMByName(const struct openvz_driver *driver,
                                    const char *name) {
     struct  openvz_vm *vm = driver->vms;
 
@@ -96,7 +99,8 @@ struct openvz_vm *openvzFindVMByName(const struct openvz_driver *driver,
 }
 
 /* Free all memory associated with a struct openvz_vm object */
-void openvzFreeVMDef(struct openvz_vm_def *def) {
+void 
+openvzFreeVMDef(struct openvz_vm_def *def) {
     struct ovz_quota *quota = def->fs.quota;
     struct ovz_ip *ip = def->net.ips;
     struct ovz_ns *ns = def->net.ns;
@@ -124,8 +128,9 @@ void openvzFreeVMDef(struct openvz_vm_def *def) {
  * Parses a libvirt XML definition of a guest, and populates the
  * the openvz_vm struct with matching data about the guests config
  */
-static struct openvz_vm_def *openvzParseXML(virConnectPtr conn,
-                                                xmlDocPtr xml) {
+static struct openvz_vm_def 
+*openvzParseXML(virConnectPtr conn,
+                        xmlDocPtr xml) {
     xmlNodePtr root = NULL;
     xmlChar *prop = NULL;
     xmlXPathContextPtr ctxt = NULL;
@@ -249,7 +254,7 @@ openvzGetVPSInfo(virConnectPtr conn) {
     FILE *fp;
     int veid, ret;
     char status[16];
-    char uuidstr[(VIR_UUID_BUFLEN * 2) + 1];
+    char uuidstr[VIR_UUID_STRING_BUFLEN];
     struct openvz_vm *vm;
     struct openvz_vm  **pnext;
     struct openvz_driver *driver;
@@ -296,15 +301,9 @@ openvzGetVPSInfo(virConnectPtr conn) {
         
         snprintf(vmdef->name, OPENVZ_NAME_MAX,  "%i", veid);
         openvzGetVPSUUID(veid, uuidstr);
-        ret = sscanf(uuidstr, "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
-                    (unsigned int *)&vmdef->uuid[0], (unsigned int *)&vmdef->uuid[1], (unsigned int *)&vmdef->uuid[2], 
-                    (unsigned int *)&vmdef->uuid[3], (unsigned int *)&vmdef->uuid[4], (unsigned int *)&vmdef->uuid[5], 
-                    (unsigned int *)&vmdef->uuid[6], (unsigned int *)&vmdef->uuid[7], (unsigned int *)&vmdef->uuid[8], 
-                    (unsigned int *)&vmdef->uuid[9], (unsigned int *)&vmdef->uuid[10], (unsigned int *)&vmdef->uuid[11], 
-                    (unsigned int *)&vmdef->uuid[12], (unsigned int *)&vmdef->uuid[13], (unsigned int *)&vmdef->uuid[14],
-                    (unsigned int *)&vmdef->uuid[15]);
-
-        if(ret != 16) {
+        ret = virUUIDParse(uuidstr, vmdef->uuid);
+
+        if(ret == -1) {
             error(conn, VIR_ERR_INTERNAL_ERROR, "UUID in config file malformed");
             return NULL;
         }
@@ -315,7 +314,8 @@ openvzGetVPSInfo(virConnectPtr conn) {
     return vm;
 }
 
-char *openvzLocateConfDir(void)
+static char 
+*openvzLocateConfDir(void)
 {
     const char *conf_dir_list[] = {"/etc/vz/conf", "/usr/local/etc/conf", NULL};
     int i=0;
@@ -330,9 +330,8 @@ char *openvzLocateConfDir(void)
 }
 
 /* Richard Steven's classic readline() function */
-
-static
-int openvz_readline(int fd, char *ptr, int maxlen)
+int 
+openvz_readline(int fd, char *ptr, int maxlen)
 {
     int n, rc;
     char c;
@@ -356,7 +355,8 @@ int openvz_readline(int fd, char *ptr, int maxlen)
     return n;
 }
 
-int openvzGetVPSUUID(int vpsid, char *uuidbuf)
+static int 
+openvzGetVPSUUID(int vpsid, char *uuidbuf)
 {
     char conf_file[PATH_MAX];
     char line[1024];
@@ -385,7 +385,7 @@ int openvzGetVPSUUID(int vpsid, char *uuidbuf)
 
         sscanf(line, "%s %s\n", iden, uuid);
         if(!strcmp(iden, "#UUID:")) {
-            strncpy(uuidbuf, uuid, (VIR_UUID_BUFLEN * 2) +1);
+            strncpy(uuidbuf, uuid, VIR_UUID_STRING_BUFLEN);
             break;
         }
     }
@@ -396,10 +396,11 @@ int openvzGetVPSUUID(int vpsid, char *uuidbuf)
  * assign if not present.
  */
 
-int openvzSetUUID(int vpsid)
+static int 
+openvzSetUUID(int vpsid)
 {
     char conf_file[PATH_MAX];
-    char uuid[(VIR_UUID_BUFLEN * 2) + 1];
+    char uuid[VIR_UUID_STRING_BUFLEN];
     unsigned char new_uuid[VIR_UUID_BUFLEN];
     char *conf_dir;
     int fd, ret, i;
@@ -418,7 +419,7 @@ int openvzSetUUID(int vpsid)
 
     if(uuid[0] == (int)NULL) {
         virUUIDGenerate(new_uuid);
-        bzero(uuid, (VIR_UUID_BUFLEN * 2) + 1);
+        bzero(uuid, VIR_UUID_STRING_BUFLEN);
         for(i = 0; i < VIR_UUID_BUFLEN; i ++)
             sprintf(uuid + (i * 2), "%02x", (unsigned char)new_uuid[i]);
     
index ffc773868ccb571bf5cd7c036d9da4df5812b6fe..8871dbfcbb85d6361ac0c35f6f57348625470747 100644 (file)
@@ -94,8 +94,8 @@ struct openvz_vm {
     struct openvz_vm *next;
 };
 
-char *openvzLocateConfDir(void);
-int readline(int fd, char *ptr, int maxlen);
+static char *openvzLocateConfDir(void);
+int openvz_readline(int fd, char *ptr, int maxlen);
 static void error (virConnectPtr conn, virErrorNumber code, const char *info);
 struct openvz_vm *openvzFindVMByID(const struct openvz_driver *driver, int id); 
 struct openvz_vm *openvzFindVMByUUID(const struct openvz_driver *driver, 
@@ -108,7 +108,7 @@ struct openvz_vm_def *openvzParseVMDef(virConnectPtr conn, const char *xmlStr,
                                             const char *displayName);
 struct openvz_vm *openvzGetVPSInfo(virConnectPtr conn);
 void openvzGenerateUUID(unsigned char *uuid);
-int openvzGetVPSUUID(int vpsid, char *uuidbuf);
-int openvzSetUUID(int vpsid);
+static int openvzGetVPSUUID(int vpsid, char *uuidbuf);
+static int openvzSetUUID(int vpsid);
 int openvzAssignUUIDs(void);
 #endif /* OPENVZ_CONF_H */
index 18afd86b391e414aabcdc4a5de0c2ebd32b1acd9..e85aa8606fd88157bd010d5416e6b3e69cdca723 100644 (file)
@@ -52,6 +52,7 @@
 
 #include "event.h"
 #include "buf.h"
+#include "util.h"
 #include "openvz_driver.h"
 #include "openvz_conf.h"
 
@@ -284,6 +285,11 @@ static virDrvOpenStatus openvzOpen(virConnectPtr conn,
         if (strcmp(name, "openvz:///system")) 
             return VIR_DRV_OPEN_DECLINED;
     }
+    /* See if we are running an OpenVZ enabled kernel */
+    if(access("/proc/vz/veinfo", F_OK) == -1 || 
+                access("/proc/user_beancounters", F_OK) == -1) {
+        return VIR_DRV_OPEN_DECLINED;
+    }
 
     conn->privateData = &ovz_driver;
 
@@ -323,19 +329,25 @@ static const char *openvzGetType(virConnectPtr conn ATTRIBUTE_UNUSED) {
 
 static int openvzListDomains(virConnectPtr conn, int *ids, int nids) {
     int got = 0;
-    int veid;
-    FILE *fp;
+    int veid, pid, outfd, errfd;
+    int ret;
+    char buf[32];
+    const char *cmd[] = {VZLIST, "-ovpsid", "-H" , NULL};
 
-    if((fp = popen(VZLIST " -o vpsid -H 2> /dev/null", "r")) == NULL){
-        error(conn, VIR_ERR_INTERNAL_ERROR, "Could not popen " VZLIST);
+    ret = virExec(conn, (char **)cmd, &pid, &outfd, &errfd);
+    if(ret == -1) {
+        error(conn, VIR_ERR_INTERNAL_ERROR, "Could not exec " VZLIST);
         return (int)NULL;
     }
 
-    while(!(feof(fp)) && got < nids){
-        fscanf(fp, "%d\n", &veid);
+    while(got < nids){
+        ret = openvz_readline(outfd, buf, 32);
+        if(!ret) break;
+        sscanf(buf, "%d", &veid);
         ids[got] = veid;
         got ++;
     }
+    waitpid(pid, NULL, 0);
 
     return got;
 }
@@ -347,23 +359,27 @@ static int openvzNumDomains(virConnectPtr conn) {
 static int openvzListDefinedDomains(virConnectPtr conn,
                             char **const names, int nnames) {
     int got = 0;
-    FILE *fp;
-    int veid;
+    int veid, pid, outfd, errfd, ret;
     char vpsname[OPENVZ_NAME_MAX];
+    char buf[32];
+    const char *cmd[] = {VZLIST, "-ovpsid", "-H", NULL};
 
     /* the -S options lists only stopped domains */
-    if((fp = popen(VZLIST " -S -o vpsid -H 2> /dev/null", "r")) == NULL){
-        error(conn, VIR_ERR_INTERNAL_ERROR, "Could not popen " VZLIST);
+    ret = virExec(conn, (char **)cmd, &pid, &outfd, &errfd);
+    if(ret == -1) {
+        error(conn, VIR_ERR_INTERNAL_ERROR, "Could not exec " VZLIST);
         return (int)NULL;
     }
 
-    while(!(feof(fp)) && got < nnames){
-        fscanf(fp, "%d\n", &veid);
+    while(got < nnames){
+        ret = openvz_readline(outfd, buf, 32);
+        if(!ret) break;
+        sscanf(buf, "%d\n", &veid);
         sprintf(vpsname, "%d", veid);
         names[got] = strdup(vpsname);
         got ++;
     }
-
+    waitpid(pid, NULL, 0);
     return got;
 }
 
index 726841338943ed107f9a160e74f02209e08234ea..c207516b7bdb272e1f5782762a88851a55d9370f 100644 (file)
@@ -50,6 +50,7 @@
 
 #include "event.h"
 #include "buf.h"
+#include "util.h"
 #include "qemu_driver.h"
 #include "qemu_conf.h"
 
@@ -330,91 +331,6 @@ qemudShutdown(void) {
     return 0;
 }
 
-static int
-qemudExec(virConnectPtr conn,
-          char **argv,
-          int *retpid, int *outfd, int *errfd) {
-    int pid, null;
-    int pipeout[2] = {-1,-1};
-    int pipeerr[2] = {-1,-1};
-
-    if ((null = open(_PATH_DEVNULL, O_RDONLY)) < 0) {
-        qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, "cannot open %s : %s",
-                         _PATH_DEVNULL, strerror(errno));
-        goto cleanup;
-    }
-
-    if ((outfd != NULL && pipe(pipeout) < 0) ||
-        (errfd != NULL && pipe(pipeerr) < 0)) {
-        qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, "cannot create pipe : %s",
-                         strerror(errno));
-        goto cleanup;
-    }
-
-    if ((pid = fork()) < 0) {
-        qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, "cannot fork child process : %s",
-                         strerror(errno));
-        goto cleanup;
-    }
-
-    if (pid) { /* parent */
-        close(null);
-        if (outfd) {
-            close(pipeout[1]);
-            qemudSetNonBlock(pipeout[0]);
-            qemudSetCloseExec(pipeout[0]);
-            *outfd = pipeout[0];
-        }
-        if (errfd) {
-            close(pipeerr[1]);
-            qemudSetNonBlock(pipeerr[0]);
-            qemudSetCloseExec(pipeerr[0]);
-            *errfd = pipeerr[0];
-        }
-        *retpid = pid;
-        return 0;
-    }
-
-    /* child */
-
-    if (pipeout[0] > 0 && close(pipeout[0]) < 0)
-        _exit(1);
-    if (pipeerr[0] > 0 && close(pipeerr[0]) < 0)
-        _exit(1);
-
-    if (dup2(null, STDIN_FILENO) < 0)
-        _exit(1);
-    if (dup2(pipeout[1] > 0 ? pipeout[1] : null, STDOUT_FILENO) < 0)
-        _exit(1);
-    if (dup2(pipeerr[1] > 0 ? pipeerr[1] : null, STDERR_FILENO) < 0)
-        _exit(1);
-
-    close(null);
-    if (pipeout[1] > 0)
-        close(pipeout[1]);
-    if (pipeerr[1] > 0)
-        close(pipeerr[1]);
-
-    execvp(argv[0], argv);
-
-    _exit(1);
-
-    return 0;
-
- cleanup:
-    if (pipeerr[0] > 0)
-        close(pipeerr[0]);
-    if (pipeerr[1] > 0)
-        close(pipeerr[1]);
-    if (pipeout[0] > 0)
-        close(pipeout[0]);
-    if (pipeout[1] > 0)
-        close(pipeout[1]);
-    if (null > 0)
-        close(null);
-    return -1;
-}
-
 /* Return -1 for error, 1 to continue reading and 0 for success */
 typedef int qemudHandlerMonitorOutput(virConnectPtr conn,
                                       struct qemud_driver *driver,
@@ -722,7 +638,7 @@ static int qemudStartVMDaemon(virConnectPtr conn,
         qemudLog(QEMUD_WARN, "Unable to write argv to logfile %d: %s",
                  errno, strerror(errno));
 
-    if (qemudExec(conn, argv, &vm->pid, &vm->stdout, &vm->stderr) == 0) {
+    if (virExecNonBlock(conn, argv, &vm->pid, &vm->stdout, &vm->stderr) == 0) {
         vm->id = driver->nextvmid++;
         vm->state = VIR_DOMAIN_RUNNING;
 
@@ -981,7 +897,7 @@ dhcpStartDhcpDaemon(virConnectPtr conn,
     if (qemudBuildDnsmasqArgv(conn, network, &argv) < 0)
         return -1;
 
-    ret = qemudExec(conn, argv, &network->dnsmasqPid, NULL, NULL);
+    ret = virExecNonBlock(conn, argv, &network->dnsmasqPid, NULL, NULL);
 
     for (i = 0; argv[i]; i++)
         free(argv[i]);
diff --git a/src/util.c b/src/util.c
new file mode 100644 (file)
index 0000000..6459951
--- /dev/null
@@ -0,0 +1,192 @@
+/*
+ * utils.c: common, generic utility functions
+ *
+ * Copyright (C) 2006, 2007 Red Hat, Inc.
+ * Copyright (C) 2006 Daniel P. Berrange
+ * Copyright (C) 2006, 2007 Binary Karma
+ * Copyright (C) 2006 Shuveb Hussain
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
+ *
+ * Author: Daniel P. Berrange <berrange@redhat.com>
+ * File created Jul 18, 2007 - Shuveb Hussain <shuveb@binarykarma.com>
+ */
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <paths.h>
+#include <errno.h>
+#include <libvirt/virterror.h>
+#include "event.h"
+#include "buf.h"
+
+#define MAX_ERROR_LEN   1024
+
+static void 
+ReportError(virConnectPtr conn,
+                      virDomainPtr dom,
+                      virNetworkPtr net,
+                      int code, const char *fmt, ...) {
+    va_list args;
+    char errorMessage[MAX_ERROR_LEN];
+
+    if (fmt) {
+        va_start(args, fmt);
+        vsnprintf(errorMessage, MAX_ERROR_LEN-1, fmt, args);
+        va_end(args);
+    } else {
+        errorMessage[0] = '\0';
+    }
+    __virRaiseError(conn, dom, net, VIR_FROM_NONE, code, VIR_ERR_ERROR,
+                    NULL, NULL, NULL, -1, -1, errorMessage);
+}
+
+static int virSetCloseExec(int fd) {
+    int flags;
+    if ((flags = fcntl(fd, F_GETFD)) < 0)
+        return -1;
+    flags |= FD_CLOEXEC;
+    if ((fcntl(fd, F_SETFD, flags)) < 0)
+        return -1;
+    return 0;
+}
+
+static int virSetNonBlock(int fd) {
+    int flags;
+    if ((flags = fcntl(fd, F_GETFL)) < 0)
+        return -1;
+    flags |= O_NONBLOCK;
+    if ((fcntl(fd, F_SETFL, flags)) < 0)
+        return -1;
+    return 0;
+}
+
+static int
+_virExec(virConnectPtr conn,
+          char **argv,
+          int *retpid, int *outfd, int *errfd, int non_block) {
+    int pid, null;
+    int pipeout[2] = {-1,-1};
+    int pipeerr[2] = {-1,-1};
+
+    if ((null = open(_PATH_DEVNULL, O_RDONLY)) < 0) {
+        ReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, "cannot open %s : %s",
+                         _PATH_DEVNULL, strerror(errno));
+        goto cleanup;
+    }
+
+    if ((outfd != NULL && pipe(pipeout) < 0) ||
+        (errfd != NULL && pipe(pipeerr) < 0)) {
+        ReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, "cannot create pipe : %s",
+                         strerror(errno));
+        goto cleanup;
+    }
+
+    if ((pid = fork()) < 0) {
+        ReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, "cannot fork child process : %s",
+                         strerror(errno));
+        goto cleanup;
+    }
+
+    if (pid) { /* parent */
+        close(null);
+        if (outfd) {
+            close(pipeout[1]);
+            if(non_block)
+                if(virSetNonBlock(pipeout[0]) == -1)
+                    ReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, 
+                            "Failed to set non-blocking file descriptor flag");
+
+            if(virSetCloseExec(pipeout[0]) == -1)
+                ReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, 
+                        "Failed to set close-on-exec file descriptor flag");
+            *outfd = pipeout[0];
+        }
+        if (errfd) {
+            close(pipeerr[1]);
+            if(non_block)
+                if(virSetNonBlock(pipeerr[0]) == -1)
+                    ReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, 
+                            "Failed to set non-blocking file descriptor flag");
+
+            if(virSetCloseExec(pipeerr[0]) == -1)
+                ReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, 
+                        "Failed to set close-on-exec file descriptor flag");
+            *errfd = pipeerr[0];
+        }
+        *retpid = pid;
+        return 0;
+    }
+
+    /* child */
+
+    if (pipeout[0] > 0 && close(pipeout[0]) < 0)
+        _exit(1);
+    if (pipeerr[0] > 0 && close(pipeerr[0]) < 0)
+        _exit(1);
+
+    if (dup2(null, STDIN_FILENO) < 0)
+        _exit(1);
+    if (dup2(pipeout[1] > 0 ? pipeout[1] : null, STDOUT_FILENO) < 0)
+        _exit(1);
+    if (dup2(pipeerr[1] > 0 ? pipeerr[1] : null, STDERR_FILENO) < 0)
+        _exit(1);
+
+    close(null);
+    if (pipeout[1] > 0)
+        close(pipeout[1]);
+    if (pipeerr[1] > 0)
+        close(pipeerr[1]);
+
+    execvp(argv[0], argv);
+
+    _exit(1);
+
+    return 0;
+
+ cleanup:
+    if (pipeerr[0] > 0)
+        close(pipeerr[0]);
+    if (pipeerr[1] > 0)
+        close(pipeerr[1]);
+    if (pipeout[0] > 0)
+        close(pipeout[0]);
+    if (pipeout[1] > 0)
+        close(pipeout[1]);
+    if (null > 0)
+        close(null);
+    return -1;
+}
+
+int
+virExec(virConnectPtr conn,
+          char **argv,
+          int *retpid, int *outfd, int *errfd) {
+
+    _virExec(conn, argv, retpid, outfd, errfd, 0);
+
+}
+
+int
+virExecNonBlock(virConnectPtr conn,
+          char **argv,
+          int *retpid, int *outfd, int *errfd) {
+
+    _virExec(conn, argv, retpid, outfd, errfd, 1);
+
+}
+
diff --git a/src/util.h b/src/util.h
new file mode 100644 (file)
index 0000000..5b84043
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * utils.h: common, generic utility functions
+ *
+ * Copyright (C) 2006, 2007 Binary Karma
+ * Copyright (C) 2006 Shuveb Hussain
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
+ *
+ * File created Jul 18, 2007 - Shuveb Hussain <shuveb@binarykarma.com>
+ */
+
+int virExec(virConnectPtr conn, char **argv, int *retpid, int *outfd, int *errfd);
+int virExecNonBlock(virConnectPtr conn, char **argv, int *retpid, int *outfd, int *errfd);
+