⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sshnet.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 2 页
字号:
	cs->resp = ns;	cs->isnew = 1;	r->ofcall.count = r->ifcall.count;	respond(r, nil);}static voidctlread(Req *r, Client *c){	char buf[32];	sprint(buf, "%d", c->num);	readstr(r, buf);	respond(r, nil);}static voidctlwrite(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 voiddataread(Req *r, Client *c){	if(c->state != Established){		respond(r, "not connected");		return;	}	queuereq(c, r);	matchmsgs(c);}static voiddatawrite(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 voidlocalread(Req *r){	char buf[128];	snprint(buf, sizeof buf, "%s!%d\n", remoteip, 0);	readstr(r, buf);	respond(r, nil);}static voidremoteread(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 voidstatusread(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 voidfsread(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 voidfswrite(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 voidfsopen(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 voidfsflush(Req *r){	int i;	for(i=0; i<nclient; i++)		if(findreq(client[i], r->oldreq))			respond(r->oldreq, "interrupted");	respond(r, nil);}static voidhandlemsg(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;	}}voidfsnetproc(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 voidfssend(Req *r){	sendp(fsreqchan, r);	recvp(fsreqwaitchan);	/* avoids need to deal with spurious flushes */}static voidfsdestroyfid(Fid *fid){	sendp(fsclunkchan, fid);	recvp(fsclunkwaitchan);}voidtakedown(Srv*){	threadexitsall("done");}Srv fs = {.attach=		fssend,.destroyfid=	fsdestroyfid,.walk1=		fswalk1,.open=		fssend,.read=		fssend,.write=		fssend,.stat=		fssend,.flush=		fssend,.end=		takedown,};voidthreadmain(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);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -