static char sccsid[] = "@(#)rfc2abap  	20.18.1.1	SAP	96/08/08";

/********************************************************************
 * Compiling: 
 *
 * -mapro -src BIN runt librfc.o                   (at SAP) 
 * -ar q librfc.a librfc.o                         (at SAP)
 * -cc rfc2abap.c -Aa -g -o rfc2abap -I. -L. -lrfc (API-USER)
 *
 *   (C) Copyright SAP AG 1994
 ********************************************************************/

/********************************************************************
*
*  ATTENTION: THIS MEMBER IS ONLY A SOFTWARE STUDY.    
*  THERE IS NO WARRANTY FOR PROPER FUNCTION! 
*
*********************************************************************/


#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>

#include "saprfc.h"
#include "sapitab.h"

#define  FUNCNAME     "RFC_ABAP_INSTALL_AND_RUN" 
#define  PROGRAMLEN   8 
#define  MESSAGELEN   50
#define  TAB_SIZE     72          /* length of PROGRAM     */
#define  LIST_SIZE    256         /* length of WRITES      */
#define  PARFILE      "rfc2abap.txt" /* name of parameterfile */
#define  BUFWID       40          /* no of argv entries    */
#define  BUFLEN       50          /* length of argv entries*/

/* rfc_error may not be static (because MS Windows cant export non statics */
void DLL_CALL_BACK_FUNCTION rfc_error( char * operation );

static void help( RFC_OPTIONS         * rfc_opt,
                  RFC_CONNOPT_R3ONLY  * connopt_r3only ); 

static int file2itab( ITAB_H itab_h, FILE * file );

static void parse_for_function(
		  char ** argv,
		  int argc,
		  char * file);

static unsigned ab_csize( char* addr,  int length);

static void     parfile_write( RFC_OPTIONS         * rfc_opt, 
                               RFC_CONNOPT_R3ONLY  * connopt_r3only,
			       FILE                * parfile );

static int  errorline;

static int f_option = 0;
static int p_option = 0;

FILE *                    file;
FILE *                    parfile;
static RFC_OPTIONS        rfc_opt;
static RFC_CONNOPT_R3ONLY sinfo;
static RFC_CONNOPT_CPIC   cinfo;
RFC_FUNCTIONNAME          func_nam; 
RFC_PARAMETER             in[3];
RFC_PARAMETER             out[4];
RFC_TABLE                 tab[3]; 
RFC_HANDLE                handle;
RFC_ENV                   rfc_env; 
char **                   exception_ptr = NULL;
char                      progname[PROGRAMLEN+1];
char                      mode[1];
char                      arglist[BUFWID][BUFLEN];
char *                    arglistptr[BUFWID];           
char                      err_message[MESSAGELEN]; 
char                      liste[LIST_SIZE];
char *                    listptr; 
int                       line, nr_of_lines, len;
ITAB_H                    program_tab; /* int. table PROGRAM */
ITAB_H                    list_tab;    /* int. table WRITES  */
int                       rc;


