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

📄 ftpd.c

📁 伯克利大学的一个ftp协议的实现源代码,包括客户端和服务器端.
💻 C
📖 第 1 页 / 共 4 页
字号:
}/* ARGSUSED */voidyyerror(char *s){	char *cp;        	(void)s; /* ignore argument */	if ((cp = strchr(cbuf,'\n'))!=NULL)		*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)	const char *path;{	FILE *message;	if (chdir(path) < 0)		perror_reply(550, path);	else {		if ((message = fopen(_PATH_CWDMESG, "r")) != NULL) {			char *cp, line[LINE_MAX];			while (fgets(line, sizeof(line), message) != NULL) {				if ((cp = strchr(line, '\n')) != NULL)					*cp = '\0';				lreply(250, "%s", line);			}			(void) fflush(stdout);			(void) fclose(message);		}		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(sn)	struct sockaddr_in *sn;{	struct hostent *hp = gethostbyaddr((char *)&sn->sin_addr,		sizeof(struct in_addr), AF_INET);	if (hp)		(void) strncpy(remotehost, hp->h_name, sizeof(remotehost)-1);	else		(void) strncpy(remotehost, inet_ntoa(sn->sin_addr),		    sizeof(remotehost)-1);	remotehost[sizeof(remotehost)-1] = '\0';#ifdef HASSETPROCTITLE	snprintf(proctitle, sizeof(proctitle), "%s: connected", remotehost);	setproctitle(proctitle);#endif /* HASSETPROCTITLE */	if (logging)		syslog(LOG_INFO, "connection from %s", remotehost);}/* * Record logout in wtmp file * and exit with supplied status. */voiddologout(status)	int status;{	sigset_t allsigs;	transflag = 0;	if (logged_in) {		sigfillset(&allsigs);		sigprocmask(SIG_BLOCK, &allsigs, NULL);		(void) seteuid((uid_t)0);		logwtmp(ttyline, "", "");		if (doutmp)			logout(utmp.ut_line);#if defined(KERBEROS)		if (!notickets && krbtkfile_env)			unlink(krbtkfile_env);#endif	}	/* beware of flushing buffers after a SIGPIPE */	_exit(status);}static voidmyoob(int signo){	char *cp;	(void)signo;	/* 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",			    (quad_t) byte_count, (quad_t) file_size);		else			reply(213, "Status: %qd bytes transferred", 			    (quad_t)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;#ifdef IP_PORTRANGE	int on;#else	u_short port;#endif	char *p, *a;	if (pw == NULL) {		reply(530, "Please login with USER and PASS");		return;	}	if (pdata >= 0)		close(pdata);	pdata = socket(AF_INET, SOCK_STREAM, 0);	if (pdata < 0) {		perror_reply(425, "Can't open passive connection");		return;	}#ifdef IP_PORTRANGE	on = high_data_ports ? IP_PORTRANGE_HIGH : IP_PORTRANGE_DEFAULT;	if (setsockopt(pdata, IPPROTO_IP, IP_PORTRANGE,		       (char *)&on, sizeof(on)) < 0)		goto pasv_error;#else#define FTP_DATA_BOTTOM 40000#define FTP_DATA_TOP    44999	if (high_data_ports) {		for (port = FTP_DATA_BOTTOM; port <= FTP_DATA_TOP; port++) {			pasv_addr = ctrl_addr;			pasv_addr.sin_port = htons(port);			if (bind(pdata, (struct sockaddr *) &pasv_addr,				 sizeof(pasv_addr)) == 0)				break;			if (errno != EADDRINUSE)				goto pasv_error;		}		if (port > FTP_DATA_TOP)			goto pasv_error;	}	else#endif	{		pasv_addr = ctrl_addr;		pasv_addr.sin_port = 0;		if (bind(pdata, (struct sockaddr *)&pasv_addr,			 sizeof(pasv_addr)) < 0)			goto pasv_error;	}	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 intguniquefd(local, nam)	const char *local;	char **nam;{	static char new[MAXPATHLEN];	struct stat st;	int count, len, fd;	char *cp;	cp = strrchr(local, '/');	if (cp)		*cp = '\0';	if (stat(cp ? local : ".", &st) < 0) {		perror_reply(553, cp ? local : ".");		return (-1);	}	if (cp)		*cp = '/';	(void) strncpy(new, local, sizeof(new)-1);	new[sizeof(new)-1] = '\0';	len = strlen(new);	if (len+2+1 >= (int)sizeof(new)-1)		return (-1);	cp = new + len;	*cp++ = '.';	for (count = 1; count < 100; count++) {		(void)snprintf(cp, sizeof(new) - (cp - new), "%d", count);		fd = open(new, O_RDWR|O_CREAT|O_EXCL, 0666);		if (fd == -1)			continue;		if (nam)			*nam = new;		return (fd);	}	reply(452, "Unique file name cannot be created.");	return (-1);}/* * Format and send reply containing system error number. */voidperror_reply(code, string)	int code;	const char *string;{	reply(code, "%s: %s.", string, strerror(errno));}static const char *onefile[] = {	"",	0};voidsend_file_list(whichf)	const char *whichf;{	struct stat st;	DIR *dirp = NULL;	struct dirent *dir;	FILE *volatile dout = NULL;	char const *const *volatile dirlist;	const char *dirname;	volatile int simple = 0;	volatile int freeglob = 0;	glob_t gl;	/* XXX: should the { go away if __linux__? */	if (strpbrk(whichf, "~{[*?") != NULL) {#ifdef __linux__	        /* see popen.c */		int flags = GLOB_NOCHECK;#else		int flags = GLOB_BRACE|GLOB_NOCHECK|GLOB_QUOTE|GLOB_TILDE;#endif		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;		}		/* The cast is necessary because of bugs in C's type system */		dirlist = (char const *const *) gl.gl_pathv;	} else {		onefile[0] = whichf;		dirlist = onefile;		simple = 1;	}	if (setjmp(urgcatch)) {		transflag = 0;		goto out;	}	while ((dirname = *dirlist++)!=NULL) {		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];#ifdef __linux__			if (!strcmp(dir->d_name, "."))				continue;			if (!strcmp(dir->d_name, ".."))				continue;#else			if (dir->d_name[0] == '.' && dir->d_namlen == 1)				continue;			if (dir->d_name[0] == '.' && dir->d_name[1] == '.' &&			    dir->d_namlen == 2)				continue;#endif			snprintf(nbuf, sizeof(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);	}}static voidreapchild(int signo){	(void)signo;	while (wait3(NULL, WNOHANG, NULL) > 0);}voidlogxfer(name, size, start)	const char *name;	off_t size;	time_t start;{	char buf[2048];	char path[MAXPATHLEN];	char vremotehost[MAXHOSTNAMELEN*4], vpath[MAXPATHLEN*4];	char *vname, *vpw;	time_t now;	if ((statfd >= 0) && (getcwd(path, sizeof(path)) != NULL)) {		time(&now);		vname = (char *)malloc(strlen(name)*4+1);		if (vname == NULL)			return;		vpw = (char *)malloc(strlen((guest) ? guestpw : pw->pw_name)*4+1);		if (vpw == NULL) {			free(vname);			return;		}		strvis(vremotehost, remotehost, VIS_SAFE|VIS_NOSLASH);		strvis(vpath, path, VIS_SAFE|VIS_NOSLASH);		strvis(vname, name, VIS_SAFE|VIS_NOSLASH);		strvis(vpw, (guest) ? guestpw : pw->pw_name, VIS_SAFE|VIS_NOSLASH);		snprintf(buf, sizeof(buf),			 "%.24s %d %s %qd %s/%s %c %s %c %c %s ftp %d %s %s\n",			 ctime(&now), now - start + (now == start),			 vremotehost, (quad_t)size, vpath, vname,			 ((type == TYPE_A) ? 'a' : 'b'), "*" /* none yet */,			 'o', ((guest) ? 'a' : 'r'),			 vpw, 0 /* none yet */,			 ((guest) ? "*" : pw->pw_name), dhostname);		write(statfd, buf, strlen(buf));		free(vname);		free(vpw);	}}

⌨️ 快捷键说明

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