1#include "config.h"
2#include <errno.h>
3#include <stdio.h>
4#include <stdlib.h>
5#include <stdarg.h>
6#define __USE_GNU
7#include <unistd.h>
8#ifdef HAVE_SYS_TYPES_H
9#include <sys/types.h>
10#endif
11#ifdef HAVE_SYS_STAT_H
12#include <sys/stat.h>
13#endif
14#ifdef HAVE_SYS_SOCKET_H
15#include <sys/socket.h>
16#endif
17#ifdef HAVE_ASM_SOCKET_H
18#include <asm/socket.h>
19#endif
20#ifdef HAVE_NETINET_IN_H
21#include <netinet/in.h>
22#endif
23#ifdef HAVE_ARPA_INET_H
24#include <arpa/inet.h>
25#endif
26#ifdef HAVE_SYS_TIME_H
27#include <sys/time.h>
28#endif
29#ifdef HAVE_TIME_H
30#include <time.h>
31#endif
32#include <fcntl.h>
33#include <string.h>
34#ifdef HAVE_WAIT_H
35# include <wait.h>
36#else
37# ifdef HAVE_SYS_WAIT_H
38#  include <sys/wait.h>
39# endif
40#endif
41
42#include <string.h> /* for strncpy */
43#include <sys/types.h>
44#include <sys/socket.h>
45#include <sys/ioctl.h>
46#include <netinet/in.h>
47#include <net/if.h>
48
49#include "mystring.h"
50#include "login.h"
51#include "logging.h"
52#include "dirlist.h"
53#include "options.h"
54#include "main.h"
55#include "targzip.h"
56#include "cwd.h"
57#include "bftpdutmp.h"
58
59#ifdef HAVE_ZLIB_H
60#include <zlib.h>
61#else
62#undef WANT_GZIP
63#endif
64
65int state = STATE_CONNECTED;
66char user[USERLEN + 1];
67struct sockaddr_in sa;
68char pasv = 0;
69int sock;
70int pasvsock;
71char *philename = NULL;
72int offset = 0;
73short int xfertype = TYPE_BINARY;
74int ratio_send = 1, ratio_recv = 1;
75long unsigned bytes_sent = 0, bytes_recvd = 0;
76int epsvall = 0;
77int xfer_bufsize;
78
79
80void control_printf(char success, char *format, ...)
81{
82	char buffer[256];
83	va_list val;
84	va_start(val, format);
85	vsnprintf(buffer, sizeof(buffer), format, val);
86	va_end(val);
87    /* Foxconn modified start pling 06/29/2010 */
88    /* Fix Chrome V4.0.249.78 FTP issue: the \r\n needs to appear
89     *  immediately after the response.
90     */
91#if 0
92	fprintf(stderr, "%s\r\n", buffer);
93#endif
94    strcat(buffer, "\r\n");
95	fprintf(stderr, "%s", buffer);
96    /* Foxconn modified end pling 06/29/2010 */
97	replace(buffer, "\r", "");
98	bftpd_statuslog(3, success, "%s", buffer);
99}
100
101void new_umask()
102{
103	int um;
104	char *foo = config_getoption("UMASK");
105	if (!foo[0])
106		um = 022;
107	else
108		um = strtoul(foo, NULL, 8);
109	umask(um);
110}
111
112void prepare_sock(int sock)
113{
114	int on = 1;
115#ifdef TCP_NODELAY
116	setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (void *) &on, sizeof(on));
117#endif
118#ifdef TCP_NOPUSH
119	setsockopt(sock, IPPROTO_TCP, TCP_NOPUSH, (void *) &on, sizeof(on));
120#endif
121#ifdef SO_REUSEADDR
122	setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void *) &on, sizeof(on));
123#endif
124#ifdef SO_REUSEPORT
125	setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, (void *) &on, sizeof(on));
126#endif
127#ifdef SO_SNDBUF
128/* Foxconn modified start, Jonathan 10/14/2011 */
129#if 1
130	/* because open 15 sessions to downlod that caused system crash, set smaller sending buffer */
131	on = 1024*128;
132#else
133	on = 1024*1024*4; /* wklin modified, 11/19/2009 */
134#endif
135/* Foxconn modified end, Jonathan 10/14/2011 */
136	setsockopt(sock, SOL_SOCKET, SO_SNDBUF, (void *) &on, sizeof(on));
137	on = 65536*10; /* wklin modified, 11/19/2009 */
138	setsockopt(sock, SOL_SOCKET, SO_RCVBUF, (void *) &on, sizeof(on));  // Foxconn added pling 06/19/2009
139#endif
140}
141
142int dataconn()
143{
144	struct sockaddr foo;
145	struct sockaddr_in local;
146	socklen_t namelen = sizeof(foo);
147	int curuid = geteuid();
148
149	memset(&foo, 0, sizeof(foo));
150	memset(&local, 0, sizeof(local));
151
152	if (pasv) {
153		sock = accept(pasvsock, (struct sockaddr *) &foo, (socklen_t *) &namelen);
154		if (sock == -1) {
155			control_printf(SL_FAILURE, "425-Unable to accept data connection.\r\n425 %s.",
156					strerror(errno));
157			return 1;
158		}
159		close(pasvsock);
160		prepare_sock(sock);
161	} else {
162		sock = socket(AF_INET, SOCK_STREAM, 0);
163		prepare_sock(sock);
164		local.sin_addr.s_addr = name.sin_addr.s_addr;
165		local.sin_family = AF_INET;
166		if (!strcasecmp(config_getoption("DATAPORT20"), "yes")) {
167			seteuid(0);
168			local.sin_port = htons(20);
169		}
170		if (bind(sock, (struct sockaddr *) &local, sizeof(local)) < 0) {
171			control_printf(SL_FAILURE, "425-Unable to bind data socket.\r\n425 %s.",
172					strerror(errno));
173			return 1;
174		}
175		if (!strcasecmp(config_getoption("DATAPORT20"), "yes"))
176			seteuid(curuid);
177		sa.sin_family = AF_INET;
178		if (connect(sock, (struct sockaddr *) &sa, sizeof(sa)) == -1) {
179			control_printf(SL_FAILURE, "425-Unable to establish data connection.\r\n"
180					"425 %s.", strerror(errno));
181			return 1;
182		}
183	}
184	control_printf(SL_SUCCESS, "150 %s data connection established.",
185			xfertype == TYPE_BINARY ? "BINARY" : "ASCII");
186	return 0;
187}
188
189void init_userinfo()
190{
191#ifndef NO_GETPWNAM
192	struct passwd *temp = getpwnam(user);
193	if (temp) {
194		userinfo.pw_name = strdup(temp->pw_name);
195		userinfo.pw_passwd = strdup(temp->pw_passwd);
196		userinfo.pw_uid = temp->pw_uid;
197		userinfo.pw_gid = temp->pw_gid;
198		userinfo.pw_gecos = strdup(temp->pw_gecos);
199		userinfo.pw_dir = strdup(temp->pw_dir);
200		userinfo.pw_shell = strdup(temp->pw_shell);
201		userinfo_set = 1;
202	}
203#endif
204}
205
206/**
207 * foxconn,start by cliff wang @ checking remote access for log
208 * */
209#if 0
210int isLanSubnet(char *ipAddr, char *lan_addr, char *lan_mask)
211{
212        long netAddr, netMask, netIp;
213
214        netAddr = inet_addr(lan_addr);
215        netMask = inet_addr(lan_mask);
216        netIp   = inet_addr(ipAddr);
217
218    	if ((netAddr & netMask) != (netIp & netMask))
219            return FALSE;
220        return TRUE;
221}
222
223static int check_ip_info_by_name(char *intf)
224{
225       int fd;
226       struct ifreq ifr;
227       struct ifreq mask;
228
229       fd = socket(AF_INET, SOCK_DGRAM, 0);
230
231       /* I want to get an IPv4 IP address */
232       ifr.ifr_addr.sa_family = AF_INET;
233
234       /* I want IP address attached to "eth0" */
235       strncpy(ifr.ifr_name, intf, IFNAMSIZ-1);
236       strncpy(mask.ifr_name, intf, IFNAMSIZ-1);
237
238       ioctl(fd, SIOCGIFADDR, &ifr);
239       ioctl(fd, SIOCGIFNETMASK, &mask);
240
241       close(fd);
242
243       /* display result */
244       printf("ip:   %s\n", inet_ntoa(((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr));
245       printf("mask: %s\n", inet_ntoa(((struct sockaddr_in *)&mask.ifr_netmask)->sin_addr));
246
247       return isLanSubnet(remotehostname,
248		          inet_ntoa(((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr),
249			  inet_ntoa(((struct sockaddr_in *)&mask.ifr_netmask)->sin_addr) );
250}
251
252int ambitWriteLog(char *pcLog, int iLen)
253{
254        FILE *fp;
255
256	if (!(fp = fopen("/dev/aglog", "r+")))
257        {
258              printf("%s:open /dev/aglog fail\n", __FUNCTION__);
259              return -1;
260        }
261
262    	*(pcLog + iLen) = '\0';
263        fwrite(pcLog, sizeof(char), iLen+1, fp);
264        fclose(fp);
265        return 0;
266}
267
268#include <sys/un.h>
269#include <stddef.h>
270
271void fifo_write(char *buf)
272{
273	char fn[]="/tmp/local_sock";
274        int wfd;
275	struct sockaddr_un name;
276        int sock;
277        size_t size;
278
279	sock = socket (PF_LOCAL, SOCK_DGRAM, 0);
280
281        name.sun_family = AF_LOCAL;
282        strncpy (name.sun_path, "/tmp/local_sock", sizeof (name.sun_path));
283        name.sun_path[sizeof (name.sun_path) - 1] = '\0';
284
285	size = (offsetof (struct sockaddr_un, sun_path) + strlen (name.sun_path) + 1);
286
287	connect(sock, (struct sockaddr *) &name, size);
288
289	write(sock, buf, strlen(buf));
290
291	fflush(sock);
292
293	close(sock);
294}
295#endif
296
297/*
298 * foxconn,end by cliff wang @ checking remote access for log
299 * **/
300
301void command_user(char *username)
302{
303	char *alias;
304
305	/* Foxconn addedd start pling 06/10/2009*/
306	/* If all shared folders are 'All - no password',
307	 * then no need to login for "FTP".
308	 * Also, take care of duplicate login.
309	 */
310	extern int all_no_password;
311
312	char modified_user[] = "guest";
313
314	//if ( strlen(username) != 0 && strcmp(username, "admin") != 0 ) {
315	if (all_no_password) {
316		if (strcmp(user, "guest") ) {
317			/* first time */
318			username = modified_user;
319		} else {
320			/* duplicate login */
321			control_printf (SL_SUCCESS, "230 User logged in.");
322			write_usb_access_log();
323			return;
324		}
325	}
326        /* foxconn, cliff wang, remove for 2nd login browser using anonymous user first */
327	/* Foxconn, cliffwang, router spec 2.0, any account can access
328	 * * non-amdin folder
329	 * * */
330	else if ( strlen(username) != 0 && strcmp(username, "anonymous") == 0 ) {
331                control_printf (SL_SUCCESS, "331 input email as password.");
332                state = STATE_USER;
333                return;
334        }
335
336	/* Foxconn added end pling 06/10/2009*/
337#if 0
338	if (state) {
339		// control_printf(SL_FAILURE, "503 Username already given.");
340		state = STATE_AUTHENTICATED;
341		return;
342	}
343#endif
344	mystrncpy(user, username, sizeof(user) - 1);
345	userinfo_set = 1; /* Dirty! */
346	alias = (char *) config_getoption("ALIAS");
347	userinfo_set = 0;
348	if (alias[0] != '\0')
349		mystrncpy(user, alias, sizeof(user) - 1);
350	init_userinfo();
351#ifdef DEBUG
352	bftpd_log("Trying to log in as %s.\n", user);
353#endif
354	expand_groups();
355	if (!strcasecmp(config_getoption("ANONYMOUS_USER"), "yes"))
356		bftpd_login("");
357	else {
358		state = STATE_USER;
359		control_printf(SL_SUCCESS, "331 Password please.");
360	}
361}
362
363void command_pass(char *password)
364{
365        /*
366	 * Foxconn, added by cliff wang @ for logging usb access for ftp
367	 * */
368        char tmpStr[64];
369        //int bIsLanIP = check_ip_info_by_name("br0");
370        //int bIsLanIP = 1;
371        //fifo_write("start to auth\n");
372
373	if ( strlen(user) != 0 && strcmp(user, "anonymous") == 0 ) {
374	     // STATE_CONNECTED, STATE_USER, STATE_AUTHENTICATED
375	     state = STATE_CONNECTED;
376             control_printf (SL_SUCCESS, "530 Sorry anonymous now allowed.");
377             exit(0);
378        }
379
380	if (state > STATE_USER) {
381		control_printf(SL_FAILURE, "503 Already logged in.");
382		return;
383	}
384
385	if (bftpd_login(password)) {
386#if 0
387                if ( !bIsLanIP ) {
388                    sprintf(tmpStr, " [USB remote access rejected] from source %s through FTP, ", remotehostname);
389                    //ambitWriteLog(tmpStr, strlen(tmpStr));
390		    fifo_write(tmpStr);
391		}
392#endif
393		write_usb_fail_log();
394
395		bftpd_log("Login as user '%s' failed.\n", user);
396                control_printf(SL_FAILURE, "421 Login incorrect.");
397  		exit(0);
398	} else {
399#if 0
400		if ( !bIsLanIP ) {
401		    sprintf(tmpStr, " [USB remote access] from source %s through FTP, ", remotehostname);
402		    //ambitWriteLog(tmpStr, strlen(tmpStr));
403		    fifo_write(tmpStr);
404	        }
405#endif
406	}
407}
408
409void command_pwd(char *params)
410{
411	char *my_cwd = NULL;
412
413	my_cwd = bftpd_cwd_getcwd();
414	if (my_cwd)
415	{
416		control_printf(SL_SUCCESS, "257 \"%s\" is the current working directory.", my_cwd);
417		free(my_cwd);
418	}
419}
420
421
422void command_type(char *params)
423{
424	if ((*params == 'A') || (*params == 'a')) {
425		control_printf(SL_SUCCESS, "200 Transfer type changed to ASCII");
426		xfertype = TYPE_ASCII;
427	} else if ((*params == 'I') || (*params == 'i')) {
428		control_printf(SL_SUCCESS, "200 Transfer type changed to BINARY");
429		xfertype = TYPE_BINARY;
430	} else
431		control_printf(SL_FAILURE, "500 Type '%c' not supported.", *params);
432}
433
434void command_port(char *params) {
435	unsigned long a0, a1, a2, a3, p0, p1, addr;
436	if (epsvall) {
437		control_printf(SL_FAILURE, "500 EPSV ALL has been called.");
438		return;
439	}
440	sscanf(params, "%lu,%lu,%lu,%lu,%lu,%lu", &a0, &a1, &a2, &a3, &p0, &p1);
441	addr = htonl((a0 << 24) + (a1 << 16) + (a2 << 8) + a3);
442	if((addr != remotename.sin_addr.s_addr) &&( strncasecmp(config_getoption("ALLOW_FXP"), "yes", 3))) {
443		control_printf(SL_FAILURE, "500 The given address is not yours.");
444		return;
445	}
446	sa.sin_addr.s_addr = addr;
447	sa.sin_port = htons((p0 << 8) + p1);
448	if (pasv) {
449		close(sock);
450		pasv = 0;
451	}
452	control_printf(SL_SUCCESS, "200 PORT %lu.%lu.%lu.%lu:%lu OK",
453			a0, a1, a2, a3, (p0 << 8) + p1);
454}
455
456void command_eprt(char *params) {
457	char delim;
458	int af;
459	char addr[51];
460	char foo[20];
461	int port;
462	if (epsvall) {
463		control_printf(SL_FAILURE, "500 EPSV ALL has been called.");
464		return;
465	}
466	if (strlen(params) < 5) {
467		control_printf(SL_FAILURE, "500 Syntax error.");
468		return;
469	}
470	delim = params[0];
471	sprintf(foo, "%c%%i%c%%50[^%c]%c%%i%c", delim, delim, delim, delim, delim);
472	if (sscanf(params, foo, &af, addr, &port) < 3) {
473		control_printf(SL_FAILURE, "500 Syntax error.");
474		return;
475	}
476	if (af != 1) {
477		control_printf(SL_FAILURE, "522 Protocol unsupported, use (1)");
478		return;
479	}
480	sa.sin_addr.s_addr = inet_addr(addr);
481	if ((sa.sin_addr.s_addr != remotename.sin_addr.s_addr) && (strncasecmp(config_getoption("ALLOW_FXP"), "yes", 3))) {
482		control_printf(SL_FAILURE, "500 The given address is not yours.");
483		return;
484	}
485	sa.sin_port = htons(port);
486	if (pasv) {
487		close(sock);
488		pasv = 0;
489	}
490	control_printf(SL_FAILURE, "200 EPRT %s:%i OK", addr, port);
491}
492
493void command_pasv(char *foo)
494{
495	int a1, a2, a3, a4;
496	socklen_t namelen;
497	struct sockaddr_in localsock;
498	char *my_override_ip;
499
500	if (epsvall) {
501		control_printf(SL_FAILURE, "500 EPSV ALL has been called.");
502		return;
503	}
504	pasvsock = socket(AF_INET, SOCK_STREAM, 0);
505	sa.sin_addr.s_addr = INADDR_ANY;
506	sa.sin_family = AF_INET;
507
508	if (!config_getoption("PASSIVE_PORTS") || !strlen(config_getoption("PASSIVE_PORTS"))) {
509		/* bind to any port */
510		sa.sin_port = 0;
511		if (bind(pasvsock, (struct sockaddr *) &sa, sizeof(sa)) == -1)
512		{
513			control_printf(SL_FAILURE, "425-Error: Unable to bind data socket.\r\n425 %s", strerror(errno));
514			return;
515		}
516	}
517
518	else {
519		int i = 0, success = 0, port;
520		for (;;) {
521			port = int_from_list(config_getoption("PASSIVE_PORTS"), i++);
522			if (port < 0)
523				break;
524			sa.sin_port = htons(port);
525			if (bind(pasvsock, (struct sockaddr *) &sa, sizeof(sa)) == 0) {
526				success = 1;
527#ifdef DEBUG
528				bftpd_log("Passive mode: Successfully bound port %d\n", port);
529#endif
530				break;
531			}
532		}   /* end of for loop */
533		if (!success) {
534			control_printf(SL_FAILURE, "425 Error: Unable to bind data socket.");
535			return;
536		}
537		prepare_sock(pasvsock);
538	}    /* end of else using list of ports */
539
540	if (listen(pasvsock, 1)) {
541		control_printf(SL_FAILURE, "425-Error: Unable to make socket listen.\r\n425 %s",
542				strerror(errno));
543		return;
544	}
545	namelen = sizeof(localsock);
546	getsockname(pasvsock, (struct sockaddr *) &localsock, (socklen_t *) &namelen);
547
548	/* see if we should over-ride the IP address sent to the client */
549	my_override_ip = config_getoption("OVERRIDE_IP");
550	if (my_override_ip[0])
551	{
552		sscanf( my_override_ip, "%i.%i.%i.%i",
553				&a1, &a2, &a3, &a4);
554	}
555	else   /* noraml, no over-ride */
556	{
557		sscanf((char *) inet_ntoa(name.sin_addr), "%i.%i.%i.%i",
558				&a1, &a2, &a3, &a4);
559	}
560
561	control_printf(SL_SUCCESS, "227 Entering Passive Mode (%i,%i,%i,%i,%i,%i)", a1, a2, a3, a4,
562			ntohs(localsock.sin_port) >> 8, ntohs(localsock.sin_port) & 0xFF);
563	pasv = 1;
564}
565
566void command_epsv(char *params)
567{
568	struct sockaddr_in localsock;
569	socklen_t namelen;
570	int af;
571	if (params[0]) {
572		if (!strncasecmp(params, "ALL", 3))
573			epsvall = 1;
574		else {
575			if (sscanf(params, "%i", &af) < 1) {
576				control_printf(SL_FAILURE, "500 Syntax error.");
577				return;
578			} else {
579				if (af != 1) {
580					control_printf(SL_FAILURE, "522 Protocol unsupported, use (1)");
581					return;
582				}
583			}
584		}
585	}
586	pasvsock = socket(AF_INET, SOCK_STREAM, 0);
587	sa.sin_addr.s_addr = INADDR_ANY;
588	sa.sin_port = 0;
589	sa.sin_family = AF_INET;
590	if (bind(pasvsock, (struct sockaddr *) &sa, sizeof(sa)) == -1) {
591		control_printf(SL_FAILURE, "500-Error: Unable to bind data socket.\r\n425 %s",
592				strerror(errno));
593		return;
594	}
595	if (listen(pasvsock, 1)) {
596		control_printf(SL_FAILURE, "500-Error: Unable to make socket listen.\r\n425 %s",
597				strerror(errno));
598		return;
599	}
600	namelen = sizeof(localsock);
601	getsockname(pasvsock, (struct sockaddr *) &localsock, (socklen_t *) &namelen);
602	control_printf(SL_SUCCESS, "229 Entering extended passive mode (|||%i|)",
603			ntohs(localsock.sin_port));
604	pasv = 1;
605}
606
607char test_abort(char selectbefore, int file, int sock)
608{
609	char str[256];
610	fd_set rfds;
611	struct timeval tv;
612	if (selectbefore) {
613		tv.tv_sec = 0;
614		tv.tv_usec = 0;
615		FD_ZERO(&rfds);
616		FD_SET(fileno(stdin), &rfds);
617		if (!select(fileno(stdin) + 1, &rfds, NULL, NULL, &tv))
618			return 0;
619	}
620	fgets(str, sizeof(str), stdin);
621	if (strstr(str, "ABOR")) {
622		control_printf(SL_SUCCESS, "426 Transfer aborted.");
623		close(file);
624		close(sock);
625		control_printf(SL_SUCCESS, "226 Aborted.");
626		bftpd_log("Client aborted file transmission.\n");
627		alarm(control_timeout);
628		return 1;
629	}
630	return 0;
631}
632
633void command_allo(char *foo)
634{
635	command_noop(foo);
636}
637
638
639/* This function allows the storage of multiple files on the server. */
640void command_mput(char *filenames)
641{
642	char filename[MAXCMD];  /* single filename */
643	int from_index, to_index;      /* position in "filenames" and "filename" */
644
645	from_index = 0;     /* start at begining of filenames */
646	memset(filename, 0, MAXCMD);       /* clear filename */
647	to_index = 0;
648
649	/* go until we find a NULL character */
650	while ( filenames[from_index] > 0)
651	{
652		/* copy filename until we hit a space */
653		if (filenames[from_index] == ' ')
654		{
655			/* got a full filename */
656			command_stor(filename);
657			/* clear filename and reset to_index */
658			to_index = 0;
659			memset(filename, 0, MAXCMD);
660
661			while (filenames[from_index] == ' ')
662				from_index++;    /* goto next position */
663		}
664
665		/* if we haven't hit a space, then copy the letter */
666		else
667		{
668			filename[to_index] = filenames[from_index];
669			to_index++;
670			from_index++;
671			/* if the next character is a NULL, then this is the end of the filename */
672			if (! filenames[from_index])
673			{
674				command_stor(filename);   /* get the file */
675				to_index = 0;             /* reset filename index */
676				memset(filename, 0, MAXCMD);    /* clear filename buffer */
677				from_index++;                /* goto next character */
678			}
679		}
680
681		/* if the buffer is getting too big, then stop */
682		if (to_index > (MAXCMD - 2) )
683		{
684			bftpd_log("Error: Filename in '%s' too long.\n", filenames);
685			return;
686		}
687
688	}   /* end of while */
689
690}
691
692
693#define MAX_BUFFER_SIZE     (4*65536)       // Foxconn added pling 06/19/2009 /* wklin modified */
694void do_stor(char *filename, int flags)
695{
696	char *buffer;
697	int fd, i, max;
698	fd_set rfds;
699	struct timeval tv;
700	char *p, *pp;
701	char *mapped = bftpd_cwd_mappath(filename);
702
703	int my_buffer_size;    /* total transfer buffer size divided by number of clients */
704	int num_clients;       /* number of clients connected to the server */
705	int new_num_clients;
706	int xfer_delay;
707	int attempt_gzip = FALSE;
708#ifdef HAVE_ZLIB_H
709	gzFile my_zip_file = NULL;
710#endif
711
712
713    /* Foxconn, added by MJ., 2010.04.08, for check if file is locked. */
714#ifdef LOCK_DEBUG
715    printf("%s begins.\n", __FUNCTION__);
716#endif
717    /*FIXME: We have to check file lock before pre_write_script */
718
719    fd = open(mapped, O_RDONLY);
720    if (fd >= 0)  /* file exists */
721    {
722        struct flock lock;
723        lock.l_type = F_WRLCK;
724        lock.l_whence = SEEK_SET;
725        lock.l_start = 0;
726        lock.l_len = 0;
727        if (!fcntl(fd, F_GETLK, &lock))
728        {
729#ifdef LOCK_DEBUG
730            printf("1.%s: l_type:%d\n", __FUNCTION__, lock.l_type);
731#endif
732            if (lock.l_type != F_UNLCK) // File is locked by other process
733            {
734                bftpd_log("Error: '%s' while trying to store file '%s'.\n",
735                        strerror(errno), filename);
736                control_printf(SL_FAILURE, "550 Error: File is read-only");
737                close(fd);     /* make sure it is not open */
738                free(mapped);
739                return;
740            }
741        }
742        close(fd);
743    }
744    /* Foxconn, ended by MJ., 2010.04.09 */
745
746
747	if (pre_write_script)
748		run_script(pre_write_script, mapped);
749
750#ifdef HAVE_ZLIB_H
751	if (! strcmp( config_getoption("GZ_UPLOAD"), "yes") )
752	{
753		attempt_gzip = TRUE;
754		strcat(mapped, ".gz");
755	}
756	else
757		attempt_gzip = FALSE;
758#endif
759
760	/* See if we should delay between data transfers */
761	xfer_delay = strtoul( config_getoption("XFER_DELAY"), NULL, 0);
762
763	/* Check to see if the file exists and if we can over-write
764	   it, if it does. -- Jesse */
765
766	fd = open(mapped, O_RDONLY);
767	if (fd >= 0)  /* file exists */
768	{
769        /* FIXME: Foxconn, commented by MJ., 2010.04.09, We have to do this before pre_write_script. */
770#if 0
771        /* Foxconn added start pling 06/25/2009 */
772        /* Try to lock this file for write access.
773         * If failed, don't allow write.
774         */
775        struct flock lock;
776        lock.l_type = F_WRLCK;
777        lock.l_whence = SEEK_SET;
778        lock.l_start = 0;
779        lock.l_len = 0;
780
781        if (!fcntl(fd, F_GETLK, &lock))
782        {
783            printf("2.%s: l_type:%d\n", __FUNCTION__, lock.l_type);
784            if (lock.l_type != F_UNLCK) // File is locked by other process
785            {
786    			bftpd_log("Error: '%s' while trying to store file '%s'.\n",
787	    				strerror(errno), filename);
788		    	control_printf(SL_FAILURE, "550 Error: File is read-only");
789			    close(fd);     /* make sure it is not open */
790    			free(mapped);
791	    		return;
792            }
793        }
794        /* Foxconn added end pling 06/25/2009 */
795#endif
796		/* close the file */
797		close(fd);
798
799		/* check if we can over-write it */
800		if ( !strcasecmp( config_getoption("ALLOWCOMMAND_DELE"), "no") )
801		{
802			bftpd_log("Not allowed to over-write '%s'.\n", filename);
803			control_printf(SL_FAILURE,
804					"553 Error: Remote file is write protected.");
805
806			free(mapped);
807			close(sock);
808			return;
809		}
810	}
811
812	if (! attempt_gzip)
813	{
814		fd = open(mapped, flags, 00666);
815		/*
816		   do this below
817		   if (mapped)
818		   free(mapped);
819		 */
820		if (fd == -1) {
821			bftpd_log("Error: '%s' while trying to store file '%s'.\n",
822					strerror(errno), filename);
823			control_printf(SL_FAILURE, "553 Error: %s.", strerror(errno));
824
825			close(fd);     /* make sure it is not open */
826			if (post_write_script)
827				run_script(post_write_script, mapped);
828			free(mapped);
829			return;
830		}
831
832        /* Foxconn added start pling 06/25/2009 */
833        /* Lock this file for write access */
834        struct flock lock;
835        lock.l_type = F_WRLCK;
836        lock.l_whence = SEEK_SET;
837        lock.l_start = 0;
838        lock.l_len = 0;
839        if (fcntl(fd, F_SETLK, &lock))
840        {
841			bftpd_log("Error: '%s' while trying to store file '%s'.\n",
842					strerror(errno), filename);
843			control_printf(SL_FAILURE, "550 Error: File is read-only");
844			close(fd);     /* make sure it is not open */
845			free(mapped);
846			return;
847        }
848        /* Foxconn added end pling 06/25/2009 */
849	}
850
851#ifdef HAVE_ZLIB_H
852	if ( attempt_gzip )
853	{
854		my_zip_file = gzopen(mapped, "wb+");
855		if (mapped)
856			free(mapped);
857		if (! my_zip_file)
858		{
859			control_printf(SL_FAILURE, "553 Error: An error occured creating compressed file.");
860			close(sock);
861			close(fd);
862			return;
863		}
864	}
865#endif
866
867	bftpd_log("Client is storing file '%s'.\n", filename);
868	if (dataconn())
869	{
870		close(fd);
871		if (post_write_script)
872			run_script(post_write_script, mapped);
873		free(mapped);
874		return;
875	}
876
877	/* Figure out how big the transfer buffer should be.
878	   This will be the total size divided by the number of clients connected.
879	   -- Jesse
880	 */
881	num_clients = bftpdutmp_usercount("*");
882    /* Foxconn modified start pling 06/19/2009 */
883    /* For better throughput performance */
884	// my_buffer_size = get_buffer_size(num_clients);
885    my_buffer_size = MAX_BUFFER_SIZE;
886    /* Foxconn modified end pling 06/19/2009 */
887
888	alarm(0);
889    /* Foxconn modified start pling 06/19/2009 */
890    /* For better throughput performance */
891	// buffer = malloc(xfer_bufsize);
892	buffer = malloc(MAX_BUFFER_SIZE);
893    /* Foxconn modified end pling 06/19/2009 */
894	/* Check to see if we are out of memory. -- Jesse */
895	if (! buffer)
896	{
897		bftpd_log("Unable to create buffer to receive file.\n", 0);
898		control_printf(SL_FAILURE, "553 Error: An unknown error occured on the server.");
899		if (fd >= 0)
900			close(fd);
901		close(sock);
902		return;
903	}
904
905	lseek(fd, offset, SEEK_SET);
906	offset = 0;
907	/* Do not use the whole buffer, because a null byte has to be
908	 * written after the string in ASCII mode. */
909	max = (sock > fileno(stdin) ? sock : fileno(stdin)) + 1;
910	for (;;) {
911		FD_ZERO(&rfds);
912		FD_SET(sock, &rfds);
913		FD_SET(fileno(stdin), &rfds);
914
915		tv.tv_sec = data_timeout;
916		tv.tv_usec = 0;
917		if (!select(max, &rfds, NULL, NULL, &tv)) {
918			close(sock);
919			close(fd);
920			control_printf(SL_FAILURE, "426 Kicked due to data transmission timeout.");
921			bftpd_log("Kicked due to data transmission timeout.\n");
922			/* Before we exit, let's remove our entry in the log file. -- Jesse */
923			if (post_write_script)
924				run_script(post_write_script, mapped);
925
926			bftpdutmp_end();
927			exit(0);
928		}
929		if (FD_ISSET(fileno(stdin), &rfds)) {
930			test_abort(0, fd, sock);
931			if (buffer)
932				free(buffer);
933			close(fd);
934			if (post_write_script)
935				run_script(post_write_script, mapped);
936			free(mapped);
937			return;
938		}
939
940		if (!((i = recv(sock, buffer, my_buffer_size - 1, 0))))
941			break;
942		bytes_recvd += i;
943		if (xfertype == TYPE_ASCII) {
944			buffer[i] = '\0';
945			/* on ASCII stransfer, strip character 13 */
946			p = pp = buffer;
947			while (*p) {
948				if ((unsigned char) *p == 13)
949					p++;
950				else
951					*pp++ = *p++;
952			}
953			*pp++ = 0;
954			i = strlen(buffer);
955		}     // end of if ASCII type transfer
956
957#ifdef HAVE_ZLIB_H
958		if (my_zip_file)
959			gzwrite( my_zip_file, buffer, i );
960#endif
961		if(! attempt_gzip)
962		{
963			/* Foxconn modify start, Max Ding, 06/09/2011 @IR-083 of WNR3500Lv2 */
964			/* IR-083: FTP write issue when drive is full
965			 * When USB disk is full, write will fail,
966			 * Solution: Then should return error, and close socket and fd.
967			 * Refer to FileZilla behavior: return "550 can't access file"
968			 */
969			if (i != write(fd, buffer, i))
970			{
971				close(sock);
972				close(fd);
973				control_printf(SL_FAILURE, "550 can't access file.");
974				bftpd_log("can't access file.\n");
975				if (post_write_script)
976					run_script(post_write_script, mapped);
977
978				bftpdutmp_end();
979				if (buffer)
980					free(buffer);
981				if (mapped)
982					free(mapped);
983				return;
984			}
985			/* Foxconn modify end, Max Ding, 06/09/2011 */
986		}
987
988		/* Check to see if our bandwidth usage should change. -- Jesse */
989		new_num_clients = bftpdutmp_usercount("*");
990		if (new_num_clients != num_clients)
991		{
992			num_clients = new_num_clients;
993			my_buffer_size = get_buffer_size(num_clients);
994		}
995
996		/* check for transfer delay */
997		if ( xfer_delay )
998		{
999			struct timeval wait_time;
1000
1001			wait_time.tv_sec = 0;
1002			wait_time.tv_usec = xfer_delay;
1003			select( 0, NULL, NULL, NULL, &wait_time);
1004		}
1005
1006
1007	}     // end of for loop, reading
1008
1009	free(buffer);
1010#ifdef HAVE_ZLIB_H
1011	gzclose(my_zip_file);
1012#else
1013	close(fd);
1014#endif
1015
1016	close(sock);
1017	alarm(control_timeout);
1018	offset = 0;
1019	control_printf(SL_SUCCESS, "226 File transmission successful.");
1020	bftpd_log("File transmission successful.\n");
1021	if (post_write_script)
1022		run_script(post_write_script, mapped);
1023
1024	free(mapped);
1025}
1026
1027void command_stor(char *filename)
1028{
1029	do_stor(filename, O_CREAT | O_WRONLY | O_TRUNC);
1030}
1031
1032void command_appe(char *filename)
1033{
1034	do_stor(filename, O_CREAT | O_WRONLY | O_APPEND);
1035}
1036
1037
1038
1039
1040/* Send multpile files to the client. */
1041void command_mget(char *filenames)
1042{
1043	char filename[MAXCMD];  /* single filename */
1044	int from_index, to_index;      /* position in "filenames" and "filename" */
1045
1046	from_index = 0;     /* start at begining of filenames */
1047	memset(filename, 0, MAXCMD);       /* clear filename */
1048	to_index = 0;
1049
1050	/* go until we find a NULL character */
1051	while ( filenames[from_index] > 0)
1052	{
1053		/* copy filename until we hit a space */
1054		if (filenames[from_index] == ' ')
1055		{
1056			/* got a full filename */
1057			command_retr(filename);
1058			/* clear filename and reset to_index */
1059			to_index = 0;
1060			memset(filename, 0, MAXCMD);
1061
1062			while (filenames[from_index] == ' ')
1063				from_index++;    /* goto next position */
1064		}
1065
1066		/* if we haven't hit a space, then copy the letter */
1067		else
1068		{
1069			filename[to_index] = filenames[from_index];
1070			to_index++;
1071			from_index++;
1072			/* if the next character is a NULL, then this is the end of the filename */
1073			if (! filenames[from_index])
1074			{
1075				command_retr(filename);   /* send the file */
1076				to_index = 0;             /* reset filename index */
1077				memset(filename, 0, MAXCMD);    /* clear filename buffer */
1078				from_index++;                /* goto next character */
1079			}
1080		}
1081
1082		/* if the buffer is getting too big, then stop */
1083		if (to_index > (MAXCMD - 2) )
1084		{
1085			bftpd_log("Error: Filename in '%s' too long.\n", filenames);
1086			return;
1087		}
1088
1089	}   /* end of while */
1090
1091}
1092
1093void command_retr(char *filename)
1094{
1095	int num_clients, new_num_clients;   /* number of connectiosn to the server */
1096	int my_buffer_size;                 /* size of the transfer buffer to use */
1097	char *mapped;
1098	char *buffer;
1099	int xfer_delay;
1100	struct timeval wait_time;
1101        ssize_t send_status;
1102#if (defined(WANT_GZIP) || defined(HAVE_ZLIB_H))
1103	gzFile gzfile;
1104#endif
1105	int phile;
1106	int i, whattodo = DO_NORMAL;
1107	struct stat statbuf;
1108#if (defined(WANT_TAR) && defined(WANT_GZIP))
1109	int filedes[2];
1110#endif
1111#if (defined(WANT_TAR) || defined(WANT_GZIP))
1112	char *foo;
1113#endif
1114#ifdef WANT_TAR
1115	char *argv[4];
1116#endif
1117
1118	xfer_delay = strtoul( config_getoption("XFER_DELAY"), NULL, 0);
1119
1120	mapped = bftpd_cwd_mappath(filename);
1121	if (! mapped)
1122	{
1123		bftpd_log("Memory error in sending file.\n", 0);
1124		control_printf(SL_FAILURE, "553 An unknown error occured on the server.", 9);
1125		return;
1126	}
1127
1128    /* Foxconn added start pling 06/07/2010 */
1129    /* BTS-A20102624: Chrome FTP fix:
1130     * handle the case where FTP client tries to access /shares/shares
1131     */
1132    if (strncmp(filename,"/shares/shares", strlen("/shares/shares")) == 0)
1133    {
1134	    if (stat(mapped, &statbuf))
1135        {
1136            free(mapped);
1137            filename += strlen("/shares");
1138            mapped = bftpd_cwd_mappath(filename);
1139        }
1140    }
1141    /* Foxconn added end pling 06/07/2010 */
1142
1143	phile = open(mapped, O_RDONLY);
1144	if (phile == -1) {       // failed to open a file
1145#if (defined(WANT_TAR) && defined(WANT_GZIP))
1146		if ((foo = strstr(filename, ".tar.gz")))
1147			if (strlen(foo) == 7) {
1148				whattodo = DO_TARGZ;
1149				*foo = '\0';
1150			}
1151#endif
1152#ifdef WANT_TAR
1153		if ((foo = strstr(filename, ".tar")))
1154			if (strlen(foo) == 4) {
1155				whattodo = DO_TARONLY;
1156				*foo = '\0';
1157			}
1158#endif
1159#ifdef WANT_GZIP
1160		if ((foo = strstr(filename, ".gz")))
1161			if (strlen(foo) == 3) {
1162				whattodo = DO_GZONLY;
1163				*foo = '\0';
1164			}
1165#endif
1166		if (whattodo == DO_NORMAL) {
1167			bftpd_log("Error: '%s' while trying to receive file '%s'.\n",
1168					strerror(errno), filename);
1169			control_printf(SL_FAILURE, "553 Error: %s.", strerror(errno));
1170			if (mapped)
1171				free(mapped);
1172			return;
1173		}
1174	}
1175
1176#ifdef HAVE_ZLIB_H
1177	else  // we did open a file
1178	{
1179		char *my_temp;
1180		char *zip_option;
1181
1182		my_temp = strstr(filename, ".gz");
1183		zip_option = config_getoption("GZ_DOWNLOAD");
1184		if (my_temp)
1185		{
1186			if ( ( strlen(my_temp) == 3) && (! strcasecmp(zip_option, "yes") ) )
1187				whattodo = DO_GZUNZIP;
1188		}
1189	}
1190#endif
1191
1192    /* Foxconn added start pling 06/25/2009 */
1193    /* Place a read Lock on this file to prevent it
1194     *  from any other write access
1195    */
1196    struct flock lock;
1197    lock.l_type = F_RDLCK;
1198    lock.l_whence = SEEK_SET;
1199    lock.l_start = 0;
1200    lock.l_len = 0;
1201
1202    fcntl(phile, F_GETLK, &lock);
1203
1204    /* Foxconn added by MJ., for file lock checking*/
1205#ifdef LOCK_DEBUG
1206    printf("1.%s: l_type:%d\n", __FUNCTION__, lock.l_type);
1207#endif
1208    if(lock.l_type == F_UNLCK)
1209    {
1210        lock.l_type = F_RDLCK;
1211        fcntl(phile, F_SETLK, &lock);
1212    }
1213    else if(lock.l_type == F_WRLCK)
1214    {//FIXME: [MJ.] Should we do this? block reading while other is writing?
1215	close(phile);
1216	if(mapped) free(mapped);
1217
1218        return;
1219    }
1220    /* Foxconn ended by MJ., for file lock checking*/
1221
1222    /* Foxconn added end pling 06/25/2009 */
1223
1224	stat(mapped, (struct stat *) &statbuf);
1225	if (S_ISDIR(statbuf.st_mode)) {
1226		control_printf(SL_FAILURE, "550 Error: Is a directory.");
1227		if (mapped)
1228			free(mapped);
1229		return;
1230	}
1231#ifndef QUICK_FIX_ISSUES
1232	//FIXME
1233	if ((((statbuf.st_size - offset) * ratio_send) / ratio_recv > bytes_recvd
1234				- bytes_sent) && (strcmp((char *) config_getoption("RATIO"), "none"))) {
1235		bftpd_log("Error: 'File too big (ratio)' while trying to receive file "
1236				"'%s'.\n", filename);
1237		control_printf(SL_FAILURE, "553 File too big. Send at least %i bytes first.",
1238				(int) (((statbuf.st_size - offset) * ratio_send) / ratio_recv)
1239				- bytes_recvd);
1240		if (mapped)
1241			free(mapped);
1242		return;
1243	}
1244#endif
1245	bftpd_log("Client is receiving file '%s'.\n", filename);
1246	switch (whattodo) {
1247#if (defined(WANT_TAR) && defined(WANT_GZIP))
1248		case DO_TARGZ:
1249			close(phile);
1250			if (dataconn()) {
1251				if (mapped)
1252					free(mapped);
1253				return;
1254			}
1255			alarm(0);
1256			pipe(filedes);
1257			if (fork()) {
1258				buffer = malloc(xfer_bufsize);
1259				/* check to make sure alloc worked */
1260				if (! buffer)
1261				{
1262					if (mapped)
1263						free(mapped);
1264					bftpd_log("Memory error in sending file.\n", 0);
1265					control_printf(SL_FAILURE, "553 An unknown error occured on the server.", 9);
1266					return;
1267				}
1268
1269				/* find the size of the transfer buffer divided by number of connections */
1270				num_clients =  bftpdutmp_usercount("*");
1271				my_buffer_size = get_buffer_size(num_clients);
1272
1273				close(filedes[1]);
1274				gzfile = gzdopen(sock, "wb");
1275				while ((i = read(filedes[0], buffer, my_buffer_size))) {
1276					gzwrite(gzfile, buffer, i);
1277					test_abort(1, phile, sock);
1278
1279					/* check for a change in number of connections */
1280					new_num_clients = bftpdutmp_usercount("*");
1281					if (new_num_clients != num_clients)
1282					{
1283						num_clients = new_num_clients;
1284						my_buffer_size = get_buffer_size(num_clients);
1285					}
1286					/* pause between transfers */
1287					if (xfer_delay)
1288					{
1289						wait_time.tv_sec = 0;
1290						wait_time.tv_usec = xfer_delay;
1291						select( 0, NULL, NULL, NULL, &wait_time);
1292					}
1293				}     // end of while
1294				free(buffer);
1295				gzclose(gzfile);
1296				wait(NULL); /* Kill the zombie */
1297			} else {
1298				stderr = devnull;
1299				close(filedes[0]);
1300				close(fileno(stdout));
1301				dup2(filedes[1], fileno(stdout));
1302				setvbuf(stdout, NULL, _IONBF, 0);
1303				argv[0] = "tar";
1304				argv[1] = "cf";
1305				argv[2] = "-";
1306				argv[3] = mapped;
1307				exit(pax_main(4, argv));
1308			}
1309			break;
1310#endif
1311#ifdef WANT_TAR
1312		case DO_TARONLY:
1313			if (dataconn()) {
1314				if (mapped)
1315					free(mapped);
1316				return;
1317			}
1318			alarm(0);
1319			if (fork())
1320				wait(NULL);
1321			else {
1322				stderr = devnull;
1323				dup2(sock, fileno(stdout));
1324				argv[0] = "tar";
1325				argv[1] = "cf";
1326				argv[2] = "-";
1327				argv[3] = mapped;
1328				exit(pax_main(4, argv));
1329			}
1330			break;
1331#endif
1332#ifdef WANT_GZIP
1333		case DO_GZONLY:
1334			if (mapped)
1335				free(mapped);
1336			if ((phile = open(mapped, O_RDONLY)) < 0) {
1337				control_printf(SL_FAILURE, "553 Error: %s.", strerror(errno));
1338				return;
1339			}
1340			if (dataconn()) {
1341				if (mapped)
1342					free(mapped);
1343				return;
1344			}
1345			alarm(0);
1346			buffer = malloc(xfer_bufsize);
1347			/* check for alloc error */
1348			if (! buffer)
1349			{
1350				bftpd_log("Memory error while sending file.", 0);
1351				control_printf(SL_FAILURE, "553 An unknown error occured on the server.", 0);
1352				if (phile) close(phile);
1353				return;
1354			}
1355
1356			/* check buffer size based on number of connections */
1357			num_clients = bftpdutmp_usercount("*");
1358			my_buffer_size = get_buffer_size(num_clients);
1359			/* Use "wb9" for maximum compression, uses more CPU time... */
1360			gzfile = gzdopen(sock, "wb");
1361			while ((i = read(phile, buffer, my_buffer_size))) {
1362				gzwrite(gzfile, buffer, i);
1363				test_abort(1, phile, sock);
1364				new_num_clients = bftpdutmp_usercount("*");
1365				if ( new_num_clients != num_clients )
1366				{
1367					num_clients = new_num_clients;
1368					my_buffer_size = get_buffer_size(num_clients);
1369				}
1370				/* pause between transfers */
1371				if (xfer_delay)
1372				{
1373					wait_time.tv_sec = 0;
1374					wait_time.tv_usec = xfer_delay;
1375					select( 0, NULL, NULL, NULL, &wait_time);
1376				}
1377			}
1378			free(buffer);
1379			close(phile);
1380			gzclose(gzfile);
1381			break;
1382#endif
1383
1384#ifdef HAVE_ZLIB_H
1385		case DO_GZUNZIP:
1386			if ( dataconn() )
1387				return;
1388
1389			gzfile = gzdopen(phile, "rb");
1390			if (! gzfile)
1391			{
1392				close(phile);
1393				bftpd_log("Memory error while sending file.", 0);
1394				control_printf(SL_FAILURE, "553 An unknown error occured on the server.", 0);
1395				return;
1396			}
1397
1398			alarm(0);
1399			buffer = malloc(xfer_bufsize);
1400			if (! buffer)
1401			{
1402				close(phile);
1403				gzclose(gzfile);
1404				bftpd_log("Memory error while sending file.", 0);
1405				control_printf(SL_FAILURE, "553 An unknown error occured on the server.", 0);
1406				return;
1407			}
1408
1409			/* check buffer size based on number of connections */
1410			num_clients = bftpdutmp_usercount("*");
1411			my_buffer_size = get_buffer_size(num_clients);
1412
1413			i = gzread(gzfile, buffer, my_buffer_size);
1414			while ( i )
1415			{
1416				write(sock, buffer, i);
1417				// test_abort(1, phile, sock);
1418
1419				new_num_clients = bftpdutmp_usercount("*");
1420				if ( new_num_clients != num_clients )
1421				{
1422					num_clients = new_num_clients;
1423					my_buffer_size = get_buffer_size(num_clients);
1424				}
1425				/* pause between transfers */
1426				if (xfer_delay)
1427				{
1428					wait_time.tv_sec = 0;
1429					wait_time.tv_usec = xfer_delay;
1430					select( 0, NULL, NULL, NULL, &wait_time);
1431				}
1432
1433				i = gzread(gzfile, buffer, my_buffer_size);
1434			}   // end of while not end of file
1435
1436			free(buffer);
1437			close(phile);
1438			gzclose(gzfile);
1439			break;    // send file and unzip on the fly
1440#endif
1441
1442		case DO_NORMAL:
1443                       /*
1444			FIXME:: We are freeing "mapped" twice. Commenting out
1445			if (mapped)
1446				free(mapped);
1447                       */
1448			if (dataconn())
1449				return;
1450			alarm(0);
1451			lseek(phile, offset, SEEK_SET);
1452			offset = 0;
1453			buffer = malloc(xfer_bufsize * 2 + 1);
1454			/* make sure buffer was created */
1455			if (! buffer)
1456			{
1457				control_printf(SL_FAILURE, "553 An unknown error occured.");
1458				bftpd_log("Memory error while trying to send file.", 0);
1459				close(sock);
1460				close(phile);
1461				return;
1462			}
1463			num_clients = bftpdutmp_usercount("*");
1464			my_buffer_size = get_buffer_size(num_clients);
1465			while ((i = read(phile, buffer, my_buffer_size))) {
1466				if (test_abort(1, phile, sock)) {
1467					free(buffer);
1468					return;
1469				}
1470
1471				if (xfertype == TYPE_ASCII) {
1472					buffer[i] = '\0';
1473					i += replace(buffer, "\n", "\r\n");
1474				}
1475				send_status = send(sock, buffer, i, 0);
1476				/* Foxconn add start, Jonathan 10/14/2011 */
1477				/* add dropped connection condition checking ,patched from v3.1 */
1478                if (send_status < 0)
1479                {
1480                   printf("426 Transfer aborted.\n");
1481                   free(buffer);
1482                   close(phile);
1483                   close(sock);
1484                   alarm(control_timeout);
1485                   control_printf(SL_SUCCESS, "426 Transfer aborted.");
1486                   control_printf(SL_SUCCESS, "226 Aborted.");
1487                   bftpd_log("File transmission interrupted. Send failed.\n");
1488                   return;
1489                }
1490				/* Foxconn add end, Jonathan 10/14/2011 */
1491
1492				bytes_sent += i;
1493
1494				new_num_clients = bftpdutmp_usercount("*");
1495                /* Foxconn modified start pling 12/30/2009 */
1496                /* Change these params only if num of clients is changed */
1497                if (new_num_clients != num_clients)
1498                {
1499                    num_clients = new_num_clients;
1500    				my_buffer_size = get_buffer_size(num_clients);
1501                }
1502                /* Foxconn modified end pling 12/30/2009 */
1503
1504				/* pause between transfers */
1505				if (xfer_delay)
1506				{
1507					wait_time.tv_sec = 0;
1508					wait_time.tv_usec = xfer_delay;
1509					select( 0, NULL, NULL, NULL, &wait_time);
1510				}
1511
1512			}       // end of while
1513			free(buffer);
1514	}
1515
1516	close(phile);
1517	close(sock);
1518	offset = 0;
1519	alarm(control_timeout);
1520	control_printf(SL_SUCCESS, "226 File transmission successful.");
1521	bftpd_log("File transmission of '%s' successful.\n", filename);
1522	if (mapped) free(mapped);
1523}
1524
1525void do_dirlist(char *dirname, char verbose)
1526{
1527	FILE *datastream;
1528	if (dirname[0] != '\0') {
1529		/* skip arguments */
1530		if (dirname[0] == '-') {
1531			while ((dirname[0] != ' ') && (dirname[0] != '\0'))
1532				dirname++;
1533			if (dirname[0] != '\0')
1534				dirname++;
1535		}
1536	}
1537	if (dataconn())
1538		return;
1539	alarm(0);
1540	datastream = fdopen(sock, "w");
1541	if (dirname[0] == '\0')
1542		dirlist("*", datastream, verbose);
1543	else {
1544		char *mapped = bftpd_cwd_mappath(dirname);
1545		/* Foxconn added start pling 09/03/2012 */
1546		/* WNDR4500v2 IR45/46/47, don't allow user to access outside /shares */
1547		if (strncmp(mapped, "/mnt/usb", 8) != 0 &&
1548			strncmp(mapped, "/shares", 7)  != 0)
1549		{
1550			bftpd_log("Access to  '%s' denied!\n", mapped);
1551			free(mapped);
1552			fclose(datastream);
1553			alarm(control_timeout);
1554			control_printf(SL_FAILURE, "550 Error: Access Denied.");
1555			return;
1556		}
1557		/* Foxconn added end pling 09/03/2012 */
1558		dirlist(mapped, datastream, verbose);
1559		free(mapped);
1560	}
1561	fclose(datastream);
1562	alarm(control_timeout);
1563	control_printf(SL_SUCCESS, "226 Directory list has been submitted.%s:%d", user, verbose);
1564}
1565
1566void command_list(char *dirname)
1567{
1568	do_dirlist(dirname, 1);
1569}
1570
1571void command_nlst(char *dirname)
1572{
1573	do_dirlist(dirname, 0);
1574}
1575
1576void command_syst(char *params)
1577{
1578	control_printf(SL_SUCCESS, "215 UNIX Type: L8");
1579}
1580
1581void command_mdtm(char *filename)
1582{
1583	struct stat statbuf;
1584	struct tm *filetime;
1585	char *fullfilename = bftpd_cwd_mappath(filename);
1586
1587    /* Foxconn added start pling 06/07/2010 */
1588    /* BTS-A20102624: Chrome FTP fix:
1589     * handle the case where FTP client tries to access /shares/shares
1590     */
1591    if (strncmp(filename,"/shares/shares", strlen("/shares/shares")) == 0)
1592    {
1593	    if (stat(fullfilename, &statbuf))
1594        {
1595            free(fullfilename);
1596            filename += strlen("/shares");
1597            fullfilename = bftpd_cwd_mappath(filename);
1598        }
1599    }
1600    /* Foxconn added end pling 06/07/2010 */
1601
1602	if (!stat(fullfilename, (struct stat *) &statbuf)) {
1603		filetime = gmtime((time_t *) & statbuf.st_mtime);
1604		control_printf(SL_SUCCESS, "213 %04i%02i%02i%02i%02i%02i",
1605				filetime->tm_year + 1900, filetime->tm_mon + 1,
1606				filetime->tm_mday, filetime->tm_hour, filetime->tm_min,
1607				filetime->tm_sec);
1608	} else {
1609		control_printf(SL_FAILURE, "550 Error while determining the modification time: %s",
1610				strerror(errno));
1611	}
1612	free(fullfilename);
1613}
1614
1615void command_cwd(char *dir)
1616{
1617	if (bftpd_cwd_chdir(dir)) {
1618		/* Foxconn modified start pling 05/14/2009 */
1619		/* Deny access to root dir - '/' */
1620		if (errno == EACCES) {
1621			bftpd_log("Error: 'Not allowed to chdir to /'.\n");
1622			control_printf(SL_FAILURE, "550 Error: Access Denied.");
1623		} else {
1624			bftpd_log("Error: '%s' while changing directory to '%s'.\n",
1625					strerror(errno), dir);
1626			control_printf(SL_FAILURE, "451 Error: %s.", strerror(errno));
1627		}
1628		/* Foxconn modified end pling 05/14/2009 */
1629	} else {
1630		bftpd_log("Changed directory to '%s'.\n", dir);
1631		control_printf(SL_SUCCESS, "250 OK");
1632	}
1633}
1634
1635void command_cdup(char *params)
1636{
1637	bftpd_log("Changed directory to '..'.\n");
1638	bftpd_cwd_chdir("..");
1639	control_printf(SL_SUCCESS, "250 OK");
1640}
1641
1642void command_dele(char *filename)
1643{
1644	char *mapped = bftpd_cwd_mappath(filename);
1645	int fd;
1646
1647    /* Foxconn, added by MJ., 2010.07.07, for check if file is locked. */
1648#ifdef LOCK_DEBUG
1649    printf("%s begins.\n", __FUNCTION__);
1650#endif
1651    /*FIXME: We have to check file lock before pre_write_script */
1652
1653    fd = open(mapped, O_RDONLY);
1654    if (fd >= 0)  /* file exists */
1655    {
1656        struct flock lock;
1657        lock.l_type = F_WRLCK;
1658        lock.l_whence = SEEK_SET;
1659        lock.l_start = 0;
1660        lock.l_len = 0;
1661        if (!fcntl(fd, F_GETLK, &lock))
1662        {
1663#ifdef LOCK_DEBUG
1664            printf("1.%s: l_type:%d\n", __FUNCTION__, lock.l_type);
1665#endif
1666            if (lock.l_type != F_UNLCK) // File is locked by other process
1667            {
1668                bftpd_log("Error: '%s' while trying to delete file '%s'.\n",
1669                        strerror(errno), filename);
1670                control_printf(SL_FAILURE, "550 Error: File is read-only");
1671                close(fd);     /* make sure it is not open */
1672                free(mapped);
1673                return;
1674            }
1675        }
1676        close(fd);
1677    }
1678    /* Foxconn, ended by MJ., 2010.07.07 */
1679
1680
1681	if (pre_write_script)
1682		run_script(pre_write_script, mapped);
1683
1684	if (unlink(mapped)) {
1685		bftpd_log("Error: '%s' while trying to delete file '%s'.\n",
1686				strerror(errno), filename);
1687		control_printf(SL_FAILURE, "451 Error: %s.", strerror(errno));
1688	} else {
1689		bftpd_log("Deleted file '%s'.\n", filename);
1690		control_printf(SL_SUCCESS, "200 OK");
1691	}
1692
1693	if (post_write_script)
1694		run_script(post_write_script, mapped);
1695
1696	free(mapped);
1697}
1698
1699void command_mkd(char *dirname)
1700{
1701	char *mapped = bftpd_cwd_mappath(dirname);
1702
1703	if (pre_write_script)
1704		run_script(pre_write_script, mapped);
1705
1706	if (mkdir(mapped, 0755)) {
1707		bftpd_log("Error: '%s' while trying to create directory '%s'.\n",
1708				strerror(errno), dirname);
1709		control_printf(SL_FAILURE, "451 Error: %s.", strerror(errno));
1710	} else {
1711		bftpd_log("Created directory '%s'.\n", dirname);
1712		control_printf(SL_SUCCESS, "257 \"%s\" has been created.", dirname);
1713	}
1714
1715	if (post_write_script)
1716		run_script(post_write_script, mapped);
1717
1718	free(mapped);
1719}
1720
1721void command_rmd(char *dirname)
1722{
1723	char *mapped = bftpd_cwd_mappath(dirname);
1724	if (pre_write_script)
1725		run_script(pre_write_script, mapped);
1726
1727	if (rmdir(mapped)) {
1728		bftpd_log("Error: '%s' while trying to remove directory '%s'.\n", strerror(errno), dirname);
1729		control_printf(SL_FAILURE, "451 Error: %s.", strerror(errno));
1730	} else {
1731		bftpd_log("Removed directory '%s'.\n", dirname);
1732		control_printf(SL_SUCCESS, "250 OK");
1733	}
1734
1735	if (post_write_script)
1736		run_script(post_write_script, mapped);
1737	free(mapped);
1738}
1739
1740void command_noop(char *params)
1741{
1742	control_printf(SL_SUCCESS, "200 OK");
1743}
1744
1745void command_rnfr(char *oldname)
1746{
1747	FILE *file;
1748	char *mapped = bftpd_cwd_mappath(oldname);
1749	if ((file = fopen(mapped, "r"))) {
1750		fclose(file);
1751		if (philename)
1752			free(philename);
1753		philename = mapped;
1754		state = STATE_RENAME;
1755		control_printf(SL_SUCCESS, "350 File exists, ready for destination name");
1756	} else {
1757		free(mapped);
1758		control_printf(SL_FAILURE, "451 Error: %s.", strerror(errno));
1759	}
1760}
1761
1762void command_rnto(char *newname)
1763{
1764	char *mapped = bftpd_cwd_mappath(newname);
1765
1766	if (pre_write_script)
1767		run_script(pre_write_script, mapped);
1768
1769	/* Foxconn added start pling 09/12/2012 */
1770	/* WNDR4500v2 IR79: Don't allow user to rename /shares */
1771	//if (strcmp(philename, "/shares") == 0)
1772//		control_printf(SL_FAILURE, "550 Error: Access Denied.");
1773//	else
1774	/* Foxconn added end pling 09/12/2012 */
1775
1776	/* Foxconn added start lawrence 09/14/2012 */
1777	/* WNDR4500v2 IR84 and IR79: Don't allow user to rename file outside /shares */
1778	if (strncmp(philename, "/shares/",8))
1779		control_printf(SL_FAILURE, "550 Error: Access Denied.");
1780	else
1781	/* Foxconn added end lawrence 09/14/2012 */
1782	if (rename(philename, mapped)) {
1783		bftpd_log("Error: '%s' while trying to rename '%s' to '%s'.\n",
1784				strerror(errno), philename, bftpd_cwd_mappath(newname));
1785		control_printf(SL_FAILURE, "451 Error: %s.", strerror(errno));
1786	} else {
1787		bftpd_log("Successfully renamed '%s' to '%s'.\n", philename, bftpd_cwd_mappath(newname));
1788		control_printf(SL_SUCCESS, "250 OK");
1789		state = STATE_AUTHENTICATED;
1790	}
1791
1792	if (post_write_script)
1793		run_script(post_write_script, mapped);
1794
1795	free(philename);
1796	free(mapped);
1797	philename = NULL;
1798}
1799
1800void command_rest(char *params)
1801{
1802	offset = strtoul(params, NULL, 10);
1803	control_printf(SL_SUCCESS, "350 Restarting at offset %i.", offset);
1804}
1805
1806void command_size(char *filename)
1807{
1808	struct stat statbuf;
1809	char *mapped = bftpd_cwd_mappath(filename);
1810
1811    /* Foxconn added start pling 06/07/2010 */
1812    /* BTS-A20102624: Chrome FTP fix:
1813     * handle the case where FTP client tries to access /shares/shares
1814     */
1815    if (strncmp(filename,"/shares/shares", strlen("/shares/shares")) == 0)
1816    {
1817	    if (stat(mapped, &statbuf))
1818        {
1819            free(mapped);
1820            filename += strlen("/shares");
1821            mapped = bftpd_cwd_mappath(filename);
1822        }
1823    }
1824    /* Foxconn added end pling 06/07/2010 */
1825
1826	if (!stat(mapped, &statbuf)) {
1827		control_printf(SL_SUCCESS, "213 %i", (int) statbuf.st_size);
1828	} else {
1829		control_printf(SL_FAILURE, "550 Error: %s.", strerror(errno));
1830	}
1831	free(mapped);
1832}
1833
1834void command_quit(char *params)
1835{
1836	control_printf(SL_SUCCESS, "221 %s", config_getoption("QUIT_MSG"));
1837	/* Make sure we log user out. -- Jesse <slicer69@hotmail.com> */
1838	bftpdutmp_end();
1839	exit(0);
1840}
1841
1842void command_stat(char *filename)
1843{
1844	char *mapped = bftpd_cwd_mappath(filename);
1845	control_printf(SL_SUCCESS, "213-Status of %s:", filename);
1846	bftpd_stat(mapped, stderr);
1847	control_printf(SL_SUCCESS, "213 End of Status.");
1848	free(mapped);
1849}
1850
1851/* SITE commands */
1852
1853void command_chmod(char *params)
1854{
1855	int permissions;
1856	char *mapped;
1857	char *my_string;
1858
1859	if (!strchr(params, ' ')) {
1860		control_printf(SL_FAILURE, "550 Usage: SITE CHMOD <permissions> <filename>");
1861		return;
1862	}
1863	my_string = strdup(strchr(params, ' ') + 1);
1864	if (! my_string)
1865	{
1866		control_printf(SL_FAILURE, "550: An error occured on the server trying to CHMOD.");
1867		return;
1868	}
1869	/* mapped = bftpd_cwd_mappath(strdup(strchr(params, ' ') + 1)); */
1870	mapped = bftpd_cwd_mappath(my_string);
1871	free(my_string);
1872
1873	if (pre_write_script)
1874		run_script(pre_write_script, mapped);
1875
1876	*strchr(params, ' ') = '\0';
1877	sscanf(params, "%o", &permissions);
1878	if (chmod(mapped, permissions))
1879		control_printf(SL_FAILURE, "Error: %s.", strerror(errno));
1880	else {
1881		bftpd_log("Changed permissions of '%s' to '%o'.\n", mapped,
1882				permissions);
1883		control_printf(SL_SUCCESS, "200 CHMOD successful.");
1884	}
1885	if (post_write_script)
1886		run_script(post_write_script, mapped);
1887
1888	free(mapped);
1889}
1890
1891void command_chown(char *params)
1892{
1893	char foo[MAXCMD + 1], owner[MAXCMD + 1], group[MAXCMD + 1],
1894	     filename[MAXCMD + 1], *mapped;
1895	int uid, gid;
1896	if (!strchr(params, ' ')) {
1897		control_printf(SL_FAILURE, "550 Usage: SITE CHOWN <owner>[.<group>] <filename>");
1898		return;
1899	}
1900	sscanf(params, "%[^ ] %s", foo, filename);
1901	if (strchr(foo, '.'))
1902		sscanf(foo, "%[^.].%s", owner, group);
1903	else {
1904		strcpy(owner, foo);
1905		group[0] = '\0';
1906	}
1907	if (!sscanf(owner, "%i", &uid))	/* Is it a number? */
1908		if (((uid = mygetpwnam(owner, passwdfile))) < 0) {
1909			control_printf(SL_FAILURE, "550 User '%s' not found.", owner);
1910			return;
1911		}
1912	if (!sscanf(group, "%i", &gid))
1913		if (((gid = mygetpwnam(group, groupfile))) < 0) {
1914			control_printf(SL_FAILURE, "550 Group '%s' not found.", group);
1915			return;
1916		}
1917	mapped = bftpd_cwd_mappath(filename);
1918	if (pre_write_script)
1919		run_script(pre_write_script, mapped);
1920
1921	if (chown(mapped, uid, gid))
1922		control_printf(SL_FAILURE, "550 Error: %s.", strerror(errno));
1923	else {
1924		bftpd_log("Changed owner of '%s' to UID %i GID %i.\n", filename, uid,
1925				gid);
1926		control_printf(SL_SUCCESS, "200 CHOWN successful.");
1927	}
1928	if (post_write_script)
1929		run_script(post_write_script, mapped);
1930	free(mapped);
1931}
1932
1933void command_site(char *str)
1934{
1935	const struct command subcmds[] = {
1936		{"chmod ", NULL, command_chmod, STATE_AUTHENTICATED},
1937		{"chown ", NULL, command_chown, STATE_AUTHENTICATED},
1938		{NULL, NULL, 0},
1939	};
1940	int i;
1941	if (!strcasecmp(config_getoption("ENABLE_SITE"), "no")) {
1942		control_printf(SL_FAILURE, "550 SITE commands are disabled.");
1943		return;
1944	}
1945	for (i = 0; subcmds[i].name; i++) {
1946		if (!strncasecmp(str, subcmds[i].name, strlen(subcmds[i].name))) {
1947			cutto(str, strlen(subcmds[i].name));
1948			subcmds[i].function(str);
1949			return;
1950		}
1951	}
1952	control_printf(SL_FAILURE, "550 Unknown command: 'SITE %s'.", str);
1953}
1954
1955void command_auth(char *type)
1956{
1957	control_printf(SL_FAILURE, "550 Not implemented yet\r\n");
1958}
1959
1960/* Foxconn added start pling 09/16/2009 */
1961void command_opts(char *params)
1962{
1963    if (strcasecmp(params, "utf8 on") == 0)
1964  		control_printf(SL_SUCCESS, "200 UTF8 ON");
1965    else
1966  		control_printf(SL_SUCCESS, "550 %s not implemented", params);
1967}
1968/* Foxconn added end pling 09/16/2009 */
1969
1970/* Command parsing */
1971
1972const struct command commands[] = {
1973	{"USER", "<sp> username", command_user, STATE_CONNECTED, 0},
1974	{"PASS", "<sp> password", command_pass, STATE_USER, 0},
1975	{"XPWD", "(returns cwd)", command_pwd, STATE_AUTHENTICATED, 1},
1976	{"PWD", "(returns cwd)", command_pwd, STATE_AUTHENTICATED, 0},
1977	{"TYPE", "<sp> type-code (A or I)", command_type, STATE_AUTHENTICATED, 0},
1978	{"PORT", "<sp> h1,h2,h3,h4,p1,p2", command_port, STATE_AUTHENTICATED, 0},
1979	{"EPRT", "<sp><d><net-prt><d><ip><d><tcp-prt><d>", command_eprt, STATE_AUTHENTICATED, 1},
1980	{"PASV", "(returns address/port)", command_pasv, STATE_AUTHENTICATED, 0},
1981	{"EPSV", "(returns address/post)", command_epsv, STATE_AUTHENTICATED, 1},
1982	{"ALLO", "<sp> size", command_allo, STATE_AUTHENTICATED, 1},
1983	{"STOR", "<sp> pathname", command_stor, STATE_AUTHENTICATED, 0},
1984	{"APPE", "<sp> pathname", command_appe, STATE_AUTHENTICATED, 1},
1985	{"RETR", "<sp> pathname", command_retr, STATE_AUTHENTICATED, 0},
1986	{"LIST", "[<sp> pathname]", command_list, STATE_AUTHENTICATED, 0},
1987	{"NLST", "[<sp> pathname]", command_nlst, STATE_AUTHENTICATED, 0},
1988	{"SYST", "(returns system type)", command_syst, STATE_CONNECTED, 0},
1989	{"MDTM", "<sp> pathname", command_mdtm, STATE_AUTHENTICATED, 1},
1990	{"XCWD", "<sp> pathname", command_cwd, STATE_AUTHENTICATED, 1},
1991	{"CWD", "<sp> pathname", command_cwd, STATE_AUTHENTICATED, 0},
1992	{"XCUP", "(up one directory)", command_cdup, STATE_AUTHENTICATED, 1},
1993	{"CDUP", "(up one directory)", command_cdup, STATE_AUTHENTICATED, 0},
1994	{"DELE", "<sp> pathname", command_dele, STATE_AUTHENTICATED, 0},
1995	{"XMKD", "<sp> pathname", command_mkd, STATE_AUTHENTICATED, 1},
1996	{"MKD", "<sp> pathname", command_mkd, STATE_AUTHENTICATED, 0},
1997	{"XRMD", "<sp> pathname", command_rmd, STATE_AUTHENTICATED, 1},
1998	{"RMD", "<sp> pathname", command_rmd, STATE_AUTHENTICATED, 0},
1999	{"NOOP", "(no operation)", command_noop, STATE_AUTHENTICATED, 0},
2000	{"RNFR", "<sp> pathname", command_rnfr, STATE_AUTHENTICATED, 0},
2001	{"RNTO", "<sp> pathname", command_rnto, STATE_RENAME, 0},
2002	{"REST", "<sp> byte-count", command_rest, STATE_AUTHENTICATED, 1},
2003	{"SIZE", "<sp> pathname", command_size, STATE_AUTHENTICATED, 1},
2004	{"QUIT", "(close control connection)", command_quit, STATE_CONNECTED, 0},
2005	{"HELP", "[<sp> command]", command_help, STATE_AUTHENTICATED, 0},
2006	{"STAT", "<sp> pathname", command_stat, STATE_AUTHENTICATED, 0},
2007	{"SITE", "<sp> string", command_site, STATE_AUTHENTICATED, 0},
2008	{"FEAT", "(returns list of extensions)", command_feat, STATE_AUTHENTICATED, 0},
2009	/*    {"AUTH", "<sp> authtype", command_auth, STATE_CONNECTED, 0},
2010	 */    {"ADMIN_LOGIN", "(admin)", command_adminlogin, STATE_CONNECTED, 0},
2011	{"MGET", "<sp> pathname", command_mget, STATE_AUTHENTICATED, 0},
2012	{"MPUT", "<sp> pathname", command_mput, STATE_AUTHENTICATED, 0},
2013	{"OPTS", "<sp> string <sp> val", command_opts, STATE_AUTHENTICATED, 0}, // Foxconn added pling 09/16/2009
2014	{NULL, NULL, NULL, 0, 0}
2015};
2016
2017void command_feat(char *params)
2018{
2019	int i;
2020	control_printf(SL_SUCCESS, "211-Extensions supported:");
2021	for (i = 0; commands[i].name; i++)
2022		if (commands[i].showinfeat)
2023			control_printf(SL_SUCCESS, " %s", commands[i].name);
2024	control_printf(SL_SUCCESS, " UTF8");    // Foxconn added pling 09/16/2009
2025	control_printf(SL_SUCCESS, "211 End");
2026}
2027
2028void command_help(char *params)
2029{
2030	int i;
2031	if (params[0] == '\0') {
2032		control_printf(SL_SUCCESS, "214-The following commands are recognized.");
2033		for (i = 0; commands[i].name; i++)
2034			control_printf(SL_SUCCESS, "214-%s", commands[i].name);
2035		control_printf(SL_SUCCESS, "214 End of help");
2036	} else {
2037		for (i = 0; commands[i].name; i++)
2038			if (!strcasecmp(params, commands[i].name))
2039				control_printf(SL_SUCCESS, "214 Syntax: %s", commands[i].syntax);
2040	}
2041}
2042
2043int parsecmd(char *str)
2044{
2045	int i;
2046	char *p, *pp, confstr[18]; /* strlen("ALLOWCOMMAND_XXXX") + 1 == 18 */
2047	p = pp = str;			/* Remove garbage in the string */
2048	while (*p)
2049		if ((unsigned char) *p < 32)
2050			p++;
2051		else
2052			*pp++ = *p++;
2053	*pp++ = 0;
2054	for (i = 0; commands[i].name; i++) {	/* Parse command */
2055		if (!strncasecmp(str, commands[i].name, strlen(commands[i].name))) {
2056			sprintf(confstr, "ALLOWCOMMAND_%s", commands[i].name);
2057			if (!strcasecmp(config_getoption(confstr), "no")) {
2058                            bftpd_log("550 The command '%s' is disabled.\n",
2059						commands[i].name);
2060                /* Foxconn modified start pling 06/25/2009 */
2061                /* Change the message sent to FTP client, as
2062                 * specified by Netgear.
2063                 */
2064                if (!strcmp(commands[i].name, "DELE") ||
2065                    !strcmp(commands[i].name, "STOR") ||
2066                    !strcmp(commands[i].name, "MKD") ||
2067                    !strcmp(commands[i].name, "RMD") ||
2068                    !strcmp(commands[i].name, "XMKD") ||
2069                    !strcmp(commands[i].name, "XRMD"))
2070			        control_printf(SL_FAILURE, "550 Read Only");
2071                else
2072				control_printf(SL_FAILURE, "550 The command '%s' is disabled.",
2073				commands[i].name);
2074                /* Foxconn modified end pling 06/25/2009 */
2075				return 1;
2076			}
2077			cutto(str, strlen(commands[i].name));
2078			p = str;
2079			while ((*p) && ((*p == ' ') || (*p == '\t')))
2080				p++;
2081			memmove(str, p, strlen(str) - (p - str) + 1);
2082			if (state >= commands[i].state_needed) {
2083				commands[i].function(str);
2084				return 0;
2085			} else {
2086				switch (state) {
2087					case STATE_CONNECTED: {
2088					      control_printf(SL_FAILURE, "503 USER expected.");
2089					      return 1;
2090			  	        }
2091					case STATE_USER: {
2092					      control_printf(SL_FAILURE, "503 PASS expected.");
2093					      return 1;
2094					}
2095					case STATE_AUTHENTICATED: {
2096					      control_printf(SL_FAILURE, "503 RNFR before RNTO expected.");
2097					      return 1;
2098				        }
2099				}
2100			}
2101		}
2102	}
2103	control_printf(SL_FAILURE, "500 Unknown command: \"%s\"", str);
2104	return 0;
2105}
2106
2107
2108int get_buffer_size(int num_connections)
2109{
2110	int buffer_size;
2111
2112	if (num_connections < 1)
2113		num_connections = 1;
2114
2115	buffer_size = xfer_bufsize / num_connections;
2116	if ( buffer_size < 2)
2117		buffer_size = 2;
2118
2119	return buffer_size;
2120}
2121
2122
2123
2124/*
2125   This function forks and runs a script. On success it
2126   returns TRUE, if an error occures, it returns FALSE.
2127 */
2128int run_script(char *script, char *path)
2129{
2130	pid_t process_id;
2131	char *command_args[] = { script, path, NULL } ;
2132	sighandler_t save_quit, save_int, save_chld;
2133
2134	/* save original signal handler values */
2135	save_quit = signal(SIGQUIT, SIG_IGN);
2136	save_int = signal(SIGINT, SIG_IGN);
2137	save_chld = signal(SIGCHLD, SIG_DFL);
2138
2139	process_id = fork();
2140	/* check for failure */
2141	if (process_id < 0)
2142	{
2143		signal(SIGQUIT, save_quit);
2144		signal(SIGINT, save_int);
2145		signal(SIGCHLD, save_chld);
2146		return FALSE;
2147	}
2148
2149	/* child process */
2150	if (process_id == 0)
2151	{
2152		signal(SIGQUIT, SIG_DFL);
2153		signal(SIGINT, SIG_DFL);
2154		signal(SIGCHLD, SIG_DFL);
2155
2156		execv(script, command_args);
2157		bftpd_log("Error trying to run script: %s\n", script);
2158		exit(127);
2159	}
2160
2161	/* parent process */
2162	do
2163	{
2164		process_id = wait4(process_id, NULL, 0, NULL);
2165	} while ( (process_id == -1) && (errno == EINTR) );
2166
2167	signal(SIGQUIT, save_quit);
2168	signal(SIGINT, save_int);
2169	signal(SIGCHLD, save_chld);
2170
2171	return TRUE;
2172}
2173
2174