static char const rcsid[] =
"@(#)$Id: swbsdftp.c,v 1.3 2000/06/25 04:49:46 jgibbons Exp $";

/*
**               Copyright (c) 2000 Relcast Engineering
**                       All rights reserved.
**
** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions
** are met:
**
** 1. Redistributions of source code must retain the above copyright
**    notice, this list of conditions and the following disclaimer.
** 2. Redistributions in binary form must reproduce the above copyright
**    notice, this list of conditions and the following disclaimer in the
**    documentation and/or other materials provided with the distribution.
**
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
** ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
** SUCH DAMAGE.
*/

/****************************************************************************
*
*  FILE:         swbsdftp.c
*
*  DESCRIPTION:  This file implements an example external program for use
*                with the Message Switch, as configured by the "prog:" keyword
*                in switch.cfg.  This program sends all the data it receives
*                from the Message Switch to an FTP server, creating a sequence
*                of files in a specified directory there.  The filenames
*                are of a form specified in argument 6, which is expected to
*                contain a string with a "printf"-style formatting code
*                embedded in it; that code will be transformed into a sequence
*                of increasing digits, so that each filename is unique.
*                For example, a 6th argument of "ftp%d" would result in a
*                sequence of filenames "ftp1", "ftp2", "ftp3", etc.
*
*                To specify this program as an endpoint for switch
*                specifications in the switch.cfg Message Switch configuration
*                file, the endpoint should have a format like this:
*
*                prog:swbsdftp~192.168.135.22~anonymous~jgibbons~incoming~ftp%d
*
*                The first argument (the file descriptor of the pipe, which
*                is immediately after the swbsdftp program name in the call to
*                this program) is not included in the endpoint specification
*                because it is inserted by the Message Switch.
*
*  CALLING SEQUENCE:
*                arg0: swbsdftp
*                arg1: the file descriptor of a pipe which connects to the
*                      Message Switch.
*                arg2: IP address of an FTP server
*                arg3: Login name on FTP server
*                arg4: password on FTP server
*                arg5: directory on FTP server
*                arg6: destination base filename on FTP server (this basename
*                      should contain a "%d" or "%x" formatting specifier)
*
*  REVISION HISTORY:
*
*   Date      Programmer     Description
*  -------   ------------   ---------------
*  09jun00   Jeff Gibbons   Original creation.
*
*****************************************************************************/

                                               /* Include files              */
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/time.h>
#include <string.h>
#include <ftpio.h>
 
                                               /* Defines                    */
#define OK 0
  
                                               /* Typedefs                   */
                                               /* Global Data                */
unsigned char rcv_message[ 16384 ];

                                               /* Local Function Prototypes  */
                                               /* Local Static Data          */
                                               /* Extern Data Declarations   */
                                               /* Extern Function Prototypes */
                                               /* Function Definitions       */

/****************************************************************************
*
*  PROGRAM:      main.c
*
*  DESCRIPTION:  Main entry point for the swbsdftp program.
*
*  CALLING SEQUENCE:   described above in file header.
*
*  REVISION HISTORY:
*
*   Date      Programmer     Description
*  -------   ------------   ---------------
*  09jun00   Jeff Gibbons   Original creation.
*  21jun00   Jeff Gibbons   Modified to use new pipe method of communication
*                           with Message Switch, rather than socket.
*
*****************************************************************************/

int
main( int argc, char **argv )
{
   int       iTotSize;
   int       iFd;
   int       iResult;
   char      clientFileName[ 256 ];
   int       clientFileIndex = 0;
   FILE     *pFtpCtrl;
   FILE     *pFtpFile;
   fd_set    sReadFds;

   if ( argc < 7 )
   {
      printf( "swbsdftp: called incorrectly: calling sequence should be:\n" );
      printf( "    swbsdftp \"filedescriptor\" \"machine\""
                            " \"username\"  \"password\"  \"directory\""
                            " \"basefilename\"\n" );
      exit( 1 );
   }
#ifdef DEBUG
   else
   {
      int  ii;
      printf( "swbsdftp debug: Initializing with these arguments:\n" );
      for ( ii = 0; ii < argc; ii++ )
         printf( "  arg%d: %s.\n", ii, argv[ii] );
      printf( "\n" );
   }
#endif

   iFd = atoi( argv[ 1 ] );
   FD_ZERO( &sReadFds );

   while ( 1 )
   {
      clientFileIndex++;
      clientFileIndex %= 1000000000;
      /*
      ** The filename argument in switch.cfg should be of the form:
      ** "file%d.ftp"  ( this program will replace the "%d" with an increasing
      ** sequence of digits, so each new ftp'ed file has a unique name ).
      */
      sprintf( clientFileName, argv[ 6 ], clientFileIndex );
      /* printf( "swbsdftp debug: writing to file: %s\n", clientFileName ); */
   
      pFtpCtrl = pFtpFile = NULL;

      FD_SET( iFd, &sReadFds );
      select( iFd + 1, &sReadFds, NULL, NULL, NULL );
      if ( 0 > ( iTotSize = read( iFd, &rcv_message, sizeof(rcv_message) ) ) )
      {
         perror( "\nERROR: swbsdftp failed reading pipe: " );
         printf( "swbsdftp: failed reading Message Switch pipe, errno %d.\n",
                 errno );
         printf( "swbsdftp:   for machine:   %s\n", argv[2] );
         printf( "swbsdftp:       username:  %s\n", argv[3] );
                                                   /* don't display password */
      /* printf( "swbsdftp:       password:  %s\n", argv[4] ); */
         printf( "swbsdftp:       directory: %s\n", argv[5] );
         printf( "swbsdftp:       basefile:  %s\n", argv[6] );
      }
      else if ( NULL == ( pFtpCtrl = ftpLogin( argv[2],
                                               argv[3],
                                               argv[4],
                                               0, 0, &iResult ) ) )
      {
         printf(
               "swbsdftp: unable to login to %s with username %s, error %d.\n",
                 argv[2], argv[3], iResult );
      }
      else if ( OK != ( iResult = ftpChdir( pFtpCtrl, argv[5] ) ) )
      {
         printf( "swbsdftp: FTP chdir to ftp://%s/%s returned error %d:\n",
                 argv[2], argv[5], iResult );
         printf( "   %s\n", ftpErrString( iResult )  );
      }
      else if ( OK != ( iResult = ftpAscii( pFtpCtrl ) ) )
      {
         printf( 
         "swbsdftp: unable to set ftp mode to ASCII on %s, error %d:\n   %s\n",
                      argv[2], iResult, ftpErrString( iResult ) );
      }
      else if ( NULL == ( pFtpFile = ftpPut( pFtpCtrl, clientFileName ) ) )
      {
         printf( "swbsdftp: STORE cmd on ftp://%s/%s/%s failed.\n",
                 argv[2], argv[5], clientFileName                   );
      }
      else
      {
         fwrite( rcv_message, sizeof( char ), iTotSize, pFtpFile );
      }
      if ( NULL != pFtpFile )
         fclose( pFtpFile );
      if ( NULL != pFtpCtrl )
         fclose( pFtpCtrl );
   }

   close(iFd);
   exit(0);
}