summaryrefslogtreecommitdiff
path: root/sys/src/cmd/ssh/sshnet.c
diff options
context:
space:
mode:
authorkhm <devnull@localhost>2017-01-12 16:36:38 -0800
committerkhm <devnull@localhost>2017-01-12 16:36:38 -0800
commitdc8c7bf2b73d608ac2483aee303a51a3507b4c5a (patch)
treef8c69dbf5f36de6f9acea724f2068054b5b8e7a6 /sys/src/cmd/ssh/sshnet.c
parentcb1555c7d741fa482c339aa9ac8a44753e2ad296 (diff)
ssh: R.I.P.
Diffstat (limited to 'sys/src/cmd/ssh/sshnet.c')
-rw-r--r--sys/src/cmd/ssh/sshnet.c1110
1 files changed, 0 insertions, 1110 deletions
diff --git a/sys/src/cmd/ssh/sshnet.c b/sys/src/cmd/ssh/sshnet.c
deleted file mode 100644
index 1de834c72..000000000
--- a/sys/src/cmd/ssh/sshnet.c
+++ /dev/null
@@ -1,1110 +0,0 @@
-/*
- * SSH network file system.
- * Presents remote TCP stack as /net-style file system.
- */
-
-#include "ssh.h"
-#include <bio.h>
-#include <ndb.h>
-#include <thread.h>
-#include <fcall.h>
-#include <9p.h>
-
-int rawhack = 1;
-Conn *conn;
-char *remoteip = "<remote>";
-char *mtpt;
-
-Cipher *allcipher[] = {
- &cipherrc4,
- &cipherblowfish,
- &cipher3des,
- &cipherdes,
- &ciphernone,
- &ciphertwiddle,
-};
-
-Auth *allauth[] = {
- &authpassword,
- &authrsa,
- &authtis,
-};
-
-char *cipherlist = "rc4 3des";
-char *authlist = "rsa password tis";
-
-Cipher*
-findcipher(char *name, Cipher **list, int nlist)
-{
- int i;
-
- for(i=0; i<nlist; i++)
- if(strcmp(name, list[i]->name) == 0)
- return list[i];
- error("unknown cipher %s", name);
- return nil;
-}
-
-Auth*
-findauth(char *name, Auth **list, int nlist)
-{
- int i;
-
- for(i=0; i<nlist; i++)
- if(strcmp(name, list[i]->name) == 0)
- return list[i];
- error("unknown auth %s", name);
- return nil;
-}
-
-void
-usage(void)
-{
- fprint(2, "usage: sshnet [-A authlist] [-c cipherlist] [-m mtpt] [user@]hostname\n");
- exits("usage");
-}
-
-int
-isatty(int fd)
-{
- char buf[64];
-
- buf[0] = '\0';
- fd2path(fd, buf, sizeof buf);
- if(strlen(buf)>=9 && strcmp(buf+strlen(buf)-9, "/dev/cons")==0)
- return 1;
- return 0;
-}
-
-enum
-{
- Qroot,
- Qcs,
- Qtcp,
- Qclone,
- Qn,
- Qctl,
- Qdata,
- Qlocal,
- Qremote,
- Qstatus,
-};
-
-#define PATH(type, n) ((type)|((n)<<8))
-#define TYPE(path) ((int)(path) & 0xFF)
-#define NUM(path) ((uint)(path)>>8)
-
-Channel *sshmsgchan; /* chan(Msg*) */
-Channel *fsreqchan; /* chan(Req*) */
-Channel *fsreqwaitchan; /* chan(nil) */
-Channel *fsclunkchan; /* chan(Fid*) */
-Channel *fsclunkwaitchan; /* chan(nil) */
-ulong time0;
-
-enum
-{
- Closed,
- Dialing,
- Established,
- Teardown,
-};
-
-char *statestr[] = {
- "Closed",
- "Dialing",
- "Established",
- "Teardown",
-};
-
-typedef struct Client Client;
-struct Client
-{
- int ref;
- int state;
- int num;
- int servernum;
- char *connect;
- Req *rq;
- Req **erq;
- Msg *mq;
- Msg **emq;
-};
-
-int nclient;
-Client **client;
-
-int
-newclient(void)
-{
- int i;
- Client *c;
-
- for(i=0; i<nclient; i++)
- if(client[i]->ref==0 && client[i]->state == Closed)
- return i;
-
- if(nclient%16 == 0)
- client = erealloc9p(client, (nclient+16)*sizeof(client[0]));
-
- c = emalloc9p(sizeof(Client));
- memset(c, 0, sizeof(*c));
- c->num = nclient;
- client[nclient++] = c;
- return c->num;
-}
-
-void
-queuereq(Client *c, Req *r)
-{
- if(c->rq==nil)
- c->erq = &c->rq;
- *c->erq = r;
- r->aux = nil;
- c->erq = (Req**)&r->aux;
-}
-
-void
-queuemsg(Client *c, Msg *m)
-{
- if(c->mq==nil)
- c->emq = &c->mq;
- *c->emq = m;
- m->link = nil;
- c->emq = (Msg**)&m->link;
-}
-
-void
-matchmsgs(Client *c)
-{
- Req *r;
- Msg *m;
- int n, rm;
-
- while(c->rq && c->mq){
- r = c->rq;
- c->rq = r->aux;
-
- rm = 0;
- m = c->mq;
- n = r->ifcall.count;
- if(n >= m->ep - m->rp){
- n = m->ep - m->rp;
- c->mq = m->link;
- rm = 1;
- }
- memmove(r->ofcall.data, m->rp, n);
- if(rm)
- free(m);
- else
- m->rp += n;
- r->ofcall.count = n;
- respond(r, nil);
- }
-}
-
-Req*
-findreq(Client *c, Req *r)
-{
- Req **l;
-
- for(l=&c->rq; *l; l=(Req**)&(*l)->aux){
- if(*l == r){
- *l = r->aux;
- if(*l == nil)
- c->erq = l;
- return r;
- }
- }
- return nil;
-}
-
-void
-dialedclient(Client *c)
-{
- Req *r;
-
- if(r=c->rq){
- if(r->aux != nil)
- sysfatal("more than one outstanding dial request (BUG)");
- if(c->state == Established)
- respond(r, nil);
- else
- respond(r, "connect failed");
- }
- c->rq = nil;
-}
-
-void
-teardownclient(Client *c)
-{
- Msg *m;
-
- c->state = Teardown;
- m = allocmsg(conn, SSH_MSG_CHANNEL_INPUT_EOF, 4);
- putlong(m, c->servernum);
- sendmsg(m);
-}
-
-void
-hangupclient(Client *c)
-{
- Req *r, *next;
- Msg *m, *mnext;
-
- c->state = Closed;
- for(m=c->mq; m; m=mnext){
- mnext = m->link;
- free(m);
- }
- c->mq = nil;
- for(r=c->rq; r; r=next){
- next = r->aux;
- respond(r, "hangup on network connection");
- }
- c->rq = nil;
-}
-
-void
-closeclient(Client *c)
-{
- Msg *m, *next;
-
- if(--c->ref)
- return;
-
- if(c->rq != nil)
- sysfatal("ref count reached zero with requests pending (BUG)");
-
- for(m=c->mq; m; m=next){
- next = m->link;
- free(m);
- }
- c->mq = nil;
-
- if(c->state != Closed)
- teardownclient(c);
-}
-
-
-void
-sshreadproc(void *a)
-{
- Conn *c;
- Msg *m;
-
- c = a;
- for(;;){
- m = recvmsg(c, -1);
- if(m == nil)
- sysfatal("eof on ssh connection");
- sendp(sshmsgchan, m);
- }
-}
-
-typedef struct Tab Tab;
-struct Tab
-{
- char *name;
- ulong mode;
-};
-
-Tab tab[] =
-{
- "/", DMDIR|0555,
- "cs", 0666,
- "tcp", DMDIR|0555,
- "clone", 0666,
- nil, DMDIR|0555,
- "ctl", 0666,
- "data", 0666,
- "local", 0444,
- "remote", 0444,
- "status", 0444,
-};
-
-static void
-fillstat(Dir *d, uvlong path)
-{
- Tab *t;
-
- memset(d, 0, sizeof(*d));
- d->uid = estrdup9p("ssh");
- d->gid = estrdup9p("ssh");
- d->qid.path = path;
- d->atime = d->mtime = time0;
- t = &tab[TYPE(path)];
- if(t->name)
- d->name = estrdup9p(t->name);
- else{
- d->name = smprint("%ud", NUM(path));
- if(d->name == nil)
- sysfatal("out of memory");
- }
- d->qid.type = t->mode>>24;
- d->mode = t->mode;
-}
-
-static void
-fsattach(Req *r)
-{
- if(r->ifcall.aname && r->ifcall.aname[0]){
- respond(r, "invalid attach specifier");
- return;
- }
- r->fid->qid.path = PATH(Qroot, 0);
- r->fid->qid.type = QTDIR;
- r->fid->qid.vers = 0;
- r->ofcall.qid = r->fid->qid;
- respond(r, nil);
-}
-
-static void
-fsstat(Req *r)
-{
- fillstat(&r->d, r->fid->qid.path);
- respond(r, nil);
-}
-
-static int
-rootgen(int i, Dir *d, void*)
-{
- i += Qroot+1;
- if(i <= Qtcp){
- fillstat(d, i);
- return 0;
- }
- return -1;
-}
-
-static int
-tcpgen(int i, Dir *d, void*)
-{
- i += Qtcp+1;
- if(i < Qn){
- fillstat(d, i);
- return 0;
- }
- i -= Qn;
- if(i < nclient){
- fillstat(d, PATH(Qn, i));
- return 0;
- }
- return -1;
-}
-
-static int
-clientgen(int i, Dir *d, void *aux)
-{
- Client *c;
-
- c = aux;
- i += Qn+1;
- if(i <= Qstatus){
- fillstat(d, PATH(i, c->num));
- return 0;
- }
- return -1;
-}
-
-static char*
-fswalk1(Fid *fid, char *name, Qid *qid)
-{
- int i, n;
- char buf[32];
- ulong path;
-
- path = fid->qid.path;
- if(!(fid->qid.type&QTDIR))
- return "walk in non-directory";
-
- if(strcmp(name, "..") == 0){
- switch(TYPE(path)){
- case Qn:
- qid->path = PATH(Qtcp, NUM(path));
- qid->type = tab[Qtcp].mode>>24;
- return nil;
- case Qtcp:
- qid->path = PATH(Qroot, 0);
- qid->type = tab[Qroot].mode>>24;
- return nil;
- case Qroot:
- return nil;
- default:
- return "bug in fswalk1";
- }
- }
-
- i = TYPE(path)+1;
- for(; i<nelem(tab); i++){
- if(i==Qn){
- n = atoi(name);
- snprint(buf, sizeof buf, "%d", n);
- if(n < nclient && strcmp(buf, name) == 0){
- qid->path = PATH(i, n);
- qid->type = tab[i].mode>>24;
- return nil;
- }
- break;
- }
- if(strcmp(name, tab[i].name) == 0){
- qid->path = PATH(i, NUM(path));
- qid->type = tab[i].mode>>24;
- return nil;
- }
- if(tab[i].mode&DMDIR)
- break;
- }
- return "directory entry not found";
-}
-
-typedef struct Cs Cs;
-struct Cs
-{
- char *resp;
- int isnew;
-};
-
-static int
-ndbfindport(char *p)
-{
- char *s, *port;
- int n;
- static Ndb *db;
-
- if(*p == '\0')
- return -1;
-
- n = strtol(p, &s, 0);
- if(*s == '\0')
- return n;
-
- if(db == nil){
- db = ndbopen("/lib/ndb/common");
- if(db == nil)
- return -1;
- }
-
- port = ndbgetvalue(db, nil, "tcp", p, "port", nil);
- if(port == nil)
- return -1;
- n = atoi(port);
- free(port);
-
- return n;
-}
-
-static void
-csread(Req *r)
-{
- Cs *cs;
-
- cs = r->fid->aux;
- if(cs->resp==nil){
- respond(r, "cs read without write");
- return;
- }
- if(r->ifcall.offset==0){
- if(!cs->isnew){
- r->ofcall.count = 0;
- respond(r, nil);
- return;
- }
- cs->isnew = 0;
- }
- readstr(r, cs->resp);
- respond(r, nil);
-}
-
-static void
-cswrite(Req *r)
-{
- int port, nf;
- char err[ERRMAX], *f[4], *s, *ns;
- Cs *cs;
-
- cs = r->fid->aux;
- s = emalloc(r->ifcall.count+1);
- memmove(s, r->ifcall.data, r->ifcall.count);
- s[r->ifcall.count] = '\0';
-
- nf = getfields(s, f, nelem(f), 0, "!");
- if(nf != 3){
- free(s);
- respond(r, "can't translate");
- return;
- }
- if(strcmp(f[0], "tcp") != 0 && strcmp(f[0], "net") != 0){
- free(s);
- respond(r, "unknown protocol");
- return;
- }
- port = ndbfindport(f[2]);
- if(port <= 0){
- free(s);
- respond(r, "no translation found");
- return;
- }
-
- ns = smprint("%s/tcp/clone %s!%d", mtpt, f[1], port);
- if(ns == nil){
- free(s);
- rerrstr(err, sizeof err);
- respond(r, err);
- return;
- }
- free(s);
- free(cs->resp);
- cs->resp = ns;
- cs->isnew = 1;
- r->ofcall.count = r->ifcall.count;
- respond(r, nil);
-}
-
-static void
-ctlread(Req *r, Client *c)
-{
- char buf[32];
-
- sprint(buf, "%d", c->num);
- readstr(r, buf);
- respond(r, nil);
-}
-
-static void
-ctlwrite(Req *r, Client *c)
-{
- char *f[3], *s;
- int nf;
- Msg *m;
-
- s = emalloc(r->ifcall.count+1);
- memmove(s, r->ifcall.data, r->ifcall.count);
- s[r->ifcall.count] = '\0';
-
- nf = tokenize(s, f, 3);
- if(nf == 0){
- free(s);
- respond(r, nil);
- return;
- }
-
- if(strcmp(f[0], "hangup") == 0){
- if(c->state != Established)
- goto Badarg;
- if(nf != 1)
- goto Badarg;
- queuereq(c, r);
- teardownclient(c);
- }else if(strcmp(f[0], "connect") == 0){
- if(c->state != Closed)
- goto Badarg;
- if(nf != 2)
- goto Badarg;
- c->connect = estrdup9p(f[1]);
- nf = getfields(f[1], f, nelem(f), 0, "!");
- if(nf != 2){
- free(c->connect);
- c->connect = nil;
- goto Badarg;
- }
- c->state = Dialing;
- m = allocmsg(conn, SSH_MSG_PORT_OPEN, 4+4+strlen(f[0])+4+4+strlen("localhost"));
- putlong(m, c->num);
- putstring(m, f[0]);
- putlong(m, ndbfindport(f[1]));
- putstring(m, "localhost");
- queuereq(c, r);
- sendmsg(m);
- }else{
- Badarg:
- respond(r, "bad or inappropriate tcp control message");
- }
- free(s);
-}
-
-static void
-dataread(Req *r, Client *c)
-{
- if(c->state != Established){
- respond(r, "not connected");
- return;
- }
- queuereq(c, r);
- matchmsgs(c);
-}
-
-static void
-datawrite(Req *r, Client *c)
-{
- Msg *m;
-
- if(c->state != Established){
- respond(r, "not connected");
- return;
- }
- if(r->ifcall.count){
- m = allocmsg(conn, SSH_MSG_CHANNEL_DATA, 4+4+r->ifcall.count);
- putlong(m, c->servernum);
- putlong(m, r->ifcall.count);
- putbytes(m, r->ifcall.data, r->ifcall.count);
- sendmsg(m);
- }
- r->ofcall.count = r->ifcall.count;
- respond(r, nil);
-}
-
-static void
-localread(Req *r)
-{
- char buf[128];
-
- snprint(buf, sizeof buf, "%s!%d\n", remoteip, 0);
- readstr(r, buf);
- respond(r, nil);
-}
-
-static void
-remoteread(Req *r, Client *c)
-{
- char *s;
- char buf[128];
-
- s = c->connect;
- if(s == nil)
- s = "::!0";
- snprint(buf, sizeof buf, "%s\n", s);
- readstr(r, buf);
- respond(r, nil);
-}
-
-static void
-statusread(Req *r, Client *c)
-{
- char buf[64];
- char *s;
-
- snprint(buf, sizeof buf, "%s!%d", remoteip, 0);
- s = statestr[c->state];
- readstr(r, s);
- respond(r, nil);
-}
-
-static void
-fsread(Req *r)
-{
- char e[ERRMAX];
- ulong path;
-
- path = r->fid->qid.path;
- switch(TYPE(path)){
- default:
- snprint(e, sizeof e, "bug in fsread path=%lux", path);
- respond(r, e);
- break;
-
- case Qroot:
- dirread9p(r, rootgen, nil);
- respond(r, nil);
- break;
-
- case Qcs:
- csread(r);
- break;
-
- case Qtcp:
- dirread9p(r, tcpgen, nil);
- respond(r, nil);
- break;
-
- case Qn:
- dirread9p(r, clientgen, client[NUM(path)]);
- respond(r, nil);
- break;
-
- case Qctl:
- ctlread(r, client[NUM(path)]);
- break;
-
- case Qdata:
- dataread(r, client[NUM(path)]);
- break;
-
- case Qlocal:
- localread(r);
- break;
-
- case Qremote:
- remoteread(r, client[NUM(path)]);
- break;
-
- case Qstatus:
- statusread(r, client[NUM(path)]);
- break;
- }
-}
-
-static void
-fswrite(Req *r)
-{
- ulong path;
- char e[ERRMAX];
-
- path = r->fid->qid.path;
- switch(TYPE(path)){
- default:
- snprint(e, sizeof e, "bug in fswrite path=%lux", path);
- respond(r, e);
- break;
-
- case Qcs:
- cswrite(r);
- break;
-
- case Qctl:
- ctlwrite(r, client[NUM(path)]);
- break;
-
- case Qdata:
- datawrite(r, client[NUM(path)]);
- break;
- }
-}
-
-static void
-fsopen(Req *r)
-{
- static int need[4] = { 4, 2, 6, 1 };
- ulong path;
- int n;
- Tab *t;
- Cs *cs;
-
- /*
- * lib9p already handles the blatantly obvious.
- * we just have to enforce the permissions we have set.
- */
- path = r->fid->qid.path;
- t = &tab[TYPE(path)];
- n = need[r->ifcall.mode&3];
- if((n&t->mode) != n){
- respond(r, "permission denied");
- return;
- }
-
- switch(TYPE(path)){
- case Qcs:
- cs = emalloc(sizeof(Cs));
- r->fid->aux = cs;
- respond(r, nil);
- break;
- case Qclone:
- n = newclient();
- path = PATH(Qctl, n);
- r->fid->qid.path = path;
- r->ofcall.qid.path = path;
- if(chatty9p)
- fprint(2, "open clone => path=%lux\n", path);
- t = &tab[Qctl];
- /* fall through */
- default:
- if(t-tab >= Qn)
- client[NUM(path)]->ref++;
- respond(r, nil);
- break;
- }
-}
-
-static void
-fsflush(Req *r)
-{
- int i;
-
- for(i=0; i<nclient; i++)
- if(findreq(client[i], r->oldreq))
- respond(r->oldreq, "interrupted");
- respond(r, nil);
-}
-
-static void
-handlemsg(Msg *m)
-{
- int chan, n;
- Client *c;
-
- switch(m->type){
- case SSH_MSG_DISCONNECT:
- case SSH_CMSG_EXIT_CONFIRMATION:
- sysfatal("disconnect");
-
- case SSH_CMSG_STDIN_DATA:
- case SSH_CMSG_EOF:
- case SSH_CMSG_WINDOW_SIZE:
- /* don't care */
- free(m);
- break;
-
- case SSH_MSG_CHANNEL_DATA:
- chan = getlong(m);
- n = getlong(m);
- if(m->rp+n != m->ep)
- sysfatal("got bad channel data");
- if(chan<nclient && (c=client[chan])->state==Established){
- queuemsg(c, m);
- matchmsgs(c);
- }else
- free(m);
- break;
-
- case SSH_MSG_CHANNEL_INPUT_EOF:
- chan = getlong(m);
- free(m);
- if(chan<nclient){
- c = client[chan];
- chan = c->servernum;
- hangupclient(c);
- m = allocmsg(conn, SSH_MSG_CHANNEL_OUTPUT_CLOSED, 4);
- putlong(m, chan);
- sendmsg(m);
- }
- break;
-
- case SSH_MSG_CHANNEL_OUTPUT_CLOSED:
- chan = getlong(m);
- if(chan<nclient)
- hangupclient(client[chan]);
- free(m);
- break;
-
- case SSH_MSG_CHANNEL_OPEN_CONFIRMATION:
- chan = getlong(m);
- c = nil;
- if(chan>=nclient || (c=client[chan])->state != Dialing){
- if(c)
- fprint(2, "cstate %d\n", c->state);
- sysfatal("got unexpected open confirmation for %d", chan);
- }
- c->servernum = getlong(m);
- c->state = Established;
- dialedclient(c);
- free(m);
- break;
-
- case SSH_MSG_CHANNEL_OPEN_FAILURE:
- chan = getlong(m);
- c = nil;
- if(chan>=nclient || (c=client[chan])->state != Dialing)
- sysfatal("got unexpected open failure");
- if(m->rp+4 <= m->ep)
- c->servernum = getlong(m);
- c->state = Closed;
- dialedclient(c);
- free(m);
- break;
- }
-}
-
-void
-fsnetproc(void*)
-{
- ulong path;
- Alt a[4];
- Cs *cs;
- Fid *fid;
- Req *r;
- Msg *m;
-
- threadsetname("fsthread");
-
- a[0].op = CHANRCV;
- a[0].c = fsclunkchan;
- a[0].v = &fid;
- a[1].op = CHANRCV;
- a[1].c = fsreqchan;
- a[1].v = &r;
- a[2].op = CHANRCV;
- a[2].c = sshmsgchan;
- a[2].v = &m;
- a[3].op = CHANEND;
-
- for(;;){
- switch(alt(a)){
- case 0:
- path = fid->qid.path;
- switch(TYPE(path)){
- case Qcs:
- cs = fid->aux;
- if(cs){
- free(cs->resp);
- free(cs);
- }
- break;
- }
- if(fid->omode != -1 && TYPE(path) >= Qn)
- closeclient(client[NUM(path)]);
- sendp(fsclunkwaitchan, nil);
- break;
- case 1:
- switch(r->ifcall.type){
- case Tattach:
- fsattach(r);
- break;
- case Topen:
- fsopen(r);
- break;
- case Tread:
- fsread(r);
- break;
- case Twrite:
- fswrite(r);
- break;
- case Tstat:
- fsstat(r);
- break;
- case Tflush:
- fsflush(r);
- break;
- default:
- respond(r, "bug in fsthread");
- break;
- }
- sendp(fsreqwaitchan, 0);
- break;
- case 2:
- handlemsg(m);
- break;
- }
- }
-}
-
-static void
-fssend(Req *r)
-{
- sendp(fsreqchan, r);
- recvp(fsreqwaitchan); /* avoids need to deal with spurious flushes */
-}
-
-static void
-fsdestroyfid(Fid *fid)
-{
- sendp(fsclunkchan, fid);
- recvp(fsclunkwaitchan);
-}
-
-void
-takedown(Srv*)
-{
- threadexitsall("done");
-}
-
-Srv fs =
-{
-.attach= fssend,
-.destroyfid= fsdestroyfid,
-.walk1= fswalk1,
-.open= fssend,
-.read= fssend,
-.write= fssend,
-.stat= fssend,
-.flush= fssend,
-.end= takedown,
-};
-
-void
-threadmain(int argc, char **argv)
-{
- int i, fd;
- char *host, *user, *p, *service;
- char *f[16];
- Msg *m;
- static Conn c;
-
- fmtinstall('B', mpfmt);
- fmtinstall('H', encodefmt);
-
- mtpt = "/net";
- service = nil;
- user = nil;
- ARGBEGIN{
- case 'B': /* undocumented, debugging */
- doabort = 1;
- break;
- case 'D': /* undocumented, debugging */
- debuglevel = strtol(EARGF(usage()), nil, 0);
- break;
- case '9': /* undocumented, debugging */
- chatty9p++;
- break;
-
- case 'A':
- authlist = EARGF(usage());
- break;
- case 'c':
- cipherlist = EARGF(usage());
- break;
- case 'm':
- mtpt = EARGF(usage());
- break;
- case 's':
- service = EARGF(usage());
- break;
- default:
- usage();
- }ARGEND
-
- if(argc != 1)
- usage();
-
- host = argv[0];
-
- if((p = strchr(host, '@')) != nil){
- *p++ = '\0';
- user = host;
- host = p;
- }
- if(user == nil)
- user = getenv("user");
- if(user == nil)
- sysfatal("cannot find user name");
-
- privatefactotum();
-
- if((fd = dial(netmkaddr(host, "tcp", "ssh"), nil, nil, nil)) < 0)
- sysfatal("dialing %s: %r", host);
-
- c.interactive = isatty(0);
- c.fd[0] = c.fd[1] = fd;
- c.user = user;
- c.host = host;
- setaliases(&c, host);
-
- c.nokcipher = getfields(cipherlist, f, nelem(f), 1, ", ");
- c.okcipher = emalloc(sizeof(Cipher*)*c.nokcipher);
- for(i=0; i<c.nokcipher; i++)
- c.okcipher[i] = findcipher(f[i], allcipher, nelem(allcipher));
-
- c.nokauth = getfields(authlist, f, nelem(f), 1, ", ");
- c.okauth = emalloc(sizeof(Auth*)*c.nokauth);
- for(i=0; i<c.nokauth; i++)
- c.okauth[i] = findauth(f[i], allauth, nelem(allauth));
-
- sshclienthandshake(&c);
-
- requestpty(&c); /* turns on TCP_NODELAY on other side */
- m = allocmsg(&c, SSH_CMSG_EXEC_SHELL, 0);
- sendmsg(m);
-
- time0 = time(0);
- sshmsgchan = chancreate(sizeof(Msg*), 16);
- fsreqchan = chancreate(sizeof(Req*), 0);
- fsreqwaitchan = chancreate(sizeof(void*), 0);
- fsclunkchan = chancreate(sizeof(Fid*), 0);
- fsclunkwaitchan = chancreate(sizeof(void*), 0);
-
- conn = &c;
- procrfork(sshreadproc, &c, 8192, RFNAMEG|RFNOTEG);
- procrfork(fsnetproc, nil, 8192, RFNAMEG|RFNOTEG);
-
- threadpostmountsrv(&fs, service, mtpt, MREPL);
- exits(0);
-}
-