"Fossies" - the Fresh Open Source Software Archive

Member "bftpd/commands.c" (10 Jan 2020, 60368 Bytes) of package /linux/privat/bftpd-5.4.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "commands.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 5.3_vs_5.4.

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