source: TI05-delivery/trunk/src/bbftp-server-3.2.0/bbftpd/bbftpd.c @ 1117

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/TI05-delivery/trunk/src/bbftp-server-3.2.0/bbftpd/bbftpd.c@1117
Revision 1117, 43.8 KB checked in by spascoe, 14 years ago (diff)

The server-side Authz extensions and python bindings have been taken out of
bbftp source files and now exist in ndg.c and ndg.h.

API documentation can now be generated with doxygen. Just type "doxygen"
in the trunk directory.

Line 
1/*
2 * bbftpd/bbftpd.c
3 * Copyright (C) 1999, 2000, 2001, 2002 IN2P3, CNRS
4 * bbftp@in2p3.fr
5 * http://doc.in2p3.fr/bbftp
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
20 */ 
21
22/****************************************************************************
23
24 
25 
26 bbftpd.c v 0.0.0  1999/11/24
27          v 1.3.0  2000/03/16   - Version in openlog
28          v 1.4.0  2000/03/22   - Modify the connection protocole
29                                  in order to send the crypt type
30                                  after the connection.
31          v 1.5.0  2000/03/24   - Change the wait timer in default
32          v 1.6.0  2000/03/24   - Change the main loop to make it more
33                                    modular
34          v 1.6.1  2000/03/24   - Portage on OSF1
35                                - Make the control socket non blocking
36          v 1.8.0  2000/04/14   - Introduce RSA Cryptage
37          v 1.8.6  2000/05/21   - Allow to run with inetd
38          v 1.8.7  2000/05/24   - Introduce version.h and config.h
39          v 1.8.10 2000/08/11   - Portage to Linux
40          v 1.9.0  2000/08/18   - Use configure to help portage
41                                - default time out set to 900 s
42          v 1.9.3  2000/10/12   - Add -b and -w option in order to overwrite
43                                  the fixed values
44          v 1.9.4  2000/10/16   - Make all sockets blocking in order
45                                  to prevent the error in case of lack
46                                  of memory
47                                - Supress %m
48          v 2.0.0  2001/03/26   - Protocol V2 implementation
49          v 2.0.1  2001/04/23   - Correct indentation
50                                - Port to IRIX
51          v 2.0.2  2001/05/07   - Add debug option for RFIO
52          v 2.1.0  2001/05/28   - Add private authentication
53                                - Correct syslog level
54                                - Add -l option
55                  v 2.2.0  2001/10/03   - Add the certificate authentication process
56
57*****************************************************************************/
58
59
60#include <bbftpd.h>
61
62#include <errno.h>
63#include <fcntl.h>
64#include <limits.h>
65#include <netdb.h>
66#include <netinet/in.h>
67#include <arpa/inet.h>
68#include <netinet/tcp.h>
69#include <pwd.h>
70#include <signal.h>
71#include <stdio.h>
72#include <syslog.h>
73#include <sys/socket.h>
74#include <sys/wait.h>
75#if TIME_WITH_SYS_TIME
76# include <sys/time.h>
77# include <time.h>
78#else
79# if HAVE_SYS_TIME_H
80#  include <sys/time.h>
81# else
82#  include <time.h>
83# endif
84#endif
85#include <sys/stat.h>
86#include <unistd.h>
87#include <utime.h>
88#if HAVE_STRING_H
89# include <string.h>
90#endif
91
92#include <common.h>
93#include <config.h>
94#include <daemon.h>
95#include <daemon_proto.h>
96#include <status.h>
97#include <structures.h>
98#include <version.h>
99#ifdef CERTIFICATE_AUTH
100#include <gssapi.h>
101#include <gfw.h>
102#endif
103#ifdef HAVE_BYTESWAP_H
104#include <byteswap.h>
105#endif
106
107#include <openssl/rsa.h>
108
109#ifdef WITH_GZIP
110#include <zlib.h>
111#endif
112
113#ifdef CERTIFICATE_AUTH
114#define OPTIONS    "bcd:fl:m:pR:suvw:"
115#else
116#define OPTIONS    "bd:e:fl:m:R:suvw:"
117#endif
118
119#ifdef NDG_AUTH
120#include <ndg.h>
121#endif
122
123/*
124** Common variables for BBFTP protocole version 1 and 2
125*/
126/*
127** be_daemon :
128**      That is the way the daemon is going to be run.
129**      0 means run by inetd (that can be done trought
130**      a wrapper)                                      (run as bbftpd)
131**      1 means that the control socket are stdin and
132**      stdout                                          (run as bbftpd -s)
133**      2 means running in background                   (run as bbftpd -b)
134**      Default 0
135*/
136int        be_daemon = 0 ;
137/*
138** daemonchar:
139**      String used to initialize openlog
140*/
141char        daemonchar[50] ;
142/*
143** fixeddataport :
144**      If set to 1 then the server will use CONTROLPORT-1
145**      to use as local port number for the data socket.
146**      It is useful to set it to 1 if the server is
147**      running behing a firewall.                      (run as bbftpd)
148**      If set to 0 then the server will not fixe the
149**      local data port                                 (run as bbftpd -f)
150**      Default 1
151*/
152int     fixeddataport = 1 ;
153/*
154** state :
155**      Define the state of the server. values differ depending
156**      of the BBFTP protocol version
157*/
158int        state ;                         
159/*
160** newcontrolport :
161**      Define the control port to listen on
162*/
163int        newcontrolport ; 
164/*
165** currentusername :
166**      Define the local username
167*/
168char currentusername[MAXLEN] ;
169/*
170** myrsa :
171**      Define the local location where is store the key pair
172*/
173RSA        *myrsa ;
174/*
175** his_addr :
176**      Remote address (the client)
177*/
178struct sockaddr_in his_addr;
179/*
180** ctrl_addr :
181**      Local adresse (the server)
182*/
183struct sockaddr_in ctrl_addr;
184/*
185** bbftpdrc:
186**      Where to store the bbftpdrc file
187*/
188char    *bbftpdrc = NULL ;
189/*
190** protocolversion :
191**      Set to 0 before any PROT message exchange, that also means
192**      that no children have been started
193*/
194int     protocolversion ;
195int     protocolmin = 1  ;
196int     protocolmax = 3  ;
197/*
198** fatherpid :
199**      The pid of the process keepng the control connection
200*/
201pid_t    fatherpid ;
202/*
203** flagsighup:
204**      Set to one when a SIGHUP is received
205**/
206int    flagsighup = 0 ;
207/*
208** killdone:
209**      Set to one when the father has send a kill to all chidren
210*/
211int    killdone= 0 ;
212/*
213** childendinerror:
214**      Set to one when one child has been detected in error in order
215**      to prevent father to send multiple answer
216*/
217int    childendinerror = 0 ;
218/*
219** unlinkfile:
220**      Set to one when father has to unlink the file to store. Used
221**      in case of child ended incorrectly (kill -9 for example)
222*/
223int    unlinkfile = 0  ;
224/*
225** debug:
226**      Set to one for RFIO debug. Valid only with the -b option
227**      set to the value needed for RFIO_TRACE
228*/
229int     debug = 0 ;
230/*
231** castfd:
232**      CASTOR file descriptor use with RFIO and CASTOR
233*/
234int     castfd ;
235/*
236** castfilename:
237**      CASTOR/SHIFT real file name
238*/
239char    *castfilename = NULL ;
240/*
241** End Common variables for BBFTP protocole version 1 and 2 ********************
242*/
243/*
244** Variables for BBFTP protocole version 1
245*/
246/*
247** msgsock :
248**      Define control socket for the server
249*/
250int     msgsock ;
251/*
252** currentfilename :
253**      Define the file we are working on
254*/
255char    currentfilename[MAXLENFILE];
256/*
257** pid_child :
258**      Array to store the children pid
259*/
260pid_t pid_child[MAXPORT] ;
261/*
262** End Variables for BBFTP protocole version 1 *********************************
263*/
264/*
265** Variables for BBFTP protocole version 2
266*/
267/*
268** incontrolsock :
269**      Define the control socket for reading
270** outcontrolsock :
271**      Define the control socket for writing
272**
273**      For be_daemon equal to 0 or 2 incontrolsock = outcontrolsock
274*/
275int     incontrolsock ;
276int     outcontrolsock ;
277/*
278** curfilename :
279**      Define the pointer to the current file
280*/
281char    *curfilename = NULL ;
282/*
283** curfilenamelen :
284**      Define the length of the memory used by curfilename
285*/
286int     curfilenamelen ;
287/*
288** realfilename :
289**      Define the pointer to the real file (= curfilename if TROPT_TMP not
290**      set)
291*/
292char    *realfilename = NULL ;
293/*
294** mychildren :
295**      Pointer to the first pid of children
296*/
297int     *mychildren = NULL ;
298/*
299** nbpidchid :
300**      Number of pid pointed by mychildren
301*/
302int     nbpidchild ;
303/*
304** myports :
305**      Pointer to the first port
306*/
307int     *myports = NULL ;
308/*
309** mysockets :
310**      Pointer to the first socket
311*/
312int     *mysockets = NULL ;
313/*
314** readbuffer :
315**      Pointer to the readbuffer
316*/
317int     *readbuffer = NULL ;
318/*
319** compbuffer :
320**      Pointer to the compression buffer
321*/
322int     *compbuffer = NULL ;
323/*
324** myumask :
325**      Umask for the bbftpd process, the default will be 022 which
326**      means that group and other write permissions are denied
327**      This can be changed by the bbftp umask command
328**/
329int     myumask = 022 ;
330/*
331**      Parameters describing the connection
332*/
333int         ackto           = ACKTO;
334int         recvcontrolto   = CONTROLSOCKTO;
335int         sendcontrolto   = SENDCONTROLTO;
336int         datato          = DATASOCKTO;
337int         checkstdinto    = CHECKSTDINTO;
338int     force_encoding  = 1;
339#ifdef CERTIFICATE_AUTH
340int     accept_certs_only = 0;
341int     accept_pass_only = 0;
342#endif
343/*
344** Parameters describing the transfer
345*/
346int     transferoption ;
347int     filemode ;
348char    lastaccess[9] ;
349char    lastmodif[9] ;
350int     sendwinsize ;       
351int     recvwinsize ;       
352int     buffersizeperstream ;
353int     requestedstreamnumber ;
354my64_t  filesize ;
355int     mycos = 0 ;
356/*
357** maxstreams :
358**      That is to fix the maximum number of stream the deamon will accept.
359**      (run as bbftpd -m 25)
360**      Default 25
361*/
362int     maxstreams = 25 ;
363/*
364** End Variables for BBFTP protocole version 2 *********************************
365*/
366/*
367 * Variables for protocol version 3 (PASV mode) ******************************
368*/
369/*
370 * Range for the ephemeral ports for data connections
371 */
372int     pasvport_min ;
373int     pasvport_max ;
374/*
375** End Variables for BBFTP protocole version 3 *********************************
376*/
377/*
378**  credentials for certificate authentication
379*/
380#ifdef CERTIFICATE_AUTH
381gss_cred_id_t   server_creds;
382#endif
383
384
385/*
386 * Stats
387*/
388struct  timeval  tstart;
389
390#ifdef NDG_PYTHON_EMBED
391int bbftpd_main (argc, argv, envp)
392#else
393main (argc,argv,envp)
394#endif //NDG_PYTHON_EMBED
395    int     argc ;
396    char    **argv ;
397    char    **envp ;
398{
399    extern char *optarg;
400    extern int optind, opterr, optopt;
401/*
402#if defined(SUNOS) || defined(_HPUX_SOURCE) || defined(IRIX)
403    int        addrlen ;
404#else
405    size_t        addrlen ;
406#endif
407*/
408#ifdef HAVE_SOCKLEN_T
409    socklen_t     addrlen ;
410#else
411    int           addrlen ;
412#endif
413    struct  timeval    wait_timer;
414    fd_set  selectmask ; 
415    int        nfds ; 
416    int        retcode ;
417    int        i, j, k ;
418    struct  message *msg ;
419    char    buffer[MINMESSLEN] ;
420    char    logmessage[1024] ;
421    char    rfio_trace[20] ;
422    struct  passwd  *mypasswd ;
423    char    *bbftpdrcfile = NULL ;
424    int     fd ;
425    char    *carret ;
426    char    *startcmd ;
427    int     nooption ;
428    struct  stat    statbuf ;
429    int     alluse ;
430   
431    sprintf(daemonchar,"bbftpd v%s",VERSION) ;
432    openlog(daemonchar, LOG_PID | LOG_NDELAY, BBFTPD_FACILITY);
433    /*
434    ** Set the log mask to BBFTPD_EMERG (0)
435    */
436    setlogmask(LOG_UPTO(BBFTPD_DEFAULT));
437    /*
438    ** Initialize variables
439    */
440    protocolversion = 0 ;
441#ifdef PORT_RANGE
442    sscanf(PORT_RANGE,"%d:%d",&pasvport_min, &pasvport_max) ;
443#endif
444
445    newcontrolport = CONTROLPORT ;
446    opterr = 0 ;
447    while ((j = getopt(argc, argv, OPTIONS)) != -1) {
448        switch (j) {
449            case 'v' :{
450                printf("bbftpd version %s\n",VERSION) ;
451                printf("Compiled with  :   default port %d\n",CONTROLPORT) ;
452                printf("                   default maximum streams = %d \n",maxstreams) ;
453#ifdef PORT_RANGE
454                printf("                   data ports range = %s \n", PORT_RANGE) ;
455#endif
456#ifdef WITH_GZIP
457                printf("                   compression with Zlib-%s\n", zlibVersion()) ;
458#endif
459                printf("                   encryption with %s \n",SSLeay_version(SSLEAY_VERSION)) ;
460#ifdef WITH_RFIO
461# ifdef CASTOR
462                printf("                   CASTOR support (RFIO)\n") ;
463# else
464                printf("                   HPSS support (RFIO)\n") ;
465# endif
466#endif
467#ifdef WITH_RFIO64
468# ifdef CASTOR
469                printf("                   CASTOR support (RFIO64)\n") ;
470# else
471                printf("                   HPSS support (RFIO64)\n") ;
472# endif
473#endif
474#ifdef AFS
475                printf("                   AFS authentication \n") ;
476#endif
477#ifdef CERTIFICATE_AUTH
478                printf("                   GSI authentication \n") ;
479#endif
480#ifdef PRIVATE_AUTH
481                printf("                   private authentication \n") ;
482#endif
483                exit(0) ;
484            }
485        }
486    }
487/* Check zlib version */
488#ifdef WITH_GZIP
489    {
490        int z0, z1;
491        if (0 != strcmp(zlibVersion(), ZLIB_VERSION)) {
492                printf ("WARNING zlib version changed since last compile.\n");
493                printf ("Compiled Version is %s\n", ZLIB_VERSION);
494                printf ("Linked   Version is %s\n", zlibVersion());
495        }
496        z0 = atoi (ZLIB_VERSION);
497        z1 = atoi (zlibVersion());
498        if (z0 != z1) {
499                printf ("ERROR: zlib is not compatible!\n");
500                printf ("zlib source can found at http://www.gzip.org/zlib/\n");
501                exit (0);
502        }
503
504    }
505#endif
506    /*
507    ** Look at the loglevel option
508    */
509    i = 0 ;
510    opterr = 0 ;
511    optind = 1 ;
512    while ((j = getopt(argc, argv, OPTIONS)) != -1) {
513        switch (j) {
514            case 'l' :{
515                for ( i=0 ; i< strlen(optarg) ; i++ ) {
516                    optarg[i] = toupper(optarg[i]) ;
517                }
518                i = 0 ;
519                if ( !strcmp(optarg,"EMERGENCY") ) {
520                    i = BBFTPD_EMERG;
521                } else if ( !strcmp(optarg,"ALERT") ) {
522                    i = BBFTPD_ALERT;
523                } else if ( !strcmp(optarg,"CRITICAL") ) {
524                    i = BBFTPD_CRIT;
525                } else if ( !strcmp(optarg,"ERROR") ) {
526                    i = BBFTPD_ERR;
527                } else if ( !strcmp(optarg,"WARNING") ) {
528                    i = BBFTPD_WARNING;
529                } else if ( !strcmp(optarg,"NOTICE") ) {
530                    i = BBFTPD_NOTICE;
531                } else if ( !strcmp(optarg,"INFORMATION") ) {
532                    i = BBFTPD_INFO;
533                } else if ( !strcmp(optarg,"DEBUG") ) {
534                    i = BBFTPD_DEBUG;
535                }
536                if ( i > 0 ) {
537                    setlogmask(LOG_UPTO(i));
538                }
539                break ;
540            }
541        }
542    }
543    syslog(BBFTPD_DEBUG,"Starting bbftpd") ;
544    opterr = 0 ;
545    optind = 1 ;
546    while ((j = getopt(argc, argv, OPTIONS)) != -1) {
547        switch (j) {
548            case 'b' :{
549                if ( be_daemon != 0 ) {
550                    syslog(BBFTPD_ERR,"-b and -s options are incompatibles") ;
551                    exit(1) ;
552                }
553                be_daemon = 2 ;
554                break ;
555            }
556            case 'd' :{
557                sscanf(optarg,"%d",&i) ;
558                if ( i > 0 ) debug = i ;
559                break ;
560            }
561            case 'e' :{
562                if ((sscanf(optarg,"%d:%d",&i, &k) == 2) && (i < k)) {
563                  pasvport_min = i; pasvport_max = k;
564                } else {
565                  syslog(BBFTPD_ERR,"Invalid port range : %s",optarg) ;
566                  fprintf(stderr,"Invalid port range : %s\n",optarg) ;
567                  exit(1) ;
568                }
569                break ;
570            }
571            case 'f' :{
572                fixeddataport = 0 ;
573                break ;
574            }
575            case 'm' :{
576                sscanf(optarg,"%d",&i) ;
577                if ( i > 0 ) maxstreams = i ;
578                break ;
579            }
580            case 'R' :{
581                bbftpdrcfile = optarg ;
582                break ;
583            }
584            case 's' :{
585                if ( be_daemon != 0 ) {
586                    syslog(BBFTPD_ERR,"-b and -s options are incompatibles") ;
587                    exit(1) ;
588                }
589#ifdef PRIVATE_AUTH
590                syslog(BBFTPD_ERR,"-s option cannot be used with private authentication") ;
591                exit(1) ;               
592#endif
593                be_daemon = 1 ;
594                break ;
595            }
596            case 'u' :{
597                force_encoding = 0 ;
598                break ;
599            }
600            case 'w' :{
601                sscanf(optarg,"%d",&newcontrolport) ;
602                break ;
603            }
604#ifdef CERTIFICATE_AUTH
605            case 'c' :{
606                accept_certs_only = 1 ;
607                break ;
608            }
609            case 'p' :{
610                accept_pass_only = 1 ;
611                break ;
612            }
613#endif
614            default : {
615                break ;
616            }
617        }
618    }
619
620/*
621** Check for the local user in order to find the .bbftpdrc file
622*/
623    if ( bbftpdrcfile == NULL ) {
624        /*
625        ** look for the local user in order to find the .bbftpdrc file
626        ** use /etc/bbftpd.conf if root
627        */
628        if ( getuid() == 0) {
629            if ( (bbftpdrcfile = (char *) malloc (strlen(BBFTPD_CONF)+1 )) == NULL ) {
630                syslog(BBFTPD_ERR, "Error allocationg space for config file name.\n") ;
631            } else {
632                strcpy(bbftpdrcfile,BBFTPD_CONF);
633            }
634        } else if ( (mypasswd = getpwuid(getuid())) == NULL ) {
635            syslog(BBFTPD_WARNING, "Unable to get passwd entry, using %s\n", BBFTPD_CONF) ;
636            if ( (bbftpdrcfile = (char *) malloc (strlen(BBFTPD_CONF)+1) ) != NULL ) {
637              strcpy(bbftpdrcfile,BBFTPD_CONF);
638            }
639        } else if ( mypasswd->pw_dir == NULL ) {
640            syslog(BBFTPD_WARNING, "No home directory, using %s\n", BBFTPD_CONF) ;
641            if ( (bbftpdrcfile = (char *) malloc (strlen(BBFTPD_CONF)+1) ) != NULL ) {
642              strcpy(bbftpdrcfile,BBFTPD_CONF);
643            }
644        } else if ( (bbftpdrcfile = (char *) malloc (strlen(mypasswd->pw_dir)+11) ) == NULL ) {
645            syslog(BBFTPD_ERR, "Error allocationg space for bbftpdrc file name, .bbftpdrc will not be used\n") ;
646        } else {
647            strcpy(bbftpdrcfile,mypasswd->pw_dir) ;
648            strcat(bbftpdrcfile,"/.bbftpdrc") ;
649            if ( stat(bbftpdrcfile,&statbuf) < 0  ) {
650                bbftpdrcfile == NULL;
651                if ( (bbftpdrcfile = (char *) malloc (strlen(BBFTPD_CONF)+1) ) != NULL ) {
652                  strcpy(bbftpdrcfile,BBFTPD_CONF);
653                }
654            }
655        }
656    }
657    if ( bbftpdrcfile != NULL ) {
658        if ( strncmp(bbftpdrcfile,"none",4) != 0 ) {
659            /*
660            ** Stat the file in order to get the length
661            */
662            if ( stat(bbftpdrcfile,&statbuf) < 0  ) {
663                /*
664                  syslog(BBFTPD_WARNING, "Error stating bbftpdrc file (%s)\n",bbftpdrcfile) ;
665                 */
666            } else if ( statbuf.st_size == 0 ) {
667                /*
668                ** do nothing
669                */
670            } else if ( (bbftpdrc = (char *) malloc (statbuf.st_size + 1 ) ) == NULL ) {
671                syslog(BBFTPD_ERR, "Error allocation memory for bbftpdrc, .bbftpdrc will not be used\n") ;
672            } else if ( ( fd  = open (bbftpdrcfile,O_RDONLY) )  < 0 ) {
673                syslog(BBFTPD_ERR, "Error openning .bbftpdrc file (%s) : %s \n",bbftpdrcfile,strerror(errno)) ;
674            } else if ( ( j = read( fd, bbftpdrc , statbuf.st_size )) != statbuf.st_size ) {
675                syslog(BBFTPD_ERR, "Error reading .bbftpdrc file (%s)\n",bbftpdrcfile) ;
676            } else {
677                bbftpdrc[j] = '\0' ;
678            }
679        }
680    }
681/*
682** Analyse the bbftpdrc command in order to supress forbiden command
683** Allowed commands are :
684**          setackto %d
685**          setrecvcontrolto %d
686**          setsendcontrolto %d
687**          setdatato %d
688**          setcheckstdinto %d
689**          setoption fixeddataport
690*/
691    if ( bbftpdrc != NULL ) {
692        carret = bbftpdrc ;
693        startcmd = bbftpdrc ;
694        /*
695        ** Strip starting CR
696        */
697        while (1) {
698            while ( *carret == 10 || *carret == ' ' ) carret++ ;
699            startcmd = carret ;
700            carret = (char *) strchr (carret, 10);
701            if ( carret == NULL ) break ;
702            *carret = '\0' ;
703            if (!strncmp(startcmd,"setackto",8)) {
704                retcode = sscanf(startcmd,"setackto %d",&alluse) ;
705                if ( retcode != 1  || alluse <= 0 ) {
706                    syslog(BBFTPD_WARNING, "Acknowledge timeout must be numeric and > 0\n") ;
707                } else {
708                    ackto = alluse ;
709                }
710            } else if (!strncmp(startcmd,"setrecvcontrolto",16)) {
711                retcode = sscanf(startcmd,"setrecvcontrolto %d",&alluse) ;
712                if ( retcode != 1  || alluse <= 0 ) {
713                    syslog(BBFTPD_WARNING, "Input control timeout must be numeric and > 0\n") ;
714                } else {
715                    recvcontrolto = alluse ;
716                }
717            } else if (!strncmp(startcmd,"setsendcontrolto",16)) {
718                retcode = sscanf(startcmd,"setsendcontrolto %d",&alluse) ;
719                if ( retcode != 1  || alluse <= 0 ) {
720                    syslog(BBFTPD_WARNING, "Output control timeout must be numeric and > 0\n") ;
721                } else {
722                    sendcontrolto = alluse ;
723                }
724            } else if (!strncmp(startcmd,"setdatato",9)) {
725                retcode = sscanf(startcmd,"setdatato %d",&alluse) ;
726                if ( retcode != 1  || alluse <= 0 ) {
727                    syslog(BBFTPD_WARNING, "Data timeout must be numeric and > 0\n") ;
728                } else {
729                    datato = alluse ;
730                }
731            } else if (!strncmp(startcmd,"setcheckstdinto",15)) {
732                retcode = sscanf(startcmd,"setcheckstdinto %d",&alluse) ;
733                if ( retcode != 1  || alluse <= 0 ) {
734                    syslog(BBFTPD_WARNING, "Check input timeout must be numeric and > 0\n") ;
735                } else {
736                    checkstdinto = alluse ;
737                }
738            } else if (!strncmp(startcmd,"setoption",9)) {
739                /*
740                ** look for the option
741                */
742                startcmd = startcmd + 9 ;
743                while (*startcmd == ' ' && *startcmd != '\0' ) startcmd++ ;
744                if ( !strncmp(startcmd,"no",2) ) {
745                    nooption = 1 ;
746                    startcmd = startcmd+2 ;
747                } else {
748                    nooption = 0 ;
749                }
750                if ( !strncmp(startcmd,"fixeddataport",9) ) {
751                    if ( nooption ) {
752                        if (fixeddataport == 1) { /* default value */
753                            fixeddataport = 0;
754                        }
755                    }
756                }
757            } else {
758                syslog(BBFTPD_WARNING, "Unkown command in .bbftpdrc file (%s)\n",startcmd) ;
759            }
760            carret++ ;
761        }
762    }
763    /*
764    ** Get 5K for castfilename in order to work with CASTOR
765    ** software (even if we are not using it)
766    */
767    if ( (castfilename = (char *) malloc (5000)) == NULL ) {
768        /*
769        ** Starting badly if we are unable to malloc 5K
770        */
771        syslog(BBFTPD_ERR,"No memory for CASTOR : %s",strerror(errno)) ;
772        fprintf(stderr,"No memory for CASTOR : %s\n",strerror(errno)) ;
773        exit(1) ;
774    }
775    /*
776    ** Reset debug to zero if -b option is not present
777    */
778    if ( (be_daemon != 2) ) debug = 0 ;
779    /*
780    ** Check if be_daemon = 0 and in this case reset the
781    ** control port to CONTROLPORT
782    */
783    if ( be_daemon == 0 ) newcontrolport = CONTROLPORT ;
784
785#ifdef CERTIFICATE_AUTH               
786    if (be_daemon != 1 && !accept_pass_only) {
787        OM_uint32 min_stat, maj_stat;
788        maj_stat = gfw_acquire_cred(&min_stat, NULL, &server_creds);
789        if (maj_stat != GSS_S_COMPLETE) {
790            gfw_msgs_list *messages = NULL;
791            gfw_status_to_strings(maj_stat, min_stat, &messages) ;
792            while (messages != NULL) {
793                syslog(BBFTPD_ERR,"gfw_acquire_cred: %s", messages->msg) ;
794                if (be_daemon == 2) fprintf(stderr,"Acquire credentials: %s\n", messages->msg) ;
795                messages = messages->next;
796            }
797            exit(1);
798        }
799    }
800#endif
801    if ( be_daemon == 2 ) {
802        /*
803        ** Run as a daemon
804        */
805#ifdef NDG_PYTHON_EMBED
806      if ((fatherpid = do_daemon(argc, argv, envp)) > 0) return fatherpid;
807#else
808        do_daemon(argc, argv, envp);
809#endif
810        /*
811        ** Check for debug
812        */
813        if ( debug != 0 ) {
814#if defined(WITH_RFIO) || defined(WITH_RFIO64)
815            sprintf(rfio_trace,"RFIO_TRACE=%d",debug) ;
816            retcode = putenv(rfio_trace) ;
817#endif
818            if ( retcode == 0 ) {
819                /*
820                ** reopen stdout to a file like /tmp/bbftpd.rfio.trace.pid
821                */
822                close(STDOUT_FILENO) ;
823                sprintf(logmessage,"/tmp/bbftp.rfio.trace.level.%d.%d",debug,getpid()) ;
824                (void) freopen(logmessage,"w",stdout) ;
825            }
826        }
827    } else if ( be_daemon == 1 ) {
828        /*
829        ** Run by a remote user
830        */
831        /*
832        ** Get the username
833        */
834        struct passwd *result ;
835        if ( (result = getpwuid(getuid())) == NULL ) {
836            syslog(BBFTPD_WARNING,"Error getting username") ;
837            sprintf(currentusername,"UID %d",getuid()) ;
838        } else {
839            strcpy(currentusername,result->pw_name) ;
840        }
841        /*
842        ** Set the control sock to stdin and stdout
843        */
844        incontrolsock = 0  ;
845        outcontrolsock = 1 ;
846        /*
847        ** As we cannot rely on the env variables to know the
848        ** remote host, we are going to wait on an undefined
849        ** port, send the MSG_LOGGED_STDIN and the port number
850        ** and wait for a connection...
851        */
852        checkfromwhere() ;
853        syslog(BBFTPD_INFO,"bbftpd started by : %s from %s",currentusername,inet_ntoa(his_addr.sin_addr)) ;
854    } else {
855        char    buffrand[NBITSINKEY] ;
856        struct timeval tp ;
857        unsigned int seed ;
858        /*
859        ** Load the error message from the crypto lib
860        */
861        ERR_load_crypto_strings() ;
862        /*
863        ** Initialize the buffrand buffer which is giong to be used to initialize the
864        ** random generator
865        */
866        /*
867        ** Take the usec to initialize the random session
868        */
869        gettimeofday(&tp,NULL) ;
870        seed = tp.tv_usec ;
871        srandom(seed) ;
872        for (i=0; i < sizeof(buffrand) ; i++) {
873            buffrand[i] = random() ;
874        }
875        /*
876        ** Initialize the random generator
877        */
878        RAND_seed(buffrand,NBITSINKEY) ;
879        incontrolsock = 0  ;
880        outcontrolsock = incontrolsock ;
881        msgsock = incontrolsock ;
882        /*
883        ** set the state
884        */
885        state = S_PROTWAIT ;
886    }
887    fatherpid = getpid() ;
888    if ( be_daemon == 2 || be_daemon == 0 ) {
889        /* Get the remote address */
890        addrlen = sizeof(his_addr);
891        if (getpeername(incontrolsock, (struct sockaddr *) &his_addr, &addrlen) < 0) {
892            syslog(BBFTPD_ERR, "getpeername (%s): %s", argv[0],strerror(errno));
893            exit(1);
894        }
895        addrlen = sizeof(ctrl_addr);
896        if (getsockname(incontrolsock, (struct sockaddr *) &ctrl_addr, &addrlen) < 0) {
897            syslog(BBFTPD_ERR, "getsockname (%s): %s", argv[0],strerror(errno));
898            exit(1);
899        }
900        syslog(BBFTPD_INFO,"Getting new bbftp connexion from : %s",inet_ntoa(his_addr.sin_addr)) ;
901        /*
902        ** Send the encryption supported
903        */
904        sendcrypt() ;
905        /*
906        ** set the state
907        */
908login:
909        state = S_CONN ;
910        nfds = sysconf(_SC_OPEN_MAX) ;
911        FD_ZERO(&selectmask) ;
912        FD_SET(incontrolsock,&selectmask) ;
913        wait_timer.tv_sec  = 10 ;
914        wait_timer.tv_usec = 0 ;
915        if ( (retcode = select(nfds,&selectmask,0,0,&wait_timer) ) == -1 ) {
916            syslog(BBFTPD_ERR,"Select error : %s",strerror(errno)) ;
917            exit(1) ;
918        } else if ( retcode == 0 ) {
919            syslog(BBFTPD_ERR,"Time OUT ") ;
920            exit(1) ;
921        } else {
922            if ( (retcode = readmessage(incontrolsock,buffer,MINMESSLEN,recvcontrolto)) < 0 ) {
923                syslog(BBFTPD_ERR,"Error reading MSG_LOG ") ;
924                exit(1) ;
925            }
926            msg = (struct message *) buffer ;
927            if ( msg->code == MSG_SERVER_STATUS ) {
928                sprintf(logmessage, "bbftpd version %s\n",VERSION) ;
929                sprintf(logmessage,"%sCompiled with  :   default port %d\n",logmessage,CONTROLPORT) ;
930#ifdef WITH_GZIP
931                sprintf(logmessage,"%s                   compression with Zlib-%s\n", logmessage,zlibVersion()) ;
932#endif
933                sprintf(logmessage,"%s                   encryption with %s \n",logmessage,SSLeay_version(SSLEAY_VERSION)) ;
934#ifdef WITH_RFIO
935# ifdef CASTOR
936                sprintf(logmessage,"%s                   CASTOR support (RFIO)\n",logmessage) ;
937# else
938                sprintf(logmessage,"%s                   HPSS support (RFIO)\n",logmessage) ;
939# endif
940#endif
941#ifdef WITH_RFIO64
942# ifdef CASTOR
943                sprintf(logmessage,"%s                   CASTOR support (RFIO64)\n",logmessage) ;
944# else
945                sprintf(logmessage,"%s                   HPSS support (RFIO64)\n",logmessage) ;
946# endif
947#endif
948#ifdef AFS
949                sprintf(logmessage,"%s                   AFS authentication \n",logmessage) ;
950#endif
951#ifdef CERTIFICATE_AUTH
952                sprintf(logmessage,"%s                   GSI authentication \n",logmessage) ;
953#endif
954#ifdef PRIVATE_AUTH
955                sprintf(logmessage,"%s                   private authentication \n",logmessage) ;
956#ifdef NDG_AUTH
957                sprintf(logmessage,"%s                   NDG private autentication/authorisation extensions \n", logmessage);
958#endif // NDG_AUTH
959#endif
960#ifdef NDG_PYTHON_EMBED
961                sprintf(logmessage,"%s                   NDG server embedded in Python \n", logmessage);
962                sprintf(logmessage,"%sRunning options:\n",logmessage) ;
963                sprintf(logmessage,"%s                   Maximum number of streams = %d \n",logmessage,maxstreams) ;
964                if (pasvport_min) {
965                    sprintf(logmessage,"%s                   data ports range = [%d-%d] \n", logmessage,pasvport_min, pasvport_max) ;
966                }
967#endif // NDG_PYTHON_EMBED
968#ifdef CERTIFICATE_AUTH
969                if (accept_pass_only) {
970                    sprintf(logmessage, "%s                   The server only accepts USER/PASS\n",logmessage);
971                }
972                if (accept_certs_only) {
973                    sprintf(logmessage, "%s                   The server only accepts certificates\n",logmessage);
974                }
975#endif
976#ifndef PRIVATE_AUTH
977                if (force_encoding) {
978                    sprintf(logmessage, "%s                   The server requires encrypted login\n",logmessage);
979                } else {
980                    sprintf(logmessage, "%s                   The server allows non-encrypted login\n",logmessage);
981                }
982#endif
983
984               
985                    reply(MSG_OK,logmessage);
986                    exit(0);
987            }
988#ifdef CERTIFICATE_AUTH
989            if ( msg->code == MSG_CERT_LOG ) {
990                int retval;
991                if (accept_pass_only) {
992                    sprintf(logmessage, "The server only accepts USER/PASS");
993                    syslog(BBFTPD_ERR,"%s",logmessage) ;
994                    reply(MSG_BAD_NO_RETRY,logmessage);
995                    exit(1);
996                }
997                retval=bbftpd_cert_receive_connection(msg->msglen);
998                if ( retval < 0 ) {
999                    /*
1000                    ** The login failed, do not wait for a new one
1001                    */
1002                                        exit(1) ;
1003                }
1004                /*
1005                ** If retval >0, means an MSG_WARN has been sent already
1006                */
1007                    state = S_PROTWAIT ;
1008                if (retval == 0) {
1009                    sprintf(logmessage,"bbftpd version %s : OK",VERSION) ;
1010                    reply(MSG_OK,logmessage) ;
1011                }
1012            } else if ( msg->code == MSG_LOG ) {
1013                if (accept_certs_only) {
1014                    sprintf(logmessage, "The server only accepts certificates");
1015                    syslog(BBFTPD_ERR,"%s",logmessage) ;
1016                    reply(MSG_BAD_NO_RETRY,logmessage);
1017                } else {
1018                    /*
1019                    ** It seems that it is the message we were waiting
1020                    ** so lets decrypt
1021                    */
1022                    if ( loginsequence() < 0 ) {
1023                        /*
1024                        ** The login failed, do not wait for a new one
1025                        */
1026                        exit(1) ;
1027                    }
1028                    state = S_PROTWAIT ;
1029                    sprintf(logmessage,"bbftpd version %s : OK",VERSION) ;
1030                    reply(MSG_OK,logmessage) ;
1031                }
1032            } else if (msg->code == MSG_CRYPT) { 
1033                if (accept_certs_only) {
1034                    sprintf(logmessage, "The server only accepts certificates");
1035                    reply(MSG_BAD_NO_RETRY,logmessage);
1036                } else if (force_encoding) {
1037                    /*
1038                    **  The client can't encode and ask if it can send uncrypted
1039                    **  login information
1040                    */
1041                    sprintf(logmessage, "The server requires encrypted login");
1042                    reply(MSG_BAD_NO_RETRY,logmessage);
1043                } else {
1044                    sprintf(logmessage, "Uncrypted login dialog accepted");
1045                    reply(MSG_OK,logmessage);
1046                    goto login;
1047                }
1048            } else {
1049                syslog(BBFTPD_ERR,"Unkown message in connected state : %d",msg->code) ;
1050                reply(MSG_BAD,"Unkown message in connected state") ;
1051                exit(1) ;
1052            }
1053#else
1054#ifndef PRIVATE_AUTH
1055            if ( msg->code == MSG_LOG ) {
1056                /*
1057                ** It seems that it is the message we were waiting
1058                ** so lets decrypt
1059                */
1060                if ( loginsequence() < 0 ) {
1061                    /*
1062                    ** The login failed, do not wait for a new one
1063                    */
1064                    exit(1) ;
1065                }
1066                state = S_PROTWAIT ;
1067                sprintf(logmessage,"bbftpd version %s : OK",VERSION) ;
1068                reply(MSG_OK,logmessage) ;
1069            } else if (msg->code == MSG_CRYPT) { 
1070                /*
1071                **  The client can't encode and ask if it can send uncrypted
1072                **  login information
1073                */
1074                if (force_encoding) {
1075                    sprintf(logmessage, "The server requires encrypted login");
1076                    reply(MSG_BAD_NO_RETRY,logmessage);
1077                    exit(1);
1078                }
1079                sprintf(logmessage, "Uncrypted login dialog accepted");
1080                reply(MSG_OK,logmessage);
1081                goto login;
1082            } else {
1083                syslog(BBFTPD_ERR,"Unkown message in connected state : %d",msg->code) ;
1084                reply(MSG_BAD,"Unkown message in connected state") ;
1085                exit(1) ;
1086            }
1087#else
1088            if ( msg->code == MSG_PRIV_LOG ) {
1089                if ( bbftpd_private_receive_connection(msg->msglen) < 0 ) {
1090                    /*
1091                    ** The login failed, do not wait for a new one
1092                    */
1093                    exit(1) ;
1094                }
1095                state = S_PROTWAIT ;
1096                sprintf(logmessage,"bbftpd version %s : OK",VERSION) ;
1097                reply(MSG_OK,logmessage) ;
1098            } else {
1099                syslog(BBFTPD_ERR,"Unkown message in connected state : %d",msg->code) ;
1100                reply(MSG_BAD,"Unkown message in connected state") ;
1101                exit(1) ;
1102            }
1103#endif
1104#endif
1105        }
1106    }
1107
1108    /*
1109    ** At this stage we are in the S_PROTWAIT state
1110    */
1111    nfds = sysconf(_SC_OPEN_MAX) ;
1112    FD_ZERO(&selectmask) ;
1113    FD_SET(incontrolsock,&selectmask) ;
1114    wait_timer.tv_sec  = 10 ;
1115    wait_timer.tv_usec = 0 ;
1116    if ( (retcode = select(nfds,&selectmask,0,0,&wait_timer) ) == -1 ) {
1117        syslog(BBFTPD_ERR,"Select error in S_PROTWAIT state : %s",strerror(errno)) ;
1118        exit(1) ;
1119    } else if ( retcode == 0 ) {
1120        syslog(BBFTPD_ERR,"Time OUT in S_PROTWAIT state") ;
1121        exit(1) ;
1122    } else {
1123        if ( (retcode = readmessage(incontrolsock,buffer,MINMESSLEN,recvcontrolto)) < 0 ) {
1124            syslog(BBFTPD_ERR,"Error reading in S_PROTWAIT state") ;
1125            exit(1) ;
1126        }
1127        msg = (struct message *) buffer ;
1128        if ( msg->code == MSG_PROT ) {
1129            /*
1130            ** The client is using bbftp v2 protocol or higher
1131            */
1132            if ( checkprotocol() < 0 ) {
1133                exit_clean() ;
1134                exit(1) ;
1135            }
1136            syslog(BBFTPD_INFO,"Using bbftp protocol version %d",protocolversion) ;
1137            state = S_LOGGED ;
1138            /*
1139            ** Initialize the variables
1140            */
1141            mychildren = NULL ;
1142            nbpidchild = 0 ;
1143            curfilename = NULL ;
1144            curfilenamelen = 0 ;
1145        } else {
1146            /*
1147            ** This is a bbftp v1 client
1148            */
1149            protocolversion = 1 ;
1150            syslog(BBFTPD_INFO,"Using bbftp protocol version 1") ;
1151            state = S_LOGGED ;
1152            /*
1153            ** So set up the v1 handlers
1154            */
1155            if ( set_signals_v1() < 0 ) {
1156                exit(1) ;
1157            }
1158            /*
1159            ** Initialize the pid array
1160            */
1161            for ( i=0 ; i< MAXPORT ; i++) {
1162                pid_child[i] = 0 ;
1163            }
1164            /*
1165            ** As we have already read the message
1166            */
1167            if ( readcontrol(msg->code,msg->msglen) < 0 ) { 
1168                clean_child() ;
1169                exit_clean() ;
1170                exit(0) ;
1171            }
1172        }
1173    }
1174    if ( protocolversion == 1 ) goto loopv1 ;
1175    if ( protocolversion == 2 || protocolversion == 3) goto loopv2 ;
1176    syslog(BBFTPD_ERR,"Unknown protocol version %d",protocolversion) ;
1177    exit(1) ;
1178/*
1179** Loop for the v2 protocol (also available for v3)
1180*/
1181loopv2:
1182    /*
1183    ** Set up v2 handlers
1184    */
1185    if ( bbftpd_setsignals() < 0 ) {
1186        exit(1) ;
1187    }
1188    /*
1189    ** Set the umask ; first unset it and then reset to the default value
1190    */
1191    umask(0) ;
1192    umask(myumask) ;
1193    for (;;) {
1194        /*
1195        ** Initialize the selectmask
1196        */
1197        nfds = sysconf(_SC_OPEN_MAX) ;
1198        FD_ZERO(&selectmask) ;
1199        FD_SET(incontrolsock,&selectmask) ;
1200        /*
1201        ** Depending on the state set a timer or not
1202        */
1203        switch (state) {
1204            case S_WAITING_STORE_START :
1205            case S_WAITING_FILENAME_STORE :
1206            case S_WAITING_FILENAME_RETR : {
1207                /*
1208                ** Timer of 10s between XX_V2 and FILENAME_XX
1209                */
1210                wait_timer.tv_sec  = 10 ;
1211                wait_timer.tv_usec = 0 ;
1212                break ;
1213            }
1214           
1215            case S_SENDING :
1216            case S_RECEIVING : {
1217                /*
1218                ** No timer while receiving or sending
1219                */
1220                wait_timer.tv_sec  = 0 ;
1221                wait_timer.tv_usec = 0 ;
1222                break ;
1223            }
1224            default : {
1225                /*
1226                ** Timer of 900s between commands
1227                */
1228                wait_timer.tv_sec  = 900 ;
1229                wait_timer.tv_usec = 0 ;
1230                break ;
1231            }
1232        }
1233        if ( (retcode = select(nfds,&selectmask,0,0,(wait_timer.tv_sec == 0) ? NULL : &wait_timer) ) == -1 ) {
1234            if ( errno != EINTR ) {
1235                syslog(BBFTPD_ERR,"Select error : %s",strerror(errno)) ;
1236            }
1237        } else if ( retcode == 0 ) {
1238            syslog(BBFTPD_ERR,"Time OUT ") ;
1239            if ( state == S_WAITING_STORE_START ) {
1240                bbftpd_storeunlink(realfilename) ;
1241            }
1242            clean_child() ;
1243            exit_clean() ;
1244            exit(0) ;
1245        } else {
1246            /*
1247            ** At this stage we can only receive a command
1248            */
1249            if ( (retcode = readmessage(incontrolsock,buffer,MINMESSLEN,recvcontrolto)) < 0 ) {
1250                if ( state == S_WAITING_STORE_START  || state == S_RECEIVING) {
1251                    bbftpd_storeunlink(realfilename) ;
1252                    sleep(5) ;
1253                }
1254                clean_child() ;
1255                exit_clean() ;
1256                exit(0) ;
1257            }
1258            if ( bbftpd_readcontrol(msg->code,msg->msglen) < 0 ) { 
1259                clean_child() ;
1260                exit_clean() ;
1261                exit(0) ;
1262            } else {
1263            }
1264        }
1265    }
1266/*
1267** Loop for the v1 protocol
1268*/
1269loopv1:
1270    for (;;) {
1271        /*
1272        ** Initialize the selectmask
1273        */
1274        nfds = sysconf(_SC_OPEN_MAX) ;
1275        FD_ZERO(&selectmask) ;
1276        FD_SET(incontrolsock,&selectmask) ;
1277        /*
1278        ** Depending on the state set a timer or not
1279        */
1280        switch (state) {
1281            case S_SENDING :
1282            case S_RECEIVING : {
1283                /*
1284                ** No timer while receiving or sending
1285                */
1286                wait_timer.tv_sec  = 0 ;
1287                wait_timer.tv_usec = 0 ;
1288                break ;
1289            }
1290            default : {
1291                /*
1292                ** Timer of 900s between commands
1293                */
1294                wait_timer.tv_sec  = 900 ;
1295                wait_timer.tv_usec = 0 ;
1296                break ;
1297            }
1298        }
1299        if ( (retcode = select(nfds,&selectmask,0,0,(wait_timer.tv_sec == 0) ? NULL : &wait_timer) ) == -1 ) {
1300            if ( errno != EINTR ) {
1301                syslog(BBFTPD_ERR,"Select error : %s",strerror(errno)) ;
1302            }
1303        } else if ( retcode == 0 ) {
1304            syslog(BBFTPD_ERR,"Time OUT ") ;
1305            clean_child() ;
1306            exit_clean() ;
1307            exit(0) ;
1308        } else {
1309            /*
1310            ** At this stage we can only receive a command
1311            */
1312            if ( (retcode = readmessage(incontrolsock,buffer,MINMESSLEN,recvcontrolto)) < 0 ) {
1313                clean_child() ;
1314                exit_clean() ;
1315                exit(0) ;
1316            }
1317            if ( readcontrol(msg->code,msg->msglen) < 0 ) { 
1318                clean_child() ;
1319                exit_clean() ;
1320                exit(0) ;
1321            } else {
1322            }
1323        }
1324    }
1325}
1326
1327void clean_child() 
1328{
1329    int    *pidfree ;
1330    int    i ;
1331   
1332    if ( protocolversion == 0 ) return ;
1333    if ( protocolversion == 1 ) {
1334        if ( killdone == 0 ) {
1335            killdone = 1 ;
1336            for ( i=0 ; i<MAXPORT ; i++) {
1337                if ( pid_child[i] != 0 ) {
1338                    syslog(BBFTPD_DEBUG,"Killing child %d",pid_child[i]) ;
1339                    kill(pid_child[i],SIGKILL) ;
1340                }
1341            }
1342        }
1343        return ;
1344    }
1345    if ( protocolversion >= 2 ) {
1346        if ( killdone == 0 ) {
1347            killdone = 1 ;
1348            pidfree = mychildren ;
1349            for ( i=0 ; i<nbpidchild ; i++) {
1350                if ( *pidfree != 0 ) {
1351                    syslog(BBFTPD_DEBUG,"Killing child %d",*pidfree) ;
1352                    kill(*pidfree,SIGKILL) ;
1353                }
1354                pidfree++ ;
1355            }
1356        }
1357        return ;
1358    }
1359}
1360
1361void exit_clean() 
1362{
1363   
1364    switch (state) {
1365        case S_CONN : {
1366            return ;
1367        }
1368        case S_LOGGED :
1369        case S_PROTWAIT :
1370        case S_WAITING_FILENAME_STORE :
1371        case S_WAITING_STORE_START :
1372        case S_SENDING:
1373        case S_RECEIVING : {
1374            syslog(BBFTPD_INFO,"User %s disconnected",currentusername) ;
1375            return ;
1376        }
1377        default :{
1378            return ;
1379        }
1380    }
1381}
1382
1383my64_t convertlong(my64_t v) {
1384    struct bb {
1385        int    fb ;
1386        int sb ;
1387    } ;
1388    struct bb *bbpt ;
1389    int     tmp ;
1390    my64_t    tmp64 ;
1391   
1392    tmp64 = v ;
1393    bbpt = (struct bb *) &tmp64 ;
1394    tmp = bbpt->fb ;
1395    bbpt->fb = ntohl(bbpt->sb) ;
1396    bbpt->sb = ntohl(tmp) ;   
1397    return tmp64 ;
1398}
1399
1400#ifndef HAVE_NTOHLL
1401my64_t ntohll(my64_t v) {
1402# ifdef HAVE_BYTESWAP_H
1403    return bswap_64(v);
1404# else
1405    long lo = v & 0xffffffff;
1406    long hi = v >> 32U;
1407    lo = ntohl(lo);
1408    hi = ntohl(hi);
1409    return ((my64_t) lo) << 32U | hi;
1410# endif
1411}
1412#define htonll ntohll
1413#endif
1414
Note: See TracBrowser for help on using the repository browser.