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

📄 ftpd_c.txt

📁 基于UNIX的FTP源代码
💻 TXT
📖 第 1 页 / 共 5 页
字号:
	recvurg = 0;
	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.
 */
static int
receive_data(FILE *instr, FILE *outstr)
{
	int c;
	int cnt;
	char buf[BUFSIZ];
	struct sigaction sa, sa_saved;
	volatile int bare_lfs = 0;

	transflag++;
	switch (type) {

	case TYPE_I:
	case TYPE_L:
		memset(&sa, 0, sizeof(sa));
		sigfillset(&sa.sa_mask);
		sa.sa_flags = SA_RESTART;
		sa.sa_handler = lostconn;
		(void) sigaction(SIGALRM, &sa, &sa_saved);
		do {
			(void) alarm ((unsigned) timeout);
			cnt = read(fileno(instr), buf, sizeof(buf));
			(void) alarm (0);
			if (recvurg)
				goto got_oob;

			if (cnt > 0) {
				if (write(fileno(outstr), buf, cnt) != cnt)
					goto file_err;
				byte_count += cnt;
			}
		} while (cnt > 0);
		(void) sigaction(SIGALRM, &sa_saved, NULL);
		if (cnt < 0)
			goto data_err;
		transflag = 0;
		return (0);

	case TYPE_E:
		reply(553, "TYPE E not implemented.");
		transflag = 0;
		return (-1);

	case TYPE_A:
		while ((c = getc(instr)) != EOF) {
			if (recvurg)
				goto got_oob;
			byte_count++;
			if (c == '\n')
				bare_lfs++;
			while (c == '\r') {
				if (ferror(outstr))
					goto data_err;
				if ((c = getc(instr)) != '\n') {
					(void) putc ('\r', outstr);
					if (c == '\0' || c == EOF)
						goto contin2;
				}
			}
			(void) putc(c, outstr);
	contin2:	;
		}
		fflush(outstr);
		if (ferror(instr))
			goto data_err;
		if (ferror(outstr))
			goto file_err;
		transflag = 0;
		if (bare_lfs) {
			lreply(226,
			    "WARNING! %d bare linefeeds received in ASCII mode",
			    bare_lfs);
			printf("   File may not have transferred correctly.\r\n");
		}
		return (0);
	default:
		reply(550, "Unimplemented TYPE %d in receive_data", type);
		transflag = 0;
		return (-1);
	}

data_err:
	transflag = 0;
	reply(426, "Data Connection");
	return (-1);

file_err:
	transflag = 0;
	reply(452, "Error writing file");
	return (-1);

got_oob:
	myoob();
	recvurg = 0;
	transflag = 0;
	return (-1);
}

void
statfilecmd(char *filename)
{
	FILE *fin;
	int c;
	int atstart;
	char line[LINE_MAX];

	(void)snprintf(line, sizeof(line), "/bin/ls -lgA %s", filename);
	fin = ftpd_popen(line, "r");
	lreply(211, "status of %s:", filename);
	atstart = 1;
	while ((c = getc(fin)) != EOF) {
		if (c == '\n') {
			if (ferror(stdout)){
				perror_reply(421, "control connection");
				(void) ftpd_pclose(fin);
				dologout(1);
				/* NOTREACHED */
			}
			if (ferror(fin)) {
				perror_reply(551, filename);
				(void) ftpd_pclose(fin);
				return;
			}
			(void) putc('\r', stdout);
		}
		if (atstart && isdigit(c))
			(void) putc(' ', stdout);
		(void) putc(c, stdout);
		atstart = (c == '\n');
	}
	(void) ftpd_pclose(fin);
	reply(211, "End of Status");
}

void
statcmd(void)
{
	union sockunion *su;
	u_char *a, *p;
	char hbuf[MAXHOSTNAMELEN];
	int ispassive;
	int error;

	lreply(211, "%s FTP server status:", hostname);
	error = getnameinfo((struct sockaddr *)&his_addr, his_addr.su_len,
	    hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST);
	printf("     Connected to %s", remotehost);
	if (error == 0 && strcmp(remotehost, hbuf) != 0)
		printf(" (%s)", hbuf);
	printf("\r\n");
	if (logged_in) {
		if (guest)
			printf("     Logged in anonymously\r\n");
		else
			printf("     Logged in as %s\r\n", pw->pw_name);
	} else if (askpasswd)
		printf("     Waiting for password\r\n");
	else
		printf("     Waiting for user name\r\n");
	printf("     TYPE: %s", typenames[type]);
	if (type == TYPE_A || type == TYPE_E)
		printf(", FORM: %s", formnames[form]);
	if (type == TYPE_L)
#if NBBY == 8
		printf(" %d", NBBY);
#else
		printf(" %d", bytesize);	/* need definition! */
#endif
	printf("; STRUcture: %s; transfer MODE: %s\r\n",
	    strunames[stru], modenames[mode]);
	ispassive = 0;
	if (data != -1)
		printf("     Data connection open\r\n");
	else if (pdata != -1) {
		printf("     in Passive mode\r\n");
		su = (union sockunion *)&pasv_addr;
		ispassive++;
		goto printaddr;
	} else if (usedefault == 0) {
		size_t alen;
		int af, i;

		su = (union sockunion *)&data_dest;
printaddr:
		/* PASV/PORT */
		if (su->su_family == AF_INET) {
			if (ispassive)
				printf("211- PASV ");
			else
				printf("211- PORT ");
			a = (u_char *)&su->su_sin.sin_addr;
			p = (u_char *)&su->su_sin.sin_port;
			printf("(%u,%u,%u,%u,%u,%u)\r\n",
			    a[0], a[1], a[2], a[3],
			    p[0], p[1]);
		}

		/* LPSV/LPRT */
		alen = 0;
		switch (su->su_family) {
		case AF_INET:
			a = (u_char *)&su->su_sin.sin_addr;
			p = (u_char *)&su->su_sin.sin_port;
			alen = sizeof(su->su_sin.sin_addr);
			af = 4;
			break;
		case AF_INET6:
			a = (u_char *)&su->su_sin6.sin6_addr;
			p = (u_char *)&su->su_sin6.sin6_port;
			alen = sizeof(su->su_sin6.sin6_addr);
			af = 6;
			break;
		default:
			af = 0;
			break;
		}
		if (af) {
			if (ispassive)
				printf("211- LPSV ");
			else
				printf("211- LPRT ");
			printf("(%u,%llu", af, (unsigned long long)alen);
			for (i = 0; i < alen; i++)
				printf(",%u", a[i]);
			printf(",%u,%u,%u)\r\n", 2, p[0], p[1]);
		}

		/* EPRT/EPSV */
		switch (su->su_family) {
		case AF_INET:
			af = 1;
			break;
		case AF_INET6:
			af = 2;
			break;
		default:
			af = 0;
			break;
		}
		if (af) {
			char pbuf[10];
			union sockunion tmp = *su;

			if (tmp.su_family == AF_INET6)
				tmp.su_sin6.sin6_scope_id = 0;
			if (getnameinfo((struct sockaddr *)&tmp, tmp.su_len,
			    hbuf, sizeof(hbuf), pbuf, sizeof(pbuf),
			    NI_NUMERICHOST | NI_NUMERICSERV) == 0) {
				if (ispassive)
					printf("211- EPSV ");
				else
					printf("211- EPRT ");
				printf("(|%u|%s|%s|)\r\n",
				    af, hbuf, pbuf);
			}
		}
	} else
		printf("     No data connection\r\n");
	reply(211, "End of status");
}

void
fatal(char *s)
{

	reply(451, "Error in server: %s", s);
	reply(221, "Closing connection due to server error.");
	dologout(0);
	/* NOTREACHED */
}

void
reply(int n, const char *fmt, ...)
{
	char *buf, *p, *next;
	int rval;
	va_list ap;

	va_start(ap, fmt);
	rval = vasprintf(&buf, fmt, ap);
	va_end(ap);
	if (rval == -1 || buf == NULL) {
		printf("412 Local resource failure: malloc\r\n");
		fflush(stdout);
		dologout(1);
	}
	next = buf;
	while ((p = strsep(&next, "\n\r"))) {
		printf("%d%s %s\r\n", n, (next != '\0') ? "-" : "", p);
		if (debug)
			syslog(LOG_DEBUG, "<--- %d%s %s", n,
			    (next != '\0') ? "-" : "", p);
	}
	(void)fflush(stdout);
	free(buf);
}


void
reply_r(int n, const char *fmt, ...)
{
	char *p, *next;
	char msg[BUFSIZ];
	char buf[BUFSIZ];
	va_list ap;
	struct syslog_data sdata = SYSLOG_DATA_INIT;

	sdata.log_fac = LOG_FTP;
	va_start(ap, fmt);
	vsnprintf(msg, sizeof(msg), fmt, ap);
	va_end(ap);

	next = msg;

	while ((p = strsep(&next, "\n\r"))) {
		snprintf(buf, sizeof(buf), "%d%s %s\r\n", n,
		    (next != '\0') ? "-" : "", p);
		write(STDOUT_FILENO, buf, strlen(buf));
		if (debug) {
			buf[strlen(buf) - 2] = '\0';
			syslog_r(LOG_DEBUG, &sdata, "<--- %s", buf);
		}
	}
}

void
lreply(int n, const char *fmt, ...)
{
	va_list ap;

	va_start(ap, fmt);
	(void)printf("%d- ", n);
	(void)vprintf(fmt, ap);
	va_end(ap);
	(void)printf("\r\n");
	(void)fflush(stdout);
	if (debug) {
		va_start(ap, fmt);
		syslog(LOG_DEBUG, "<--- %d- ", n);
		vsyslog(LOG_DEBUG, fmt, ap);
		va_end(ap);
	}
}

static void
ack(char *s)
{

	reply(250, "%s command successful.", s);
}

void
nack(char *s)
{

	reply(502, "%s command not implemented.", s);
}

/* ARGSUSED */
void
yyerror(char *s)
{
	cbuf[strcspn(cbuf, "\n")] = '\0';
	reply(500, "'%s': command not understood.", cbuf);
}

void
delete(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");
}

void
cwd(char *path)
{
	FILE *message;

	if (chdir(path) < 0)
		perror_reply(550, path);
	else {
		if ((message = fopen(_PATH_CWDMESG, "r")) != NULL) {
			char line[LINE_MAX];

			while (fgets(line, sizeof(line), message) != NULL) {
				line[strcspn(line, "\n")] = '\0';
				lreply(250, "%s", line);
			}
			(void) fflush(stdout);
			(void) fclose(message);
		}
		ack("CWD");
	}
}

void
replydirname(const char *name, const char *message)
{
	char *p, *ep;
	char npath[MAXPATHLEN * 2];

	p = npath;
	ep = &npath[sizeof(npath) - 1];
	while (*name) {
		if (*name == '"') {
			if (ep - p < 2)
				break;
			*p++ = *name++;
			*p++ = '"';
		} else {
			if (ep - p < 1)
				break;
			*p++ = *name++;
		}
	}
	*p = '\0';
	reply(257, "\"%s\" %s", npath, message);
}

void
makedir(char *name)
{

	LOGCMD("mkdir", name);
	if (mkdir(name, 0777) < 0)
		perror_reply(550, name);
	else
		replydirname(name, "directory created.");
}

void
removedir(char *name)
{

	LOGCMD("rmdir", name);
	if (rmdir(name) < 0)
		perror_reply(550, name);
	else
		ack("RMD");
}

void
pwd(void)
{
	char path[MAXPATHLEN];

	if (getcwd(path, sizeof(path)) == NULL)
		perror_reply(550, "Can't get current directory");
	else
		replydirname(path, "is current directory.");
}

char *
renamefrom(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);
}

void
renamecmd(char *from, char *to)
{

	LOGCMD2("rename", from, to);
	if (rename(from, to) < 0)
		perror_reply(550, "rename");
	else
		ack("RNTO");
}

static void
dolog(struct sockaddr *sa)
{
	char hbuf[sizeof(remotehost)];

	if (getnameinfo(sa, sa->sa_len, hbuf, sizeof(hbuf), NULL, 0, 0) == 0)
		(void) strlcpy(remotehost, hbuf, sizeof(remotehost));
	else
		(void) strlcpy(remotehost, "unknown", sizeof(remotehost));

#ifdef HASSETPROCTITLE
	snprintf(proctitle, sizeof(proctitle), "%s: connected", remotehost);
	setproctitle("%s", proctitle);
#endif /* HASSETPROCTITLE */

	if (logging)
		syslog(LOG_INFO, "connection from %s", remotehost);
}

/*
 * Record logout in wtmp file and exit with supplied status.
 * NOTE: because this is called from signal handlers it cannot
 *       use stdio (or call other functions that use stdio).
 */
void
dologout(int status)
{

	transflag = 0;

	if (logged_in) {
		sigprocmask(SIG_BLOCK, &allsigs, NULL);
		ftpdlogwtmp(ttyline, "", "");
		if (doutmp)
			ftpd_logout(utmp.ut_line);
	}
	/* beware of flushing buffers after a SIGPIPE */
	_exit(status);
}

/*ARGSUSED*/
static void
sigurg(int signo)
{

	recvurg = 1;
}

⌨️ 快捷键说明

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