Hi, libvirt developers
I found very interesting libvirt and i wrote patch for BZ#732264
I added support for parsing ~/.virsh/rc file.
rc file in format KEY = VALUE
symbol '#' - comment
Now, only one value added for parsing - VIRSH_DEFAULT_CONNECT_URI.
This value can be overwrite by env variable VIRSH_DEFAULT_CONNECT_URI.
Thanks
P.S. How to add patch file? As attached file or in mail body?
P.P.S. I am using irc, my nick - fenksa
---
diff --git a/tools/virsh.c b/tools/virsh.c
index e712e53..8360c57 100644
--- a/tools/virsh.c
+++ b/tools/virsh.c
@@ -33,6 +33,7 @@
#include <signal.h>
#include <poll.h>
#include <strings.h>
+#include <pwd.h>
#include <libxml/parser.h>
#include <libxml/tree.h>
@@ -19313,6 +19314,132 @@ vshParseArgv(vshControl *ctl, int argc, char **argv)
return true;
}
+#define DEFAULT_RC_FILENAME ".virsh/rc"
+
+static const char*
+vshRcPath(vshControl* ctl) {
+ const char* home;
+ char* path;
+
+ home = virGetUserDirectory(getuid());
+ path = vshMalloc(ctl, strlen(home) + strlen(DEFAULT_RC_FILENAME) + 2);
+
+ memcpy(path, home, strlen(home));
+ path[strlen(home)] = '/';
+ memcpy(path + strlen(home) + 1, DEFAULT_RC_FILENAME,
strlen(DEFAULT_RC_FILENAME));
+
+ VIR_FREE(home);
+
+ return path;
+}
+
+typedef struct {
+ char* buf;
+ int len;
+ int p;
+} RcParseBuffer;
+
+static void
+vshClearRcParseBuffer(RcParseBuffer* buf) {
+ buf->p = 0;
+ bzero(buf->buf, buf->len);
+}
+
+static void
+vshInitRcParseBuffer(vshControl* ctl, RcParseBuffer* buf, int len) {
+ buf->buf = vshMalloc(ctl, len);
+ buf->len = len;
+ vshClearRcParseBuffer(buf);
+};
+
+static void
+vshAddCharRcParseBuffer(RcParseBuffer* buf, char ch) {
+ if (buf->p < buf->len) {
+ buf->buf[buf->p] = ch;
+ buf->p = buf->p + 1;
+ }
+}
+
+static void
+vshParseRc(vshControl *ctl)
+{
+ int fd;
+ const char* fileName = vshRcPath(ctl);
+ bool parseValue = false;
+
+ RcParseBuffer keyBuffer;
+ RcParseBuffer valueBuffer;
+ char buffer[1024];
+
+ vshInitRcParseBuffer(ctl, &keyBuffer, 255);
+ vshInitRcParseBuffer(ctl, &valueBuffer, 255);
+
+ /* open ~/.virsh/rc file */
+ if ((fd = open(fileName, O_RDONLY)) <= 0) {
+ vshDebug(ctl, VSH_ERR_INFO, "can't open file %s\n", fileName);
+ goto cleanup;
+ }
+
+ struct stat statBuf;
+ if (fstat(fd, &statBuf) == -1) {
+ vshDebug(ctl, VSH_ERR_INFO, "file %s not stated\n", fileName);
+ goto cleanup;
+ }
+
+ if (!S_ISREG(statBuf.st_mode)) {
+ vshError(ctl, _("file %s is not regular\n"), fileName);
+ goto cleanup;
+ }
+
+ int bytesRead;
+ while ((bytesRead = read(fd, buffer, sizeof(buffer))) > 0) {
+ for (int i = 0; i < bytesRead; i++) {
+ /* ignore empty spaces and comments */
+ if (buffer[i] == ' ' || buffer[i] == '#') {
+ continue;
+ }
+
+ /* found separator = */
+ if (buffer[i] == '=') {
+ if (!parseValue) {
+ parseValue = true;
+ continue;
+ }
+ }
+
+ /* end of line*/
+ if (buffer[i] == '\n') {
+ if (STREQ(keyBuffer.buf, "VIRSH_DEFAULT_CONNECT_URI")) {
+ ctl->name = vshStrdup(ctl, valueBuffer.buf);
+ }
+
+ vshClearRcParseBuffer(&keyBuffer);
+ vshClearRcParseBuffer(&valueBuffer);
+
+ parseValue = false;
+ continue;
+ }
+
+ if (parseValue) {
+ vshAddCharRcParseBuffer(&valueBuffer, buffer[i]);
+ } else {
+ vshAddCharRcParseBuffer(&keyBuffer, buffer[i]);
+ }
+ }
+ }
+
+cleanup:
+ if (fd >= 0) {
+ if (close(fd) < 0) {
+ vshError(ctl, _("cannot close file %s"), fileName);
+ }
+ }
+ VIR_FREE(fileName);
+ VIR_FREE(keyBuffer.buf);
+ VIR_FREE(valueBuffer.buf);
+}
+
+
int
main(int argc, char **argv)
{
@@ -19355,6 +19482,8 @@ main(int argc, char **argv)
else
progname++;
+ vshParseRc(ctl);
+
if ((defaultConn = getenv("VIRSH_DEFAULT_CONNECT_URI"))) {
ctl->name = vshStrdup(ctl, defaultConn);
}
--
With best wishes, Maxim Sditanov