int main( int argc, char ** argv )
{

#ifdef SAPonApple
   MacInit(&argc, &argv);
#endif

   for ( rc = 0; rc < PROGRAMLEN; progname[rc++] = ' ' );
   progname[PROGRAMLEN] = '\0';

   memset( err_message, ' ', sizeof( err_message ) );
   memset( func_nam,      0, sizeof( func_nam ) );
   strcpy( func_nam, FUNCNAME); 

   /* some initializing */

   rfc_opt.destination = " ";
   rfc_opt.user     = " ";
   rfc_opt.connopt  = &sinfo;
   rfc_opt.mode     = RFC_MODE_R3ONLY;
   rfc_opt.client   = "000";
   rfc_opt.language = "E";
   rfc_opt.trace    = 0;

   sinfo.hostname         = " ";
   sinfo.gateway_host     = " ";
   sinfo.gateway_service  = " ";

   /* read parameters from file */

   parfile = fopen( PARFILE, "rt" );
   if ( parfile )
   {
     rc = 0; 
     while(   ( fgets(arglist[rc], BUFWID, parfile) != NULL ) 
	   && ( rc < BUFLEN ) )
     {
       len = strlen(arglist[rc]) - 1;
       arglist[rc][len] = '\0';
       arglistptr[rc] = arglist[rc]; 
       rc++;
     }
     *arglist[rc] = (char)NULL;    
     arglistptr[rc] = arglist[rc];
     RfcConnArgv( arglistptr, &rfc_opt, &cinfo ,&sinfo);
     rc = 0; 
   }

   if ( argc == 1 )  /* null arguments */ 
   { 
     help( &rfc_opt, &sinfo ); 
     exit(RFC_OK);
   }   
   if( argv[1] != NULL )
   {
     if( strcmp( argv[1], "-?" ) == 0 )
     {
       fprintf( stderr, "unknown option %s\n", argv[1] );
       help( &rfc_opt, &sinfo );
       exit(RFC_OK);
     }
   }

   /* 'progname' is the name of the unix file containing the ABAP source */

   parse_for_function( argv, argc, progname );

   if ( f_option == 1 )
   {
     file = fopen( progname, "rt" );

     if( file == NULL )
     { 
       char * ptr = strerror( errno );
       errorline = __LINE__;
       fprintf( stderr, "%s (%d)\n", ptr, errorline );
       exit( RFC_FAILURE );
     }
   }

   RfcConnArgv( argv, &rfc_opt, &cinfo ,&sinfo);

   parfile = fopen( PARFILE, "wt" );
   if ( parfile )
   {
     parfile_write( &rfc_opt, &sinfo, parfile ); 
   }
   
   handle = RfcOpen( &rfc_opt );

   if( handle == RFC_HANDLE_NULL )
   {
     fprintf( stderr, "Null connection to %s on %s \n",
					    rfc_opt.destination,
			 		    sinfo.hostname );
     exit(RFC_FAILURE);
   }
   else
   {
     fprintf( stdout, "Connected to %s \n",sinfo.hostname );
   }

   /* import parameters of function module in lib */

   program_tab = ItCreate( progname, TAB_SIZE,  0, 0 ); 
   list_tab    = ItCreate( "WRITES", LIST_SIZE, 0, 0 ); 

   if ( f_option == 1)
          rc = file2itab( program_tab, file );

   memset(out,0,sizeof(out));

   out[0].name = "PROGRAMNAME";
   out[0].nlen = 11;
   out[0].type = TYPC;
   out[0].addr = progname; 
   out[0].leng = PROGRAMLEN;

   out[1].name = "MODE";
   out[1].nlen = 4;
   out[1].type = TYPC;

   if ( p_option == 1 )    mode[0]  = 'P';  /* program exists */
   if ( f_option == 1 )    mode[0]  = 'F';

   out[1].addr = mode; 
   out[1].leng = 1;

   out[2].name = NULL;

   /* Exporting parameters of function module */

   in[0].name = "ERRORMESSAGE";
   in[0].nlen = 12;
   in[0].type = TYPC;
   in[0].addr = err_message; 
   in[0].leng = sizeof( err_message );

   in[1].name = NULL;
  
   /* table with ABAP source */

   tab[0].name = "PROGRAM";
   tab[0].nlen = 7;
   tab[0].type = TYPC;
   tab[0].ithandle = program_tab;
   tab[0].leng = TAB_SIZE;

  /* and table with the results */

   tab[1].name = "WRITES";
   tab[1].nlen = 6;
   tab[1].type = TYPC;
   tab[1].ithandle = list_tab;
   tab[1].leng = LIST_SIZE;

   tab[2].name = NULL;
   tab[2].ithandle = ITAB_NULL;

   rfc_env.allocate = NULL;
   rfc_env.errorhandler  = rfc_error;

   RfcEnvironment ( &rfc_env );

   RfcCallReceive( handle,
                   func_nam,
                   out,
                   in,
                   tab,
                   exception_ptr );

   if( exception_ptr != NULL )
     fprintf( stderr, "%s\n", *exception_ptr );  
   for ( rc = 0; rc < MESSAGELEN; rc ++ )
   {
      if ( err_message[rc] != ' ' )                /* not initial */
      {
         fprintf( stderr, ">> Syntax Error: %s\n",err_message );
         RfcClose( handle );
         exit (RFC_EXCEPTION);
      }
   }

 /* print table WRITES */

   nr_of_lines = ItFill( list_tab );
   for ( line=1; line <= nr_of_lines; line++)
   {
     listptr = (char *) ItGetLine( list_tab, line );
     len = ab_csize( listptr, LIST_SIZE); /* -->STRLEN in ABAP */ 
     memcpy( liste, (char *) ItGetLine( list_tab, line ), len);
     liste[len] = '\0'; 
	 /* no trailing SPACES will be shown */
     fprintf( stdout, "%s\n", liste );
   }

   RfcClose( handle );
   return 0;

}/* main() */


static int file2itab( ITAB_H itab_h, FILE * file )
{
   int    l = ItLeng( itab_h );
   char   buffer[256];

   for(;;)
   {
     char * p;
     int    read_l;

     p = fgets( buffer, sizeof(buffer), file );
     if( p == NULL )
     {
	if( ferror( file ) )
	{
	   errorline = __LINE__;
	   return 1;
	}
	else
	{
	   return 0;
	}
     }
     read_l = strlen(p);
     if( p[read_l - 1] == '\n' ) read_l--;
     if( read_l > l ) read_l = l;
     p = (char *) ItAppLine( itab_h );
     if( p == NULL )
     {
	errorline = __LINE__;
	return  2;
     }
     if( read_l < l )
     {
       memcpy( p, buffer, read_l );
       memset( p + read_l, ' ', l - read_l );
     }
     else
     {
       memcpy( p, buffer, l );
     }
   }
} /* file2itab */


