
/**********************************************************************/
/*                                                                    */
/* Copyright (c) 2001 by Sun Microsystems, Inc.                       */
/* All rights reserved.                                               */
/*                                                                    */
/**********************************************************************/



/* $Date:   06 Nov 2002 17:26:56  $ */
/* $Modtime:   06 Nov 2002 15:49:12  $ */

#ifndef	lint
#ifdef __STDC__
const
#endif
static char sccsid[] = "@(#) $Workfile:   fsusrexit.c  $ $Revision:   1.0.1.0  $";
#endif

/*
 * $Log:   /CSO/pd134126/MBM920p4/unikixebm/ebmsrc/rtsfs/PVCS/fsusrexit.c_v  $
 * 
 *    Rev 1.0.1.0   06 Nov 2002 17:26:56   pd134126
 * B4735071
 * BT=4735071 insure KIX-SIT-DB-NAME is set for rtsfs kxsysinfo call
 * 
 *    Rev 1.0   18 Sep 2001 13:54:06   unikix
 * Initial 9.2
 * 
 *    Rev 1.0   31 Jan 2000 15:34:56   unikix
 * Initial 9.0
 * 
 *    Rev 1.7   11/07/97 10:19:28   unikix
 * B2590
 * Updated which usrname/usrpasswd fields were being updated to
 * allow default values for RDBMS_USRNAME(PASSWD)
 * 
 *    Rev 1.6   11/06/97 15:51:44   giulio
 * B2590
 * changed the way rdbms field are populated.
 * RDBM_CONNECT is still the only mandatory parameter.
 * The parameters SRVNAME and DBNAME are set if the variable is set
 * otherwise defaults to blank.
 * The parameters USRNAME and PSWNAME are set if the variable is set
 * otherwise defaults to the CONNECT value.
 * 
 *    Rev 1.5   07/18/97 10:15:40   prabha
 * Changed kxsysinfo function to padd with TRANS SIT information.
 * For now, RTS_RDBMS values are poppulated into relevent fields
 * to support RDBMS modules from unikix.
 * 
 *    Rev 1.4   10/25/96 16:22:06   giulio
 * updated for DB2/6000
 * 
 *    Rev 1.3   10/25/96 10:18:14   giulio
 * B001732 changed RDBMS_CONNECT message
 * 
 *    Rev 1.2   10/25/96 08:45:12   giulio
 * B001732 B001733 B001734
 * Sybase wants space terminated field for the connect login-id and passwd
 * 
 *    Rev 1.1   10/24/96 11:30:26   giulio
 * B001732
 * B001733
 * B001734
 * rtsfs uses now the usr exit function defined under unikixcom/src/usrsrc
 * rtsfs supports now CA-DATACOM, Sybase and DB26000
 * the user does not have to change the SQL CONNECT statement to specify 
 * the login id name or the database name. 
 * A new variable must be set RDBMS_CONNECT
 * with the name to be used in the SQL CONNECT statement.
 * 
 *    Rev 1.0   08/16/96 15:02:00   unikix
 * Initial EBM8.1.0.0
 * 
 *    Rev 1.1   11/13/95 10:51:00   ranad
 * B001214
 * moved cobinit check to kxusr_allocate and fsusr_allocate
 * 
 *    Rev 1.0   08/15/95 09:29:40   ranad
 * Initial revision.
 */
/**********************************************************************/
/************************************************************************/
/*    User exit module to accomodate external access methods such       */
/*    as Oracle, Informix, Ingres, etc...                               */
/*    User exit calls currently supported are:                          */
/*                                                                      */
/*      1. Allocate/open                                                */
/*      2. Deallocate/close                                             */
/*      3. Commit                                                       */
/*      4. Rollback                                                     */

/*    An environment variable, RTS_RDBMS, is initialized to allow       */
/*    the user exit functions to make logic choices based on a          */
/*    particular application.                                           */

/*    Once the user exit functions are coded, the inst_rtsfs command    */
/*    must be executed.                                                 */
/************************************************************************/

#include <stdio.h>
extern char rts_rdbms[];
#ifdef SYBASE10
#ifdef AIX
#include <sys/types.h>
#ifndef RS6v41
#include <errno.h>
#endif  /*  RS6v41 condition */
#endif  /*  RS6000 condition */
#endif  /*  SYBASE10 condition */


