mirror of
https://github.com/9fans/plan9port.git
synced 2025-01-24 11:41:58 +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>
|
Abhishek Kulkarni <adkulkar@umail.iu.edu>
|
||||||
Albert Lee <trisk@acm.jhu.edu>
|
Albert Lee <trisk@acm.jhu.edu>
|
||||||
|
Akshat Kumar <seed@mail.nanosouffle.net>
|
||||||
André Günther <Andre.G@gmx.de>
|
André Günther <Andre.G@gmx.de>
|
||||||
Anthony Martin <ality@pbrane.org>
|
Anthony Martin <ality@pbrane.org>
|
||||||
Anthony Sorace <a@9srv.net>
|
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