void DLL_CALL_BACK_FUNCTION rfc_error( char * operation )
{
   RFC_ERROR_INFO error_info;
   fprintf( stderr, "RFC error : operation/code %s\n", operation );
   memset( &error_info, 0, sizeof( error_info ) );
   RfcLastError( &error_info );
   fprintf( stderr, "Error info :\n" );
   fprintf( stderr, "key     : %s\n", error_info.key );
   fprintf( stderr, "status  : %s\n", error_info.status );
   fprintf( stderr, "message : %s\n", error_info.message );
   fprintf( stderr, "internal: %s\n", error_info.intstat );
   RfcClose( RFC_HANDLE_NULL );
   exit( RFC_FAILURE );
} /* rfc_error */


static void help( RFC_OPTIONS         * rfc_opt,
                  RFC_CONNOPT_R3ONLY  * connopt_r3only) 
{

#define NL "\n"
#define BL fprintf(stdout,   

 BL NL);

 BL"ABAP/4 EXECUTE                                       "   NL
   "Syntax : rfc2abap [connect options] <func options>   "   NL 
   "                                                     "   NL
   "connect options =                                    "   NL      );
                                                                  
 BL"      -d <destination>     %s\n", rfc_opt->destination           );
 BL"      -u <userid>          %s\n", rfc_opt->user                  ); 
 BL"      -p <password>        ...  \n"                              );
 BL"      -c <client>          %s\n", rfc_opt->client                );
 BL"      -l <language>        %s\n", rfc_opt->language              ); 
 BL"      -t <Trace>           %d\n", rfc_opt->trace                 ); 
 BL"      -h <hostname>        %s\n", connopt_r3only->hostname       ); 
 BL"      -s <system number>   %d\n", connopt_r3only->sysnr          ); 
 BL"      -g <gateway host>    %s\n", connopt_r3only->gateway_host   ); 
 BL"      -x <gateway service> %s\n", connopt_r3only->gateway_service);
 BL"      -?                   this text                 "   NL  NL
 "func options =                                         "   NL  
 "      -f <file with abapsource>                        "   NL
 "      -r <available program on SAP R/3>                "   NL  NL
 "For the following calls the connect options may be ommited."   NL  );
   return;
} /* help */


static void parse_for_function( char ** argv,
				int     argc,
				char *  file) 
{
 int i;
 while (--argc)
 {
   if( strcmp( argv[argc],"-f" ) == 0 )
   {
      f_option = 1; p_option = 0; 
      strncpy( file, argv[argc + 1], PROGRAMLEN );
      file[PROGRAMLEN] = '\0';
   }

   if( strcmp( argv[argc],"-r" ) == 0 )
   {
      f_option = 0; p_option = 1; 
      strcpy( file, argv[argc + 1] );
	  /* fill the rest with blanks */
      for( i=strlen(file); i<PROGRAMLEN; file[i]=' ', i++ ); 
   }
 }
 if ( f_option == 0 && p_option == 0 )
 {
   fprintf(stderr, ">> Error: no program or file entered !\n");
   exit(1);
 }
 
 if ( f_option == 1 && p_option == 1 )
 {
   fprintf(stderr, ">> Error: program and file entered !\n");
   exit(1);
 }
return;
} /* parse_for_function */


static unsigned ab_csize ( char* addr,  int length)
{
     register char * ptr = addr + length;
     while( ptr > addr )
     {
       if( *(--ptr) != ' ' )
	return (unsigned) (long) ( ++ptr - addr );
     }      	
     return 0;
} /* ab_csize */


static void     parfile_write( RFC_OPTIONS         * rfc_opt, 
                               RFC_CONNOPT_R3ONLY  * connopt_r3only,
			       FILE * parfile )
{ 
  char buf[20];

  if (rfc_opt->destination != NULL)
  {
    fputs( "-d\n", parfile );
    fputs( rfc_opt->destination, parfile);
    fputs( "\n", parfile );
  }
  if (rfc_opt->user != NULL)
  {
    fputs( "-u\n", parfile );
    fputs( rfc_opt->user, parfile);
    fputs( "\n", parfile );
  }
  if (rfc_opt->password != NULL)
  {
    fputs( "-p\n", parfile );
    fputs( rfc_opt->password , parfile );
    fputs( "\n", parfile );
  }
  if (rfc_opt->client != NULL)
  {
    fputs( "-c\n", parfile );
    fputs( rfc_opt->client, parfile);
    fputs( "\n", parfile );
  }
  if (rfc_opt->language != NULL)
  {
    fputs( "-l\n", parfile );
    fputs( rfc_opt->language, parfile);
    fputs( "\n", parfile );
  }
  if (connopt_r3only->hostname != NULL)
  {
    fputs( "-h\n", parfile );
    fputs( connopt_r3only->hostname, parfile);
    fputs( "\n", parfile );
  }

  fputs( "-s\n", parfile );
  sprintf( buf, "%d\n", connopt_r3only->sysnr );
  fputs( buf, parfile);

  if (connopt_r3only->gateway_host != NULL)
  {
    fputs( "-g\n", parfile );
    fputs( connopt_r3only->gateway_host, parfile);
    fputs( "\n", parfile );
  }
  if (connopt_r3only->gateway_service != NULL)
  {
    fputs( "-x\n", parfile );
    fputs( connopt_r3only->gateway_service, parfile);
    fputs( "\n", parfile );
  }
} /* parfile_write */

