#include #include #include #include #include #pragma varargck type "P" char* int nsrv; Dir *srv; Biobuf stdout; typedef struct Mount Mount; struct Mount { char *cmd; char *flag; char *new; char *old; char *spec; }; void xlatemnt(Mount*); char *quote(char*); int rflag; void usage(void) { fprint(2, "usage: ns [-r] [pid]\n"); exits("usage"); } void main(int argc, char **argv) { Mount *m; int line, fd, n, pid; char buf[1024], *av[5]; ARGBEGIN{ case 'r': rflag++; break; default: usage(); }ARGEND if(argc > 1) usage(); if(argc == 1){ pid = atoi(argv[0]); if(pid == 0) usage(); }else pid = getpid(); Binit(&stdout, 1, OWRITE); sprint(buf, "/proc/%d/ns", pid); fd = open(buf, OREAD); if(fd < 0) { fprint(2, "ns: open %s: %r\n", buf); exits("open ns"); } for(line=1; ; line++) { n = read(fd, buf, sizeof(buf)); if(n == sizeof(buf)) { fprint(2, "ns: ns string too long\n"); exits("read ns"); } if(n < 0) { fprint(2, "ns: read %r\n"); exits("read ns"); } if(n == 0) break; buf[n] = '\0'; m = mallocz(sizeof(Mount), 1); if(m == nil) { fprint(2, "ns: no memory: %r\n"); exits("no memory"); } n = tokenize(buf, av, 5); switch(n){ case 2: if(strcmp(av[0], "cd") == 0){ Bprint(&stdout, "%s %s\n", av[0], av[1]); continue; } /* fall through */ default: fprint(2, "ns: unrecognized format of ns file: %d elements on line %d\n", n, line); exits("format"); case 5: m->cmd = strdup(av[0]); m->flag = strdup(av[1]); m->new = strdup(av[2]); m->old = strdup(av[3]); m->spec = strdup(av[4]); break; case 4: if(av[1][0] == '-'){ m->cmd = strdup(av[0]); m->flag = strdup(av[1]); m->new = strdup(av[2]); m->old = strdup(av[3]); m->spec = strdup(""); }else{ m->cmd = strdup(av[0]); m->flag = strdup(""); m->new = strdup(av[1]); m->old = strdup(av[2]); m->spec = strdup(av[3]); } break; case 3: m->cmd = strdup(av[0]); m->flag = strdup(""); m->new = strdup(av[1]); m->old = strdup(av[2]); m->spec = strdup(""); break; } if(!rflag && strcmp(m->cmd, "mount")==0) xlatemnt(m); Bprint(&stdout, "%s %s %s %s %s\n", m->cmd, m->flag, quote(m->new), quote(m->old), quote(m->spec)); free(m->cmd); free(m->flag); free(m->new); free(m->old); free(m->spec); free(m); } exits(nil); } void xlatemnt(Mount *m) { int n, fd; char *s, *t, *net, *port; char buf[256]; if(strncmp(m->new, "/net/", 5) != 0) return; s = strdup(m->new); net = s+5; for(t=net; *t!='/'; t++) if(*t == '\0') goto Return; *t = '\0'; port = t+1; for(t=port; *t!='/'; t++) if(*t == '\0') goto Return; *t = '\0'; if(strcmp(t+1, "data") != 0) goto Return; snprint(buf, sizeof buf, "/net/%s/%s/remote", net, port); fd = open(buf, OREAD); if(fd < 0) goto Return; n = read(fd, buf, sizeof buf); close(fd); if(n<=1 || n>sizeof buf) goto Return; if(buf[n-1] == '\n') --n; buf[n] = '\0'; t = malloc(strlen(net)+1+n+1); if(t == nil) goto Return; sprint(t, "%s!%s", net, buf); free(m->new); m->new = t; Return: free(s); } char* quote(char *s) { static char buf[3][1024]; static int i; char *p, *ep; if(strpbrk(s, " '\\\t#$") == nil) return s; i = (i+1)%3; p = &buf[i][0]; ep = &buf[i][1024]; *p++ = '\''; while(p < ep-5){ switch(*s){ case '\0': goto out; case '\'': *p++ = '\''; break; } *p++ = *s++; } out: *p++ = '\''; *p = '\0'; return buf[i]; }