/************************************************************************/
/*  Define user functions prototypes ORACLE, INFORMIX, INGRES etc.      */
/*  These names can be changed if necessary or desired                  */
/************************************************************************/

#ifdef ORACLE
#define ORACLE_AM 1
static int oracle_allocate();
static int oracle_deallocate();
static int oracle_commit();
static int oracle_rollback();
#else
#define ORACLE_AM 0
#endif

#ifdef INFORMIX
#define INFORMIX_AM 1
static int informix_allocate();
static int informix_deallocate();
static int informix_commit();
static int informix_rollback();
#else
#define INFORMIX_AM 0
#endif

#ifdef SYBASE
#define SYBASE_AM 1
static int sybase_allocate();
static int sybase_deallocate();
static int sybase_commit();
static int sybase_rollback();
#else
#define SYBASE_AM 0
#endif

#ifdef DBTWO
#define DBTWO_AM 1
static int  dbtwo_allocate();
static int  dbtwo_deallocate();
static int  dbtwo_commit();
static int  dbtwo_rollback();
#else
#define  DBTWO_AM 0
#endif

#ifdef DATACOM
#define DATACOM_AM 1
static int  datacom_allocate();
static int  datacom_deallocate();
static int  datacom_commit();
static int  datacom_rollback();
#else
#define  DATACOM_AM 0
#endif

#ifdef INGRES
#define INGRES_AM 1
static int ingres_allocate();
static int ingres_deallocate();
static int ingres_commit();
static int ingres_rollback();
#else
#define INGRES_AM 0
#endif
static int dummy_function();

/************************************************************************/
/*  Calclulate the maximum number of access methods.                    */
/************************************************************************/

#define MAX_AM ORACLE_AM + \
               INFORMIX_AM + \
               INGRES_AM + \
               SYBASE_AM + \
               DBTWO_AM + \
               DATACOM_AM

/************************************************************************/
/*  Define the prototype structure for pointers to user functions       */
/*  DO NOT CHANGE                                                       */
/************************************************************************/

struct user_exits {
  int (*user_allocate)();
  int (*user_deallocate)();
  int (*user_commit)();
  int (*user_rollback)();
};

/****************************************************************************/
/*  Define the occurrences of access method user exits and                  */
/*  initialize the prototype ORACLE,INFORMIX,INGRES,etc. function addresses */
/*  Functions must be initialized in the order as defined in the            */
/*  'user_exits' prototype; i.e. allocate, deallocate, commit, rollback     */
/****************************************************************************/

struct user_exits fsexits[MAX_AM+1] = {
#ifdef ORACLE
     oracle_allocate,
     oracle_deallocate,
     oracle_commit,
     oracle_rollback,
#endif
#ifdef INFORMIX
     informix_allocate,
     informix_deallocate,
     informix_commit,
     informix_rollback,
#endif
#ifdef SYBASE
     sybase_allocate,
     sybase_deallocate,
     sybase_commit,
     sybase_rollback,
#endif
#ifdef DBTWO
    dbtwo_allocate,
    dbtwo_deallocate,
    dbtwo_commit,
    dbtwo_rollback,
#endif
#ifdef DATACOM
    datacom_allocate,
    datacom_deallocate,
    datacom_commit,
    datacom_rollback,
#endif
#ifdef INGRES
     ingres_allocate,
     ingres_deallocate,
     ingres_commit,
     ingres_rollback,
#endif
/************************************************************************/
/*  Do not remove the following function definition, it is required to  */
/*  satisfy C syntax.                                                   */
/************************************************************************/
     dummy_function
     };

static int i;
static int rcode;
static int errind;

/************************************************************************/
/*                                                                      */
/*   The following code is specific to the support of Oracle databases. */
/*   The routines called by the functions below can be found in the     */
/*   FSORACLE.pco source.                                               */
/*                                                                      */
/************************************************************************/

#ifdef ORACLE
/********************************************************************/
/*     ORACLE          allocate/open function                       */
/********************************************************************/

static int oracle_allocate() {
   if (strcmp(rts_rdbms,"ORA_APPL") == 0) {
      return(KXORALGN());
   }
return(0);
}

