219 lines
3.4 KiB
C
219 lines
3.4 KiB
C
#include <u.h>
|
|
#include <libc.h>
|
|
#include <bio.h>
|
|
#include <auth.h>
|
|
#include <fcall.h>
|
|
|
|
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], quote(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];
|
|
}
|