2016-11-25 17:18:40 +01:00
|
|
|
/*
|
|
|
|
* This file is part of the UCB release of Plan 9. It is subject to the license
|
|
|
|
* terms in the LICENSE file found in the top-level directory of this
|
|
|
|
* distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
|
|
|
|
* part of the UCB release of Plan 9, including this file, may be copied,
|
|
|
|
* modified, propagated, or distributed except according to the terms contained
|
|
|
|
* in the LICENSE file.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <u.h>
|
2017-04-19 23:33:14 +02:00
|
|
|
#include <lib9.h>
|
2016-11-25 17:18:40 +01:00
|
|
|
#include <bio.h>
|
|
|
|
#include <auth.h>
|
2016-12-01 00:09:42 +01:00
|
|
|
#include <9P2000.h>
|
2016-11-25 17:18:40 +01:00
|
|
|
|
|
|
|
#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)
|
|
|
|
{
|
2017-10-25 00:22:26 +02:00
|
|
|
fprint(2, "usage: ns/cat [-r] [pid]\n");
|
2016-11-25 17:18:40 +01:00
|
|
|
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 int32_t\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];
|
|
|
|
}
|