/********************************************************************/
/*     ORACLE          deallocate/close function                    */
/********************************************************************/

static int oracle_deallocate() {
   if (strcmp(rts_rdbms,"ORA_APPL") == 0) {
      return(KXORALGF());
   }
return(0);
}

/********************************************************************/
/*     ORACLE          commit function                              */
/********************************************************************/

static int oracle_commit() {
   if (strcmp(rts_rdbms,"ORA_APPL") == 0) {
      return(KXORASAVE());
   }
return(0);
}

/********************************************************************/
/*     ORACLE          rollback function                            */
/********************************************************************/

static int oracle_rollback() {
   if (strcmp(rts_rdbms,"ORA_APPL") == 0) {
      return(KXORAUNDO());
   }
return(0);
}

#endif           /* End Oracle code */

/************************************************************************/
/*                                                                      */
/*   The following code is specific to the support of Informix databases*/
/*   The routines called by the functions below can be found in the     */
/*   FSINFSRV.eco source.                                               */
/*                                                                      */
/************************************************************************/

#ifdef INFORMIX

/********************************************************************/
/*     INFORMIX        allocate/open function                       */
/********************************************************************/

static int informix_allocate() {
   if (strcmp(rts_rdbms,"INF_APPL") == 0) {
      return(KXINFLGN());
   }
return(0);
}

/********************************************************************/
/*     INFORMIX        deallocate/close function                    */
/********************************************************************/

static int informix_deallocate() {
   if (strcmp(rts_rdbms,"INF_APPL") == 0) {
      return(KXINFLGF());
   }
return(0);
}


/********************************************************************/
/*     INFORMIX        commit function                              */
/********************************************************************/

static int informix_commit() {
   if (strcmp(rts_rdbms,"INF_APPL") == 0) {
      return(KXINFCOM());
   }
return(0);
}

/********************************************************************/
/*     INFORMIX        rollback function                            */
/********************************************************************/

static int informix_rollback() {
   if (strcmp(rts_rdbms,"INF_APPL") == 0) {
      return(KXINFROL());
   }
return(0);
}

#endif              /* End Informix code */

/************************************************************************/
/*                                                                      */
/*   The following code is specific to the support of Sybase databases  */
/*   The routines called by the functions below can be found in the     */
/*   KXSYBASE.cop.                                                      */
/************************************************************************/

#ifdef SYBASE

/********************************************************************/
/*     SYBASE        allocate/open function                         */
/********************************************************************/

static int sybase_allocate() {
/*----------------------------------------------------------------------*/
/* RS6000 and SYBASE10 specific for changing process group id           */
/*----------------------------------------------------------------------*/
#ifdef SYBASE10
#ifdef AIX
 int lrc;
 pid_t l_pgid;

 l_pgid = getpid();
 lrc    = setpgid(l_pgid, l_pgid);
 if (lrc != 0)
    {
    printf("rtsfs: Error setpgid() returns - errno %d, returncode %d\n",errno,lrc);
    return(-1);
    }
#endif  /*  AIX condition */
#endif  /*  SYBASE10 condition */
/*----------------------------------------------------------------------*/
   if (strcmp(rts_rdbms,"SYB_APPL") == 0) {
      return(KXSYBLGN());
   }
return(0);
}

/********************************************************************/
/*     SYBASE        deallocate/close function                      */
/********************************************************************/

static int sybase_deallocate() {
   if (strcmp(rts_rdbms,"SYB_APPL") == 0) {
      return(KXSYBLGF());
   }
return(0);
}

/********************************************************************/
/*     SYBASE        commit function                                */
/********************************************************************/

static int sybase_commit() {
   if (strcmp(rts_rdbms,"SYB_APPL") == 0) {
      return(KXSYBSAVE());
   }
return(0);
}

/********************************************************************/
/*     SYBASE        rollback function                              */
/********************************************************************/

static int sybase_rollback() {
   if (strcmp(rts_rdbms,"SYB_APPL") == 0) {
      return(KXSYBUNDO());
   }
return(0);
}

#endif              /* End Sybase code */

/************************************************************************/
/*                                                                      */
/*   The following code is specific to the support of Ingres databases  */
/*   The routines called by the functions below can be found in the     */
/*   KXDATACOM.dco.                                                      */
/************************************************************************/

#ifdef DATACOM

/********************************************************************/
/*     DATACOM        allocate/open function                         */
/********************************************************************/

static int datacom_allocate() {
   if (strcmp(rts_rdbms,"DAT_APPL") == 0) {
      return(KXDCOMLGN());
   }
return(0);
}

/********************************************************************/
/*     DATACOM        deallocate/close function                      */
/********************************************************************/

static int datacom_deallocate() {
   if (strcmp(rts_rdbms,"DAT_APPL") == 0) {
      return(KXDCOMLGF());
   }
return(0);
}

/********************************************************************/
/*     DATACOM        commit function                                */
/********************************************************************/

static int datacom_commit() {
   if (strcmp(rts_rdbms,"DAT_APPL") == 0) {
      return(KXDCOMSAVE());
   }
return(0);
}

/********************************************************************/
/*     DATACOM        rollback function                              */
/********************************************************************/

static int datacom_rollback() {
   if (strcmp(rts_rdbms,"DAT_APPL") == 0) {
      return(KXDCOMUNDO());
   }
return(0);
}

#endif              /* End Datacom code */

/************************************************************************/
/*                                                                      */
/*   The following code is specific to the support of Ingres databases  */
/*   The routines called by the functions below can be found in the     */
/*   KXDB2.cbl.                                                      */
/************************************************************************/

#ifdef DBTWO

/********************************************************************/
/*     DB26000        allocate/open function                         */
/********************************************************************/

static int dbtwo_allocate() {
   if (strcmp(rts_rdbms,"DB2_APPL") == 0) {
      return(KXDB2LGN());
   }
return(0);
}

/********************************************************************/
/*     DB26000        deallocate/close function                      */
/********************************************************************/

static int dbtwo_deallocate() {
   if (strcmp(rts_rdbms,"DB2_APPL") == 0) {
      return(KXDB2LGF());
   }
return(0);
}

/********************************************************************/
/*     DB26000        commit function                                */
/********************************************************************/

static int dbtwo_commit() {
   if (strcmp(rts_rdbms,"DB2_APPL") == 0) {
      return(KXDB2SAVE());
   }
return(0);
}

/********************************************************************/
/*     DB26000        rollback function                              */
/********************************************************************/

static int dbtwo_rollback() {
   if (strcmp(rts_rdbms,"DB2_APPL") == 0) {
      return(KXDB2UNDO());
   }
return(0);
}

#endif              /* End db26000 code */

/************************************************************************/
/*                                                                      */
/*   The following code is specific to the support of Ingres databases  */
/*   The routines called by the functions below can be found in the     */
/*   FSINGRES.scb.                                                      */
/************************************************************************/

#ifdef INGRES

/********************************************************************/
/*     INGRES        allocate/open function                         */
/********************************************************************/

static int ingres_allocate() {
   if (strcmp(rts_rdbms,"ING_APPL") == 0) {
      return(KXINGLGN());
   }
return(0);
}

/********************************************************************/
/*     INGRES        deallocate/close function                      */
/********************************************************************/

static int ingres_deallocate() {
   if (strcmp(rts_rdbms,"ING_APPL") == 0) {
      return(KXINGLGF());
   }
return(0);
}

/********************************************************************/
/*     INGRES        commit function                                */
/********************************************************************/

static int ingres_commit() {
   if (strcmp(rts_rdbms,"ING_APPL") == 0) {
      return(KXINGSAVE());
   }
return(0);
}

/********************************************************************/
/*     INGRES        rollback function                              */
/********************************************************************/

static int ingres_rollback() {
   if (strcmp(rts_rdbms,"ING_APPL") == 0) {
      return(KXINGUNDO());
   }
return(0);
}

#endif              /* End Ingres code */

/********************************************************************/
/*                                                                  */
/*  The following code is the interface code between the user exit  */
/*  module and the transaction or batch processor.                  */
/*                                                                  */
/*  It should not be necessary to change this code, but if you      */
/*  do then be very careful.                                        */
/*                                                                  */
/********************************************************************/

/*  Entry points called by the BATCH system - DO NOT CHANGE           */

extern int fsuser_allocate();
extern int fsuser_deallocate();
extern int fsuser_commit();
extern int fsuser_rollback();
static int dummy_function() {}
/********************************************************************/
/*  entry point for user ALLOCATE/OPEN function. For each access    */
/*  method in the table, the designated allocate/open function will */
/*  be executed                                                     */
/********************************************************************/

int fsuser_allocate() {

#ifdef AIXMF32
      cobinit();
#endif

errind = 0;
	for (i=0; i < MAX_AM; i++) {
	    if (fsexits[i].user_allocate != NULL) {
	       rcode = fsexits[i].user_allocate();
	       if (rcode) {
		  errind = rcode;
	       }
	    }
	}
	return(errind);
}

/********************************************************************/
/*  entry point for user DEALLOCATE/CLOSE function. For each access */
/*  method in the table, the designated deallocate/close function   */
/*  will be executed                                                */
/********************************************************************/

int fsuser_deallocate() {
errind = 0;
	for (i=0; i < MAX_AM; i++) {
	    if (fsexits[i].user_deallocate != NULL) {
	       rcode = fsexits[i].user_deallocate();
	       if (rcode) {
		  errind = rcode;
	       }
	    }
	}
	return(errind);
}


/********************************************************************/
/*  entry point for user COMMIT   function. For each access         */
/*  method in the table, the designated commit function will        */
/*  be executed                                                     */
/********************************************************************/

int fsuser_commit() {
errind = 0;

	for (i=0; i < MAX_AM; i++) {
	    if (fsexits[i].user_commit != NULL) {
	       rcode = fsexits[i].user_commit();
	       if (rcode) {
		  errind = rcode;
	       }
	    }
	}
	return(errind);
}

/********************************************************************/
/*  entry point for user ROLLBACK function. For each access         */
/*  method in the table, the designated rollback function will      */
/*  be executed                                                     */
/********************************************************************/

int fsuser_rollback() {
errind = 0;
	for (i=0; i < MAX_AM; i++) {
	    if (fsexits[i].user_rollback != NULL) {
	       rcode = fsexits[i].user_rollback();
	       if (rcode) {
          errind = rcode;
	       }
	    }
	}
	return(errind);
}

static struct lsyspar {
	char    cur_sysname [8];
	char    cur_svrname [8]; /* Case 2240 */
	char    cur_dbname  [8]; /* Case 2240 */
	char    cur_usrname [8]; /* Case 2240 */
	char    cur_usrpass [8]; /* Case 2240 */
	char    cur_tranidx [3];
} lsyspar;

#define MAX_APPL_LENGTH 8
static char rdbms_connect[ MAX_APPL_LENGTH + 1 ];
static char rdbms_svrname[ MAX_APPL_LENGTH + 1 ]; /* Case 2240 */
static char rdbms_dbname [ MAX_APPL_LENGTH + 1 ]; /* Case 2240 */
static char rdbms_usrname[ MAX_APPL_LENGTH + 1 ]; /* Case 2240 */
static char rdbms_usrpass[ MAX_APPL_LENGTH + 1 ]; /* Case 2240 */

int kxsysinfo(papplnam)
struct lsyspar *papplnam;             /* application name for user exit use*/
{
	char pidxnum[3];
	char *test_appl;

