X-Git-Url: http://git.linux-vserver.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=util-vserver%2Fsrc%2Fvserver-info.c;h=9976e9921e024ca4ab00add806187b0f6e37da0f;hb=7fdb31f6a9475c02a5e56e3a83c22f37ede24792;hp=625e656e08c64fc8f64eaaa986922fbac7f25a10;hpb=f7184df7c2f4f95f69dd28bf834609f06a2ff909;p=util-vserver.git diff --git a/util-vserver/src/vserver-info.c b/util-vserver/src/vserver-info.c index 625e656..9976e99 100644 --- a/util-vserver/src/vserver-info.c +++ b/util-vserver/src/vserver-info.c @@ -20,6 +20,7 @@ # include #endif +#include "lib/utils-legacy.h" #include "pathconfig.h" #include "util.h" @@ -33,17 +34,21 @@ #include #include #include +#include +#include #define ENSC_WRAPPERS_FCNTL 1 #define ENSC_WRAPPERS_IO 1 #define ENSC_WRAPPERS_UNISTD 1 +#define ENSC_WRAPPERS_VSERVER 1 #include -typedef enum { tgNONE,tgCONTEXT, tgRUNNING, +typedef enum { tgNONE,tgCONTEXT, tgID, tgRUNNING, tgVDIR, tgNAME, tgCFGDIR, tgAPPDIR, - tgAPIVER, + tgAPIVER, tgPXID, tgINITPID, tgINITPID_PID, tgXID, tgUTS, tgSYSINFO, + tgFEATURE, } VserverTag; static struct { @@ -51,7 +56,9 @@ static struct { VserverTag const val; char const * const descr; } const TAGS[] = { - { "CONTEXT", tgCONTEXT, "the current and/or assigned context" }, + { "CONTEXT", tgCONTEXT, ("the current and/or assigned context; when an optinal argument " + "evaluates to false,only the current context will be printed") }, + { "ID", tgID, "gives out the vserver-id for the context-xid" }, { "RUNNING", tgRUNNING, "gives out '1' when vserver is running; else, it fails without output" }, { "VDIR", tgVDIR, "gives out the root-directory of the vserver" }, { "NAME", tgNAME, "gives out the name of the vserver" }, @@ -65,6 +72,8 @@ static struct { "context, sysname, nodename, release, version, " "machine and domainname") }, { "SYSINFO", tgSYSINFO, "gives out information about the systen" }, + { "FEATURE", tgFEATURE, "returns 0 iff the queried feature is supported" }, + { "PXID", tgPXID, "returns the xid of the parent context" }, }; int wrapper_exit_code = 1; @@ -174,18 +183,90 @@ getXid(char *buf, char const *vserver) } static char * -getInitPid(char *buf, xid_t xid) +getPXid(char UNUSED *buf, char const UNUSED *vserver) +{ + // TODO: implement me when available + return 0; +} + +static char * +getInitPid_native(char *buf, xid_t xid) { struct vc_vx_info info; if (vc_get_vx_info(xid, &info)==-1) perror("vc_get_vx_info()"); else { - utilvserver_fmt_long(buf, info.xid); + utilvserver_fmt_long(buf, info.initpid); + return buf; + } + + return 0; +} + +#if defined(VC_ENABLE_API_COMPAT) || defined(VC_ENABLE_API_V11) +static int +selectPid(struct dirent const *ent) +{ + return atoi(ent->d_name)!=0; +} + +static bool +getInitPid_internal(pid_t pid, xid_t xid, pid_t *res) +{ + *res = -1; + + for (;*res==-1;) { + size_t bufsize = utilvserver_getProcEntryBufsize(); + char buf[bufsize+1]; + char *pos = 0; + + pos = utilvserver_getProcEntry(pid, "\ns_context: ", buf, bufsize); + if (pos==0 && errno==EAGAIN) continue; + + if (pos==0 || (xid_t)atoi(pos)!=xid) return false; + + buf[bufsize] = '\0'; + pos = strstr(buf, "\ninitpid: "); + + if (pos!=0) { + pos += sizeof("\ninitpid: ")-1; + if (strncmp(pos, "none", 4)==0) *res = -1; + else *res = atoi(pos); + } + } + + return true; +} + +static char * +getInitPid_emulated(char *buf, xid_t xid) +{ + struct dirent **namelist; + int n; + + switchToWatchXid(0); // ignore errors silently... + n = scandir("/proc", &namelist, selectPid, alphasort); + if (n<0) perror("scandir()"); + else while (n--) { + pid_t pid; + if (!getInitPid_internal(atoi(namelist[n]->d_name), xid, &pid)) continue; + + utilvserver_fmt_long(buf, pid); return buf; } return 0; } +#endif // VC_ENABLE_API_COMPAT + +static char * +getInitPid(char *buf, xid_t xid) +{ + if (vc_isSupported(vcFEATURE_VINFO)) + return getInitPid_native(buf, xid); + else + return getInitPid_emulated(buf, xid); +} static char * getInitPidPid(char *buf, char const *vserver) @@ -197,7 +278,7 @@ getInitPidPid(char *buf, char const *vserver) if (xid==VC_NOCTX) perror("vc_get_task_xid()"); else if (vc_get_vx_info(xid, &info)==-1) perror("vc_get_vx_info()"); else { - utilvserver_fmt_long(buf, info.xid); + utilvserver_fmt_long(buf, info.initpid); return buf; } @@ -280,9 +361,10 @@ printSysInfo(char *buf) } static char * -getContext(char *buf, char const *vserver) +getContext(char *buf, char const *vserver, bool allow_only_static) { - xid_t xid = vc_getVserverCtx(vserver, vcCFG_AUTO, true, 0); + xid_t xid = vc_getVserverCtx(vserver, vcCFG_AUTO, + allow_only_static, 0); if (xid==VC_NOCTX) return 0; utilvserver_fmt_long(buf, xid); @@ -290,11 +372,22 @@ getContext(char *buf, char const *vserver) } static int +testFeature(int argc, char *argv[]) +{ + return (argc>0 && vc_isSupportedString(argv[0])) ? EXIT_SUCCESS : EXIT_FAILURE; +} + +static bool +str2bool(char const *str) +{ + return atoi(str)!=0 || strchr("yYtY", str[0])!=0 || strcasecmp("true", str)==0; +} + +static int execQuery(char const *vserver, VserverTag tag, int argc, char *argv[]) { char const * res = 0; char buf[sizeof(xid_t)*4 + 1024]; - xid_t xid = *vserver!='\0' ? (xid_t)(atoi(vserver)) : VC_SAMECTX; memset(buf, 0, sizeof buf); switch (tag) { @@ -311,15 +404,26 @@ execQuery(char const *vserver, VserverTag tag, int argc, char *argv[]) res = (vc_getVserverCtx(vserver, vcCFG_AUTO, false, 0)==VC_NOCTX) ? 0 : "1"; break; - case tgCONTEXT : res = getContext(buf, vserver); break; - case tgXID : res = getXid(buf, vserver); break; - case tgINITPID : res = getInitPid(buf, xid); break; + case tgCONTEXT : res = getContext(buf, vserver, + argc==0 || str2bool(argv[0])); break; case tgINITPID_PID : res = getInitPidPid(buf, vserver); break; case tgAPIVER : res = getAPIVer(buf); break; - case tgUTS : res = getUTS(buf, xid, argc, argv); break; + case tgXID : res = getXid(buf, vserver); break; + case tgPXID : res = getPXid(buf, vserver); break; case tgSYSINFO : return printSysInfo(buf); break; + case tgFEATURE : return testFeature(argc,argv); break; + + default : { + xid_t xid = *vserver!='\0' ? vc_xidopt2xid(vserver,true,0) : VC_SAMECTX; + + switch (tag) { + case tgID : res = vc_getVserverByCtx(xid,0,0); break; + case tgINITPID : res = getInitPid(buf, xid); break; + case tgUTS : res = getUTS(buf, xid, argc, argv); break; - default : assert(false); abort(); // TODO + default : assert(false); abort(); // TODO + } + } } if (res==0) return EXIT_FAILURE;