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

📄 ftpd.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 3 页
字号:
	if (data != -1)		printf("     Data connection open\r\n");	else if (pdata != -1) {		printf("     in Passive mode");		sin = &pasv_addr;		goto printaddr;	} else if (usedefault == 0) {		printf("     PORT");		sin = &data_dest;printaddr:		a = (u_char *) &sin->sin_addr;		p = (u_char *) &sin->sin_port;#define UC(b) (((int) b) & 0xff)		printf(" (%d,%d,%d,%d,%d,%d)\r\n", UC(a[0]),			UC(a[1]), UC(a[2]), UC(a[3]), UC(p[0]), UC(p[1]));#undef UC	} else		printf("     No data connection\r\n");	reply(211, "End of status");}voidfatal(s)	char *s;{	reply(451, "Error in server: %s\n", s);	reply(221, "Closing connection due to server error.");	dologout(0);	/* NOTREACHED */}void#if __STDC__reply(int n, const char *fmt, ...)#elsereply(n, fmt, va_alist)	int n;	char *fmt;        va_dcl#endif{	va_list ap;#if __STDC__	va_start(ap, fmt);#else	va_start(ap);#endif	(void)printf("%d ", n);	(void)vprintf(fmt, ap);	(void)printf("\r\n");	(void)fflush(stdout);	if (debug) {		syslog(LOG_DEBUG, "<--- %d ", n);		vsyslog(LOG_DEBUG, fmt, ap);	}}void#if __STDC__lreply(int n, const char *fmt, ...)#elselreply(n, fmt, va_alist)	int n;	char *fmt;        va_dcl#endif{	va_list ap;#if __STDC__	va_start(ap, fmt);#else	va_start(ap);#endif	(void)printf("%d- ", n);	(void)vprintf(fmt, ap);	(void)printf("\r\n");	(void)fflush(stdout);	if (debug) {		syslog(LOG_DEBUG, "<--- %d- ", n);		vsyslog(LOG_DEBUG, fmt, ap);	}}static voidack(s)	char *s;{	reply(250, "%s command successful.", s);}voidnack(s)	char *s;{	reply(502, "%s command not implemented.", s);}/* ARGSUSED */voidyyerror(s)	char *s;{	char *cp;	if (cp = strchr(cbuf,'\n'))		*cp = '\0';	reply(500, "'%s': command not understood.", cbuf);}voiddelete(name)	char *name;{	struct stat st;	LOGCMD("delete", name);	if (stat(name, &st) < 0) {		perror_reply(550, name);		return;	}	if ((st.st_mode&S_IFMT) == S_IFDIR) {		if (rmdir(name) < 0) {			perror_reply(550, name);			return;		}		goto done;	}	if (unlink(name) < 0) {		perror_reply(550, name);		return;	}done:	ack("DELE");}voidcwd(path)	char *path;{	if (chdir(path) < 0)		perror_reply(550, path);	else		ack("CWD");}voidmakedir(name)	char *name;{	LOGCMD("mkdir", name);	if (mkdir(name, 0777) < 0)		perror_reply(550, name);	else		reply(257, "MKD command successful.");}voidremovedir(name)	char *name;{	LOGCMD("rmdir", name);	if (rmdir(name) < 0)		perror_reply(550, name);	else		ack("RMD");}voidpwd(){	char path[MAXPATHLEN + 1];	if (getwd(path) == (char *)NULL)		reply(550, "%s.", path);	else		reply(257, "\"%s\" is current directory.", path);}char *renamefrom(name)	char *name;{	struct stat st;	if (stat(name, &st) < 0) {		perror_reply(550, name);		return ((char *)0);	}	reply(350, "File exists, ready for destination name");	return (name);}voidrenamecmd(from, to)	char *from, *to;{	LOGCMD2("rename", from, to);	if (rename(from, to) < 0)		perror_reply(550, "rename");	else		ack("RNTO");}static voiddolog(sin)	struct sockaddr_in *sin;{	struct hostent *hp = gethostbyaddr((char *)&sin->sin_addr,		sizeof(struct in_addr), AF_INET);	if (hp)		(void) strncpy(remotehost, hp->h_name, sizeof(remotehost));	else		(void) strncpy(remotehost, inet_ntoa(sin->sin_addr),		    sizeof(remotehost));#ifdef SETPROCTITLE	snprintf(proctitle, sizeof(proctitle), "%s: connected", remotehost);	setproctitle(proctitle);#endif /* SETPROCTITLE */	if (logging)		syslog(LOG_INFO, "connection from %s", remotehost);}/* * Record logout in wtmp file * and exit with supplied status. */voiddologout(status)	int status;{	if (logged_in) {		(void) seteuid((uid_t)0);		logwtmp(ttyline, "", "");	}	/* beware of flushing buffers after a SIGPIPE */	_exit(status);}static voidmyoob(signo)	int signo;{	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 goodbye.");		dologout(0);	}	upper(cp);	if (strcmp(cp, "ABOR\r\n") == 0) {		tmpline[0] = '\0';		reply(426, "Transfer aborted. Data connection closed.");		reply(226, "Abort successful");		longjmp(urgcatch, 1);	}	if (strcmp(cp, "STAT\r\n") == 0) {		if (file_size != (off_t) -1)			reply(213, "Status: %qd of %qd bytes transferred",			    byte_count, file_size);		else			reply(213, "Status: %qd bytes transferred", byte_count);	}}/* * Note: a response of 425 is not mentioned as a possible response to *	the PASV command in RFC959. However, it has been blessed as *	a legitimate response by Jon Postel in a telephone conversation *	with Rick Adams on 25 Jan 89. */voidpassive(){	int len;	char *p, *a;	pdata = socket(AF_INET, SOCK_STREAM, 0);	if (pdata < 0) {		perror_reply(425, "Can't open passive connection");		return;	}	pasv_addr = ctrl_addr;	pasv_addr.sin_port = 0;	(void) seteuid((uid_t)0);	if (bind(pdata, (struct sockaddr *)&pasv_addr, sizeof(pasv_addr)) < 0) {		(void) seteuid((uid_t)pw->pw_uid);		goto pasv_error;	}	(void) seteuid((uid_t)pw->pw_uid);	len = sizeof(pasv_addr);	if (getsockname(pdata, (struct sockaddr *) &pasv_addr, &len) < 0)		goto pasv_error;	if (listen(pdata, 1) < 0)		goto pasv_error;	a = (char *) &pasv_addr.sin_addr;	p = (char *) &pasv_addr.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]));	return;pasv_error:	(void) close(pdata);	pdata = -1;	perror_reply(425, "Can't open passive connection");	return;}/* * Generate unique name for file with basename "local". * The file named "local" is already known to exist. * Generates failure reply on error. */static char *gunique(local)	char *local;{	static char new[MAXPATHLEN];	struct stat st;	int count;	char *cp;	cp = strrchr(local, '/');	if (cp)		*cp = '\0';	if (stat(cp ? local : ".", &st) < 0) {		perror_reply(553, cp ? local : ".");		return ((char *) 0);	}	if (cp)		*cp = '/';	(void) strcpy(new, local);	cp = new + strlen(new);	*cp++ = '.';	for (count = 1; count < 100; count++) {		(void)sprintf(cp, "%d", count);		if (stat(new, &st) < 0)			return (new);	}	reply(452, "Unique file name cannot be created.");	return (NULL);}/* * Format and send reply containing system error number. */voidperror_reply(code, string)	int code;	char *string;{	reply(code, "%s: %s.", string, strerror(errno));}static char *onefile[] = {	"",	0};voidsend_file_list(whichf)	char *whichf;{	struct stat st;	DIR *dirp = NULL;	struct dirent *dir;	FILE *dout = NULL;	char **dirlist, *dirname;	int simple = 0;	int freeglob = 0;	glob_t gl;	if (strpbrk(whichf, "~{[*?") != NULL) {		int flags = GLOB_BRACE|GLOB_NOCHECK|GLOB_QUOTE|GLOB_TILDE;		memset(&gl, 0, sizeof(gl));		freeglob = 1;		if (glob(whichf, flags, 0, &gl)) {			reply(550, "not found");			goto out;		} else if (gl.gl_pathc == 0) {			errno = ENOENT;			perror_reply(550, whichf);			goto out;		}		dirlist = gl.gl_pathv;	} else {		onefile[0] = whichf;		dirlist = onefile;		simple = 1;	}	if (setjmp(urgcatch)) {		transflag = 0;		goto out;	}	while (dirname = *dirlist++) {		if (stat(dirname, &st) < 0) {			/*			 * If user typed "ls -l", etc, and the client			 * used NLST, do what the user meant.			 */			if (dirname[0] == '-' && *dirlist == NULL &&			    transflag == 0) {				retrieve("/bin/ls %s", dirname);				goto out;			}			perror_reply(550, whichf);			if (dout != NULL) {				(void) fclose(dout);				transflag = 0;				data = -1;				pdata = -1;			}			goto out;		}		if (S_ISREG(st.st_mode)) {			if (dout == NULL) {				dout = dataconn("file list", (off_t)-1, "w");				if (dout == NULL)					goto out;				transflag++;			}			fprintf(dout, "%s%s\n", dirname,				type == TYPE_A ? "\r" : "");			byte_count += strlen(dirname) + 1;			continue;		} else if (!S_ISDIR(st.st_mode))			continue;		if ((dirp = opendir(dirname)) == NULL)			continue;		while ((dir = readdir(dirp)) != NULL) {			char nbuf[MAXPATHLEN];			if (dir->d_name[0] == '.' && dir->d_namlen == 1)				continue;			if (dir->d_name[0] == '.' && dir->d_name[1] == '.' &&			    dir->d_namlen == 2)				continue;			sprintf(nbuf, "%s/%s", dirname, dir->d_name);			/*			 * We have to do a stat to insure it's			 * not a directory or special file.			 */			if (simple || (stat(nbuf, &st) == 0 &&			    S_ISREG(st.st_mode))) {				if (dout == NULL) {					dout = dataconn("file list", (off_t)-1,						"w");					if (dout == NULL)						goto out;					transflag++;				}				if (nbuf[0] == '.' && nbuf[1] == '/')					fprintf(dout, "%s%s\n", &nbuf[2],						type == TYPE_A ? "\r" : "");				else					fprintf(dout, "%s%s\n", nbuf,						type == TYPE_A ? "\r" : "");				byte_count += strlen(nbuf) + 1;			}		}		(void) closedir(dirp);	}	if (dout == NULL)		reply(550, "No files found.");	else if (ferror(dout) != 0)		perror_reply(550, "Data connection");	else		reply(226, "Transfer complete.");	transflag = 0;	if (dout != NULL)		(void) fclose(dout);	data = -1;	pdata = -1;out:	if (freeglob) {		freeglob = 0;		globfree(&gl);	}}#ifdef SETPROCTITLE/* * Clobber argv so ps will show what we're doing.  (Stolen from sendmail.) * Warning, since this is usually started from inetd.conf, it often doesn't * have much of an environment or arglist to overwrite. */void#if __STDC__setproctitle(const char *fmt, ...)#elsesetproctitle(fmt, va_alist)	char *fmt;        va_dcl#endif{	int i;	va_list ap;	char *p, *bp, ch;	char buf[LINE_MAX];#if __STDC__	va_start(ap, fmt);#else	va_start(ap);#endif	(void)vsnprintf(buf, sizeof(buf), fmt, ap);	/* make ps print our process name */	p = Argv[0];	*p++ = '-';	i = strlen(buf);	if (i > LastArgv - p - 2) {		i = LastArgv - p - 2;		buf[i] = '\0';	}	bp = buf;	while (ch = *bp++)		if (ch != '\n' && ch != '\r')			*p++ = ch;	while (p < LastArgv)		*p++ = ' ';}#endif /* SETPROCTITLE */

⌨️ 快捷键说明

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