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 #include #include +#include #include #include @@ -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); }