mirror of
https://github.com/9fans/plan9port.git
synced 2025-01-12 11:10:07 +00:00
src/cmd: Add a repurposed import(4), called `9import', to the ports.
The code is adapted from Plan 9's import(4); this allows us to speak that protocol. We don't currently support AAN (in the works) or TLS/SSL. Thanks to David for help with the man page, testing, and development. R=0intro, rsc CC=plan9port.codebot http://codereview.appspot.com/6458100
This commit is contained in:
parent
37f8ed2410
commit
ac3ba726f9
3 changed files with 319 additions and 0 deletions
|
@ -5,6 +5,7 @@
|
|||
|
||||
Abhishek Kulkarni <adkulkar@umail.iu.edu>
|
||||
Albert Lee <trisk@acm.jhu.edu>
|
||||
Akshat Kumar <seed@mail.nanosouffle.net>
|
||||
André Günther <Andre.G@gmx.de>
|
||||
Anthony Martin <ality@pbrane.org>
|
||||
Anthony Sorace <a@9srv.net>
|
||||
|
|
79
man/man4/9import.4
Normal file
79
man/man4/9import.4
Normal file
|
@ -0,0 +1,79 @@
|
|||
.TH 9IMPORT 4
|
||||
.SH NAME
|
||||
9import \- import a name space from a remote system
|
||||
.SH SYNOPSIS
|
||||
.B 9import
|
||||
[
|
||||
.I options
|
||||
]
|
||||
.I system
|
||||
.I file
|
||||
[
|
||||
.I mountpoint
|
||||
]
|
||||
.SH DESCRIPTION
|
||||
The
|
||||
.I 9import
|
||||
tool allows an arbitrary
|
||||
.I file
|
||||
on a remote
|
||||
.I system,
|
||||
with the capability of running the Plan 9
|
||||
.IR exportfs (4)
|
||||
service,
|
||||
to be imported into the local name space.
|
||||
Usually
|
||||
.I file
|
||||
is a directory, so the complete
|
||||
file tree under the directory is made available.
|
||||
.PP
|
||||
A process is started on the
|
||||
remote machine, with authority of the user of
|
||||
.IR 9import ,
|
||||
to perform work for the local machine using the
|
||||
.IR exportfs (4)
|
||||
service.
|
||||
The default port used is TCP 17007.
|
||||
If
|
||||
.I mountpoint
|
||||
is omitted, then
|
||||
.I 9import
|
||||
uses the name of the remote
|
||||
.I file
|
||||
as the local mount point.
|
||||
.PP
|
||||
The options are:
|
||||
.TF "-s namexxx"
|
||||
.PD
|
||||
.TP
|
||||
.B -A
|
||||
Skip the authentication protocol.
|
||||
This is useful for connecting to foreign systems like Inferno.
|
||||
.TP
|
||||
.B -k \fIkeypattern
|
||||
Use
|
||||
.I keypattern
|
||||
to select a key to authenticate to the remote side
|
||||
(see
|
||||
.IR auth (2)).
|
||||
.TP
|
||||
.B -p
|
||||
Push the
|
||||
.IR aan (8)
|
||||
filter onto the connection to protect against
|
||||
temporary network outages.
|
||||
.TP
|
||||
.B -s \fIname
|
||||
Post the connection's mountable file descriptor as
|
||||
.BI /srv/ name\fR.
|
||||
.SH SOURCE
|
||||
.B \*9/src/cmd/9import.c
|
||||
.SH SEE ALSO
|
||||
.IR srv (4),
|
||||
.IR aan (8),
|
||||
.IR listen1 (8),
|
||||
.B cs
|
||||
in
|
||||
.IR ndb (7)
|
||||
.SH BUGS
|
||||
Encryption is not implemented.
|
239
src/cmd/9import.c
Normal file
239
src/cmd/9import.c
Normal file
|
@ -0,0 +1,239 @@
|
|||
#include <u.h>
|
||||
#include <libc.h>
|
||||
#include <auth.h>
|
||||
#include <thread.h>
|
||||
|
||||
enum {
|
||||
Encnone,
|
||||
Encssl,
|
||||
Enctls,
|
||||
};
|
||||
|
||||
static char *encprotos[] = {
|
||||
[Encnone] = "clear",
|
||||
[Encssl] = "ssl",
|
||||
[Enctls] = "tls",
|
||||
nil,
|
||||
};
|
||||
|
||||
char *keyspec = "";
|
||||
char *filterp;
|
||||
char *ealgs = "rc4_256 sha1";
|
||||
int encproto = Encnone;
|
||||
AuthInfo *ai;
|
||||
int debug;
|
||||
int doauth = 1;
|
||||
int timedout;
|
||||
|
||||
int connectez(char*, char*);
|
||||
void sysfatal(char*, ...);
|
||||
void usage(void);
|
||||
int filter(int, char *, char *);
|
||||
|
||||
int
|
||||
catcher(void *v, char *msg)
|
||||
{
|
||||
timedout = 1;
|
||||
if(strcmp(msg, "alarm") == 0)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
lookup(char *s, char *l[])
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; l[i] != 0; i++)
|
||||
if (strcmp(l[i], s) == 0)
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static char*
|
||||
srvname(char *addr)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i=0; i<strlen(addr); i++){
|
||||
if(addr[i] == '!')
|
||||
addr[i] = ':';
|
||||
}
|
||||
return addr;
|
||||
}
|
||||
|
||||
void
|
||||
threadmain(int argc, char **argv)
|
||||
{
|
||||
char *mntpt, *srvpost, srvfile[64];
|
||||
int fd;
|
||||
|
||||
quotefmtinstall();
|
||||
srvpost = nil;
|
||||
ARGBEGIN{
|
||||
case 'A':
|
||||
doauth = 0;
|
||||
break;
|
||||
case 'd':
|
||||
debug++;
|
||||
break;
|
||||
case 'E':
|
||||
if ((encproto = lookup(EARGF(usage()), encprotos)) < 0)
|
||||
usage();
|
||||
break;
|
||||
case 'e':
|
||||
ealgs = EARGF(usage());
|
||||
if(*ealgs == 0 || strcmp(ealgs, "clear") == 0)
|
||||
ealgs = nil;
|
||||
break;
|
||||
case 'k':
|
||||
keyspec = EARGF(usage());
|
||||
break;
|
||||
case 'p':
|
||||
filterp = unsharp("#9/bin/aan");
|
||||
break;
|
||||
case 's':
|
||||
srvpost = EARGF(usage());
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
}ARGEND;
|
||||
|
||||
mntpt = 0; /* to shut up compiler */
|
||||
switch(argc) {
|
||||
case 2:
|
||||
mntpt = argv[1];
|
||||
break;
|
||||
case 3:
|
||||
mntpt = argv[2];
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
|
||||
if(encproto != Encnone)
|
||||
sysfatal("%s: tls and ssl have not yet been implemented", argv[0]);
|
||||
|
||||
threadnotify(catcher, 1);
|
||||
alarm(60*1000);
|
||||
|
||||
fd = connectez(argv[0], argv[1]);
|
||||
|
||||
fprint(fd, "impo %s %s\n", filterp? "aan": "nofilter",
|
||||
encprotos[encproto]);
|
||||
|
||||
if (filterp)
|
||||
fd = filter(fd, filterp, argv[0]);
|
||||
|
||||
if(srvpost == nil)
|
||||
srvpost = srvname(argv[0]);
|
||||
sprint(srvfile, "%s", srvpost);
|
||||
|
||||
if(post9pservice(fd, srvfile, mntpt) < 0)
|
||||
sysfatal("can't post %s: %r", argv[1]);
|
||||
alarm(0);
|
||||
|
||||
threadexitsall(0);
|
||||
}
|
||||
|
||||
/* the name "connect" is special */
|
||||
int
|
||||
connectez(char *system, char *tree)
|
||||
{
|
||||
char buf[ERRMAX], *na;
|
||||
int fd, n;
|
||||
char *authp;
|
||||
|
||||
na = netmkaddr(system, "tcp", "exportfs");
|
||||
threadsetname("dial %s", na);
|
||||
if((fd = dial(na, nil, nil, nil)) < 0)
|
||||
sysfatal("can't dial %s: %r", system);
|
||||
|
||||
if(doauth){
|
||||
authp = "p9any";
|
||||
threadsetname("auth_proxy auth_getkey proto=%q role=client %s",
|
||||
authp, keyspec);
|
||||
ai = auth_proxy(fd, auth_getkey, "proto=%q role=client %s",
|
||||
authp, keyspec);
|
||||
if(ai == nil)
|
||||
sysfatal("%r: %s", system);
|
||||
}
|
||||
|
||||
threadsetname("writing tree name %s", tree);
|
||||
n = write(fd, tree, strlen(tree));
|
||||
if(n < 0)
|
||||
sysfatal("can't write tree: %r");
|
||||
|
||||
strcpy(buf, "can't read tree");
|
||||
|
||||
threadsetname("awaiting OK for %s", tree);
|
||||
n = read(fd, buf, sizeof buf - 1);
|
||||
if(n!=2 || buf[0]!='O' || buf[1]!='K'){
|
||||
if (timedout)
|
||||
sysfatal("timed out connecting to %s", na);
|
||||
buf[sizeof buf - 1] = '\0';
|
||||
sysfatal("bad remote tree: %s", buf);
|
||||
}
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
void
|
||||
usage(void)
|
||||
{
|
||||
fprint(2, "usage: 9import [-A] [-E clear|ssl|tls] "
|
||||
"[-e 'crypt auth'|clear] [-k keypattern] [-p] [-s srv] host remotefs [mountpoint]\n");
|
||||
threadexitsall("usage");
|
||||
}
|
||||
|
||||
/* Network on fd1, mount driver on fd0 */
|
||||
int
|
||||
filter(int fd, char *cmd, char *host)
|
||||
{
|
||||
int p[2], len, argc;
|
||||
char newport[256], buf[256], *s;
|
||||
char *argv[16], *file, *pbuf;
|
||||
|
||||
if ((len = read(fd, newport, sizeof newport - 1)) < 0)
|
||||
sysfatal("filter: cannot write port; %r");
|
||||
newport[len] = '\0';
|
||||
|
||||
if ((s = strchr(newport, '!')) == nil)
|
||||
sysfatal("filter: illegally formatted port %s", newport);
|
||||
|
||||
strecpy(buf, buf+sizeof buf, netmkaddr(host, "tcp", "0"));
|
||||
pbuf = strrchr(buf, '!');
|
||||
strecpy(pbuf, buf+sizeof buf, s);
|
||||
|
||||
if(debug)
|
||||
fprint(2, "filter: remote port %s\n", newport);
|
||||
|
||||
argc = tokenize(cmd, argv, nelem(argv)-2);
|
||||
if (argc == 0)
|
||||
sysfatal("filter: empty command");
|
||||
argv[argc++] = "-c";
|
||||
argv[argc++] = buf;
|
||||
argv[argc] = nil;
|
||||
file = argv[0];
|
||||
if (s = strrchr(argv[0], '/'))
|
||||
argv[0] = s+1;
|
||||
|
||||
if(pipe(p) < 0)
|
||||
sysfatal("pipe: %r");
|
||||
|
||||
switch(rfork(RFNOWAIT|RFPROC|RFFDG)) {
|
||||
case -1:
|
||||
sysfatal("rfork record module: %r");
|
||||
case 0:
|
||||
dup(p[0], 1);
|
||||
dup(p[0], 0);
|
||||
close(p[0]);
|
||||
close(p[1]);
|
||||
exec(file, argv);
|
||||
sysfatal("exec record module: %r");
|
||||
default:
|
||||
close(fd);
|
||||
close(p[0]);
|
||||
}
|
||||
return p[1];
|
||||
}
|
Loading…
Reference in a new issue