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

📄 proto.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 2 页
字号:
#include <u.h>#include <libc.h>#include <bio.h>#include <ip.h>#include <mp.h>#include <libsec.h>#include <auth.h>#include <fcall.h>#include <ctype.h>#include <String.h>#include "ftpfs.h"enum{	/* return codes */	Extra=		1,	Success=	2,	Incomplete=	3,	TempFail=	4,	PermFail=	5,	Impossible=	6,};Node	*remdir;		/* current directory on remote machine */Node	*remroot;		/* root directory on remote machine */int	ctlfd;			/* fd for control connection */Biobuf	ctlin;			/* input buffer for control connection */Biobuf	stdin;			/* input buffer for standard input */Biobuf	dbuf;			/* buffer for data connection */char	msg[512];		/* buffer for replies */char	net[Maxpath];		/* network for connections */int	listenfd;		/* fd to listen on for connections */char	netdir[Maxpath];int	os, defos;char	topsdir[64];		/* name of listed directory for TOPS */String	*remrootpath;	/* path on remote side to remote root */char	*user;int	nopassive;long	lastsend;extern int usetls;static void	sendrequest(char*, char*);static int	getreply(Biobuf*, char*, int, int);static int	active(int, Biobuf**, char*, char*);static int	passive(int, Biobuf**, char*, char*);static int	data(int, Biobuf**, char*, char*);static int	port(void);static void	ascii(void);static void	image(void);static void	unixpath(Node*, String*);static void	vmspath(Node*, String*);static void	mvspath(Node*, String*);static Node*	vmsdir(char*);static int	getpassword(char*, char*);static int	nw_mode(char dirlet, char *s);/* *  connect to remote server, default network is "tcp/ip" */voidhello(char *dest){	char *p;	char dir[Maxpath];	TLSconn conn;	Binit(&stdin, 0, OREAD);	/* init for later use */	ctlfd = dial(netmkaddr(dest, "tcp", "ftp"), 0, dir, 0);	if(ctlfd < 0){		fprint(2, "can't dial %s: %r\n", dest);		exits("dialing");	}			Binit(&ctlin, ctlfd, OREAD);	/* remember network for the data connections */	p = strrchr(dir+1, '/');	if(p == 0)		fatal("wrong dial(2) linked with ftp");	*p = 0;	safecpy(net, dir, sizeof(net));	/* wait for hello from other side */	if(getreply(&ctlin, msg, sizeof(msg), 1) != Success)		fatal("bad hello");	if(strstr(msg, "Plan 9"))		os = Plan9;	if(usetls){		sendrequest("AUTH", "TLS");		if(getreply(&ctlin, msg, sizeof(msg), 1) != Success)			fatal("bad auth tls");		ctlfd = tlsClient(ctlfd, &conn);		if(ctlfd < 0)			fatal("starting tls: %r");		free(conn.cert);		Binit(&ctlin, ctlfd, OREAD);		sendrequest("PBSZ", "0");		if(getreply(&ctlin, msg, sizeof(msg), 1) != Success)			fatal("bad pbsz 0");		sendrequest("PROT", "P");		if(getreply(&ctlin, msg, sizeof(msg), 1) != Success)			fatal("bad prot p");	}}/* *  login to remote system */voidrlogin(char *rsys, char *keyspec){	char *line;	char pass[128];	UserPasswd *up;	up = nil;	for(;;){		if(up == nil && os != Plan9)			up = auth_getuserpasswd(auth_getkey, "proto=pass server=%s service=ftp %s", rsys, keyspec);		if(up != nil){			sendrequest("USER", up->user);		} else {			print("User[default = %s]: ", user);			line = Brdline(&stdin, '\n');			if(line == 0)				exits(0);			line[Blinelen(&stdin)-1] = 0;			if(*line){				free(user);				user = strdup(line);			}			sendrequest("USER", user);		}		switch(getreply(&ctlin, msg, sizeof(msg), 1)){		case Success:			goto out;		case Incomplete:			break;		case TempFail:		case PermFail:			continue;		}		if(up != nil){			sendrequest("PASS", up->passwd);		} else {			if(getpassword(pass, pass+sizeof(pass)) < 0)				exits(0);			sendrequest("PASS", pass);		}		if(getreply(&ctlin, msg, sizeof(msg), 1) == Success){			if(strstr(msg, "Sess#"))				defos = MVS;			break;		}	}out:	if(up != nil){		memset(up, 0, sizeof(*up));		free(up);	}}/* *  login to remote system with given user name and password. */voidclogin(char *cuser, char *cpassword){	free(user);	user = strdup(cuser);	if (strcmp(user, "anonymous") != 0 &&	    strcmp(user, "ftp") != 0)		fatal("User must be 'anonymous' or 'ftp'");	sendrequest("USER", user);	switch(getreply(&ctlin, msg, sizeof(msg), 1)){	case Success:		return;	case Incomplete:		break;	case TempFail:	case PermFail:		fatal("login failed");	}	if (cpassword == 0)		fatal("password needed");	sendrequest("PASS", cpassword);	if(getreply(&ctlin, msg, sizeof(msg), 1) != Success)		fatal("password failed");	if(strstr(msg, "Sess#"))		defos = MVS;	return;}/* *  find out about the other side.  go to it's root if requested.  set *  image mode if a Plan9 system. */voidpreamble(char *mountroot){	char *p, *ep;	int rv;	OS *o;	/*	 *  create a root directory mirror	 */	remroot = newnode(0, s_copy("/"));	remroot->d->qid.type = QTDIR;	remroot->d->mode = DMDIR|0777;	remdir = remroot;	/*	 *  get system type	 */	sendrequest("SYST", nil);	switch(getreply(&ctlin, msg, sizeof(msg), 1)){	case Success:		for(o = oslist; o->os != Unknown; o++)			if(strncmp(msg+4, o->name, strlen(o->name)) == 0)				break;		os = o->os;		if(os == NT)			os = Unix;		break;	default:		os = defos;		break;	}	if(os == Unknown)		os = defos;	remrootpath = s_reset(remrootpath);	switch(os){	case NetWare:              /*               * Request long, rather than 8.3 filenames,               * where the Servers & Volume support them.               */              sendrequest("SITE LONG", nil);              getreply(&ctlin, msg, sizeof(msg), 0);              /* FALL THRU */	case Unix:	case Plan9:		/*		 *  go to the remote root, if asked		 */		if(mountroot){			sendrequest("CWD", mountroot);			getreply(&ctlin, msg, sizeof(msg), 0);		} else {			s_append(remrootpath, "/usr/");			s_append(remrootpath, user);		}		/*		 *  get the root directory		 */		sendrequest("PWD", nil);		rv = getreply(&ctlin, msg, sizeof(msg), 1);		if(rv == PermFail){			sendrequest("XPWD", nil);			rv = getreply(&ctlin, msg, sizeof(msg), 1);		}		if(rv == Success){			p = strchr(msg, '"');			if(p){				p++;				ep = strchr(p, '"');				if(ep){					*ep = 0;					s_append(s_reset(remrootpath), p);				}			}		}		break;	case Tops:	case VM:		/*		 *  top directory is a figment of our imagination.		 *  make it permanently cached & valid.		 */		CACHED(remroot);		VALID(remroot);		remroot->d->atime = time(0) + 100000;		/*		 *  no initial directory.  We are in the		 *  imaginary root.		 */		remdir = newtopsdir("???");		topsdir[0] = 0;		if(os == Tops && readdir(remdir) >= 0){			CACHED(remdir);			if(*topsdir)				remdir->remname = s_copy(topsdir);			VALID(remdir);		}		break;	case VMS:		/*		 *  top directory is a figment of our imagination.		 *  make it permanently cached & valid.		 */		CACHED(remroot);		VALID(remroot);		remroot->d->atime = time(0) + 100000;		/*		 *  get current directory		 */		sendrequest("PWD", nil);		rv = getreply(&ctlin, msg, sizeof(msg), 1);		if(rv == PermFail){			sendrequest("XPWD", nil);			rv = getreply(&ctlin, msg, sizeof(msg), 1);		}		if(rv == Success){			p = strchr(msg, '"');			if(p){				p++;				ep = strchr(p, '"');				if(ep){					*ep = 0;					remroot = remdir = vmsdir(p);				}			}		}		break;	case MVS:		usenlst = 1;		break;	}	if(os == Plan9)		image();}static voidascii(void){	sendrequest("TYPE A", nil);	switch(getreply(&ctlin, msg, sizeof(msg), 0)){	case Success:		break;	default:		fatal("can't set type to ascii");	}}static voidimage(void){	sendrequest("TYPE I", nil);	switch(getreply(&ctlin, msg, sizeof(msg), 0)){	case Success:		break;	default:		fatal("can't set type to image/binary");	}}/* *  decode the time fields, return seconds since epoch began */char *monthchars = "janfebmaraprmayjunjulaugsepoctnovdec";static Tm now;static ulongcracktime(char *month, char *day, char *yr, char *hms){	Tm tm;	int i;	char *p;	/* default time */	if(now.year == 0)		now = *localtime(time(0));	tm = now;	tm.yday = 0;	/* convert ascii month to a number twixt 1 and 12 */	if(*month >= '0' && *month <= '9'){		tm.mon = atoi(month) - 1;		if(tm.mon < 0 || tm.mon > 11)			tm.mon = 5;	} else {		for(p = month; *p; p++)			*p = tolower(*p);		for(i = 0; i < 12; i++)			if(strncmp(&monthchars[i*3], month, 3) == 0){				tm.mon = i;				break;			}	}	tm.mday = atoi(day);	if(hms){		tm.hour = strtol(hms, &p, 0);		if(*p == ':'){			tm.min = strtol(p+1, &p, 0);			if(*p == ':')				tm.sec = strtol(p+1, &p, 0);		}		if(tolower(*p) == 'p')			tm.hour += 12;	}	if(yr){		tm.year = atoi(yr);		if(tm.year >= 1900)			tm.year -= 1900;	} else {		if(tm.mon > now.mon || (tm.mon == now.mon && tm.mday > now.mday+1))			tm.year--;	}	/* convert to epoch seconds */	return tm2sec(&tm);}/* *  decode a Unix or Plan 9 file mode */static ulongcrackmode(char *p){	ulong flags;	ulong mode;	int i;	flags = 0;	switch(strlen(p)){	case 10:	/* unix and new style plan 9 */		switch(*p){		case 'l':			return DMSYML|0777;		case 'd':			flags |= DMDIR;		case 'a':			flags |= DMAPPEND;		}		p++;		if(p[2] == 'l')			flags |= DMEXCL;		break;	case 11:	/* old style plan 9 */		switch(*p++){		case 'd':			flags |= DMDIR;			break;		case 'a':			flags |= DMAPPEND;			break;		}		if(*p++ == 'l')			flags |= DMEXCL;		break;	default:		return DMDIR|0777;	}	mode = 0;	for(i = 0; i < 3; i++){		mode <<= 3;		if(*p++ == 'r')			mode |= DMREAD;		if(*p++ == 'w')			mode |= DMWRITE;		if(*p == 'x' || *p == 's' || *p == 'S')			mode |= DMEXEC;		p++;	}	return mode | flags;}/* *  find first punctuation */char*strpunct(char *p){	int c;	for(;c = *p; p++){		if(ispunct(c))			return p;	}	return 0;}/* *  decode a Unix or Plan 9 directory listing */static Dir*crackdir(char *p, String **remname){	char *field[15];	char *dfield[4];	char *cp;	String *s;	int dn, n;	Dir d, *dp;	memset(&d, 0, sizeof(d));	n = getfields(p, field, 15, 1, " \t");	if(n > 2 && strcmp(field[n-2], "->") == 0)		n -= 2;	switch(os){	case TSO:		cp = strchr(field[0], '.');		if(cp){			*cp++ = 0;			s = s_copy(cp);			d.uid = field[0];		} else {			s = s_copy(field[0]);			d.uid = "TSO";		}		d.gid = "TSO";		d.mode = 0666;		d.length = 0;		d.atime = 0;		break;	case OS½:		s = s_copy(field[n-1]);		d.uid = "OS½";		d.gid = d.uid;		d.mode = 0666;		switch(n){		case 5:			if(strcmp(field[1], "DIR") == 0)				d.mode |= DMDIR;			d.length = atoi(field[0]);			dn = getfields(field[2], dfield, 4, 1, "-");			if(dn == 3)				d.atime = cracktime(dfield[0], dfield[1], dfield[2], field[3]);			break;		}		break;	case Tops:		if(n != 4){ /* tops directory name */			safecpy(topsdir, field[0], sizeof(topsdir));			return 0;		}		s = s_copy(field[3]);		d.length = atoi(field[0]);		d.mode = 0666;		d.uid = "Tops";		d.gid = d.uid;		dn = getfields(field[1], dfield, 4, 1, "-");		if(dn == 3)			d.atime = cracktime(dfield[1], dfield[0], dfield[2], field[2]);		else			d.atime = time(0);		break;	case VM:		switch(n){		case 9:			s = s_copy(field[0]);			s_append(s, ".");			s_append(s, field[1]);			d.length = atoi(field[3])*atoi(field[4]);			if(*field[2] == 'F')				d.mode = 0666;			else				d.mode = 0777;			d.uid = "VM";			d.gid = d.uid;			dn = getfields(field[6], dfield, 4, 1, "/-");			if(dn == 3)				d.atime = cracktime(dfield[0], dfield[1], dfield[2], field[7]);			else				d.atime = time(0);			break;		case 1:			s = s_copy(field[0]);			d.uid = "VM";			d.gid = d.uid;			d.mode = 0777;			d.atime = 0;			break;		default:			return nil;		}		break;	case VMS:		switch(n){		case 6:			for(cp = field[0]; *cp; cp++)				*cp = tolower(*cp);			cp = strchr(field[0], ';');			if(cp)				*cp = 0;			d.mode = 0666;			cp = field[0] + strlen(field[0]) - 4;			if(strcmp(cp, ".dir") == 0){				d.mode |= DMDIR;				*cp = 0;			}			s = s_copy(field[0]);			d.length = atoi(field[1])*512;			field[4][strlen(field[4])-1] = 0;			d.uid = field[4]+1;			d.gid = d.uid;			dn = getfields(field[2], dfield, 4, 1, "/-");			if(dn == 3)				d.atime = cracktime(dfield[1], dfield[0], dfield[2], field[3]);			else				d.atime = time(0);			break;		default:			return nil;		}		break;	case NetWare:		switch(n){		case 8:		/* New style */			s = s_copy(field[7]);			d.uid = field[2];			d.gid = d.uid;			d.mode = nw_mode(field[0][0], field[1]);			d.length = atoi(field[3]);			if(strchr(field[6], ':'))				d.atime = cracktime(field[4], field[5], nil, field[6]);			else				d.atime = cracktime(field[4], field[5], field[6], nil);			break;		case 9:			s = s_copy(field[8]);			d.uid = field[2];			d.gid = d.uid;			d.mode = 0666;			if(*field[0] == 'd')				d.mode |= DMDIR;			d.length = atoi(field[3]);			d.atime = cracktime(field[4], field[5], field[6], field[7]);			break;		case 1:			s = s_copy(field[0]);			d.uid = "none";			d.gid = d.uid;			d.mode = 0777;			d.atime = 0;			break;		default:			return nil;		}		break;	case Unix:	case Plan9:	default:		switch(n){		case 8:		/* ls -l */			s = s_copy(field[7]);			d.uid = field[2];			d.gid = d.uid;			d.mode = crackmode(field[0]);			d.length = atoi(field[3]);			if(strchr(field[6], ':'))				d.atime = cracktime(field[4], field[5], 0, field[6]);			else				d.atime = cracktime(field[4], field[5], field[6], 0);			break;		case 9:		/* ls -lg */			s = s_copy(field[8]);			d.uid = field[2];			d.gid = field[3];			d.mode = crackmode(field[0]);			d.length = atoi(field[4]);			if(strchr(field[7], ':'))				d.atime = cracktime(field[5], field[6], 0, field[7]);			else				d.atime = cracktime(field[5], field[6], field[7], 0);			break;		case 10:	/* plan 9 */			s = s_copy(field[9]);			d.uid = field[3];			d.gid = field[4];			d.mode = crackmode(field[0]);			d.length = atoi(field[5]);			if(strchr(field[8], ':'))				d.atime = cracktime(field[6], field[7], 0, field[8]);			else				d.atime = cracktime(field[6], field[7], field[8], 0);			break;		case 4:		/* a Windows_NT version */			s = s_copy(field[3]);			d.uid = "NT";			d.gid = d.uid;			if(strcmp("<DIR>", field[2]) == 0){				d.length = 0;				d.mode = DMDIR|0777;			} else {				d.mode = 0666;				d.length = atoi(field[2]);			}			dn = getfields(field[0], dfield, 4, 1, "/-");			if(dn == 3)				d.atime = cracktime(dfield[0], dfield[1], dfield[2], field[1]);			break;		case 1:			s = s_copy(field[0]);			d.uid = "none";			d.gid = d.uid;			d.mode = 0777;			d.atime = 0;			break;		default:			return nil;		}	}	d.muid = d.uid;	d.qid.type = (d.mode & DMDIR) ? QTDIR : QTFILE;	d.mtime = d.atime;	if(ext && (d.qid.type & QTDIR) == 0)		s_append(s, ext);	d.name = s_to_c(s);	/* allocate a freeable dir structure */	dp = reallocdir(&d, 0);	*remname = s;	return dp;}/* *  probe files in a directory to see if they are directories *//* *  read a remote directory */intreaddir(Node *node){	Biobuf *bp;	char *line;	Node *np;	Dir *d;	long n;	int tries, x, files;	static int uselist;	int usenlist;	String *remname;	if(changedir(node) < 0)		return -1;	usenlist = 0;	for(tries = 0; tries < 3; tries++){		if(usenlist || usenlst)			x = data(OREAD, &bp, "NLST", nil);		else if(os == Unix && !uselist)			x = data(OREAD, &bp, "LIST -l", nil);		else			x = data(OREAD, &bp, "LIST", nil);		switch(x){		case Extra:			break;/*		case TempFail:			continue;*/		default:			if(os == Unix && uselist == 0){				uselist = 1;				continue;			}			return seterr(nosuchfile);		}		files = 0;		while(line = Brdline(bp, '\n')){			n = Blinelen(bp);			if(debug)				write(2, line, n);			if(n > 1 && line[n-2] == '\r')				n--;			line[n - 1] = 0;			d = crackdir(line, &remname);			if(d == nil)				continue;			files++;			np = extendpath(node, remname);			d->qid.path = np->d->qid.path;			d->qid.vers = np->d->qid.vers;			d->type = np->d->type;			d->dev = 1;			/* mark node as valid */			if(os == MVS && node == remroot){				d->qid.type = QTDIR;				d->mode |= DMDIR;			}			free(np->d);			np->d = d;		}		close(Bfildes(bp));		switch(getreply(&ctlin, msg, sizeof(msg), 0)){		case Success:			if(files == 0 && !usenlst && !usenlist){				usenlist = 1;				continue;			}			if(files && usenlist)				usenlst = 1;			if(usenlst)				node->chdirunknown = 1;			return 0;		case TempFail:			break;		default:			return seterr(nosuchfile);		}	}	return seterr(nosuchfile);}/* *  create a remote directory */

⌨️ 快捷键说明

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