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

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

A python module which provides a function to start the daemon can be
built using the setup.py script. This method of invoking the server
has been briefly tested but no test cases yet.

I've taken out the initialisation/finalisation hooks from the auth API because
we shouldn't need them now. They were written assuming the python interpretter
was going to be embedded within bbftpd, but I've inverted the embedding by
wrapping bbftpd.c:main in a python extension function.

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