Skip to content
Snippets Groups Projects
ftpsrvr.c 181 KiB
Newer Older
		DESCRIBE_COMPILER(compiler);
		lprintf(LOG_INFO,"Compiled %s %s with %s", __DATE__, __TIME__, compiler);
		sbbs_srand();	/* Seed random number generator */
rswindell's avatar
rswindell committed
			cleanup(1,__LINE__);
		lprintf(LOG_INFO,"Initializing on %.24s with options: %x"
			,ctime_r(&t,str),startup->options);
		if(chdir(startup->ctrl_dir)!=0)
			lprintf(LOG_ERR,"!ERROR %d changing directory to: %s", errno, startup->ctrl_dir);

		/* Initial configuration and load from CNF files */
		SAFECOPY(scfg.ctrl_dir, startup->ctrl_dir);
		lprintf(LOG_INFO,"Loading configuration files from %s", scfg.ctrl_dir);
		SAFECOPY(error,UNKNOWN_LOAD_ERROR);
		if(!load_cfg(&scfg, text, TRUE, error)) {
			lprintf(LOG_CRIT,"!ERROR %s",error);
			lprintf(LOG_CRIT,"!Failed to load configuration files");
rswindell's avatar
rswindell committed
			cleanup(1,__LINE__);
			SAFECOPY(startup->host_name,scfg.sys_inetaddr);
		if((t=checktime())!=0) {   /* Check binary time */
			lprintf(LOG_ERR,"!TIME PROBLEM (%ld)",t);
			uptime=time(NULL);	/* this must be done *after* setting the timezone */
			SAFECOPY(scfg.temp_dir,startup->temp_dir);
			SAFECOPY(scfg.temp_dir,"../temp");
	   	prep_dir(scfg.ctrl_dir, scfg.temp_dir, sizeof(scfg.temp_dir));
		if(!isdir(scfg.temp_dir) && MKDIR(scfg.temp_dir) != 0) {
			lprintf(LOG_ERR, "Error %d creating temp directory: %s", errno, scfg.temp_dir);
			cleanup(1,__LINE__);
			break;
		}
		lprintf(LOG_DEBUG,"Temporary file directory: %s", scfg.temp_dir);
		if(!isdir(scfg.temp_dir)) {
			lprintf(LOG_CRIT,"!Invalid temp directory: %s", scfg.temp_dir);
		if(!startup->max_clients) {
			startup->max_clients=scfg.sys_nodes;
			if(startup->max_clients<10)
				startup->max_clients=10;
		}
		lprintf(LOG_DEBUG,"Maximum clients: %d",startup->max_clients);
		/* Sanity-check the passive port range */
		if(startup->pasv_port_low || startup->pasv_port_high) {
			if(startup->pasv_port_low > startup->pasv_port_high
				|| startup->pasv_port_high-startup->pasv_port_low < (startup->max_clients-1)) {
				lprintf(LOG_WARNING,"!Correcting Passive Port Range (Low: %u, High: %u)"
					,startup->pasv_port_low,startup->pasv_port_high);
				if(startup->pasv_port_low)
					startup->pasv_port_high = startup->pasv_port_low+(startup->max_clients-1);
				else
					startup->pasv_port_low = startup->pasv_port_high-(startup->max_clients-1);
			}
			lprintf(LOG_DEBUG,"Passive Port Low: %u",startup->pasv_port_low);
			lprintf(LOG_DEBUG,"Passive Port High: %u",startup->pasv_port_high);
		}

		lprintf(LOG_DEBUG,"Maximum inactivity: %d seconds",startup->max_inactivity);
		protected_uint32_init(&active_clients, 0);
		strlwr(scfg.sys_id); /* Use lower-case unix-looking System ID for group name */
		for(i=0;i<scfg.total_libs;i++) {
			strlwr(scfg.lib[i]->sname);
			dotname(scfg.lib[i]->sname,scfg.lib[i]->sname);
		}
		/* open a socket and wait for a client */
deuce's avatar
deuce committed
		ftp_set = xpms_create(startup->bind_retry_count, startup->bind_retry_delay, lprintf);
		
		if(ftp_set == NULL) {
			lprintf(LOG_CRIT,"!ERROR %d creating FTP socket set", ERROR_VALUE);
			cleanup(1, __LINE__);
			return;
deuce's avatar
deuce committed
		lprintf(LOG_DEBUG,"FTP Server socket set created");
deuce's avatar
deuce committed
		/*
		 * Add interfaces
		 */
		xpms_add_list(ftp_set, PF_UNSPEC, SOCK_STREAM, 0, startup->interfaces, startup->port, "FTP Server", ftp_open_socket_cb, startup->seteuid, NULL);
		/* Setup recycle/shutdown semaphore file lists */
		shutdown_semfiles=semfile_list_init(scfg.ctrl_dir,"shutdown","ftp");
		recycle_semfiles=semfile_list_init(scfg.ctrl_dir,"recycle","ftp");
		semfile_list_add(&recycle_semfiles,startup->ini_fname);
		SAFEPRINTF(path,"%sftpsrvr.rec",scfg.ctrl_dir);	/* legacy */
		semfile_list_add(&recycle_semfiles,path);
		if(!initialized) {
			semfile_list_check(&initialized,recycle_semfiles);
			semfile_list_check(&initialized,shutdown_semfiles);
		/* signal caller that we've started up successfully */
		if(startup->started!=NULL)
deuce's avatar
deuce committed
		lprintf(LOG_INFO,"FTP Server thread started");
deuce's avatar
deuce committed
		while(ftp_set!=NULL && !terminate_server) {
			if(protected_uint32_value(thread_count) <= 1) {
				if(!(startup->options&FTP_OPT_NO_RECYCLE)) {
					if((p=semfile_list_check(&initialized,recycle_semfiles))!=NULL) {
						lprintf(LOG_INFO,"0000 Recycle semaphore file (%s) detected",p);
						break;
					}
					if(startup->recycle_now==TRUE) {
						lprintf(LOG_NOTICE,"0000 Recycle semaphore signaled");
						startup->recycle_now=FALSE;
						break;
					}
				if(((p=semfile_list_check(&initialized,shutdown_semfiles))!=NULL
						&& lprintf(LOG_INFO,"0000 Shutdown semaphore file (%s) detected",p))
					|| (startup->shutdown_now==TRUE
						&& lprintf(LOG_INFO,"0000 Shutdown semaphore signaled"))) {
					startup->shutdown_now=FALSE;
					terminate_server=TRUE;
deuce's avatar
deuce committed
			if(ftp_set==NULL || terminate_server)	/* terminated */
deuce's avatar
deuce committed
			/* now wait for connection */
			client_addr_len = sizeof(client_addr);
deuce's avatar
deuce committed
			client_socket = xpms_accept(ftp_set, &client_addr, &client_addr_len, startup->sem_chk_freq*1000, NULL);
			if(client_socket == INVALID_SOCKET)
deuce's avatar
deuce committed

				startup->socket_open(startup->cbdata,TRUE);
deuce's avatar
deuce committed
			inet_addrtop(&client_addr, client_ip, sizeof(client_ip));
			if(trashcan(&scfg,client_ip,"ip-silent")) {
deuce's avatar
deuce committed
				ftp_close_socket(&client_socket,&none,__LINE__);
			if(protected_uint32_value(active_clients)>=startup->max_clients) {
runderwo's avatar
 
runderwo committed
				lprintf(LOG_WARNING,"%04d !MAXIMUM CLIENTS (%d) reached, access denied"
					,client_socket, startup->max_clients);
deuce's avatar
deuce committed
				sockprintf(client_socket,-1,"421 Maximum active clients reached, please try again later.");
deuce's avatar
deuce committed
				ftp_close_socket(&client_socket,&none,__LINE__);
			if((ftp=malloc(sizeof(ftp_t)))==NULL) {
				lprintf(LOG_CRIT,"%04d !ERROR allocating %d bytes of memory for ftp_t"
					,client_socket,(int)sizeof(ftp_t));
deuce's avatar
deuce committed
				sockprintf(client_socket,-1,"421 System error, please try again later.");
deuce's avatar
deuce committed
				ftp_close_socket(&client_socket,&none,__LINE__);
deuce's avatar
deuce committed
			memcpy(&ftp->client_addr, &client_addr, client_addr_len);
			ftp->client_addr_len = client_addr_len;
			protected_uint32_adjust(&thread_count,1);
#if 0 /* def _DEBUG */
		lprintf(LOG_DEBUG,"0000 terminate_server: %d",terminate_server);
#endif
		if(protected_uint32_value(active_clients)) {
			lprintf(LOG_INFO,"0000 Waiting for %d active clients to disconnect..."
deuce's avatar
deuce committed
				, protected_uint32_value(active_clients));
			while(protected_uint32_value(active_clients)) {
				if(time(NULL)-start > startup->max_inactivity * 2) {
					lprintf(LOG_WARNING,"0000 !TIMEOUT waiting for %d active clients"
deuce's avatar
deuce committed
						, protected_uint32_value(active_clients));
			lprintf(LOG_INFO, "0000 Done waiting for active clients to disconnect");
rswindell's avatar
rswindell committed
		cleanup(0,__LINE__);
			lprintf(LOG_INFO,"Recycling server...");
			mswait(2000);
			if(startup->recycle!=NULL)
				startup->recycle(startup->cbdata);
	protected_uint32_destroy(thread_count);