ftpd.c

来自「<B>Digital的Unix操作系统VAX 4.2源码</B>」· C语言 代码 · 共 1,298 行 · 第 1/2 页

C
1,298
字号
 * encapulation of the date subject * to Mode, Structure, and Type. * * NB: Form isn't handled. */send_data(instr, outstr)	FILE *instr, *outstr;{	register int c;	int netfd, filefd, cnt;	char buf[BUFSIZ];	transflag++;	if (setjmp(urgcatch)) {		transflag = 0;		return(-1);	}	switch (type) {	case TYPE_A:		while ((c = getc(instr)) != EOF) {			if (c == '\n') {				if (ferror (outstr)) {					transflag = 0;					return (1);				}				(void) putc('\r', outstr);			}			(void) putc(c, outstr);		/*	if (c == '\r')			*/		/*		putc ('\0', outstr);	*/		}		transflag = 0;		if (ferror (instr) || ferror (outstr)) {			return (1);		}		return (0);			case TYPE_I:	case TYPE_L:		netfd = fileno(outstr);		filefd = fileno(instr);		while ((cnt = read(filefd, buf, sizeof (buf))) > 0) {			if (write(netfd, buf, cnt) < 0) {				transflag = 0;				return (1);			}		}		transflag = 0;		return (cnt < 0);	}	reply(550, "Unimplemented TYPE %d in send_data", type);	transflag = 0;	return (-1);}/* * Transfer data from peer to * "outstr" using the appropriate * encapulation of the data subject * to Mode, Structure, and Type. * * N.B.: Form isn't handled. */receive_data(instr, outstr)	FILE *instr, *outstr;{	register int c;	int cnt;	char buf[BUFSIZ];	transflag++;	if (setjmp(urgcatch)) {		transflag = 0;		return(-1);	}	switch (type) {	case TYPE_I:	case TYPE_L:		while ((cnt = read(fileno(instr), buf, sizeof buf)) > 0) {			if (write(fileno(outstr), buf, cnt) < 0) {				transflag = 0;				return (1);			}		}		transflag = 0;		return (cnt < 0);	case TYPE_E:		reply(553, "TYPE E not implemented.");		transflag = 0;		return (-1);	case TYPE_A:		while ((c = getc(instr)) != EOF) {			while (c == '\r') {				if (ferror (outstr)) {					transflag = 0;					return (1);				}				if ((c = getc(instr)) != '\n')					(void) putc ('\r', outstr);			/*	if (c == '\0')			*/			/*		continue;		*/			}			(void) putc (c, outstr);		}		transflag = 0;		if (ferror (instr) || ferror (outstr))			return (1);		return (0);	}	transflag = 0;	fatal("Unknown type in receive_data.");	/*NOTREACHED*/}fatal(s)	char *s;{	reply(451, "Error in server: %s\n", s);	reply(221, "Closing connection due to server error.");	dologout(0);}reply(va_alist)va_dcl{	va_list args;	int n;	char *s;	va_start(args);	n = va_arg(args, int);	s = va_arg(args, char *);	sprintf(aud_msg, "%d ", n);	vsprintf(aud_msg+strlen(aud_msg), s, args);	fputs(aud_msg, stdout);	puts("\r");	(void) fflush(stdout);	if (debug) {		char buf[BUFSIZ];		syslog(LOG_DEBUG, "<--- %d ", n);		vsprintf(buf, s, args);		syslog(LOG_DEBUG, buf);	}}lreply(va_alist)va_dcl{	va_list args;	int n;	char *s;	va_start(args);	n = va_arg(args, int);	s = va_arg(args, char *);	sprintf(aud_msg, "%d-", n);	vsprintf(aud_msg+strlen(aud_msg), s, args);	fputs(aud_msg, stdout);	puts("\r");	(void) fflush(stdout);	if (debug) {		char buf[BUFSIZ];		syslog(LOG_DEBUG, "<--- %d- ", n);		vsprintf(buf, s, args);		syslog(LOG_DEBUG, buf);	}}ack(s)	char *s;{	reply(250, "%s command successful.", s);}nack(s)	char *s;{	reply(502, "%s command not implemented.", s);}yyerror(s)	char *s;{	char *cp;	cp = index(cbuf,'\n');	*cp = '\0';	reply(500, "'%s': command not understood.",cbuf);}delete(name)	char *name;{	struct stat st;	if (stat(name, &st) < 0) {		reply(550, "%s: %s.", name, sys_errlist[errno]);		return;	}	if ((st.st_mode&S_IFMT) == S_IFDIR) {		if (rmdir(name) < 0) {			reply(550, "%s: %s.", name, sys_errlist[errno]);			return;		}		goto done;	}	if (unlink(name) < 0) {		reply(550, "%s: %s.", name, sys_errlist[errno]);		return;	}done:	ack("DELE");}cwd(path)	char *path;{	if (chdir(path) < 0) {		reply(550, "%s: %s.", path, sys_errlist[errno]);		return;	}	ack("CWD");}makedir(name)	char *name;{	struct stat st;	int dochown = stat(name, &st) < 0;		if (mkdir(name, 0777) < 0) {		reply(550, "%s: %s.", name, sys_errlist[errno]);		return;	}	if (dochown)		(void) chown(name, pw->pw_uid, -1);	reply(257, "MKD command successful.");}removedir(name)	char *name;{	if (rmdir(name) < 0) {		reply(550, "%s: %s.", name, sys_errlist[errno]);		return;	}	ack("RMD");}pwd(){	char path[MAXPATHLEN + 1];	if (getwd(path) == NULL) {		reply(550, "%s.", path);		return;	}	reply(257, "\"%s\" is current directory.", path);}char *renamefrom(name)	char *name;{	struct stat st;	if (stat(name, &st) < 0) {		reply(550, "%s: %s.", name, sys_errlist[errno]);		return ((char *)0);	}	reply(350, "File exists, ready for destination name");	return (name);}renamecmd(from, to)	char *from, *to;{	if (rename(from, to) < 0) {		reply(550, "rename: %s.", sys_errlist[errno]);		return;	}	ack("RNTO");}dolog(sin)	struct sockaddr_in *sin;{	struct hostent *hp = gethostbyaddr(&sin->sin_addr,		sizeof (struct in_addr), AF_INET);	time_t t;	extern char *ctime();	char *ti;	char st[80];	if (hp) {		(void) strncpy(remotehost, hp->h_name, sizeof (remotehost));		endhostent();	} else		(void) strncpy(remotehost, inet_ntoa(sin->sin_addr),		    sizeof (remotehost));	if (!logging)		return;	t = time((time_t *) 0);	ti = ctime(&t);	strncpy(st,ti,strlen(ti)-1); /* get rid of CR */	syslog(LOG_INFO,"FTPD: connection from %s at %s", remotehost, st);}#include <utmp.h>#define	SCPYN(a, b)	(void) strncpy(a, b, sizeof (a))struct	utmp utmp;/* * Record login in wtmp file. */dologin(p)	struct passwd *p;{	char line[32];	if (wtmp >= 0) {		/* hack, but must be unique and no tty line */		(void) sprintf(line, "ftp%d", getpid());		SCPYN(utmp.ut_line, line);		SCPYN(utmp.ut_name, p->pw_name);		SCPYN(utmp.ut_host, remotehost);		utmp.ut_time = (long) time((time_t *) 0);		(void) write(wtmp, (char *)&utmp, sizeof (utmp));		if (!guest) {		/* anon must hang on */			(void) close(wtmp);			wtmp = -1;		}	}}/* * Record logout in wtmp file * and exit with supplied status. */dologout(status)	int status;{	if (logged_in) {		(void) seteuid(0);		if (wtmp < 0)			wtmp = open("/usr/adm/wtmp", O_WRONLY|O_APPEND);		if (wtmp >= 0) {			SCPYN(utmp.ut_name, "");			SCPYN(utmp.ut_host, "");			utmp.ut_time = (long) time((time_t *) 0);			(void) write(wtmp, (char *)&utmp, sizeof (utmp));			(void) close(wtmp);		}	}	/* beware of flushing buffers after a SIGPIPE */	_exit(status);}/* * Special version of popen which avoids * call to shell.  This insures noone may  * create a pipe to a hidden program as a side * effect of a list or dir command. */#define	tst(a,b)	(*mode == 'r'? (b) : (a))#define	RDR	0#define	WTR	1static	int popen_pid[5];static char *nextarg(cpp)	char *cpp;{	register char *cp = cpp;	if (cp == 0)		return (cp);	while (*cp && *cp != ' ' && *cp != '\t')		cp++;	if (*cp == ' ' || *cp == '\t') {		*cp++ = '\0';		while (*cp == ' ' || *cp == '\t')			cp++;	}	if (cp == cpp)		return ((char *)0);	return (cp);}FILE *popen(cmd, mode)	char *cmd, *mode;{	int p[2], ac, gac;	register myside, hisside, pid;	char *av[20], *gav[512];	register char *cp;	if (pipe(p) < 0)		return (NULL);	cp = cmd, ac = 0;	/* break up string into pieces */	do {		av[ac++] = cp;		cp = nextarg(cp);	} while (cp && *cp && ac < 20);	av[ac] = (char *)0;	gav[0] = av[0];	/* glob each piece */	for (gac = ac = 1; av[ac] != NULL; ac++) {		char **pop;		extern char **glob(), **copyblk();		pop = glob(av[ac]);		if (pop == (char **)NULL) {	/* globbing failed */			char *vv[2];			vv[0] = av[ac];			vv[1] = 0;			pop = copyblk(vv);		}		av[ac] = (char *)pop;		/* save to free later */		while (*pop && gac < 512)			gav[gac++] = *pop++;	}	gav[gac] = (char *)0;	myside = tst(p[WTR], p[RDR]);	hisside = tst(p[RDR], p[WTR]);	if ((pid = fork()) == 0) {		/* myside and hisside reverse roles in child */		(void) close(myside);		(void) dup2(hisside, tst(0, 1));		(void) close(hisside);		execv(gav[0], gav);		_exit(1);	}	for (ac = 1; av[ac] != NULL; ac++)		blkfree((char **)av[ac]);	if (pid == -1)		return (NULL);	popen_pid[myside] = pid;	(void) close(hisside);	return (fdopen(myside, mode));}pclose(ptr)	FILE *ptr;{	register f, r;	register void (*hstat)(), (*istat)(), (*qstat)();	int status;	f = fileno(ptr);	(void) fclose(ptr);	istat = signal(SIGINT, SIG_IGN);	qstat = signal(SIGQUIT, SIG_IGN);	hstat = signal(SIGHUP, SIG_IGN);	while ((r = wait(&status)) != popen_pid[f] && r != -1)		;	if (r == -1)		status = -1;	(void) signal(SIGINT, istat);	(void) signal(SIGQUIT, qstat);	(void) signal(SIGHUP, hstat);	return (status);}/* * Check user requesting login priviledges. * Disallow anyone who does not have a standard * shell returned by getusershell() (/etc/shells). * Disallow anyone mentioned in the file FTPUSERS * to allow people such as uucp to be avoided. */checkuser(name)	register char *name;{	register char *cp;	FILE *fd;	struct passwd *p;	char *shell;	int found = 0;	char line[BUFSIZ], *index(), *getusershell();	if ((p = getpwnam(name)) == NULL)		return (0);	if ((shell = p->pw_shell) == NULL || *shell == 0)		shell = "/bin/sh";#ifdef 43BSD	while ((cp = getusershell()) != NULL)		if (strcmp(cp, shell) == 0)			break;	endusershell();#else	endpwent();#endif 43BSD	if (cp == NULL)		return (0);	if ((fd = fopen(FTPUSERS, "r")) == NULL)		return (1);	while (fgets(line, sizeof (line), fd) != NULL) {		if ((cp = index(line, '\n')) != NULL)			*cp = '\0';		if (strcmp(line, name) == 0) {			found++;			break;		}	}	(void) fclose(fd);	return (!found);}voidmyoob(){	char *cp;	/* only process if transfer occurring */	if (!transflag) {		return;	}	cp = tmpline;	if (getline(cp, 7, stdin) == NULL) {		reply(221, "You could at least say goodby.");		dologout(0);	}	upper(cp);	if (strcmp(cp, "ABOR\r\n"))		return;	tmpline[0] = '\0';	reply(426,"Transfer aborted. Data connection closed.");	reply(226,"Abort successful");	longjmp(urgcatch, 1);}/* * Note: The 530 reply codes could be 4xx codes, except nothing is * given in the state tables except 421 which implies an exit.  (RFC959) */passive(){	int len;	struct sockaddr_in tmp;	register char *p, *a;	pdata = socket(AF_INET, SOCK_STREAM, 0);	if (pdata < 0) {		reply(530, "Can't open passive connection");		return;	}	tmp = ctrl_addr;	tmp.sin_port = 0;	seteuid(0);	if (bind(pdata, (struct sockaddr *) &tmp, sizeof(tmp)) < 0) {		seteuid(pw->pw_uid);		(void) close(pdata);		pdata = -1;		reply(530, "Can't open passive connection");		return;	}	seteuid(pw->pw_uid);	len = sizeof(tmp);	if (getsockname(pdata, (char *) &tmp, &len) < 0) {		(void) close(pdata);		pdata = -1;		reply(530, "Can't open passive connection");		return;	}	if (listen(pdata, 1) < 0) {		(void) close(pdata);		pdata = -1;		reply(530, "Can't open passive connection");		return;	}	a = (char *) &tmp.sin_addr;	p = (char *) &tmp.sin_port;#define UC(b) (((int) b) & 0xff)	reply(227, "Entering Passive Mode (%d,%d,%d,%d,%d,%d)", UC(a[0]),		UC(a[1]), UC(a[2]), UC(a[3]), UC(p[0]), UC(p[1]));}char *gunique(local)	char *local;{	static char new[MAXPATHLEN];	char *cp = rindex(local, '/');	int d, count=0;	char ext = '1';	if (cp) {		*cp = '\0';	}	d = access(cp ? local : ".", 2);	if (cp) {		*cp = '/';	}	if (d < 0) {		syslog(LOG_ERR, "%s: %m", local);		return((char *) 0);	}	(void) strcpy(new, local);	cp = new + strlen(new);	*cp++ = '.';	while (!d) {		if (++count == 100) {			reply(452, "Unique file name not cannot be created.");			return((char *) 0);		}		*cp++ = ext;		*cp = '\0';		if (ext == '9') {			ext = '0';		}		else {			ext++;		}		if ((d = access(new, 0)) < 0) {			break;		}		if (ext != '0') {			cp--;		}		else if (*(cp - 2) == '.') {			*(cp - 1) = '1';		}		else {			*(cp - 2) = *(cp - 2) + 1;			cp--;		}	}	return(new);}

⌨️ 快捷键说明

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