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

📄 ftpd.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 3 页
字号:
/* *  chdir */intcwdcmd(char *dir){	char *rp;	char buf[Maxpath];	/* shell cd semantics */	if(dir == 0 || *dir == 0){		if(isnone)			rp = "/";		else {			snprint(buf, sizeof buf, "/usr/%s", user);			rp = buf;		}		if(accessok(rp) == 0)			rp = nil;	} else		rp = abspath(dir);	if(rp == nil)		return reply("550 Permission denied");	if(chdir(rp) < 0)		return reply("550 Cwd failed: %r");	strcpy(curdir, rp);	return reply("250 directory changed to %s", curdir);}/* *  chdir .. */intcdupcmd(char *dp){	USED(dp);	return cwdcmd("..");}intquitcmd(char *arg){	USED(arg);	reply("200 Bye");	if(pid)		postnote(PNPROC, pid, "kill");	return -1;}inttypecmd(char *arg){	int c;	char *x;	x = arg;	if(arg == 0)		return reply("501 Type command needs arguments");	while(c = *arg++){		switch(tolower(c)){		case 'a':			type = Tascii;			break;		case 'i':		case 'l':			type = Timage;			break;		case '8':		case ' ':		case 'n':		case 't':		case 'c':			break;		default:			return reply("501 Unimplemented type %s", x);		}	}	return reply("200 Type %s", type==Tascii ? "Ascii" : "Image");}intmodecmd(char *arg){	if(arg == 0)		return reply("501 Mode command needs arguments");	while(*arg){		switch(tolower(*arg)){		case 's':			mode = Mstream;			break;		default:			return reply("501 Unimplemented mode %c", *arg);		}		arg++;	}	return reply("200 Stream mode");}intstructcmd(char *arg){	if(arg == 0)		return reply("501 Struct command needs arguments");	for(; *arg; arg++){		switch(tolower(*arg)){		case 'f':			structure = Sfile;			break;		default:			return reply("501 Unimplemented structure %c", *arg);		}	}	return reply("200 File structure");}intportcmd(char *arg){	char *field[7];	int n;	if(arg == 0)		return reply("501 Port command needs arguments");	n = getfields(arg, field, 7, 0, ", ");	if(n != 6)		return reply("501 Incorrect port specification");	snprint(data, sizeof data, "tcp!%.3s.%.3s.%.3s.%.3s!%d", field[0], field[1], field[2],		field[3], atoi(field[4])*256 + atoi(field[5]));	return reply("200 Data port is %s", data);}intmountnet(void){	int rv;	rv = 0;	if(bind("#/", "/", MAFTER) < 0){		logit("can't bind #/ to /: %r");		return reply("500 can't bind #/ to /: %r");	}	if(bind(nci->spec, "/net", MBEFORE) < 0){		logit("can't bind %s to /net: %r", nci->spec);		rv = reply("500 can't bind %s to /net: %r", nci->spec);		unmount("#/", "/");	}	return rv;}voidunmountnet(void){	unmount(0, "/net");	unmount("#/", "/");}intpasvcmd(char *arg){	NetConnInfo *nnci;	Passive *p;	USED(arg);	p = &passive;	if(p->inuse){		close(p->afd);		p->inuse = 0;	}	if(mountnet() < 0)		return 0;	p->afd = announce("tcp!*!0", passive.adir);	if(p->afd < 0){		unmountnet();		return reply("500 No free ports");	}	nnci = getnetconninfo(p->adir, -1);	unmountnet();	/* parse the local address */	if(debug)		logit("local sys is %s", nci->lsys);	parseip(p->ipaddr, nci->lsys);	if(ipcmp(p->ipaddr, v4prefix) == 0 || ipcmp(p->ipaddr, IPnoaddr) == 0)		parseip(p->ipaddr, nci->lsys);	p->port = atoi(nnci->lserv);	freenetconninfo(nnci);	p->inuse = 1;	return reply("227 Entering Passive Mode (%d,%d,%d,%d,%d,%d)",		p->ipaddr[IPv4off+0], p->ipaddr[IPv4off+1], p->ipaddr[IPv4off+2], p->ipaddr[IPv4off+3],		p->port>>8, p->port&0xff);}enum{	Narg=32,};int Cflag, rflag, tflag, Rflag;int maxnamelen;int col;char*mode2asc(int m){	static char asc[12];	char *p;	strcpy(asc, "----------");	if(DMDIR & m)		asc[0] = 'd';	if(DMAPPEND & m)		asc[0] = 'a';	else if(DMEXCL & m)		asc[3] = 'l';	for(p = asc+1; p < asc + 10; p += 3, m<<=3){		if(m & 0400)			p[0] = 'r';		if(m & 0200)			p[1] = 'w';		if(m & 0100)			p[2] = 'x';	}	return asc;}voidlistfile(Biobufhdr *b, char *name, int lflag, char *dname){	char ts[32];	int n, links, pad;	long now;	char *x;	Dir *d;	x = abspath(name);	if(x == nil)		return;	d = dirstat(x);	if(d == nil)		return;	if(isnone){		if(strncmp(x, "/incoming/", sizeof("/incoming/")-1) != 0)			d->mode &= ~0222;		d->uid = "none";		d->gid = "none";	}	strcpy(ts, ctime(d->mtime));	ts[16] = 0;	now = time(0);	if(now - d->mtime > 6*30*24*60*60)		memmove(ts+11, ts+23, 5);	if(lflag){		/* Unix style long listing */		if(DMDIR&d->mode){			links = 2;			d->length = 512;		} else			links = 1;				Bprint(b, "%s %3d %-8s %-8s %7lld %s ",			mode2asc(d->mode), links,			d->uid, d->gid, d->length, ts+4);	}	if(Cflag && maxnamelen < 40){		n = strlen(name);		pad = ((col+maxnamelen)/(maxnamelen+1))*(maxnamelen+1);		if(pad+maxnamelen+1 < 60){			Bprint(b, "%*s", pad-col+n, name);			col = pad+n;		}		else{			Bprint(b, "\r\n%s", name);			col = n;		}	}	else{		if(dname)			Bprint(b, "%s/", dname);		Bprint(b, "%s\r\n", name);	}	free(d);}intdircomp(void *va, void *vb){	int rv;	Dir *a, *b;	a = va;	b = vb;	if(tflag)		rv = b->mtime - a->mtime;	else		rv = strcmp(a->name, b->name);	return (rflag?-1:1)*rv;}voidlistdir(char *name, Biobufhdr *b, int lflag, int *printname, Globlist *gl){	Dir *p;	int fd, n, i, l;	char *dname;	uvlong total;	col = 0;	fd = open(name, OREAD);	if(fd < 0){		Bprint(b, "can't read %s: %r\r\n", name);		return;	}	dname = 0;	if(*printname){		if(Rflag || lflag)			Bprint(b, "\r\n%s:\r\n", name);		else			dname = name;	}	n = dirreadall(fd, &p);	close(fd);	if(Cflag){		for(i = 0; i < n; i++){			l = strlen(p[i].name);			if(l > maxnamelen)				maxnamelen = l;		}	}	/* Unix style total line */	if(lflag){		total = 0;		for(i = 0; i < n; i++){			if(p[i].qid.type & QTDIR)				total += 512;			else				total += p[i].length;		}		Bprint(b, "total %ulld\r\n", total/512);	}		qsort(p, n, sizeof(Dir), dircomp);	for(i = 0; i < n; i++){		if(Rflag && (p[i].qid.type & QTDIR)){			*printname = 1;			globadd(gl, name, p[i].name);		}		listfile(b, p[i].name, lflag, dname);	}	free(p);}voidlist(char *arg, int lflag){	Dir *d;	Globlist *gl;	Glob *g;	int dfd, printname;	int i, n, argc;	char *alist[Narg];	char **argv;	Biobufhdr bh;	uchar buf[512];	char *p, *s;	if(arg == 0)		arg = "";	if(debug)		logit("ls %s (. = %s)", arg, curdir);	/* process arguments, understand /bin/ls -l option */	argv = alist;	argv[0] = "/bin/ls";	argc = getfields(arg, argv+1, Narg-2, 1, " \t") + 1;	argv[argc] = 0;	rflag = 0;	tflag = 0;	Rflag = 0;	Cflag = 0;	col = 0;	ARGBEGIN{	case 'l':		lflag++;		break;	case 'R':		Rflag++;		break;	case 'C':		Cflag++;		break;	case 'r':		rflag++;		break;	case 't':		tflag++;		break;	}ARGEND;	if(Cflag)		lflag = 0;	dfd = dialdata();	if(dfd < 0){		reply("425 Error opening data connection:%r");		return;	}	reply("150 Opened data connection (%s)", data);	Binits(&bh, dfd, OWRITE, buf, sizeof(buf));	if(argc == 0){		argc = 1;		argv = alist;		argv[0] = ".";	}	for(i = 0; i < argc; i++){		chdir(curdir);		gl = glob(argv[i]);		if(gl == nil)			continue;				printname = gl->first != nil && gl->first->next != nil;		maxnamelen = 8;		if(Cflag)			for(g = gl->first; g; g = g->next)				if(g->glob && (n = strlen(s_to_c(g->glob))) > maxnamelen)					maxnamelen = n;		while(s = globiter(gl)){			if(debug)				logit("glob %s", s);			p = abspath(s);			if(p == nil){				free(s);				continue;			}			d = dirstat(p);			if(d == nil){				free(s);				continue;			}			if(d->qid.type & QTDIR)				listdir(s, &bh, lflag, &printname, gl);			else				listfile(&bh, s, lflag, 0);			free(s);			free(d);		}		globlistfree(gl);	}	if(Cflag)		Bprint(&bh, "\r\n");	Bflush(&bh);	close(dfd);	reply("226 Transfer complete (list %s)", arg);}intnamelistcmd(char *arg){	return asproc(list, arg, 0);}intlistcmd(char *arg){	return asproc(list, arg, 1);}/* *  return the size of the file */intsizecmd(char *arg){	Dir *d;	int rv;	if(arg == 0)		return reply("501 Size command requires pathname");	arg = abspath(arg);	d = dirstat(arg);	if(d == nil)		return reply("501 %r accessing %s", arg);	rv = reply("213 %lld", d->length);	free(d);	return rv;}/* *  return the modify time of the file */intmdtmcmd(char *arg){	Dir *d;	Tm *t;	int rv;	if(arg == 0)		return reply("501 Mdtm command requires pathname");	if(arg == 0)		return reply("550 Permission denied");	d = dirstat(arg);	if(d == nil)		return reply("501 %r accessing %s", arg);	t = gmtime(d->mtime);	rv = reply("213 %4.4d%2.2d%2.2d%2.2d%2.2d%2.2d",			t->year+1900, t->mon+1, t->mday,			t->hour, t->min, t->sec);	free(d);	return rv;}/* *  set an offset to start reading a file from *  only lasts for one command */intrestartcmd(char *arg){	if(arg == 0)		return reply("501 Restart command requires offset");	offset = atoll(arg);	if(offset < 0){		offset = 0;		return reply("501 Bad offset");	}	return reply("350 Restarting at %lld. Send STORE or RETRIEVE", offset);}/* *  send a file to the user */intcrlfwrite(int fd, char *p, int n){	char *ep, *np;	char buf[2*Nbuf];	for(np = buf, ep = p + n; p < ep; p++){		if(*p == '\n')			*np++ = '\r';		*np++ = *p;	}	if(write(fd, buf, np - buf) == np - buf)		return n;	else		return -1;}voidretrievedir(char *arg){	int n;	char *p;	String *file;	if(type != Timage){		reply("550 This file requires type binary/image");		return;	}	file = s_copy(arg);	p = strrchr(s_to_c(file), '/');	if(p != s_to_c(file)){		*p++ = 0;		chdir(s_to_c(file));	} else {		chdir("/");		p = s_to_c(file)+1;	}	n = transfer("/bin/tar", "c", p, 0, 1);	if(n < 0)		logit("get %s failed", arg);	else		logit("get %s OK %d", arg, n);	s_free(file);}voidretrieve(char *arg, int arg2){	int dfd, fd, n, i, bytes;	Dir *d;	char buf[Nbuf];	char *p, *ep;	USED(arg2);	p = strchr(arg, '\r');	if(p){		logit("cr in file name", arg);		*p = 0;	}	fd = open(arg, OREAD);	if(fd == -1){		n = strlen(arg);		if(n > 4 && strcmp(arg+n-4, ".tar") == 0){

⌨️ 快捷键说明

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