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

📄 ftpd.c

📁 ftp服务器源程序
💻 C
📖 第 1 页 / 共 3 页
字号:
/*  ftpd.c: BetaFTPD main    Copyright (C) 1999-2000 Steinar H. Gunderson    This program is is free software; you can redistribute it and/or modify    it under the terms of the GNU General Public License, version 2 if the    License as published by the Free Software Foundation.    This program is distributed in the hope that it will be useful,    but WITHOUT ANY WARRANTY; without even the implied warranty of    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    GNU General Public License for more details.    You should have received a copy of the GNU General Public License    along with this program; if not, write to the Free Software    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.*//* * Special note: this file has been overwritten by another (0-byte) file, been * through the dead, and restored (with the help of dd, grep, gpm, vi and less) * with a sucess rate of 99.9%. Show it a little respect -- don't add junk * to it. :-) */#define _GNU_SOURCE#if HAVE_CONFIG_H#include <config.h>#endif#if HAVE_ERRNO_H#include <errno.h>#endif#if HAVE_STROPTS_H#include <stropts.h>#endif#if HAVE_SYS_CONF_H#include <sys/conf.h>#endif#if HAVE_FCNTL_H#include <fcntl.h>#endif#if HAVE_STDIO_H#include <stdio.h>#endif#if HAVE_ASSERT_H#include <assert.h>#endif#if HAVE_STRING_H#include <string.h>#endif#if HAVE_STRINGS_H#include <strings.h>#endif#if HAVE_STDARG_H#include <stdarg.h>#endif#if HAVE_STDLIB_H#include <stdlib.h>#endif#if HAVE_UNISTD_H#include <unistd.h>#endif#if HAVE_ARPA_INET_H#include <arpa/inet.h>#endif#if HAVE_SYS_STAT_H#include <sys/stat.h>#endif#if HAVE_SYS_IOCTL_H#include <sys/ioctl.h>#endif#if HAVE_NETINET_IN_SYSTM_H#include <netinet/in_systm.h>#endif#if HAVE_NETINET_IP_H#include <netinet/ip.h>#endif#if HAVE_NETINET_TCP_H#include <netinet/tcp.h>#endif#if HAVE_LINUX_SOCKET_H#include <linux/socket.h>#endif#if HAVE_LINUX_TCP_H#include <linux/tcp.h>#endif#if HAVE_MMAP#include <sys/mman.h>#endif#if HAVE_TIME_H#include <time.h>#endif#if HAVE_SYS_TIME_H#include <sys/time.h>#endif#if HAVE_SYS_TIME_H#include <sys/time.h>#endif#if HAVE_SYS_FILIO_H#include <sys/filio.h>#endif#if HAVE_NETDB_H#include <netdb.h>#endif#if HAVE_SIGNAL_H#include <signal.h>#endif#if HAVE_GLOB_H#include <glob.h>#endif#if HAVE_SYS_SIGNAL_H#include <sys/signal.h>#endif#if HAVE_SYS_POLL_H#include <sys/poll.h>#endif#if HAVE_SYS_SENDFILE_H#include <sys/sendfile.h>#endif/* * <linux/socket.h> does not export this to glibc2 systems, and it isn't * always defined anywhere else. */#if !defined(TCP_CORK) && defined(__linux__)#define TCP_CORK 3#endif#include <ftpd.h>#include <cmds.h>#if WANT_ASCII#include <ascii.h>#endif#if WANT_DCACHE#include <dcache.h>#endif#ifndef MAP_FAILED#define MAP_FAILED -1#endifstruct conn *first_conn = NULL;struct ftran *first_ftran = NULL;#if WANT_DCACHEstruct dcache *first_dcache = NULL;#endif#if HAVE_POLLunsigned int highest_fds = 0;#define FD_MAX 1024#define fds_send fdsstruct pollfd fds[FD_MAX];#define MAXCLIENTS FD_MAX#elsefd_set master_fds, master_send_fds;#define MAXCLIENTS FD_SETSIZE#endif#if WANT_XFERLOGFILE *xferlog = NULL;#endif#if HAVE_LINUX_SENDFILEint sendfile_supported = 1;#endif/* * This variable specifies if it's soon time to check for timed out * clients, and timed out directory listing cache entries. It is * set to 1 by a signal handler every minute, and set to 0 when the * checking has been performed. */int time_to_check = 1;#ifndef HAVE_SPRINTF/* * snprintf():	snprintf() replacement for systems that miss it. Note *		that this implementation does _not_ necessarily protect *		against all buffer overflows. Get a real snprintf() in *		your C library. That being said, the 8k limit is *		substantially larger than any other string in BetaFTPD, *		which should make such an attack harder. */int snprintf(char *str, size_t n, const char *format, ...){	char buf[8192];	va_list args;	int err;	va_start(args, format);	err = vsprintf(buf, format, args);	va_end(args);	buf[(int)n] = 0;	strcpy(str, buf);	return err;}#endif#ifndef HAVE_VSNPRINTF/* * vsnprintf:	vsnprintf() replacement for systems that miss it. Please *		see snprintf (above) for more information. */int vsnprintf(char *str, size_t n, const char *format, va_list ap){	char buf[8192];	int err;	err = vsprintf(buf, format, ap);	buf[(int)n] = 0;	strcpy(str, buf);	return err;}#endif/* * add_fd():	Add an fd to the set we monitor. Return 0 on success. *		This code is shared between poll() and select() versions. */int add_fd(const int fd, const int events){#if HAVE_POLL	if (fd >= FD_MAX) {		printf("add_fd(%d, %x): failed\n", fd, events);		return E2BIG;	}	fds[fd].fd = fd;	fds[fd].events = events;	if (highest_fds < fd) 		highest_fds = fd;#else 	if (fd >= FD_SETSIZE)		return E2BIG;	if (events & POLLIN)		FD_SET(fd, &master_fds);	if (events & POLLOUT)		FD_SET(fd, &master_send_fds);#endif	return 0;}/* * del_fd():	Close and remove an fd from the set(s) we monitor. (See also add_fd().) */void del_fd(const int fd){#if HAVE_POLL	if (fd >= FD_MAX)		return;	fds[fd].fd = -1;	fds[fd].events = 0;	/* Reduce poll()'s workload by not making it watch past end of array */	while ((highest_fds > 0) && (fds[highest_fds].fd == -1))	 	highest_fds--;#else 	if (fd >= FD_SETSIZE)		return;	FD_CLR(fd, &master_fds);	FD_CLR(fd, &master_send_fds);#endif	close(fd);}#if 0void list_clients(){	struct conn *c = first_conn;	printf("list_clients:\n");	while (c && c->next_conn) {		c = c->next_conn;		printf("list_clients: fd %d\n", c->sock);	}}#endif/* * add_to_linked_list(): *		Inserts an element (conn, ftran or dcache) into its linked list. *		The list is placed at the beginning, right after the (bogus) *		first element of the list. */void add_to_linked_list(struct list_element * const first,			struct list_element * const elem){	elem->prev = first;        if (first) {                elem->next = first->next;                if (elem->next) elem->next->prev = elem;                first->next = elem;        } else {		/* this is the bogus head of the list */                elem->next = NULL;        }}/* * remove_from_linked_list(): *		Removes an element (conn, ftran or dcache) from its linked list, *		then frees it. */void remove_from_linked_list(struct list_element * const elem){	if (elem->prev != NULL) elem->prev->next = elem->next;	if (elem->next != NULL) elem->next->prev = elem->prev;	free(elem);}/* * alloc_new_conn(): *		Allocates a new control connection (type `struct conn'), *		initializes it, and adds it to the linked list. The connection *		operates on the socket SOCK. */struct conn *alloc_new_conn(const int sock){	const unsigned int one = 1;	struct conn *c = (struct conn *)(malloc(sizeof(struct conn)));	if (c == NULL) return c;	if (sock != -1) {		ioctl(sock, FIONBIO, &one);		if (add_fd(sock, POLLIN) != 0) {			/* temp unavail */			send(sock, "230 Server too busy, please try again later.\r\n", 46, 0);			close(sock);			return NULL;		}		add_to_linked_list((struct list_element *)first_conn,			           (struct list_element *)c);	} else {		/* this is the bogus head of the list */		c->next_conn = NULL;		c->prev_conn = NULL;	}	c->transfer = NULL;	c->sock = sock;	c->buf_len = c->auth = c->rest_pos = 0;#if WANT_ASCII	c->ascii_mode = 0;#endif	/*	 * equals:	 * strcpy(c->curr_dir, "/");	 * strcpy(c->last_cmd, "");	 * strcpy(c->rename_from, "")	 */	c->curr_dir[0] = '/';#if WANT_FULLSCREEN	c->curr_dir[1] = c->last_cmd[0] = c->rename_from[0] = '\0';#else	c->curr_dir[1] = c->rename_from[0] = '\0';#endif	time(&(c->last_transfer));	/*list_clients();*/	return c;}/* * alloc_new_ftran(): *		Allocates a new data connection (type `struct ftran'), and *		adds it to the linked list. The connection operates on the *		socket SOCK, and has the control connection C as its parent. */struct ftran *alloc_new_ftran(const int sock, const struct conn * const c){	struct ftran *f = (struct ftran *)(malloc(sizeof(struct ftran)));	if (f == NULL) return f;	if (c == NULL) {		/* this is the bogus head of the list */		f->next_ftran = NULL;		f->prev_ftran = NULL;	} else {		add_to_linked_list((struct list_element *)first_ftran,				   (struct list_element *)f);	}#if HAVE_MMAP	f->file_data = NULL;#endif	f->owner = (struct conn * const)c;	f->sock = sock;	f->state = 0;	f->local_file = -1;#if WANT_DCACHE	f->dir_cache = NULL;#endif	f->dir_listing = 0;	return f;}/* * destroy_conn(): *		Destroy a control connection, remove it from the linked *		list, and clean up after it. */void destroy_conn(struct conn * const c){	if (c == NULL) return;	del_fd(c->sock);	destroy_ftran(c->transfer);	remove_from_linked_list((struct list_element *)c);}/* * destroy_ftran(): *		Destroy a data connection, remove it from the linked list, *		and clean up after it. * *		For some reason, TCP_CORK (Linux 2.2.x-only) doesn't flush *		even _after_ the socket is closed, so we zero it just before *		closing. We also zero just before sending the last packet, *		as it seems to be needed on some systems. * *		If you wonder why I check for `defined(SOL_TCP)' and don't *		provide an alternative, see the comments on init_file_transfer(). */void destroy_ftran(struct ftran * const f){	const unsigned int zero = 0;	if (f == NULL) return;#if defined(TCP_CORK) && defined(SOL_TCP)	setsockopt(f->sock, SOL_TCP, TCP_CORK, (void *)&zero, sizeof(zero));#endif	del_fd(f->sock);#if WANT_DCACHE	if (f->dir_cache) {		time(&(f->dir_cache->last_used));		f->dir_cache->use_count--;		f->dir_cache = NULL;	} else#endif#if HAVE_MMAP		if (f->file_data) {			if (f->dir_listing) {				free(f->file_data);				f->file_data = NULL;			} else {				munmap(f->file_data, f->size);			}		}	if (!f->dir_listing)#endif		if (f->local_file != -1) close(f->local_file);#if !HAVE_MMAP	if (f->dir_listing) unlink(f->filename);#endif	f->owner->transfer = NULL;#if WANT_DCACHE	if (f->dir_cache != NULL) f->dir_cache->use_count--;#endif	remove_from_linked_list((struct list_element *)f);}

⌨️ 快捷键说明

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