 memset(rdbms_connect,' ',sizeof(rdbms_connect));
 memset(rdbms_svrname,' ',sizeof(rdbms_svrname)); /* Case 2240 */
 memset(rdbms_dbname ,' ',sizeof(rdbms_dbname )); /* Case 2240 */
 memset(rdbms_usrname,' ',sizeof(rdbms_usrname)); /* Case 2240 */
 memset(rdbms_usrpass,' ',sizeof(rdbms_usrpass)); /* Case 2240 */
	if((test_appl=(char *)getenv("RDBMS_CONNECT"))!=NULL) 
	   {
	   if(strlen(test_appl) > MAX_APPL_LENGTH) 
	     {
	     printf("rtsfs: The length of the specified RDBMS_CONNECT=%s application name exceeds %d chars\n",test_appl,MAX_APPL_LENGTH);
	     strncpy(rdbms_connect,"        ",MAX_APPL_LENGTH);
             } 
	   else 
	     {
	     strncpy(rdbms_connect,test_appl,strlen(test_appl));
	     }
	   } 
	   else 
	     {
	     printf("rtsfs: ERROR. The RDBMS_CONNECT environment variable is not set.\n");
	     printf("rtsfs: The value of the RDBMS_CONNECT environment variable is used\n");
	     printf("       on the SQL \"CONNECT\" statement to connect the RDBMS.\n");
	     strncpy(rdbms_connect,"        ",MAX_APPL_LENGTH);
             }
    /* Begin B2590 */
	   if((test_appl=(char *)getenv("RDBMS_SVRNAME"))!=NULL) {
	     if(strlen(test_appl) > MAX_APPL_LENGTH) {
	       printf("rtsfs: The length of the specified RDBMS_SVRNAME=%s application name exceeds %d chars\n",test_appl,MAX_APPL_LENGTH);
	       strncpy(rdbms_svrname,"        ",MAX_APPL_LENGTH);
      } else {
	       strncpy(rdbms_svrname,test_appl,strlen(test_appl));
	     }
	   } 
	   if((test_appl=(char *)getenv("RDBMS_DBNAME"))!=NULL) {
	     if(strlen(test_appl) > MAX_APPL_LENGTH) {
	       printf("rtsfs: The length of the specified RDBMS_DBNAME=%s application name exceeds %d chars\n",test_appl,MAX_APPL_LENGTH);
	       strncpy(rdbms_dbname,"        ",MAX_APPL_LENGTH);
      } else {
	       strncpy(rdbms_dbname,test_appl,strlen(test_appl));
	     }
	/* Begin BT=4735071 */
	   } else {
             memcpy(rdbms_dbname,rdbms_connect,MAX_APPL_LENGTH);
	/* End	 BT=4735071 */
	   } 
	   if((test_appl=(char *)getenv("RDBMS_USRNAME"))!=NULL) {
	     if(strlen(test_appl) > MAX_APPL_LENGTH) {
	       printf("rtsfs: The length of the specified RDBMS_USRNAME=%s application name exceeds %d chars\n",test_appl,MAX_APPL_LENGTH);
	       strncpy(rdbms_usrname,"        ",MAX_APPL_LENGTH);
      } else {
	       strncpy(rdbms_usrname,test_appl,strlen(test_appl));
	     }
	   } else {
	     memcpy(rdbms_usrname,rdbms_connect,MAX_APPL_LENGTH);
    }
	   if((test_appl=(char *)getenv("RDBMS_USRPASS"))!=NULL) {
	     if(strlen(test_appl) > MAX_APPL_LENGTH) {
	       printf("rtsfs: The length of the specified RDBMS_USRPASS=%s application name exceeds %d chars\n",test_appl,MAX_APPL_LENGTH);
	       strncpy(rdbms_usrpass,"        ",MAX_APPL_LENGTH);
      } else {
	       strncpy(rdbms_usrpass,test_appl,strlen(test_appl));
	     }
	   } else {
	     memcpy(rdbms_usrpass,rdbms_usrname,MAX_APPL_LENGTH);
    }
    /* End B2590 */
	   sprintf(pidxnum,"%3d",1);
	   memcpy(papplnam->cur_sysname,rdbms_connect,MAX_APPL_LENGTH);
	   memcpy(papplnam->cur_svrname,rdbms_svrname,MAX_APPL_LENGTH);
	   memcpy(papplnam->cur_dbname ,rdbms_dbname ,MAX_APPL_LENGTH);
	   memcpy(papplnam->cur_usrname,rdbms_usrname,MAX_APPL_LENGTH);
	   memcpy(papplnam->cur_usrpass,rdbms_usrpass,MAX_APPL_LENGTH);
	   memcpy(papplnam->cur_tranidx,pidxnum,3);
           return(0);
} /* kxsysinfo */

int kxtctinfo()
{
	 printf("rtsfs: invalid call to kxtctinfo()\n");
  return(0);
}

static struct lmsgstr {
 char cur_errno [4];
 char cur_func  [20];
 char cur_msg   [60];
} lmsgstr;

int kxsetmsg(pcblmsg)
struct lmsgstr *pcblmsg;
{
  printf("rtsfs: RDBMS error=%d, func=%s, msg=%s\n",
               atoi(pcblmsg->cur_errno),
               pcblmsg->cur_func,
               pcblmsg->cur_msg);
  return(0);
}
