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

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

Updated python code to reflect the renaming of the delivery package to pybbftp.
Some C tidying to reduce compiler warnings.

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 (int argc, char **argv, char **envp)
392#else
393main (argc,argv,envp)
394    int     argc ;
395    char    **argv ;
396    char    **envp ;
397#endif //NDG_PYTHON_EMBED
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.