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

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

I've created a bbftpd log facility to replace syslog.
At present it allows you to log messages to a file in addition
to syslog. This should help testing on other machines.

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 bbftpd_log 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 <bbftpd_log.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#ifdef NO_SYSLOG
433    bbftpd_openlogfile("bbftpd.log", daemonchar, LOG_PID | LOG_NDELAY, BBFTPD_FACILITY);
434#else
435    bbftpd_openlog(daemonchar, LOG_PID | LOG_NDELAY, BBFTPD_FACILITY);
436#endif
437    /*
438    ** Set the log mask to BBFTPD_EMERG (0)
439    */
440    setlogmask(LOG_UPTO(BBFTPD_DEFAULT));
441    /*
442    ** Initialize variables
443    */
444    protocolversion = 0 ;
445#ifdef PORT_RANGE
446    sscanf(PORT_RANGE,"%d:%d",&pasvport_min, &pasvport_max) ;
447#endif
448
449    newcontrolport = CONTROLPORT ;
450    opterr = 0 ;
451    while ((j = getopt(argc, argv, OPTIONS)) != -1) {
452        switch (j) {
453            case 'v' :{
454                printf("bbftpd version %s\n",VERSION) ;
455                printf("Compiled with  :   default port %d\n",CONTROLPORT) ;
456                printf("                   default maximum streams = %d \n",maxstreams) ;
457#ifdef PORT_RANGE
458                printf("                   data ports range = %s \n", PORT_RANGE) ;
459#endif
460#ifdef WITH_GZIP
461                printf("                   compression with Zlib-%s\n", zlibVersion()) ;
462#endif
463                printf("                   encryption with %s \n",SSLeay_version(SSLEAY_VERSION)) ;
464#ifdef WITH_RFIO
465# ifdef CASTOR
466                printf("                   CASTOR support (RFIO)\n") ;
467# else
468                printf("                   HPSS support (RFIO)\n") ;
469# endif
470#endif
471#ifdef WITH_RFIO64
472# ifdef CASTOR
473                printf("                   CASTOR support (RFIO64)\n") ;
474# else
475                printf("                   HPSS support (RFIO64)\n") ;
476# endif
477#endif
478#ifdef AFS
479                printf("                   AFS authentication \n") ;
480#endif
481#ifdef CERTIFICATE_AUTH
482                printf("                   GSI authentication \n") ;
483#endif
484#ifdef PRIVATE_AUTH
485                printf("                   private authentication \n") ;
486#endif
487                exit(0) ;
488            }
489        }
490    }
491/* Check zlib version */
492#ifdef WITH_GZIP
493    {
494        int z0, z1;
495        if (0 != strcmp(zlibVersion(), ZLIB_VERSION)) {
496                printf ("WARNING zlib version changed since last compile.\n");
497                printf ("Compiled Version is %s\n", ZLIB_VERSION);
498                printf ("Linked   Version is %s\n", zlibVersion());
499        }
500        z0 = atoi (ZLIB_VERSION);
501        z1 = atoi (zlibVersion());
502        if (z0 != z1) {
503                printf ("ERROR: zlib is not compatible!\n");
504                printf ("zlib source can found at http://www.gzip.org/zlib/\n");
505                exit (0);
506        }
507
508    }
509#endif
510    /*
511    ** Look at the loglevel option
512    */
513    i = 0 ;
514    opterr = 0 ;
515    optind = 1 ;
516    while ((j = getopt(argc, argv, OPTIONS)) != -1) {
517        switch (j) {
518            case 'l' :{
519                for ( i=0 ; i< strlen(optarg) ; i++ ) {
520                    optarg[i] = toupper(optarg[i]) ;
521                }
522                i = 0 ;
523                if ( !strcmp(optarg,"EMERGENCY") ) {
524                    i = BBFTPD_EMERG;
525                } else if ( !strcmp(optarg,"ALERT") ) {
526                    i = BBFTPD_ALERT;
527                } else if ( !strcmp(optarg,"CRITICAL") ) {
528                    i = BBFTPD_CRIT;
529                } else if ( !strcmp(optarg,"ERROR") ) {
530                    i = BBFTPD_ERR;
531                } else if ( !strcmp(optarg,"WARNING") ) {
532                    i = BBFTPD_WARNING;
533                } else if ( !strcmp(optarg,"NOTICE") ) {
534                    i = BBFTPD_NOTICE;
535                } else if ( !strcmp(optarg,"INFORMATION") ) {
536                    i = BBFTPD_INFO;
537                } else if ( !strcmp(optarg,"DEBUG") ) {
538                    i = BBFTPD_DEBUG;
539                }
540                if ( i > 0 ) {
541                    setlogmask(LOG_UPTO(i));
542                }
543                break ;
544            }
545        }
546    }
547    bbftpd_log(BBFTPD_DEBUG,"Starting bbftpd") ;
548    opterr = 0 ;
549    optind = 1 ;
550    while ((j = getopt(argc, argv, OPTIONS)) != -1) {
551        switch (j) {
552            case 'b' :{
553                if ( be_daemon != 0 ) {
554                    bbftpd_log(BBFTPD_ERR,"-b and -s options are incompatibles") ;
555                    exit(1) ;
556                }
557                be_daemon = 2 ;
558                break ;
559            }
560            case 'd' :{
561                sscanf(optarg,"%d",&i) ;
562                if ( i > 0 ) debug = i ;
563                break ;
564            }
565            case 'e' :{
566                if ((sscanf(optarg,"%d:%d",&i, &k) == 2) && (i < k)) {
567                  pasvport_min = i; pasvport_max = k;
568                } else {
569                  bbftpd_log(BBFTPD_ERR,"Invalid port range : %s",optarg) ;
570                  fprintf(stderr,"Invalid port range : %s\n",optarg) ;
571                  exit(1) ;
572                }
573                break ;
574            }
575            case 'f' :{
576                fixeddataport = 0 ;
577                break ;
578            }
579            case 'm' :{
580                sscanf(optarg,"%d",&i) ;
581                if ( i > 0 ) maxstreams = i ;
582                break ;
583            }
584            case 'R' :{
585                bbftpdrcfile = optarg ;
586                break ;
587            }
588            case 's' :{
589                if ( be_daemon != 0 ) {
590                    bbftpd_log(BBFTPD_ERR,"-b and -s options are incompatibles") ;
591                    exit(1) ;
592                }
593#ifdef PRIVATE_AUTH
594                bbftpd_log(BBFTPD_ERR,"-s option cannot be used with private authentication") ;
595                exit(1) ;               
596#endif
597                be_daemon = 1 ;
598                break ;
599            }
600            case 'u' :{
601                force_encoding = 0 ;
602                break ;
603            }
604            case 'w' :{
605                sscanf(optarg,"%d",&newcontrolport) ;
606                break ;
607            }
608#ifdef CERTIFICATE_AUTH
609            case 'c' :{
610                accept_certs_only = 1 ;
611                break ;
612            }
613            case 'p' :{
614                accept_pass_only = 1 ;
615                break ;
616            }
617#endif
618            default : {
619                break ;
620            }
621        }
622    }
623
624/*
625** Check for the local user in order to find the .bbftpdrc file
626*/
627    if ( bbftpdrcfile == NULL ) {
628        /*
629        ** look for the local user in order to find the .bbftpdrc file
630        ** use /etc/bbftpd.conf if root
631        */
632        if ( getuid() == 0) {
633            if ( (bbftpdrcfile = (char *) malloc (strlen(BBFTPD_CONF)+1 )) == NULL ) {
634                bbftpd_log(BBFTPD_ERR, "Error allocationg space for config file name.\n") ;
635            } else {
636                strcpy(bbftpdrcfile,BBFTPD_CONF);
637            }
638        } else if ( (mypasswd = getpwuid(getuid())) == NULL ) {
639            bbftpd_log(BBFTPD_WARNING, "Unable to get passwd entry, using %s\n", BBFTPD_CONF) ;
640            if ( (bbftpdrcfile = (char *) malloc (strlen(BBFTPD_CONF)+1) ) != NULL ) {
641              strcpy(bbftpdrcfile,BBFTPD_CONF);
642            }
643        } else if ( mypasswd->pw_dir == NULL ) {
644            bbftpd_log(BBFTPD_WARNING, "No home directory, using %s\n", BBFTPD_CONF) ;
645            if ( (bbftpdrcfile = (char *) malloc (strlen(BBFTPD_CONF)+1) ) != NULL ) {
646              strcpy(bbftpdrcfile,BBFTPD_CONF);
647            }
648        } else if ( (bbftpdrcfile = (char *) malloc (strlen(mypasswd->pw_dir)+11) ) == NULL ) {
649            bbftpd_log(BBFTPD_ERR, "Error allocationg space for bbftpdrc file name, .bbftpdrc will not be used\n") ;
650        } else {
651            strcpy(bbftpdrcfile,mypasswd->pw_dir) ;
652            strcat(bbftpdrcfile,"/.bbftpdrc") ;
653            if ( stat(bbftpdrcfile,&statbuf) < 0  ) {
654                bbftpdrcfile == NULL;
655                if ( (bbftpdrcfile = (char *) malloc (strlen(BBFTPD_CONF)+1) ) != NULL ) {
656                  strcpy(bbftpdrcfile,BBFTPD_CONF);
657                }
658            }
659        }
660    }
661    if ( bbftpdrcfile != NULL ) {
662        if ( strncmp(bbftpdrcfile,"none",4) != 0 ) {
663            /*
664            ** Stat the file in order to get the length
665            */
666            if ( stat(bbftpdrcfile,&statbuf) < 0  ) {
667                /*
668                  bbftpd_log(BBFTPD_WARNING, "Error stating bbftpdrc file (%s)\n",bbftpdrcfile) ;
669                 */
670            } else if ( statbuf.st_size == 0 ) {
671                /*
672                ** do nothing
673                */
674            } else if ( (bbftpdrc = (char *) malloc (statbuf.st_size + 1 ) ) == NULL ) {
675                bbftpd_log(BBFTPD_ERR, "Error allocation memory for bbftpdrc, .bbftpdrc will not be used\n") ;
676            } else if ( ( fd  = open (bbftpdrcfile,O_RDONLY) )  < 0 ) {
677                bbftpd_log(BBFTPD_ERR, "Error openning .bbftpdrc file (%s) : %s \n",bbftpdrcfile,strerror(errno)) ;
678            } else if ( ( j = read( fd, bbftpdrc , statbuf.st_size )) != statbuf.st_size ) {
679                bbftpd_log(BBFTPD_ERR, "Error reading .bbftpdrc file (%s)\n",bbftpdrcfile) ;
680            } else {
681                bbftpdrc[j] = '\0' ;
682            }
683        }
684    }
685/*
686** Analyse the bbftpdrc command in order to supress forbiden command
687** Allowed commands are :
688**          setackto %d
689**          setrecvcontrolto %d
690**          setsendcontrolto %d
691**          setdatato %d
692**          setcheckstdinto %d
693**          setoption fixeddataport
694*/
695    if ( bbftpdrc != NULL ) {
696        carret = bbftpdrc ;
697        startcmd = bbftpdrc ;
698        /*
699        ** Strip starting CR
700        */
701        while (1) {
702            while ( *carret == 10 || *carret == ' ' ) carret++ ;
703            startcmd = carret ;
704            carret = (char *) strchr (carret, 10);
705            if ( carret == NULL ) break ;
706            *carret = '\0' ;
707            if (!strncmp(startcmd,"setackto",8)) {
708                retcode = sscanf(startcmd,"setackto %d",&alluse) ;
709                if ( retcode != 1  || alluse <= 0 ) {
710                    bbftpd_log(BBFTPD_WARNING, "Acknowledge timeout must be numeric and > 0\n") ;
711                } else {
712                    ackto = alluse ;
713                }
714            } else if (!strncmp(startcmd,"setrecvcontrolto",16)) {
715                retcode = sscanf(startcmd,"setrecvcontrolto %d",&alluse) ;
716                if ( retcode != 1  || alluse <= 0 ) {
717                    bbftpd_log(BBFTPD_WARNING, "Input control timeout must be numeric and > 0\n") ;
718                } else {
719                    recvcontrolto = alluse ;
720                }
721            } else if (!strncmp(startcmd,"setsendcontrolto",16)) {
722                retcode = sscanf(startcmd,"setsendcontrolto %d",&alluse) ;
723                if ( retcode != 1  || alluse <= 0 ) {
724                    bbftpd_log(BBFTPD_WARNING, "Output control timeout must be numeric and > 0\n") ;
725                } else {
726                    sendcontrolto = alluse ;
727                }
728            } else if (!strncmp(startcmd,"setdatato",9)) {
729                retcode = sscanf(startcmd,"setdatato %d",&alluse) ;
730                if ( retcode != 1  || alluse <= 0 ) {
731                    bbftpd_log(BBFTPD_WARNING, "Data timeout must be numeric and > 0\n") ;
732                } else {
733                    datato = alluse ;
734                }
735            } else if (!strncmp(startcmd,"setcheckstdinto",15)) {
736                retcode = sscanf(startcmd,"setcheckstdinto %d",&alluse) ;
737                if ( retcode != 1  || alluse <= 0 ) {
738                    bbftpd_log(BBFTPD_WARNING, "Check input timeout must be numeric and > 0\n") ;
739                } else {
740                    checkstdinto = alluse ;
741                }
742            } else if (!strncmp(startcmd,"setoption",9)) {
743                /*
744                ** look for the option
745                */
746                startcmd = startcmd + 9 ;
747                while (*startcmd == ' ' && *startcmd != '\0' ) startcmd++ ;
748                if ( !strncmp(startcmd,"no",2) ) {
749                    nooption = 1 ;
750                    startcmd = startcmd+2 ;
751                } else {
752                    nooption = 0 ;
753                }
754                if ( !strncmp(startcmd,"fixeddataport",9) ) {
755                    if ( nooption ) {
756                        if (fixeddataport == 1) { /* default value */
757                            fixeddataport = 0;
758                        }
759                    }
760                }
761            } else {
762                bbftpd_log(BBFTPD_WARNING, "Unkown command in .bbftpdrc file (%s)\n",startcmd) ;
763            }
764            carret++ ;
765        }
766    }
767    /*
768    ** Get 5K for castfilename in order to work with CASTOR
769    ** software (even if we are not using it)
770    */
771    if ( (castfilename = (char *) malloc (5000)) == NULL ) {
772        /*
773        ** Starting badly if we are unable to malloc 5K
774        */
775        bbftpd_log(BBFTPD_ERR,"No memory for CASTOR : %s",strerror(errno)) ;
776        fprintf(stderr,"No memory for CASTOR : %s\n",strerror(errno)) ;
777        exit(1) ;
778    }
779    /*
780    ** Reset debug to zero if -b option is not present
781    */
782    if ( (be_daemon != 2) ) debug = 0 ;
783    /*
784    ** Check if be_daemon = 0 and in this case reset the
785    ** control port to CONTROLPORT
786    */
787    if ( be_daemon == 0 ) newcontrolport = CONTROLPORT ;
788
789#ifdef CERTIFICATE_AUTH               
790    if (be_daemon != 1 && !accept_pass_only) {
791        OM_uint32 min_stat, maj_stat;
792        maj_stat = gfw_acquire_cred(&min_stat, NULL, &server_creds);
793        if (maj_stat != GSS_S_COMPLETE) {
794            gfw_msgs_list *messages = NULL;
795            gfw_status_to_strings(maj_stat, min_stat, &messages) ;
796            while (messages != NULL) {
797                bbftpd_log(BBFTPD_ERR,"gfw_acquire_cred: %s", messages->msg) ;
798                if (be_daemon == 2) fprintf(stderr,"Acquire credentials: %s\n", messages->msg) ;
799                messages = messages->next;
800            }
801            exit(1);
802        }
803    }
804#endif
805    if ( be_daemon == 2 ) {
806        /*
807        ** Run as a daemon
808        */
809#ifdef NDG_PYTHON_EMBED
810      if ((fatherpid = do_daemon(argc, argv, envp)) > 0) return fatherpid;
811#else
812        do_daemon(argc, argv, envp);
813#endif
814        /*
815        ** Check for debug
816        */
817        if ( debug != 0 ) {
818#if defined(WITH_RFIO) || defined(WITH_RFIO64)
819            sprintf(rfio_trace,"RFIO_TRACE=%d",debug) ;
820            retcode = putenv(rfio_trace) ;
821#endif
822            if ( retcode == 0 ) {
823                /*
824                ** reopen stdout to a file like /tmp/bbftpd.rfio.trace.pid
825                */
826                close(STDOUT_FILENO) ;
827                sprintf(logmessage,"/tmp/bbftp.rfio.trace.level.%d.%d",debug,getpid()) ;
828                (void) freopen(logmessage,"w",stdout) ;
829            }
830        }
831    } else if ( be_daemon == 1 ) {
832        /*
833        ** Run by a remote user
834        */
835        /*
836        ** Get the username
837        */
838        struct passwd *result ;
839        if ( (result = getpwuid(getuid())) == NULL ) {
840            bbftpd_log(BBFTPD_WARNING,"Error getting username") ;
841            sprintf(currentusername,"UID %d",getuid()) ;
842        } else {
843            strcpy(currentusername,result->pw_name) ;
844        }
845        /*
846        ** Set the control sock to stdin and stdout
847        */
848        incontrolsock = 0  ;
849        outcontrolsock = 1 ;
850        /*
851        ** As we cannot rely on the env variables to know the
852        ** remote host, we are going to wait on an undefined
853        ** port, send the MSG_LOGGED_STDIN and the port number
854        ** and wait for a connection...
855        */
856        checkfromwhere() ;
857        bbftpd_log(BBFTPD_INFO,"bbftpd started by : %s from %s",currentusername,inet_ntoa(his_addr.sin_addr)) ;
858    } else {
859        char    buffrand[NBITSINKEY] ;
860        struct timeval tp ;
861        unsigned int seed ;
862        /*
863        ** Load the error message from the crypto lib
864        */
865        ERR_load_crypto_strings() ;
866        /*
867        ** Initialize the buffrand buffer which is giong to be used to initialize the
868        ** random generator
869        */
870        /*
871        ** Take the usec to initialize the random session
872        */
873        gettimeofday(&tp,NULL) ;
874        seed = tp.tv_usec ;
875        srandom(seed) ;
876        for (i=0; i < sizeof(buffrand) ; i++) {
877            buffrand[i] = random() ;
878        }
879        /*
880        ** Initialize the random generator
881        */
882        RAND_seed(buffrand,NBITSINKEY) ;
883        incontrolsock = 0  ;
884        outcontrolsock = incontrolsock ;
885        msgsock = incontrolsock ;
886        /*
887        ** set the state
888        */
889        state = S_PROTWAIT ;
890    }
891    fatherpid = getpid() ;
892    if ( be_daemon == 2 || be_daemon == 0 ) {
893        /* Get the remote address */
894        addrlen = sizeof(his_addr);
895        if (getpeername(incontrolsock, (struct sockaddr *) &his_addr, &addrlen) < 0) {
896            bbftpd_log(BBFTPD_ERR, "getpeername (%s): %s", argv[0],strerror(errno));
897            exit(1);
898        }
899        addrlen = sizeof(ctrl_addr);
900        if (getsockname(incontrolsock, (struct sockaddr *) &ctrl_addr, &addrlen) < 0) {
901            bbftpd_log(BBFTPD_ERR, "getsockname (%s): %s", argv[0],strerror(errno));
902            exit(1);
903        }
904        bbftpd_log(BBFTPD_INFO,"Getting new bbftp connexion from : %s",inet_ntoa(his_addr.sin_addr)) ;
905        /*
906        ** Send the encryption supported
907        */
908        sendcrypt() ;
909        /*
910        ** set the state
911        */
912login:
913        state = S_CONN ;
914        nfds = sysconf(_SC_OPEN_MAX) ;
915        FD_ZERO(&selectmask) ;
916        FD_SET(incontrolsock,&selectmask) ;
917        wait_timer.tv_sec  = 10 ;
918        wait_timer.tv_usec = 0 ;
919        if ( (retcode = select(nfds,&selectmask,0,0,&wait_timer) ) == -1 ) {
920            bbftpd_log(BBFTPD_ERR,"Select error : %s",strerror(errno)) ;
921            exit(1) ;
922        } else if ( retcode == 0 ) {
923            bbftpd_log(BBFTPD_ERR,"Time OUT ") ;
924            exit(1) ;
925        } else {
926            if ( (retcode = readmessage(incontrolsock,buffer,MINMESSLEN,recvcontrolto)) < 0 ) {
927                bbftpd_log(BBFTPD_ERR,"Error reading MSG_LOG ") ;
928                exit(1) ;
929            }
930            msg = (struct message *) buffer ;
931            if ( msg->code == MSG_SERVER_STATUS ) {
932                sprintf(logmessage, "bbftpd version %s\n",VERSION) ;
933                sprintf(logmessage,"%sCompiled with  :   default port %d\n",logmessage,CONTROLPORT) ;
934#ifdef WITH_GZIP
935                sprintf(logmessage,"%s                   compression with Zlib-%s\n", logmessage,zlibVersion()) ;
936#endif
937                sprintf(logmessage,"%s                   encryption with %s \n",logmessage,SSLeay_version(SSLEAY_VERSION)) ;
938#ifdef WITH_RFIO
939# ifdef CASTOR
940                sprintf(logmessage,"%s                   CASTOR support (RFIO)\n",logmessage) ;
941# else
942                sprintf(logmessage,"%s                   HPSS support (RFIO)\n",logmessage) ;
943# endif
944#endif
945#ifdef WITH_RFIO64
946# ifdef CASTOR
947                sprintf(logmessage,"%s                   CASTOR support (RFIO64)\n",logmessage) ;
948# else
949                sprintf(logmessage,"%s                   HPSS support (RFIO64)\n",logmessage) ;
950# endif
951#endif
952#ifdef AFS
953                sprintf(logmessage,"%s                   AFS authentication \n",logmessage) ;
954#endif
955#ifdef CERTIFICATE_AUTH
956                sprintf(logmessage,"%s                   GSI authentication \n",logmessage) ;
957#endif
958#ifdef PRIVATE_AUTH
959                sprintf(logmessage,"%s                   private authentication \n",logmessage) ;
960#ifdef NDG_AUTH
961                sprintf(logmessage,"%s                   NDG private autentication/authorisation extensions \n", logmessage);
962#endif // NDG_AUTH
963#endif
964#ifdef NDG_PYTHON_EMBED
965                sprintf(logmessage,"%s                   NDG server embedded in Python \n", logmessage);
966                sprintf(logmessage,"%sRunning options:\n",logmessage) ;
967                sprintf(logmessage,"%s                   Maximum number of streams = %d \n",logmessage,maxstreams) ;
968                if (pasvport_min) {
969                    sprintf(logmessage,"%s                   data ports range = [%d-%d] \n", logmessage,pasvport_min, pasvport_max) ;
970                }
971#endif // NDG_PYTHON_EMBED
972#ifdef CERTIFICATE_AUTH
973                if (accept_pass_only) {
974                    sprintf(logmessage, "%s                   The server only accepts USER/PASS\n",logmessage);
975                }
976                if (accept_certs_only) {
977                    sprintf(logmessage, "%s                   The server only accepts certificates\n",logmessage);
978                }
979#endif
980#ifndef PRIVATE_AUTH
981                if (force_encoding) {
982                    sprintf(logmessage, "%s                   The server requires encrypted login\n",logmessage);
983                } else {
984                    sprintf(logmessage, "%s                   The server allows non-encrypted login\n",logmessage);
985                }
986#endif
987
988               
989                    reply(MSG_OK,logmessage);
990                    exit(0);
991            }
992#ifdef CERTIFICATE_AUTH
993            if ( msg->code == MSG_CERT_LOG ) {
994                int retval;
995                if (accept_pass_only) {
996                    sprintf(logmessage, "The server only accepts USER/PASS");
997                    bbftpd_log(BBFTPD_ERR,"%s",logmessage) ;
998                    reply(MSG_BAD_NO_RETRY,logmessage);
999                    exit(1);
1000                }
1001                retval=bbftpd_cert_receive_connection(msg->msglen);
1002                if ( retval < 0 ) {
1003                    /*
1004                    ** The login failed, do not wait for a new one
1005                    */
1006                                        exit(1) ;
1007                }
1008                /*
1009                ** If retval >0, means an MSG_WARN has been sent already
1010                */
1011                    state = S_PROTWAIT ;
1012                if (retval == 0) {
1013                    sprintf(logmessage,"bbftpd version %s : OK",VERSION) ;
1014                    reply(MSG_OK,logmessage) ;
1015                }
1016            } else if ( msg->code == MSG_LOG ) {
1017                if (accept_certs_only) {
1018                    sprintf(logmessage, "The server only accepts certificates");
1019                    bbftpd_log(BBFTPD_ERR,"%s",logmessage) ;
1020                    reply(MSG_BAD_NO_RETRY,logmessage);
1021                } else {
1022                    /*
1023                    ** It seems that it is the message we were waiting
1024                    ** so lets decrypt
1025                    */
1026                    if ( loginsequence() < 0 ) {
1027                        /*
1028                        ** The login failed, do not wait for a new one
1029                        */
1030                        exit(1) ;
1031                    }
1032                    state = S_PROTWAIT ;
1033                    sprintf(logmessage,"bbftpd version %s : OK",VERSION) ;
1034                    reply(MSG_OK,logmessage) ;
1035                }
1036            } else if (msg->code == MSG_CRYPT) { 
1037                if (accept_certs_only) {
1038                    sprintf(logmessage, "The server only accepts certificates");
1039                    reply(MSG_BAD_NO_RETRY,logmessage);
1040                } else if (force_encoding) {
1041                    /*
1042                    **  The client can't encode and ask if it can send uncrypted
1043                    **  login information
1044                    */
1045                    sprintf(logmessage, "The server requires encrypted login");
1046                    reply(MSG_BAD_NO_RETRY,logmessage);
1047                } else {
1048                    sprintf(logmessage, "Uncrypted login dialog accepted");
1049                    reply(MSG_OK,logmessage);
1050                    goto login;
1051                }
1052            } else {
1053                bbftpd_log(BBFTPD_ERR,"Unkown message in connected state : %d",msg->code) ;
1054                reply(MSG_BAD,"Unkown message in connected state") ;
1055                exit(1) ;
1056            }
1057#else
1058#ifndef PRIVATE_AUTH
1059            if ( msg->code == MSG_LOG ) {
1060                /*
1061                ** It seems that it is the message we were waiting
1062                ** so lets decrypt
1063                */
1064                if ( loginsequence() < 0 ) {
1065                    /*
1066                    ** The login failed, do not wait for a new one
1067                    */
1068                    exit(1) ;
1069                }
1070                state = S_PROTWAIT ;
1071                sprintf(logmessage,"bbftpd version %s : OK",VERSION) ;
1072                reply(MSG_OK,logmessage) ;
1073            } else if (msg->code == MSG_CRYPT) { 
1074                /*
1075                **  The client can't encode and ask if it can send uncrypted
1076                **  login information
1077                */
1078                if (force_encoding) {
1079                    sprintf(logmessage, "The server requires encrypted login");
1080                    reply(MSG_BAD_NO_RETRY,logmessage);
1081                    exit(1);
1082                }
1083                sprintf(logmessage, "Uncrypted login dialog accepted");
1084                reply(MSG_OK,logmessage);
1085                goto login;
1086            } else {
1087                bbftpd_log(BBFTPD_ERR,"Unkown message in connected state : %d",msg->code) ;
1088                reply(MSG_BAD,"Unkown message in connected state") ;
1089                exit(1) ;
1090            }
1091#else
1092            if ( msg->code == MSG_PRIV_LOG ) {
1093                if ( bbftpd_private_receive_connection(msg->msglen) < 0 ) {
1094                    /*
1095                    ** The login failed, do not wait for a new one
1096                    */
1097                    exit(1) ;
1098                }
1099                state = S_PROTWAIT ;
1100                sprintf(logmessage,"bbftpd version %s : OK",VERSION) ;
1101                reply(MSG_OK,logmessage) ;
1102            } else {
1103                bbftpd_log(BBFTPD_ERR,"Unkown message in connected state : %d",msg->code) ;
1104                reply(MSG_BAD,"Unkown message in connected state") ;
1105                exit(1) ;
1106            }
1107#endif
1108#endif
1109        }
1110    }
1111
1112    /*
1113    ** At this stage we are in the S_PROTWAIT state
1114    */
1115    nfds = sysconf(_SC_OPEN_MAX) ;
1116    FD_ZERO(&selectmask) ;
1117    FD_SET(incontrolsock,&selectmask) ;
1118    wait_timer.tv_sec  = 10 ;
1119    wait_timer.tv_usec = 0 ;
1120    if ( (retcode = select(nfds,&selectmask,0,0,&wait_timer) ) == -1 ) {
1121        bbftpd_log(BBFTPD_ERR,"Select error in S_PROTWAIT state : %s",strerror(errno)) ;
1122        exit(1) ;
1123    } else if ( retcode == 0 ) {
1124        bbftpd_log(BBFTPD_ERR,"Time OUT in S_PROTWAIT state") ;
1125        exit(1) ;
1126    } else {
1127        if ( (retcode = readmessage(incontrolsock,buffer,MINMESSLEN,recvcontrolto)) < 0 ) {
1128            bbftpd_log(BBFTPD_ERR,"Error reading in S_PROTWAIT state") ;
1129            exit(1) ;
1130        }
1131        msg = (struct message *) buffer ;
1132        if ( msg->code == MSG_PROT ) {
1133            /*
1134            ** The client is using bbftp v2 protocol or higher
1135            */
1136            if ( checkprotocol() < 0 ) {
1137                exit_clean() ;
1138                exit(1) ;
1139            }
1140            bbftpd_log(BBFTPD_INFO,"Using bbftp protocol version %d",protocolversion) ;
1141            state = S_LOGGED ;
1142            /*
1143            ** Initialize the variables
1144            */
1145            mychildren = NULL ;
1146            nbpidchild = 0 ;
1147            curfilename = NULL ;
1148            curfilenamelen = 0 ;
1149        } else {
1150            /*
1151            ** This is a bbftp v1 client
1152            */
1153            protocolversion = 1 ;
1154            bbftpd_log(BBFTPD_INFO,"Using bbftp protocol version 1") ;
1155            state = S_LOGGED ;
1156            /*
1157            ** So set up the v1 handlers
1158            */
1159            if ( set_signals_v1() < 0 ) {
1160                exit(1) ;
1161            }
1162            /*
1163            ** Initialize the pid array
1164            */
1165            for ( i=0 ; i< MAXPORT ; i++) {
1166                pid_child[i] = 0 ;
1167            }
1168            /*
1169            ** As we have already read the message
1170            */
1171            if ( readcontrol(msg->code,msg->msglen) < 0 ) { 
1172                clean_child() ;
1173                exit_clean() ;
1174                exit(0) ;
1175            }
1176        }
1177    }
1178    if ( protocolversion == 1 ) goto loopv1 ;
1179    if ( protocolversion == 2 || protocolversion == 3) goto loopv2 ;
1180    bbftpd_log(BBFTPD_ERR,"Unknown protocol version %d",protocolversion) ;
1181    exit(1) ;
1182/*
1183** Loop for the v2 protocol (also available for v3)
1184*/
1185loopv2:
1186    /*
1187    ** Set up v2 handlers
1188    */
1189    if ( bbftpd_setsignals() < 0 ) {
1190        exit(1) ;
1191    }
1192    /*
1193    ** Set the umask ; first unset it and then reset to the default value
1194    */
1195    umask(0) ;
1196    umask(myumask) ;
1197    for (;;) {
1198        /*
1199        ** Initialize the selectmask
1200        */
1201        nfds = sysconf(_SC_OPEN_MAX) ;
1202        FD_ZERO(&selectmask) ;
1203        FD_SET(incontrolsock,&selectmask) ;
1204        /*
1205        ** Depending on the state set a timer or not
1206        */
1207        switch (state) {
1208            case S_WAITING_STORE_START :
1209            case S_WAITING_FILENAME_STORE :
1210            case S_WAITING_FILENAME_RETR : {
1211                /*
1212                ** Timer of 10s between XX_V2 and FILENAME_XX
1213                */
1214                wait_timer.tv_sec  = 10 ;
1215                wait_timer.tv_usec = 0 ;
1216                break ;
1217            }
1218           
1219            case S_SENDING :
1220            case S_RECEIVING : {
1221                /*
1222                ** No timer while receiving or sending
1223                */
1224                wait_timer.tv_sec  = 0 ;
1225                wait_timer.tv_usec = 0 ;
1226                break ;
1227            }
1228            default : {
1229                /*
1230                ** Timer of 900s between commands
1231                */
1232                wait_timer.tv_sec  = 900 ;
1233                wait_timer.tv_usec = 0 ;
1234                break ;
1235            }
1236        }
1237        if ( (retcode = select(nfds,&selectmask,0,0,(wait_timer.tv_sec == 0) ? NULL : &wait_timer) ) == -1 ) {
1238            if ( errno != EINTR ) {
1239                bbftpd_log(BBFTPD_ERR,"Select error : %s",strerror(errno)) ;
1240            }
1241        } else if ( retcode == 0 ) {
1242            bbftpd_log(BBFTPD_ERR,"Time OUT ") ;
1243            if ( state == S_WAITING_STORE_START ) {
1244                bbftpd_storeunlink(realfilename) ;
1245            }
1246            clean_child() ;
1247            exit_clean() ;
1248            exit(0) ;
1249        } else {
1250            /*
1251            ** At this stage we can only receive a command
1252            */
1253            if ( (retcode = readmessage(incontrolsock,buffer,MINMESSLEN,recvcontrolto)) < 0 ) {
1254                if ( state == S_WAITING_STORE_START  || state == S_RECEIVING) {
1255                    bbftpd_storeunlink(realfilename) ;
1256                    sleep(5) ;
1257                }
1258                clean_child() ;
1259                exit_clean() ;
1260                exit(0) ;
1261            }
1262            if ( bbftpd_readcontrol(msg->code,msg->msglen) < 0 ) { 
1263                clean_child() ;
1264                exit_clean() ;
1265                exit(0) ;
1266            } else {
1267            }
1268        }
1269    }
1270/*
1271** Loop for the v1 protocol
1272*/
1273loopv1:
1274    for (;;) {
1275        /*
1276        ** Initialize the selectmask
1277        */
1278        nfds = sysconf(_SC_OPEN_MAX) ;
1279        FD_ZERO(&selectmask) ;
1280        FD_SET(incontrolsock,&selectmask) ;
1281        /*
1282        ** Depending on the state set a timer or not
1283        */
1284        switch (state) {
1285            case S_SENDING :
1286            case S_RECEIVING : {
1287                /*
1288                ** No timer while receiving or sending
1289                */
1290                wait_timer.tv_sec  = 0 ;
1291                wait_timer.tv_usec = 0 ;
1292                break ;
1293            }
1294            default : {
1295                /*
1296                ** Timer of 900s between commands
1297                */
1298                wait_timer.tv_sec  = 900 ;
1299                wait_timer.tv_usec = 0 ;
1300                break ;
1301            }
1302        }
1303        if ( (retcode = select(nfds,&selectmask,0,0,(wait_timer.tv_sec == 0) ? NULL : &wait_timer) ) == -1 ) {
1304            if ( errno != EINTR ) {
1305                bbftpd_log(BBFTPD_ERR,"Select error : %s",strerror(errno)) ;
1306            }
1307        } else if ( retcode == 0 ) {
1308            bbftpd_log(BBFTPD_ERR,"Time OUT ") ;
1309            clean_child() ;
1310            exit_clean() ;
1311            exit(0) ;
1312        } else {
1313            /*
1314            ** At this stage we can only receive a command
1315            */
1316            if ( (retcode = readmessage(incontrolsock,buffer,MINMESSLEN,recvcontrolto)) < 0 ) {
1317                clean_child() ;
1318                exit_clean() ;
1319                exit(0) ;
1320            }
1321            if ( readcontrol(msg->code,msg->msglen) < 0 ) { 
1322                clean_child() ;
1323                exit_clean() ;
1324                exit(0) ;
1325            } else {
1326            }
1327        }
1328    }
1329}
1330
1331void clean_child() 
1332{
1333    int    *pidfree ;
1334    int    i ;
1335   
1336    if ( protocolversion == 0 ) return ;
1337    if ( protocolversion == 1 ) {
1338        if ( killdone == 0 ) {
1339            killdone = 1 ;
1340            for ( i=0 ; i<MAXPORT ; i++) {
1341                if ( pid_child[i] != 0 ) {
1342                    bbftpd_log(BBFTPD_DEBUG,"Killing child %d",pid_child[i]) ;
1343                    kill(pid_child[i],SIGKILL) ;
1344                }
1345            }
1346        }
1347        return ;
1348    }
1349    if ( protocolversion >= 2 ) {
1350        if ( killdone == 0 ) {
1351            killdone = 1 ;
1352            pidfree = mychildren ;
1353            for ( i=0 ; i<nbpidchild ; i++) {
1354                if ( *pidfree != 0 ) {
1355                    bbftpd_log(BBFTPD_DEBUG,"Killing child %d",*pidfree) ;
1356                    kill(*pidfree,SIGKILL) ;
1357                }
1358                pidfree++ ;
1359            }
1360        }
1361        return ;
1362    }
1363}
1364
1365void exit_clean() 
1366{
1367   
1368    switch (state) {
1369        case S_CONN : {
1370            return ;
1371        }
1372        case S_LOGGED :
1373        case S_PROTWAIT :
1374        case S_WAITING_FILENAME_STORE :
1375        case S_WAITING_STORE_START :
1376        case S_SENDING:
1377        case S_RECEIVING : {
1378            bbftpd_log(BBFTPD_INFO,"User %s disconnected",currentusername) ;
1379            return ;
1380        }
1381        default :{
1382            return ;
1383        }
1384    }
1385}
1386
1387my64_t convertlong(my64_t v) {
1388    struct bb {
1389        int    fb ;
1390        int sb ;
1391    } ;
1392    struct bb *bbpt ;
1393    int     tmp ;
1394    my64_t    tmp64 ;
1395   
1396    tmp64 = v ;
1397    bbpt = (struct bb *) &tmp64 ;
1398    tmp = bbpt->fb ;
1399    bbpt->fb = ntohl(bbpt->sb) ;
1400    bbpt->sb = ntohl(tmp) ;   
1401    return tmp64 ;
1402}
1403
1404#ifndef HAVE_NTOHLL
1405my64_t ntohll(my64_t v) {
1406# ifdef HAVE_BYTESWAP_H
1407    return bswap_64(v);
1408# else
1409    long lo = v & 0xffffffff;
1410    long hi = v >> 32U;
1411    lo = ntohl(lo);
1412    hi = ntohl(hi);
1413    return ((my64_t) lo) << 32U | hi;
1414# endif
1415}
1416#define htonll ntohll
1417#endif
1418
Note: See TracBrowser for help on using the repository browser.