/*
* bbftpc/bbftp.c
* Copyright (C) 1999, 2000, 2001, 2002 IN2P3, CNRS
* bbftp@in2p3.fr
* http://doc.in2p3.fr/bbftp
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/****************************************************************************
bbftp.c v 2.0.0 2001/03/01 - Complete rewriting for version 2.0.0
v 2.0.1 2001/04/19 - Correct indentation
- Verify if -s is present on shhremotecmd
and add it if not (in order to fit v 1.9.4-tja1
behaviour)
v 2.1.0 2001/05/21 - Add debug
- Add -m option to have special output
- Set -v before all options
- Correct case where the last line in control
file has no CR
v 2.1.2 2001/11/19 - Fix COS 0 case
v 2.2.0 2001/10/03 - Add certificate authentication mode
*****************************************************************************/
#include <errno.h>
#include <fcntl.h>
#include <netdb.h>
#include <netinet/in.h>
#include <pwd.h>
#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <time.h>
#include <bbftp.h>
#include <client.h>
#include <client_proto.h>
#include <common.h>
#include <config.h>
#include <structures.h>
#include <version.h>
#ifdef WITH_SSL
#include <openssl/rsa.h>
#endif
#define SETTOZERO 0
#define SETTOONE 1
#define SSHREMOTECMD "bbftpd -s"
#define SSHCMD "ssh -q"
/*
#ifdef CERTIFICATE_AUTH
#define OPTIONS "qbcde:f:i:l:mno:p:r:R:tu:vVw:W"
#else
*/
#ifdef PRIVATE_AUTH
#define OPTIONS "qbcde:f:i:l:mno:p:P:r:R:tu:vVw:WD::"
#else
#define OPTIONS "qbcde:E:f:g:i:I:l:L:mno:p:r:R:sStu:vVw:WD::"
#endif
/*
#endif
*/
int state = SETTOZERO ;
/*
** timestamp:
** Every message on standart error and standart output are
** timestamped
*/
int timestamp = SETTOZERO ;
/*
** protocolmin:
** Minimum protocol supportted
*/
int protocolmin = 2 ;
int protocolmax = 3 ;
int protocol ;
/*
** debug:
** Set to one to print more debugging information
*/
int debug = SETTOZERO ;
/*
** verbose:
** Set to one to print information
*/
int verbose = SETTOZERO ;
/*
** warning:
** Set to one to print warning to stderr
*/
int warning = SETTOZERO ;
/*
** statoutput:
** Set to one for special output
*/
int statoutput = SETTOZERO ;
/*
** globaltrymax:
** Number of try in case or recoverable error
*/
int globaltrymax = NBTRYMAX ;
/*
** newcontrolport:
** Control port to be used
*/
int newcontrolport = CONTROLPORT ;
/*
** usessh:
** Set to one when using ssh to start the remote daemon
*/
int usessh = SETTOZERO ;
/*
** sshbatchmode:
** This is set to non-zero if running in batch mode (that is, password
** and passphrase queries are not allowed).
*/
int sshbatchmode = SETTOZERO ;
/*
** sshchildpid:
** To keep the ssh child pid
*/
int sshchildpid = SETTOZERO ;
/*
** For ssh
*/
char *sshidentityfile = NULL ;
char *sshremotecmd = NULL ;
char *sshcmd = NULL ;
/*
** usecert:
** Set to one if using certificate authentifaction
*/
int usecert = SETTOZERO ;
/*
** useprivate:
** Set to one if using private authentication
*/
int useprivate = SETTOZERO ;
/*
** privatestr:
** Pointer to a private string used for private authentication
**
*/
char *privatestr = NULL ;
/*
** hisctladdr:
** the remote address
*/
struct sockaddr_in hisctladdr ;
/*
** myctladdr:
** the local address
*/
struct sockaddr_in myctladdr ;
/*
** bbftprc:
** Where to store the bbftprc file
*/
char *bbftprc = NULL ;
/*
** Variable defining the local options :
**
** localcos:
** Value of the local class of service (in case of RFIO ability)
**
** localumask:
** Local umask taken by the umask command at start and
** modified by the setlocalumask command
**
** localrfio:
** set to one when using rfio for local files
**
*/
int localumask ;
#if defined(WITH_RFIO) || defined(WITH_RFIO64)
int localcos = SETTOZERO ;
#endif
/*
** Variables defining both side options :
**
** usetmpfile:
** Set to one when using tmpname for file creation
**
** usegzipcompress:
** Set to one when using tmpname for file creation
**
** keepaccess:
** Set to one when keeping access time and modification
**
** keepmode:
** Set to one when keeping file mode
**
** creatdir:
** Set to one when automatic directory creation is needed
*/
int sendwinsize = 256 ;
int recvwinsize = 256 ;
int nbport = 1 ;
int ackto = ACKTO;
int recvcontrolto = CONTROLSOCKTO;
int sendcontrolto = SENDCONTROLTO;
int datato = DATASOCKTO;
/*
** Variables remote side options :
**
** remoterfio:
** Set to one when rfio for remote file
**
** remoteumask:
** if set to zero do not set remote umask
**
** remotecos:
** if not set to zero do set remote cos
**
** remotedir :
** if not set to NULL change dir after connection
**
*/
int remoteumask = SETTOZERO ;
int remotecos = SETTOZERO ;
char *remotedir = NULL ;
/*
** incontrolsock :
** Define the control socket for reading
** outcontrolsock :
** Define the control socket for writing
**
** For normal use : incontrolsock = outcontrolsock
*/
int incontrolsock ;
int outcontrolsock ;
/*
** myexitcode :
** Contains the first error code that has to be return when program
** is ended
*/
int myexitcode = SETTOZERO ;
char *hostname = NULL ;
struct hostent *hp = NULL ;
char *username = NULL ;
char *password = NULL ;
#ifdef CERTIFICATE_AUTH
char *service = NULL ;
#endif
/*
** mychildren :
** Pointer to the first pid of children
*/
int *mychildren = NULL ;
/*
** nbpidchid :
** Number of pid pointed by mychildren
*/
int nbpidchild ;
/*
** castfd:
** CASTOR file descriptor
*/
int castfd = -1 ;
char *castfilename = NULL ;
/*
** Parameters describing the transfer ********************
*/
int transferoption = TROPT_TMP | TROPT_DIR | TROPT_MODE | TROPT_ACC;
int filemode ;
char lastaccess[9] ;
char lastmodif[9] ;
int buffersizeperstream = 256 ;
int requestedstreamnumber ;
my64_t filesize ;
/*
** curfilename :
** Define the pointer to the current file
*/
char *curfilename = NULL ;
/*
** realfilename :
** Define the pointer to the real file (= curfilename if TROPT_TMP not
** set)
*/
char *realfilename = NULL ;
int *myports = NULL ;
int *mysockets = NULL ;
char *readbuffer = NULL ;
char *compbuffer = NULL ;
int resfd = -1 ;
/*
** Simulation mode (option -n)
*/
int simulation_mode = SETTOZERO;
/*
**
*/
int connectionisbroken = SETTOZERO ;
/*
* Range for the ephemeral ports for data connections
*/
int pasvport_min = 0 ;
int pasvport_max = 0 ;
main(argc, argv, envp)
int argc;
char **argv;
char **envp;
{
extern char *optarg;
extern int optind, opterr, optopt;
/*
** Variable set by options
*/
char *inputfile = NULL ;
char *resultfile = NULL ;
char *outputfile = NULL ;
char *errorfile = NULL ;
char *bbftpcmd = NULL ;
int background = SETTOZERO ;
/*
** For hostname
*/
int hosttype = 0 ;
char *calchostname ;
/*
** For local user
*/
struct passwd *mypasswd ;
char *bbftprcfile = NULL ;
int fd ;
char *carret ;
char *startcmd ;
int nooption ;
struct stat statbuf ;
int retcode ;
int i, j, k ;
int stderrfd ;
int stdoutfd ;
int infd ;
char calcmaxline[1] ;
int maxlen ;
int lengthread ;
char *buffercmd ;
int alluse ;
char *tmpsshremotecmd ;
char logmessage[1024] ;
char minbuffer[MINMESSLEN] ;
struct message *msg ;
/*
** Get local umask
*/
localumask = umask(0) ;
/*
** and reset it to the correct value
*/
umask(localumask) ;
/*
** First check for timestamp in order to have a common output
*/
opterr = 0 ;
while ((j = getopt(argc, argv, OPTIONS)) != -1) {
switch (j) {
case 't' :{
timestamp = SETTOONE ;
break ;
}
}
}
#ifdef PRIVATE_AUTH
useprivate = SETTOONE ;
usessh = SETTOZERO ;
#endif
/*
#ifdef CERTIFICATE_AUTH
usecert = SETTOONE ;
useprivate = SETTOZERO ;
usessh = SETTOZERO ;
#endif
*/
/*
** Check for -v option
*/
opterr = 0 ;
optind = 1 ;
while ((j = getopt(argc, argv, OPTIONS)) != -1) {
switch (j) {
case 'v' :{
printmessage(stdout,CASE_NORMAL,0,timestamp,"bbftp version %s\n",VERSION) ;
printmessage(stdout,CASE_NORMAL,0,timestamp,"Compiled with : default port %d\n",CONTROLPORT) ;
#ifdef PORT_RANGE
printmessage(stdout,CASE_NORMAL,0,timestamp," data ports range = %s \n", PORT_RANGE) ;
#endif
#ifdef WITH_GZIP
printmessage(stdout,CASE_NORMAL,0,timestamp," compression with Zlib-%s\n", zlibVersion()) ;
#endif
#ifdef WITH_SSL
printmessage(stdout,CASE_NORMAL,0,timestamp," encryption with %s \n",SSLeay_version(SSLEAY_VERSION)) ;
#endif
#ifdef WITH_RFIO
printmessage(stdout,CASE_NORMAL,0,timestamp," RFIO interface \n") ;
#endif
#ifdef WITH_RFIO64
printmessage(stdout,CASE_NORMAL,0,timestamp," RFIO64 interface \n") ;
#endif
#ifdef CASTOR
printmessage(stdout,CASE_NORMAL,0,timestamp," CASTOR support \n") ;
#endif
#ifdef AFS
printmessage(stdout,CASE_NORMAL,0,timestamp," AFS authentication \n") ;
#endif
#ifdef PRIVATE_AUTH
printmessage(stdout,CASE_NORMAL,0,timestamp," private authentication \n") ;
#else
printmessage(stdout,CASE_NORMAL,0,timestamp," default ssh command = %s \n",SSHCMD) ;
printmessage(stdout,CASE_NORMAL,0,timestamp," default ssh remote command = %s \n",SSHREMOTECMD) ;
# ifdef CERTIFICATE_AUTH
printmessage(stdout,CASE_NORMAL,0,timestamp," certificate authentication enabled\n") ;
# endif
#endif
printmessage(stdout,CASE_NORMAL,0,timestamp," default number of tries = %d \n",NBTRYMAX) ;
printmessage(stdout,CASE_NORMAL,0,timestamp," default sendwinsize = %d Kbytes\n",sendwinsize) ;
printmessage(stdout,CASE_NORMAL,0,timestamp," default recvwinsize = %d Kbytes\n",recvwinsize) ;
printmessage(stdout,CASE_NORMAL,0,timestamp," default number of stream = %d \n",nbport) ;
exit(0) ;
}
}
}
/*
** Check for stderr replacement
*/
opterr = 0 ;
optind = 1 ;
while ((j = getopt(argc, argv, OPTIONS)) != -1) {
switch (j) {
case 'f' :{
errorfile = optarg ;
break ;
}
}
}
if ( errorfile != NULL ) {
if ( (stderrfd = open(errorfile,O_CREAT|O_WRONLY|O_SYNC|O_TRUNC,0777)) < 0 ) {
printmessage(stderr,CASE_FATAL_ERROR,10,timestamp,"Error openning error file (%s) : %s\n",errorfile,strerror(errno)) ;
}
close(STDERR_FILENO);
if ( fcntl(stderrfd,F_DUPFD,STDERR_FILENO) != STDERR_FILENO ) {
printmessage(stderr,CASE_FATAL_ERROR,11,timestamp,"Error dup on error file (%s) : %s\n",errorfile,strerror(errno)) ;
}
}
/*
** Check for stdout replacement
*/
opterr = 0 ;
optind = 1 ;
while ((j = getopt(argc, argv, OPTIONS)) != -1) {
switch (j) {
case 'o' :{
outputfile = optarg ;
break ;
}
}
}
if ( outputfile != NULL ) {
if ( (stdoutfd = open(outputfile,O_CREAT|O_WRONLY|O_SYNC|O_TRUNC,0777)) < 0 ) {
printmessage(stderr,CASE_FATAL_ERROR,12,timestamp,"Error openning output file (%s) : %s\n",outputfile,strerror(errno)) ;
}
close(STDOUT_FILENO);
if ( fcntl(stdoutfd,F_DUPFD,STDOUT_FILENO) != STDOUT_FILENO ) {
printmessage(stderr,CASE_FATAL_ERROR,13,timestamp,"Error dup on output file (%s) : %s\n",outputfile,strerror(errno)) ;
}
}
/*
** Block all signals , the routine will exit in case of error
*/
blockallsignals() ;
/*
** Now all the others
*/
opterr = 0 ;
optind = 1 ;
while ((j = getopt(argc, argv, OPTIONS)) != -1) {
switch (j) {
case 'b' :{
background = SETTOONE ;
break ;
}
case 'c' :{
#ifdef WITH_GZIP
transferoption = transferoption | TROPT_GZIP ;
#else
printmessage(stderr,CASE_FATAL_ERROR,7,timestamp,"option -c is not available: bbftp was built without compression utility\n") ;
#endif
break ;
}
case 'd' :{
debug = 1 ;
break ;
}
case 'D' :{
if (optarg) {
if ((sscanf(optarg,"%d:%d",&i, &k) == 2) && (i < k)) {
pasvport_min = i; pasvport_max = k;
} else {
printmessage(stderr,CASE_FATAL_ERROR,4,timestamp,"Invalid port range : %s\n",optarg) ;
}
} else {
#ifdef PORT_RANGE
sscanf(PORT_RANGE,"%d:%d",&pasvport_min, &pasvport_max) ;
#endif
if (0 == pasvport_max) {
pasvport_min = 0;
pasvport_max = 1;
}
}
protocolmax = 2 ;
break ;
}
case 'e' : {
bbftpcmd = optarg ;
break ;
}
case 'E' : {
sshremotecmd = optarg ;
usessh = 1 ;
break ;
}
case 'f' :{
errorfile = optarg ;
break ;
}
#ifdef CERTIFICATE_AUTH
case 'g' :{
service = optarg ;
break ;
}
#endif
case 'i' :{
inputfile = optarg ;
if ( stat (inputfile,&statbuf) < 0 ) {
printmessage(stderr,CASE_FATAL_ERROR,7,timestamp,"Input file (%s) cannot be stated\n",inputfile) ;
}
if ( (resultfile = (char *) malloc (strlen(inputfile) + 5 )) == NULL ) {
printmessage(stderr,CASE_FATAL_ERROR,1,timestamp,"Cannot malloc space for result file name\n") ;
}
strcpy(resultfile,inputfile) ;
strcat(resultfile,".res") ;
break ;
}
case 'I' :{
sshidentityfile = optarg ;
usessh = 1 ;
/*
** Check if file exists
*/
if ( stat (sshidentityfile,&statbuf) < 0 ) {
printmessage(stderr,CASE_FATAL_ERROR,5,timestamp,"SSH identity file (%s) cannot be stated\n",sshidentityfile) ;
}
break ;
}
case 'L' : {
sshcmd = optarg ;
usessh = 1 ;
break ;
}
case 'm' :{
statoutput = SETTOONE ;
break ;
}
case 'n':{
simulation_mode = SETTOONE ;
break ;
}
case 'o' :{
outputfile = optarg ;
break ;
}
case 'P' :{
privatestr = optarg ;
break ;
}
case 'q' :{
transferoption = transferoption | TROPT_QBSS ;
break ;
}
case 'p' :{
retcode = sscanf(optarg,"%d",&alluse) ;
if ( retcode != 1 || alluse < 0) {
printmessage(stderr,CASE_FATAL_ERROR,3,timestamp,"Number of streams must be numeric and > 0\n") ;
}
nbport = alluse ;
break ;
}
case 'r' :{
retcode = sscanf(optarg,"%d",&alluse) ;
if ( retcode != 1 || alluse <= 0) {
printmessage(stderr,CASE_FATAL_ERROR,4,timestamp,"Number of tries must be numeric > 0\n") ;
}
globaltrymax = alluse ;
break ;
}
case 'R' :{
bbftprcfile = optarg ;
break ;
}
case 's' :{
usessh = SETTOONE ;
break ;
}
case 'S' :{
usessh = SETTOONE ;
sshbatchmode = SETTOONE ;
break ;
}
case 't' :{
timestamp = SETTOONE ;
break ;
}
case 'u' :{
username = optarg ;
break ;
}
case 'V':{
verbose = SETTOONE ;
break ;
}
case 'w' :{
retcode = sscanf(optarg,"%d",&alluse) ;
if ( retcode != 1 || alluse <= 0) {
printmessage(stderr,CASE_FATAL_ERROR,4,timestamp,"Control port must be numeric\n") ;
}
newcontrolport = alluse ;
break ;
}
case 'W':{
warning = SETTOONE ;
break ;
}
default : {
Usage() ;
printmessage(stderr,CASE_FATAL_ERROR,6,timestamp,"Error on command line (unsupported option -%c)\n",optopt) ;
}
}
}
/*
** Get 5K for castfilename in order to work with CASTOR
** software (even if we are not using it)
*/
if ( (castfilename = (char *) malloc (5000)) == NULL ) {
/*
** Starting badly if we are unable to malloc 5K
*/
printmessage(stderr,CASE_FATAL_ERROR,10,timestamp,"No memory for CASTOR : %s\n",strerror(errno)) ;
}
/*
** Reset all outputs variable if statoutput is set to one
*/
if ( statoutput ) {
debug = SETTOZERO ;
verbose = SETTOZERO ;
warning = SETTOZERO ;
timestamp = SETTOZERO ;
}
/*
#ifdef PRIVATE_AUTH
useprivate = SETTOONE ;
usessh = SETTOZERO ;
#endif
#ifdef CERTIFICATE_AUTH
usecert = SETTOONE ;
useprivate = SETTOZERO ;
usessh = SETTOZERO ;
#endif
*/
/*
** Check all ssh stuff
*/
if ( usessh) {
if ( sshremotecmd == NULL ) {
/*
** Malloc space and set the default
*/
if ( (sshremotecmd = (char *) malloc (strlen(SSHREMOTECMD)+1) ) == NULL ) {
printmessage(stderr,CASE_FATAL_ERROR,8,timestamp,"Cannot malloc space for ssh remote cmd\n") ;
}
strcpy(sshremotecmd,SSHREMOTECMD) ;
} else {
/*
** Verify if -s is present if not add it (in order to fit v 1.9.4-tja1
** behaviour)
*/
if ( strstr(sshremotecmd," -s") == NULL ) {
if ( ( tmpsshremotecmd = (char *) malloc (strlen(sshremotecmd) + 4) ) == NULL ) {
printmessage(stderr,CASE_FATAL_ERROR,8,timestamp,"Cannot malloc space for ssh remote cmd\n") ;
}
sprintf(tmpsshremotecmd,"%s -s",sshremotecmd) ;
sshremotecmd = tmpsshremotecmd ;
}
}
if ( sshcmd == NULL ) {
if ( (sshcmd = (char *) malloc (strlen(SSHCMD)+1) ) == NULL ) {
printmessage(stderr,CASE_FATAL_ERROR,9,timestamp,"Cannot malloc space for ssh cmd\n") ;
}
strcpy(sshcmd,SSHCMD) ;
}
}
/*
** Check hostname
*/
if ( optind != argc-1 ) {
Usage() ;
printmessage(stderr,CASE_FATAL_ERROR,14,timestamp,"No hostname on command line\n") ;
} else {
hostname= argv[optind] ;
}
/*
** Check if hostname is in numeric format
*/
for (j=0 ; j < strlen(hostname) ; j++) {
if ( isalpha(hostname[j]) ) {
/*
** One alpha caractere means no numeric form
*/
hosttype = 1 ;
break ;
} else if ( isdigit(hostname[j]) ) {
} else if ( hostname[j] == '.' ) {
} else {
printmessage(stderr,CASE_FATAL_ERROR,15,timestamp,"Invalid hostname (%s)\n",hostname) ;
}
}
if ( hosttype == 0 ) {
/*
** Numeric format
*/
hisctladdr.sin_addr.s_addr = 0 ;
hisctladdr.sin_addr.s_addr = inet_addr(hostname) ;
if (hisctladdr.sin_addr.s_addr == -1 ) {
printmessage(stderr,CASE_FATAL_ERROR,16,timestamp,"Invalid IP address (%s)\n",hostname) ;
}
calchostname = (char *)inet_ntoa(hisctladdr.sin_addr) ;
if ( strcmp(hostname,calchostname) ) {
printmessage(stderr,CASE_FATAL_ERROR,16,timestamp,"Invalid IP address (%s)\n",hostname) ;
}
} else {
/*
** Alpha format
*/
if ( (hp = gethostbyname(hostname) ) == NULL ) {
printmessage(stderr,CASE_FATAL_ERROR,17,timestamp,"Hostname no found (%s)\n",hostname) ;
} else {
if (hp->h_length > (int)sizeof(hisctladdr.sin_addr)) {
hp->h_length = sizeof(hisctladdr.sin_addr);
}
memcpy(&hisctladdr.sin_addr, hp->h_addr_list[0], hp->h_length) ;
}
}
/*
** Check for input file or command line
*/
if ( inputfile == NULL && bbftpcmd == NULL ) {
printmessage(stderr,CASE_FATAL_ERROR,20,timestamp,"Error on command line (-i or -e option are mandatory)\n") ;
}
/*
** Check username if not in certificate authentication mode
*/
if ( username == NULL ) {
#ifdef CERTIFICATE_AUTH
if (usessh) {
Usage() ;
printmessage(stderr,CASE_FATAL_ERROR,18,timestamp,"No username given\n") ;
} else {
usecert = SETTOONE;
}
#else
Usage() ;
printmessage(stderr,CASE_FATAL_ERROR,18,timestamp,"No username given\n") ;
#endif
}
/*
** Check for the local user in order to find the .bbftprc file
*/
if ( bbftprcfile == NULL ) {
/*
** look for the local user in order to find the .bbftprc file
*/
if ( (mypasswd = getpwuid(getuid())) == NULL ) {
if ( warning ) printmessage(stderr,CASE_WARNING,6,timestamp,"Unable to get passwd entry, .bbftprc will not be used\n") ;
} else if ( mypasswd->pw_dir == NULL ) {
if ( warning ) printmessage(stderr,CASE_WARNING,7,timestamp,"No home directory, .bbftprc will not be used\n") ;
} else if ( (bbftprcfile = (char *) malloc (strlen(mypasswd->pw_dir)+10) ) == NULL ) {
if ( warning ) printmessage(stderr,CASE_WARNING,8,timestamp,"Error allocationg space for bbftprc file name, .bbftprc will not be used\n") ;
} else {
strcpy(bbftprcfile,mypasswd->pw_dir) ;
strcat(bbftprcfile,"/.bbftprc") ;
}
}
if ( bbftprcfile != NULL ) {
if ( strncmp(bbftprcfile,"none",4) != 0 ) {
/*
** Stat the file in order to get the length
*/
if ( stat(bbftprcfile,&statbuf) < 0 ) {
if ( warning ) printmessage(stderr,CASE_WARNING,9,timestamp,"Error stating bbftprc file (%s)\n",bbftprcfile) ;
} else if ( statbuf.st_size == 0 ) {
/*
** do nothing
*/
} else if ( (bbftprc = (char *) malloc (statbuf.st_size + 1 ) ) == NULL ) {
if ( warning ) printmessage(stderr,CASE_WARNING,10,timestamp,"Error allocation memory for bbftprc, .bbftprc will not be used\n") ;
} else if ( ( fd = open (bbftprcfile,O_RDONLY) ) < 0 ) {
if ( warning ) printmessage(stderr,CASE_WARNING,11,timestamp,"Error openning .bbftprc file (%s) : %s \n",bbftprcfile,strerror(errno)) ;
} else if ( ( j = read( fd, bbftprc , statbuf.st_size )) != statbuf.st_size ) {
if ( warning ) printmessage(stderr,CASE_WARNING,12,timestamp,"Error reading .bbftprc file (%s)\n",bbftprcfile) ;
} else {
bbftprc[j] = '\0' ;
}
}
}
/*
** Analyse the bbftprc command in order to supress forbiden command
** Allowed commands are :
** setbuffersize %d
** setlocalcos %d
** setremotecos %d
** setlocalumask %ooo
** setremoteumask %ooo
** setsendwinsize %d
** setrecvwinsize %d
** setnbstream %d
** setoption [ [no]createdir | [no]tmpfile | [no]remoterfio | [no]localrfio | [no]keepmode |[no]keepaccess |[no]gzip]
**
*/
if ( bbftprc != NULL ) {
carret = bbftprc ;
startcmd = bbftprc ;
/*
** Strip starting CR
*/
while (1) {
while ( *carret == 10 || *carret == ' ' ) carret++ ;
startcmd = carret ;
carret = (char *) strchr (carret, 10);
if ( carret == NULL ) break ;
*carret = '\0' ;
if ( !strncmp(startcmd,"setbuffersize",13)) {
retcode = sscanf(startcmd,"setbuffersize %d",&alluse) ;
if ( retcode != 1 || alluse < 0 ) {
if ( warning ) printmessage(stderr,CASE_WARNING,5,timestamp,"Buffersize in bbftprc file must be numeric > 0\n") ;
} else {
buffersizeperstream = alluse ;
}
#if defined(WITH_RFIO) || defined(WITH_RFIO64)
} else if ( !strncmp(startcmd,"setlocalcos",11)) {
retcode = sscanf(startcmd,"setlocalcos %d",&alluse) ;
if ( retcode != 1 /*|| alluse < 0*/) {
if ( warning ) printmessage(stderr,CASE_WARNING,14,timestamp,"Local COS in bbftprc file must be numeric\n") ;
} else {
localcos = alluse ;
}
#endif
} else if (!strncmp(startcmd,"setremotecos",12)) {
retcode = sscanf(startcmd,"setremotecos %d",&alluse) ;
if ( retcode != 1 /*|| alluse < 0*/) {
if ( warning ) printmessage(stderr,CASE_WARNING,15,timestamp,"Remote COS in bbftprc file must be numeric\n") ;
}else {
remotecos = alluse ;
}
} else if (!strncmp(startcmd,"setlocalumask",13)) {
retcode = sscanf(startcmd,"setlocalumask %o",&alluse) ;
if ( retcode != 1 || alluse < 0) {
if ( warning ) printmessage(stderr,CASE_WARNING,16,timestamp,"Local umask in bbftprc file must be numeric\n") ;
} else {
localumask = alluse ;
umask(localumask) ;
}
} else if (!strncmp(startcmd,"setremoteumask",14)) {
retcode = sscanf(startcmd,"setremoteumask %o",&alluse) ;
if ( retcode != 1 || alluse < 0) {
if ( warning ) printmessage(stderr,CASE_WARNING,17,timestamp,"Remote umask in bbftprc file must be numeric\n") ;
}else {
remoteumask = alluse ;
umask(localumask) ;
}
} else if (!strncmp(startcmd,"setsendwinsize",14)) {
retcode = sscanf(startcmd,"setsendwinsize %d",&alluse) ;
if ( retcode != 1 || alluse < 0 ) {
if ( warning ) printmessage(stderr,CASE_WARNING,18,timestamp,"Send window size in bbftprc file must be numeric\n") ;
} else {
sendwinsize = alluse ;
}
} else if (!strncmp(startcmd,"setrecvwinsize",14)) {
retcode = sscanf(startcmd,"setrecvwinsize %d",&alluse) ;
if ( retcode != 1 || alluse < 0 ) {
if ( warning ) printmessage(stderr,CASE_WARNING,19,timestamp,"Receive window size in bbftprc file must be numeric\n") ;
}else {
recvwinsize = alluse ;
}
} else if (!strncmp(startcmd,"setnbstream",11)) {
retcode = sscanf(startcmd,"setnbstream %d",&alluse) ;
if ( retcode != 1 || alluse <= 0 ) {
if ( warning ) printmessage(stderr,CASE_WARNING,19,timestamp,"Number of streams in bbftprc file must be numeric and > 0\n") ;
} else {
nbport = alluse ;
}
} else if (!strncmp(startcmd,"setackto",8)) {
retcode = sscanf(startcmd,"setackto %d",&alluse) ;
if ( retcode != 1 || alluse <= 0 ) {
if ( warning ) printmessage(stderr,CASE_WARNING,19,timestamp,"Acknowledge timeout must be numeric and > 0\n") ;
} else {
ackto = alluse ;
}
} else if (!strncmp(startcmd,"setrecvcontrolto",16)) {
retcode = sscanf(startcmd,"setrecvcontrolto %d",&alluse) ;
if ( retcode != 1 || alluse <= 0 ) {
if ( warning ) printmessage(stderr,CASE_WARNING,19,timestamp,"Input control timeout must be numeric and > 0\n") ;
} else {
recvcontrolto = alluse ;
}
} else if (!strncmp(startcmd,"setsendcontrolto",16)) {
retcode = sscanf(startcmd,"setsendcontrolto %d",&alluse) ;
if ( retcode != 1 || alluse <= 0 ) {
if ( warning ) printmessage(stderr,CASE_WARNING,19,timestamp,"Output control timeout must be numeric and > 0\n") ;
} else {
sendcontrolto = alluse ;
}
} else if (!strncmp(startcmd,"setdatato",9)) {
retcode = sscanf(startcmd,"setdatato %d",&alluse) ;
if ( retcode != 1 || alluse <= 0 ) {
if ( warning ) printmessage(stderr,CASE_WARNING,19,timestamp,"Data timeout must be numeric and > 0\n") ;
} else {
datato = alluse ;
}
} else if (!strncmp(startcmd,"setoption",9)) {
/*
** look for the option
*/
startcmd = startcmd + 9 ;
while (*startcmd == ' ' && *startcmd != '\0' ) startcmd++ ;
if ( !strncmp(startcmd,"no",2) ) {
nooption = SETTOONE ;
startcmd = startcmd+2 ;
} else {
nooption = SETTOZERO ;
}
if ( !strncmp(startcmd,"createdir",9) ) {
if ( nooption ) {
transferoption = transferoption & ~TROPT_DIR ;
} else {
transferoption = transferoption | TROPT_DIR ;
}
} else if ( !strncmp(startcmd,"tmpfile",7) ) {
if ( nooption ) {
transferoption = transferoption & ~TROPT_TMP ;
} else {
transferoption = transferoption | TROPT_TMP ;
}
} else if ( !strncmp(startcmd,"remoterfio",10) ) {
if ( nooption ) {
transferoption = transferoption & ~TROPT_RFIO ;
} else {
transferoption = transferoption | TROPT_RFIO ;
}
} else if ( !strncmp(startcmd,"localrfio",9) ) {
if ( nooption ) {
transferoption = transferoption & ~TROPT_RFIO_O ;
} else {
#if defined(WITH_RFIO) || defined(WITH_RFIO64)
transferoption = transferoption | TROPT_RFIO_O ;
#else
if (warning) printmessage(stderr,CASE_WARNING,20,timestamp,"Incorrect command : setoption localrfio (RFIO not supported)\n",buffercmd) ;
#endif
}
} else if ( !strncmp(startcmd,"keepmode",8) ) {
if ( nooption ) {
transferoption = transferoption & ~TROPT_MODE ;
} else {
transferoption = transferoption | TROPT_MODE ;
}
} else if ( !strncmp(startcmd,"keepaccess",10) ) {
if ( nooption ) {
transferoption = transferoption & ~TROPT_ACC ;
} else {
transferoption = transferoption | TROPT_ACC ;
}
} else if ( !strncmp(startcmd,"gzip",4) ) {
if ( nooption ) {
transferoption = transferoption & ~TROPT_GZIP ;
} else {
#ifdef WITH_GZIP
transferoption = transferoption | TROPT_GZIP ;
#else
printmessage(stderr,CASE_FATAL_ERROR,7,timestamp,"gzip option is not available: bbftp was built without compression utility\n") ;
#endif
}
} else if ( !strncmp(startcmd,"qbss",4) ) {
if ( nooption ) {
transferoption = transferoption & ~TROPT_QBSS ;
} else {
transferoption = transferoption | TROPT_QBSS ;
}
} else {
if ( warning ) printmessage(stderr,CASE_WARNING,20,timestamp,"Unkown option in .bbftprc file (%s)\n",startcmd) ;
}
} else {
if ( warning ) printmessage(stderr,CASE_WARNING,13,timestamp,"Unkown command in .bbftprc file (%s)\n",startcmd) ;
}
carret++ ;
}
}
if ( debug ) {
if (simulation_mode) {
printmessage(stdout,CASE_NORMAL,0,timestamp,"** SIMULATION MODE: No data written **\n") ;
}
printmessage(stdout,CASE_NORMAL,0,timestamp,"Starting parameters -----------------\n") ;
printmessage(stdout,CASE_NORMAL,0,timestamp,"number of tries = %d\n",globaltrymax) ;
printmessage(stdout,CASE_NORMAL,0,timestamp,"number of streams = %d\n",nbport) ;
printmessage(stdout,CASE_NORMAL,0,timestamp,"localumask = %03o\n",localumask) ;
printmessage(stdout,CASE_NORMAL,0,timestamp,"remoteumask = %03o\n",remoteumask) ;
#if defined(WITH_RFIO) || defined(WITH_RFIO64)
printmessage(stdout,CASE_NORMAL,0,timestamp,"localcos = %d\n",localcos) ;
#endif
printmessage(stdout,CASE_NORMAL,0,timestamp,"remotecos = %d\n",remotecos) ;
printmessage(stdout,CASE_NORMAL,0,timestamp,"buffersize = %d KB\n",buffersizeperstream) ;
printmessage(stdout,CASE_NORMAL,0,timestamp,"sendwinsize = %d KB\n",sendwinsize) ;
printmessage(stdout,CASE_NORMAL,0,timestamp,"recvwinsize = %d KB\n",recvwinsize) ;
printmessage(stdout,CASE_NORMAL,0,timestamp,"ackto = %d s\n",ackto) ;
printmessage(stdout,CASE_NORMAL,0,timestamp,"recvcontrolto = %d s\n",recvcontrolto) ;
printmessage(stdout,CASE_NORMAL,0,timestamp,"sendcontrolto = %d s\n",sendcontrolto) ;
printmessage(stdout,CASE_NORMAL,0,timestamp,"datato = %d s\n",datato) ;
printmessage(stdout,CASE_NORMAL,0,timestamp,"option %s\n", ((transferoption & TROPT_DIR ) == TROPT_DIR) ? "createdir" : "nocreatedir") ;
printmessage(stdout,CASE_NORMAL,0,timestamp,"option %s\n", ((transferoption & TROPT_TMP ) == TROPT_TMP) ? "tmpfile" : "notmpfile") ;
printmessage(stdout,CASE_NORMAL,0,timestamp,"option %s\n", ((transferoption & TROPT_RFIO ) == TROPT_RFIO) ? "remoterfio" : "noremoterfio") ;
#if defined(WITH_RFIO) || defined(WITH_RFIO64)
printmessage(stdout,CASE_NORMAL,0,timestamp,"option %s\n", ((transferoption & TROPT_RFIO_O ) == TROPT_RFIO_O) ? "localrfio" : "nolocalrfio") ;
#endif
printmessage(stdout,CASE_NORMAL,0,timestamp,"option %s\n", ((transferoption & TROPT_MODE ) == TROPT_MODE) ? "keepmode" : "nokeepmode") ;
printmessage(stdout,CASE_NORMAL,0,timestamp,"option %s\n", ((transferoption & TROPT_ACC ) == TROPT_ACC) ? "keepaccess" : "nokeepaccess") ;
#ifdef WITH_GZIP
printmessage(stdout,CASE_NORMAL,0,timestamp,"option %s\n", ((transferoption & TROPT_GZIP ) == TROPT_GZIP) ? "gzip" : "nogzip") ;
#endif
printmessage(stdout,CASE_NORMAL,0,timestamp,"option %s\n", ((transferoption & TROPT_QBSS ) == TROPT_QBSS) ? "qbss" : "noqbss") ;
printmessage(stdout,CASE_NORMAL,0,timestamp,"-------------------------------------\n") ;
printmessage(stdout,CASE_NORMAL,0,timestamp,"Connection mode ---------------------\n") ;
if ( usecert ) {
/* if ( username == NULL ) {*/
printmessage(stdout,CASE_NORMAL,0,timestamp,"Using certificate authentication\n") ;
/* } else {
printmessage(stdout,CASE_NORMAL,0,timestamp,"Using standard bbftp mode\n") ;
}*/
} else if ( useprivate ) {
printmessage(stdout,CASE_NORMAL,0,timestamp,"Using private authentication\n") ;
} else if ( usessh) {
printmessage(stdout,CASE_NORMAL,0,timestamp,"Using ssh mode\n") ;
printmessage(stdout,CASE_NORMAL,0,timestamp," ssh command = %s \n",sshcmd) ;
printmessage(stdout,CASE_NORMAL,0,timestamp," ssh remote command = %s \n",sshremotecmd) ;
} else {
printmessage(stdout,CASE_NORMAL,0,timestamp,"Using standard bbftp mode\n",localumask) ;
}
printmessage(stdout,CASE_NORMAL,0,timestamp,"-------------------------------------\n") ;
}
/*
** Open the input file if needed
*/
if ( inputfile != NULL ) {
if ( (infd = open(inputfile,O_RDONLY)) < 0 ) {
printmessage(stderr,CASE_FATAL_ERROR,21,timestamp,"Error opening input file (%s) : %s\n",inputfile,strerror(errno)) ;
}
if ( (resfd = open(resultfile,O_CREAT|O_WRONLY|O_SYNC|O_TRUNC,0777)) < 0 ) {
printmessage(stderr,CASE_FATAL_ERROR,22,timestamp,"Error opening result file (%s) : %s\n",resultfile,strerror(errno)) ;
}
/*
** Now calc the max line of the input file in order to malloc
** the buffer
*/
maxlen = 0 ;
j = 0 ;
while ( (lengthread = read (infd,calcmaxline,1)) == 1 ) {
if ( calcmaxline[0] == 10 ) {
if ( j > maxlen ) {
maxlen = j ;
}
j = 0 ;
} else {
j++ ;
}
}
if ( lengthread < 0 ) {
printmessage(stderr,CASE_FATAL_ERROR,24,timestamp,"Error reading input file (%s) : %s\n",inputfile,strerror(errno)) ;
} else if ( lengthread == 0 ) {
if ( j > maxlen ) {
maxlen = j ;
}
}
/*
** Reset the file at start position
*/
lseek(infd,0,SEEK_SET) ;
if ( (buffercmd = (char *) malloc (maxlen+2) ) == NULL ) {
printmessage(stderr,CASE_FATAL_ERROR,23,timestamp,"Unable to malloc memory for command : %s\n",strerror(errno)) ;
}
} else {
if ( (buffercmd = (char *) malloc (strlen(bbftpcmd)+1)) == NULL ) {
printmessage(stderr,CASE_FATAL_ERROR,23,timestamp,"Unable to malloc memory for command : %s\n",strerror(errno)) ;
}
}
/*
** Ask for password if not in ssh mode
*/
#ifdef PRIVATE_AUTH
if ( bbftp_private_getargs(logmessage) < 0 ) {
printmessage(stderr,CASE_FATAL_ERROR,19,timestamp,"Error while private authentication : %s\n",logmessage) ;
}
#else
if ((!usessh && !usecert)/* || (usecert && username)*/) {
# ifdef AFS
char *reasonString, passwordBuffer[1024] ;
long code ;
if ( (code = ka_UserReadPassword("Password: ", passwordBuffer, sizeof(passwordBuffer), &reasonString)) ) {
printmessage(stderr,CASE_FATAL_ERROR,19,timestamp,"Error while entering password\n") ;
}
if ( ( password = (char *) malloc (strlen(passwordBuffer) + 1) ) == NULL ) {
printmessage(stderr,CASE_FATAL_ERROR,54,timestamp,"Unable to store password : malloc failed (%s)\n",strerror(errno)) ;
return -1 ;
}
strcpy(password, passwordBuffer);
# else
# ifdef USE_GETPASSPHRASE
password = (char *) getpassphrase("Password: ") ;
if ( strlen(password) == 0 ) {
printmessage(stderr,CASE_FATAL_ERROR,19,timestamp,"Password is mandatory\n") ;
}
# else
printmessage(stdout,CASE_NORMAL,0,0,"Password: ") ;
password = (char *) getpass("") ;
# endif /* USE_GETPASSPHRASE */
# endif /* AFS */
}
#endif
/*
** Set in background if required
*/
if ( background ) {
retcode = fork() ;
if ( retcode < 0 ) printmessage(stderr,CASE_FATAL_ERROR,31,timestamp,"Error forking while setting in background\n") ;
if ( retcode > 0 ) exit(0) ;
setsid() ;
if ( verbose ) printmessage(stdout,CASE_NORMAL,0,timestamp,"Starting under pid %d\n",getpid());
}
/*
** Set the signals
*/
bbftp_setsignals() ;
/*
** Now we've got all informations to make the connection
*/
if ( debug )
printmessage(stdout,CASE_NORMAL,0,timestamp,"Connecting to server ----------------\n",localumask) ;
reconnecttoserver() ;
if ( debug )
printmessage(stdout,CASE_NORMAL,0,timestamp,"Connecting end ---------------------\n",localumask) ;
/*
** Start the infinite loop
*/
maxlen = 0 ;
retcode = 0 ;
while (retcode == 0 ) {
if ( inputfile != NULL ) {
j = 0 ;
while ( (lengthread = read (infd,&buffercmd[j],1)) == 1 ) {
if ( buffercmd[j] == 10 ) {
buffercmd[j] = 0 ;
break ;
} else {
j++ ;
}
}
if ( lengthread < 0 ) {
printmessage(stderr,CASE_FATAL_ERROR,24,timestamp,"Error reading input file (%s) : %s\n",inputfile,strerror(errno)) ;
} else if ( lengthread == 0 ) {
if ( j == 0 ) {
retcode = 1 ;
break ;
} else {
buffercmd[j+1] = 0 ;
}
}
if ( treatcommand(buffercmd) == 0 ) {
write(resfd,buffercmd,strlen(buffercmd)) ;
write(resfd," OK\n",4) ;
} else {
write(resfd,buffercmd,strlen(buffercmd)) ;
write(resfd," FAILED\n",8) ;
}
} else {
/*
** the command may be under the form cmd ; cmd ; cmd....
*/
j = 0 ;
while ((maxlen < strlen(bbftpcmd)) && (bbftpcmd[maxlen] == ' ')) maxlen++ ;
while ( (maxlen < strlen(bbftpcmd)) && (bbftpcmd[maxlen] != ';') ) {
buffercmd[j] = bbftpcmd[maxlen] ;
j++ ;
maxlen++ ;
}
if ( maxlen == strlen(bbftpcmd) ) retcode = 1 ;
buffercmd[j] = 0 ;
if ( treatcommand(buffercmd) == 0 ) {
if (!verbose && !statoutput) printmessage(stdout,CASE_NORMAL,0,timestamp,"%s OK\n",buffercmd);
} else {
if (!verbose && !statoutput) printmessage(stdout,CASE_NORMAL,0,timestamp,"%s FAILED\n",buffercmd);
}
maxlen++ ;
}
}
if ( inputfile != NULL ) {
close(infd) ;
close(resfd) ;
}
msg = (struct message *)minbuffer ;
msg->code = MSG_CLOSE_CONN ;
msg->msglen = 0 ;
/*
** We do not care of the result because this routine is called
** only at the end of the client
*/
writemessage(outcontrolsock,minbuffer,MINMESSLEN,sendcontrolto,0) ;
sleep(1) ;
bbftp_close_control() ;
exit(myexitcode) ;
}
syntax highlighted by Code2HTML, v. 0.9.1