Esempio n. 1
0
/*{
** Name: psy_qminit	- Allocate and initialize the PSY_CB
**
** Description:
**      This function allocates and initialzes the qrymod control
**	block, PSY_CB.  It is called by the grammar.
**
** Inputs:
**	sess_cb				Current session control block
**	psq_cb
**	    .err_blk			Filled in if an error happens
**	mstream				memory stream to use for allocating a
**					PSY_CB
**
** Outputs:
**	sess_cb
**	    .pss_object			Points to allocated psy_cb
**	Returns:
**	    E_DB_OK			Success
**	    Other			Return code from called functions
**	Exceptions:
**	    none
**
** Side Effects:
**	    Allocates memory
**
** History:
**      22-jul-89 (ralph)
**          Written.
**	08-aug-90 (ralph)
**	    Initialize new psy_cb fields.
**	14-jul-92 (andre)
**	    init PSY_CB.psy_flags
**	14-jul-92 (andre)
**	    added mstream to the function's interface which will enable it to no
**	    longer assume that PSY_CB must be allocated from any given stream.
**	20-jul-92 (andre)
**	    added initialization for psy_xcolq
**	20-jul-92 (andre)
**	    iprocessing DROP PROCEDURE (psq_cb->psq_mode == PSQ_DRODBP), memory
**	    stream has already been opened, so don't do it here
**	21-jul-92 (andre)
**	    removed initialization for psy_xcolq;
**
**	    replaced code initializing various fields to 0 with a call to MEfill
**	    to fill a newly allocated PSY_CB with 0's
**	06-dec-92 (andre)
**	    Added code to initialize psy_u_colq and psy_r_colq
**	10-jul-93 (andre)
**	    cast QUinit()'s arg to (QUEUE *) to agree with the prototype
**	    declaration
**	 7-jan-94 (swm)
**	    Bug #58635
**	    Added PTR cast for qsf_owner which has changed type to PTR.
**	28-apr-94 (andre)
**	    (part of fix for bug 62890)
**	    if the statement was generated internally 
**	    (psq_cb->psq_info->pst_execflags & PST_SYSTEM_GENERATED), set 
**	    PSY_SYSTEM_GENEARTED in psy_cb->psy_flags.
*/
DB_STATUS
psy_qminit(
	PSS_SESBLK	    *sess_cb,
	PSQ_CB		    *psq_cb,
	PSF_MSTREAM	    *mstream)
{
    DB_STATUS	    status;
    PSY_CB	    *psy_cb;

    /*
    ** open the memory stream unless we are processing DROP PROCEDURE, in which
    ** case it has already been opened
    */
    if (psq_cb->psq_mode != PSQ_DRODBP)
    {
	/* Allocate the PSY_CB statement */
	status = psf_mopen(sess_cb, QSO_QP_OBJ, mstream, &psq_cb->psq_error);
	if (status != E_DB_OK)
	    return (status);
    }

    status = psf_malloc(sess_cb, mstream, sizeof(PSY_CB), &sess_cb->pss_object,
	&psq_cb->psq_error);
    if (status != E_DB_OK)
	return (status);

    status = psf_mroot(sess_cb, mstream, sess_cb->pss_object, &psq_cb->psq_error);
    if (status != E_DB_OK)
	return (status);

    psy_cb = (PSY_CB *) sess_cb->pss_object;

    MEfill(sizeof(PSY_CB), (u_char) 0, (PTR) psy_cb);

    /* Fill in control block header */
    psy_cb->psy_length	 = sizeof(PSY_CB);
    psy_cb->psy_type	 = PSYCB_CB;
    psy_cb->psy_owner	 = (PTR)DB_PSF_ID;
    psy_cb->psy_ascii_id = PSYCB_ASCII_ID;

    (VOID) QUinit((QUEUE *) &psy_cb->psy_usrq);	/* No users */
    (VOID) QUinit((QUEUE *) &psy_cb->psy_tblq);	/* No tables */
    (VOID) QUinit((QUEUE *) &psy_cb->psy_colq);	/* No columns */
    (VOID) QUinit((QUEUE *) &psy_cb->psy_u_colq);
    (VOID) QUinit((QUEUE *) &psy_cb->psy_r_colq);

    /*
    ** remember whether the statement was generated internally
    */
    if (   psq_cb->psq_info 
	&& psq_cb->psq_info->pst_execflags & PST_SYSTEM_GENERATED)
    {
	psy_cb->psy_flags |= PSY_SYSTEM_GENERATED;
    }

    return(E_DB_OK);
}
Esempio n. 2
0
GCD_CIB *
gcd_new_cib( u_i2 count )
{
    GCD_CIB	*cib = NULL;
    u_i2	len = sizeof( GCD_CIB ) + (sizeof(CONN_PARM) * (count - 1));

    if ( count < ARR_SIZE( GCD_global.cib_free ) )
	if (! (cib = (GCD_CIB *)QUremove(GCD_global.cib_free[count].q_next)))
	    if ( (cib = (GCD_CIB *)MEreqmem( 0, len, FALSE, NULL )) )
		cib->id = GCD_global.cib_total++;

    if ( ! cib )
	gcu_erlog(0, GCD_global.language, E_GC4808_NO_MEMORY, NULL, 0, NULL);
    else  
    {
	u_i4	id = cib->id;
	char	buff[16];

	MEfill( len, 0, (PTR)cib );
	cib->id = id;
	cib->parm_max = count;
	QUinit( &cib->caps );

	MOulongout( 0, (u_i8)cib->id, sizeof( buff ), buff );
	MOattach( MO_INSTANCE_VAR, GCD_MIB_DBMS, buff, (PTR)cib );

	GCD_global.cib_active++;

	if ( GCD_global.gcd_trace_level >= 6 )
	    TRdisplay( "%4d    GCD new CIB (%d)\n", -1, cib->id );
    }

    return( cib );
}
Esempio n. 3
0
GCADM_SCB *
gcadm_new_scb( i4 aid, PTR gca_cb )
{
   GCADM_SCB  *scb;

    scb = (GCADM_SCB *)(* GCADM_global.alloc_rtn )( sizeof( GCADM_SCB ) );
   
    if ( scb )
    {
	MEfill( sizeof( GCADM_SCB ), 0, scb);
	scb->buffer = (char *) (*GCADM_global.alloc_rtn)
			    ( GCADM_global.gcadm_buff_len );
   }
   
    if ( scb->buffer )
    {
	scb->aid  =  aid;
	scb->gca_cb = gca_cb;
	QUinit( &scb->q );
	QUinsert( &scb->q, GCADM_global.scb_q.q_prev); 
    }
    else
    {
	(*GCADM_global.dealloc_rtn)( (PTR)scb );
	scb = NULL;
    }

    return( scb );
}
Esempio n. 4
0
II_EXTERN IIAPI_THREAD *
IIapi_thread( II_VOID )
{
    IIAPI_THREAD	*thread;
    STATUS		status;
    i4		tid = PCtid();

    IIAPI_TRACE( IIAPI_TR_VERBOSE )
	( "IIapi_thread(%d): retrieving local storage\n", tid );

    status = MEtls_get( &IIapi_static->api_thread, (PTR *)&thread );

    if ( status != OK )
    {
	IIAPI_TRACE( IIAPI_TR_ERROR )
	    ( "IIapi_thread: error retrieving local storage: 0x%x\n", status );
	
	return( NULL );
    }

    if ( ! thread )
    {
	thread = (IIAPI_THREAD *)MEreqmem( 0, sizeof( IIAPI_THREAD ),
					   TRUE, &status );
	
	if ( ! thread )
	{
	    IIAPI_TRACE( IIAPI_TR_FATAL )
		( "IIapi_thread: error allocating local storage 0x%x\n",
		  status );
	}
	else
	{
	    IIAPI_TRACE( IIAPI_TR_INFO )
		("IIapi_thread(%d): allocated local storage %p\n",tid,thread);
	
	    QUinit( &thread->api_op_q );

	    status = MEtls_set( &IIapi_static->api_thread, (PTR)thread );

	    if ( status != OK )
	    {
		IIAPI_TRACE( IIAPI_TR_ERROR )
		    ( "IIapi_thread: error saving local storage 0x%x\n",
		      status );
	    
		MEfree( (PTR)thread );
		thread = NULL;
	    }
	}
    }

    IIAPI_TRACE( IIAPI_TR_DETAIL )
	( "IIapi_thread(%d): retrieved local storage %p\n", tid, thread );

    return( thread );
}
Esempio n. 5
0
/*{
** Name:	IIME_adAddTag	- Add a node of allocated memory to a tag.
**
** Description:
**	This routine is called when a new block of dynamic memory is being
**	allocated under a tag.  It is called by MEdoAlloc.  The job
**	of this routine is to store the allocated memory so that it
**	will be freed with the other blocks allocated under this tag when
**	MEtfree is called.
**
**	It works by checking the hash table for an METAGNODE for this tag.
**	If none is found, a new METAGNODE is allocated for this tag.
**	Then the block of memory is put on the QUEUE for the METAGNODE.
**
** Inputs:
**	tag		The tag under which this block of memory is
**			being allocated.
**
**	node		The block of memory being allocated.
**
** Side Effects:
**	This will take a node off freelist, and if necessary will allocate
**	dynamic memory.
**
** History:
**	5-dec-1989 (Joe)
**	    First Written
*/
VOID
IIME_atAddTag(
	i4	tag,
	ME_NODE	*node)
{
    register METAGNODE	**first;

# ifdef OS_THREADS_USED
    CS_synch_lock( &MEtaglist_mutex );
# endif /* OS_THREADS_USED */

    /*
    ** Note that first is a pointer to a pointer.
    ** The loop will cause a return from the routine if the tag already
    ** has an METAGNODE in the hash table.
    ** If the loop finishes, then first will point to the pointer
    ** that must contain the METAGNODE.
    */
    for (first = &(htab[tag%256]);
	 *first != NULL;
	 first = &((*first)->met_hash))
    {
	if ((*first)->met_tag == tag)
	{
	    (void)QUinsert((QUEUE *) node, (QUEUE *) (*first)->met_list.MElast);
# ifdef OS_THREADS_USED
	    CS_synch_unlock( &MEtaglist_mutex );
# endif /* OS_THREADS_USED */
	    return;
	}
    }
    if (freelist == NULL)
    {
	register METAGNODE	*next;
	register int		i;

	freelist = (METAGNODE *)
			MEreqmem(0, sizeof(METAGNODE)*50, TRUE, NULL);
	for (i = 0, next = freelist; i < 49; i++)
	{
	    next->met_hash = next + 1;
	    next = next->met_hash;
	}
	next->met_hash = NULL;
    }
    *first = freelist;
    freelist = freelist->met_hash;
    (*first)->met_hash = NULL;
    (*first)->met_tag = tag;
    QUinit((QUEUE *)&((*first)->met_list));
    (void)QUinsert((QUEUE *) node, (QUEUE *) (*first)->met_list.MElast);
# ifdef OS_THREADS_USED
    CS_synch_unlock( &MEtaglist_mutex );
# endif /* OS_THREADS_USED */
    return;
}
Esempio n. 6
0
GCADM_RCB *
gcadm_new_rcb( )
{
   GCADM_RCB  *rcb;


    rcb = (GCADM_RCB *)(* GCADM_global.alloc_rtn )( sizeof( GCADM_RCB ) );
   
    if ( rcb )  
    {
	MEfill(sizeof( GCADM_RCB ), 0, rcb);
	QUinit( &rcb->q );
    }

    return( rcb );
}
Esempio n. 7
0
GCD_CCB *
gcd_new_ccb( void )
{
    GCD_CCB	*ccb;

    if ( ! (ccb = (GCD_CCB *)QUremove( GCD_global.ccb_free.q_next )) )
	if ( (ccb = (GCD_CCB *)MEreqmem( 0, sizeof(GCD_CCB), FALSE, NULL )) )
	    ccb->id = GCD_global.ccb_total++;

    if ( ! ccb )
	gcu_erlog(0, GCD_global.language, E_GC4808_NO_MEMORY, NULL, 0, NULL);
    else
    {
	u_i4	id = ccb->id;

	MEfill( sizeof( GCD_CCB ), 0, (PTR)ccb );
	ccb->id = id;
	ccb->use_cnt = 1;
	ccb->max_buff_len = 1 << DAM_TL_PKT_MIN;
	ccb->tl.proto_lvl = DAM_TL_PROTO_1;
	ccb->xact.auto_mode = GCD_XACM_DBMS;
	ccb->api.env = NULL;
	QUinit( &ccb->q );
	QUinit( &ccb->rcb_q );
	QUinit( &ccb->gcc.send_q );
	QUinit( &ccb->msg.msg_q );
	QUinit( &ccb->msg.info_q );
	QUinit( &ccb->stmt.stmt_q );
	QUinit( &ccb->rqst.rqst_q );

	GCD_global.ccb_active++;
	QUinsert( &ccb->q, &GCD_global.ccb_q );

	if ( GCD_global.gcd_trace_level >= 5 )
	    TRdisplay( "%4d    GCD new CCB (%d)\n", ccb->id, ccb->id );
    }

    return( ccb );
}
Esempio n. 8
0
II_EXTERN IIAPI_ENVHNDL *
IIapi_initAPI( II_LONG version, II_LONG timeout )
{
    IIAPI_ENVHNDL	*envHndl;
    IIAPI_ENVHNDL	*defEnvHndl;
    II_BOOL		first_init = FALSE;
    STATUS		status;
    char		*env;

    if ( ! IIapi_static )
    {
	/*
	** Perform global initializations which are
	** environment independent.  
	*/
	first_init = TRUE;

	if ( ! ( IIapi_static = (IIAPI_STATIC *)
		 MEreqmem( 0, sizeof( IIAPI_STATIC ), TRUE, &status ) ) )
	    return( NULL );

	QUinit( &IIapi_static->api_env_q );

	if ( MUi_semaphore( &IIapi_static->api_semaphore ) != OK )
	    goto muiFail;

	if ( MEtls_create( &IIapi_static->api_thread ) != OK )
	    goto metFail;

	/*
	** Initialize sub-systems.
	*/
	IIAPI_INITTRACE();
	IIAPI_TRACE( IIAPI_TR_TRACE )( "IIapi_initAPI: initializing API.\n" );

	/*
	** Make sure II_SYSTEM or similar is set to provide useful feedback
	** rather than just failing in one of following subsystems.
	*/
	NMgtAt( SYSTEM_LOCATION_VARIABLE, &env );
	if ( env == NULL || *env == EOS )
	{
	    IIAPI_TRACE( IIAPI_TR_FATAL )
		( "IIapi_initAPI: error - %s not set.\n",
		  SYSTEM_LOCATION_VARIABLE );
	    goto adfFail;
	}
	
	IIapi_init_mib();
	if ( ! IIapi_initADF() )	goto adfFail;
	if ( ! IIapi_initGCA(timeout) )	goto gcaFail;

	/* Initialize the unicode collation values */
	IIapi_static->api_unicol_init = FALSE;
	IIapi_static->api_ucode_ctbl = NULL; 
	IIapi_static->api_ucode_cvtbl = NULL;

	/*
	** Create the default environment.
	*/
	if ( ! (IIapi_static->api_env_default = 
				(PTR)IIapi_createEnvHndl( IIAPI_VERSION_1 )) )
	    goto defFail;

	/* Spoken Language to use */

    	if( ( status = ERlangcode( (char *)NULL, 
				   &IIapi_static->api_slang ) != OK) )
    	{
	    IIAPI_TRACE( IIAPI_TR_ERROR )
		( "IIapi_initAPI: error initializing lang 0x%x\n", status );

	    return( NULL );
    	}

	/*
	** The SQL state machines are used by default prior to
	** IIapi_connect() being called, so make sure they are
	** initialized.
	*/
	if ( IIapi_sm_init( IIAPI_SMT_SQL ) != IIAPI_ST_SUCCESS )
	    goto envFail;
    }

    /*
    ** Now do environment specific initialization.
    */
    defEnvHndl = IIapi_defaultEnvHndl();

    if ( version == IIAPI_VERSION_1 )
    {
	/*
	** Version 1 initializers share the default
	** environment.  Keep track of the number of
	** initializers so that IIapi_termAPI() can
	** determine when to do global shutdown.
	*/
	envHndl = defEnvHndl;

	MUp_semaphore( &defEnvHndl->en_semaphore );
	defEnvHndl->en_initCount++;
	MUv_semaphore( &defEnvHndl->en_semaphore );
    }
    else
    {
	/*
	** Create a new environment for the initializer.
	** These environments are saved on the global
	** environment queue.  The caller may also make
	** API calls using the default environment handle, 
	** so increment the default environment handle
	** initialization count.
	*/
	if ( (envHndl = IIapi_createEnvHndl( version )) )
	{
	    MUp_semaphore( &IIapi_static->api_semaphore );
	    QUinsert( (QUEUE *)envHndl, &IIapi_static->api_env_q );
	    MUv_semaphore( &IIapi_static->api_semaphore );

	    MUp_semaphore( &defEnvHndl->en_semaphore );
	    defEnvHndl->en_initCount++;
	    MUv_semaphore( &defEnvHndl->en_semaphore );
	}
	else
	{
	    /*
	    ** We may need to undo the global initialization.
	    ** If not, the NULL environment handle will simply
	    ** be returned.
	    */
	    if ( first_init )  goto envFail;
	}
    }

    return( envHndl );

  envFail:
    IIapi_deleteEnvHndl( (IIAPI_ENVHNDL *)IIapi_static->api_env_default );

  defFail:
    IIapi_termGCA();

  gcaFail:
    IIapi_termADF();

  adfFail:
    IIAPI_TERMTRACE();
    MEtls_destroy( &IIapi_static->api_thread, NULL );

  metFail:
    MUr_semaphore( &IIapi_static->api_semaphore );

  muiFail:
    MEfree( (PTR)IIapi_static );
    IIapi_static = NULL;

    return( NULL );
}
Esempio n. 9
0
static STATUS
initialize( i4 argc, char **argv )
{
    CL_ERR_DESC	cl_err;
    char	*instance = ERx("*");
    char	*env;
    char	name[ 16 ];
    i4		i;

    GCD_global.language = 1;
    MHsrand( TMsecs() );

    for( i = 1; i < argc; i++ )
	if ( ! STbcompare( argv[i], 0, ERx("-instance"), 9, TRUE ) )
	{
	    if ( argv[i][9] == ERx('=')  &&  argv[i][10] != EOS )
		instance = &argv[i][10];
	    else  if ( argv[i][9] == EOS  &&  (i + 1) < argc )
		instance = argv[++i];
	    break;
	}

    NMgtAt( ERx("II_INSTALLATION"), &env );
    STprintf( name, ERx("II_CHARSET%s"), (env  &&  *env) ? env : "" );
    NMgtAt( name, &env );

    if ( ! env  ||  ! *env || STlength(env) > CM_MAXATTRNAME)
    {
	switch( CMgetDefCS() )
	{
#if ( !defined(UNIX) && !defined(VMS) )
	case CM_IBM :	    env = "IBMPC850";	break;
#endif
	case CM_DECMULTI :  env = "DECMULTI";	break;
	default :	    env = "ISO88591";	break;
	}
    }

    GCD_global.charset = STalloc( env );
    CVupper( GCD_global.charset );
    gcu_read_cset( gcd_cset_id );

    if ( CMset_attr( GCD_global.charset, &cl_err) != OK )
    {
	gcu_erlog( 0, GCD_global.language, 
		    E_GC0105_GCN_CHAR_INIT, NULL, 0, NULL );
	return( E_GC0105_GCN_CHAR_INIT );
    }

    PMinit();

    switch( PMload( (LOCATION *)NULL, (PM_ERR_FUNC *)NULL ) )
    {
	case OK: break;

	case PM_FILE_BAD:
	    gcu_erlog( 0, GCD_global.language, 
			E_GC003D_BAD_PMFILE, NULL, 0, NULL );
	    return( E_GC003D_BAD_PMFILE );
	    break;

	default:
	    gcu_erlog( 0, GCD_global.language, 
			E_GC003E_PMLOAD_ERR, NULL, 0, NULL );
	    return( E_GC003E_PMLOAD_ERR );
	    break;
    }

    PMsetDefault( 0, SystemCfgPrefix );
    PMsetDefault( 1, PMhost() );
    PMsetDefault( 2, ERx("gcd") );
    PMsetDefault( 3, instance );

    gcd_tl_services[0] = &gcd_dmtl_service;
    gcd_tl_services[1] = &gcd_jctl_service;
    GCD_global.tl_services = gcd_tl_services;
    GCD_global.tl_srvc_cnt = ARR_SIZE( gcd_tl_services );

    QUinit( &GCD_global.pib_q );
    QUinit( &GCD_global.rcb_q );
    QUinit( &GCD_global.ccb_q );
    QUinit( &GCD_global.ccb_free );
    for( i = 0; i < ARR_SIZE( GCD_global.cib_free ); i++ )  
	QUinit( &GCD_global.cib_free[ i ] );

    env = NULL;
    gcu_get_tracesym( NULL, ERx("!.client_max"), &env );
    if ( env  &&  *env )
    {
	i4 count;

	if ( CVal( env, &count ) == OK  &&  count > 0 )
	    GCD_global.client_max = count;
    }

    env = NULL;
    gcu_get_tracesym( NULL, ERx("!.client_timeout"), &env );
    if ( env  &&  *env )  
    {
	i4 timeout;

	if ( CVal( env, &timeout ) == OK  &&  timeout > 0 )
	    GCD_global.client_idle_limit = timeout * 60; /* Cnvt to seconds */
    }

    env = NULL;
    gcu_get_tracesym( NULL, ERx("!.connect_pool_status"), &env );
    if ( env  &&  *env )
    {
	if ( ! STbcompare( env, 0, "optional", 0, TRUE ) )
	    GCD_global.client_pooling = TRUE;

	if ( GCD_global.client_pooling  ||
	     ! STbcompare( env, 0, "on", 0, TRUE ) )
	{
	    env = NULL;
	    gcu_get_tracesym( NULL, ERx("!.connect_pool_size"), &env );
	    if ( env  &&  *env )  CVal( env, &GCD_global.pool_max );

	    env = NULL;
	    gcu_get_tracesym( NULL, ERx("!.connect_pool_expire"), &env );
	    if ( env  &&  *env )  
	    {
		i4 limit;

		if ( CVal( env, &limit ) == OK  &&  limit > 0 )
		    GCD_global.pool_idle_limit = limit * 60; /* Seconds */
	    }
	}
    }

    env = NULL;
    gcu_get_tracesym( "II_GCD_TRACE", ERx("!.gcd_trace_level"), &env );
    if ( env  &&  *env )  CVal( env, &GCD_global.gcd_trace_level );

    env = NULL;
    gcu_get_tracesym( "II_GCD_LOG", ERx("!.gcd_trace_log"), &env );
    if ( env  &&  *env ) 
	TRset_file( TR_F_OPEN, env, (i4)STlength( env ), &cl_err );

    return( OK );
}
Esempio n. 10
0
SQLRETURN  SQL_API SQLSetEnvAttr (
    SQLHENV    EnvironmentHandle,
    SQLINTEGER Attribute,
    SQLPOINTER ValuePtr,
    SQLINTEGER StringLength)
{
    RETCODE rc, traceRet = 1;
    pENV penv = (pENV)EnvironmentHandle;
    IISETENVATTR_PARAM *iiSetEnvAttrParam;
    i4 value = (i4)(SCALARP)ValuePtr;

    if (block_init)
        ODBC_TRACE_ENTRY(ODBC_TR_TRACE, IITraceSQLSetEnvAttr(EnvironmentHandle,
            Attribute, ValuePtr, StringLength), traceRet);

    /*
    ** Connection pooling is set in the CLI before any drivers are loaded.
    */
    if (!EnvironmentHandle)
    {
        if (Attribute != SQL_ATTR_CONNECTION_POOLING)
        {
            rc = SQL_INVALID_HANDLE;
            goto exit_routine;
        }
        if (!block_init)
        {
            /*
            ** Initialize the CLI control block if connection pooling is 
            ** specified.
            */
            if (value == SQL_CP_ONE_PER_DRIVER || value == SQL_CP_ONE_PER_HENV)
            {
                IIodbc_initControlBlock();
                if (IIodbc_cb.timeout != -1)
                    IIodbc_createPoolThread();
                block_init = TRUE;
            }
        }
        
        if (value == SQL_CP_ONE_PER_DRIVER)
        {
            ODBC_EXEC_TRACE(ODBC_TR_TRACE)
                ("SQLSetEnvAttr: driver pool initialized\n");
            IIodbc_cb.pooling = DRIVER_POOL;
            QUinit(&IIodbc_cb.pool_q);
        }
        else if (value == SQL_CP_ONE_PER_HENV)
        {
            IIodbc_cb.pooling = HENV_POOL;
        }
        else if (value != SQL_CP_OFF)
        {
            /* 
            ** If the pooling arguments are invalid, only SQL_INVALID_HANDLE 
            ** can be returned because no environment handle exists.
            */
            rc = SQL_INVALID_HANDLE;
            goto exit_routine;
        } /* if (!initPool) */
        rc = SQL_SUCCESS;
        goto exit_routine;
    } /* if (!EnvironmentHandle) */
    
    
    if (Attribute == SQL_ATTR_CP_MATCH && value == SQL_CP_RELAXED_MATCH)
        penv->relaxed_match = TRUE;
    else
        penv->relaxed_match = FALSE;

    /*
    **  If the driver isn't loaded yet, set a placeholder to do this 
    **  later.
    */
    if ( !IISetEnvAttr )
    {
        if (Attribute == SQL_ATTR_ODBC_VERSION)
            penv->envAttrValue = ValuePtr;
        iiSetEnvAttrParam = 
        (IISETENVATTR_PARAM *)MEreqmem(0, sizeof(IISETENVATTR_PARAM), 
            TRUE, NULL);
        penv->setEnvAttr_count++;
        iiSetEnvAttrParam->Attribute = Attribute;
        iiSetEnvAttrParam->EnvironmentHandle = EnvironmentHandle;
        iiSetEnvAttrParam->ValuePtr = ValuePtr;
        iiSetEnvAttrParam->StringLength = StringLength;
        QUinsert((QUEUE *)iiSetEnvAttrParam, &penv->setEnvAttr_q);
        rc = SQL_SUCCESS;
        goto exit_routine;
    }

    if (penv->hdr.state < E2)
    {
        resetErrorBuff(penv, SQL_HANDLE_ENV);

        rc = IISetEnvAttr (
            penv->hdr.driverHandle,
            Attribute,
            ValuePtr,
            StringLength);
    }
    else
        rc = SQL_ERROR;

    applyLock(SQL_HANDLE_ENV, penv);
    if (rc != SQL_SUCCESS)
    {
        penv->hdr.driverError = TRUE;
        penv->errHdr.rc = rc;
    }
    releaseLock(SQL_HANDLE_ENV, penv);
    
exit_routine:
    ODBC_TRACE(ODBC_TR_TRACE, IITraceReturn(traceRet, rc));
    return rc;
}
Esempio n. 11
0
main(int argc, char **argv)
{
    STATUS status = OK;
    VMS_STATUS vStatus;
    char srcbuf[NAME_FILE_SIZE];
    char dstbuf[NAME_FILE_SIZE];
    char delFile[NAME_FILE_SIZE];
    struct dsc$descriptor_s filename_d = 
        { sizeof (delFile) - 1,
            DSC$K_DTYPE_T,
            DSC$K_CLASS_S,
            delFile
        };
    FILE *srcFile = NULL;
    FILE *dstFile = NULL;
    FILE *nameFile = NULL;
    LOCATION loc;
    bool clusterArg = FALSE;
    bool unclusterArg = FALSE;
    bool writeOutput = FALSE;
    bool validSyntax;
    bool clustered = FALSE;
    bool v1DecryptErr = FALSE;
    bool rewrite = FALSE;
    bool isLogin = FALSE;
    i4   total_recs = 0;
    char local_host[MAX_LOC+CM_MAXATTRNAME];
    char config_host[MAX_LOC+CM_MAXATTRNAME];
    i2 i,j;
    i4 active_rec;
    i4 offset;
    char *onOff = NULL;
    bool srcOpened=FALSE;
    bool dstOpened=FALSE;
    bool printable = TRUE;
    GCN_QUEUE *gcn_q;
    GCN_QUEUE *merge_q;
    i4 rec_len = 0;
    QUEUE *q;
    u_i1  local_mask[ 8 ];        /* Must be 8 bytes */
    char name[MAX_LOC+CM_MAXATTRNAME];
    i4 count;
    char *p = NULL;
    i4 dcryptFail = 0;
    i2 pc;
    char *pv[ 3 ];
    GCN_DB_REC0 tmp_rec;
    SYSTIME timestamp;

    MEadvise(ME_INGRES_ALLOC);
    SIeqinit();
    GChostname( local_host, sizeof(local_host));
    STcopy (PMhost(), config_host);
    if (argc == 1)
       validSyntax = TRUE;
    /*
    ** Parse input arguments.
    */    
    for (i = 1; i < argc; i++)
    {
        validSyntax = FALSE;
        for (j = 0; j < argLen; j++)
        {
            if (!STncasecmp(arg[j],argv[i], STlength(argv[i])))
            {
                switch(j)
                {
                    case HELP1:
                    case HELP2:
                    case HELP3:
                    case HELP4:
                       usage();
                       break;

                    case VERBOSE:
                       validSyntax = TRUE;
                       verboseArg = TRUE;
                       break;

                    case CLUSTER:
                       validSyntax = TRUE;
                       clusterArg = TRUE;
                       writeOutput = TRUE;
                       break;

                    case UNCLUSTER:
                       validSyntax = TRUE;
                       unclusterArg = TRUE;
                       writeOutput = TRUE;
                       break;
                }
            } /* if (!STncasecmp(arg[j],argv[i], STlength(argv[i]))) */
            if (validSyntax)
                break;
        } /* for (j = 0; j < argLen; j++) */
        if (!validSyntax)
            break;
    } /* for (i = 1; i < argc; i++) */

    if (!validSyntax)
    {
        usage();
        PCexit(1);
    }

    if (clusterArg && unclusterArg)
    {
        SIprintf("Cannot specify both -c and -u\n\n");
            usage();
        PCexit(1);
    }

    if (verboseArg)
        SIprintf("Local host is %s\n", local_host);

    /*
    ** Generate key seeds for encoding and decoding.
    */
    STpolycat( 2, GCN_LOGIN_PREFIX, local_host, name );
    gcn_init_mask( name, sizeof( local_mask ), local_mask );

    QUinit(&gcn_qhead);
    QUinit(&merge_qhead);
    PMinit();

    /*
    ** See if this is a clustered installation.  If it is, 
    ** the node, login, and attribute files have no file extension.
    */
    if ( PMload( (LOCATION *)NULL, (PM_ERR_FUNC *)NULL ) != OK )
    {
        SIprintf("Error reading config.dat, exiting\n");
        goto cvt_exit;      
    }

    PMsetDefault( 0, SystemCfgPrefix );
    PMsetDefault( 1, config_host );
    PMsetDefault( 2, ERx("gcn") );

    status = PMget( ERx("!.cluster_mode"), &onOff);
    if (onOff && *onOff)
        ;
    else
        onOff = "OFF";

    if (verboseArg)
        SIprintf("Cluster mode is %s\n", onOff);

    if (!clusterArg && !unclusterArg)
        clustered = !STncasecmp(onOff, "ON", STlength(onOff));

    /*
    ** Rewrite the named GCN files.  For clustered installations, the
    ** node, login and attribute files have no hostname extension.
    */
    for ( i = 0; i < NBR_NAMED_FILES; i++ )
    {  
        /*
        ** Ticket files are simply deleted.
        */
        if (i == IILTICKET || i == IIRTICKET)
        {
            STprintf(delFile, "II_SYSTEM:[INGRES.FILES.NAME]II%s*;*", 
                named_file[i].file);
            if (verboseArg)
                SIprintf("Deleting %s\n", delFile);
            filename_d.dsc$w_length = STlength(delFile);
            vStatus = lib$delete_file(&filename_d,0,0,0,0,0,0,0,0,0);
            if (!vStatus & STS$M_SUCCESS)
                SIprintf("delete of %s failed, status is 0x%d\n", delFile,
                    vStatus);
            continue;
        }    
 
        rewrite = FALSE;
        if (!clusterArg && !unclusterArg)
            writeOutput = FALSE;
        if ( ( status = NMloc( FILES, PATH & FILENAME, 
            (char *)NULL, &loc ) ) != OK )
        {
            SIprintf("iicvtgcn: Could not find II_SYSTEM:[ingres.files]\n");
            goto cvt_exit;
        }
     
        LOfaddpath( &loc, "name", &loc );

        if (clustered || unclusterArg)
        {
            if (named_file[i].add_cluster_node)
                STprintf( srcbuf, "II%s_%s", named_file[i].file,config_host);
            else
                STprintf(srcbuf, "II%s", named_file[i].file);
        }
        else 
            STprintf( srcbuf, "II%s_%s", named_file[i].file,config_host);

        if (verboseArg)
            SIprintf("Opening %s for input\n", srcbuf);

        LOfstfile( srcbuf, &loc );

        /*
        ** Ignore non-existent files.
        */
        if ( LOexist( &loc ) != OK )
        {
            if (verboseArg)
                SIprintf("%s does not exist\n", srcbuf);
            continue;
        }
        /*
        ** Open the existing file as "regular" RACC.
        */
        status = SIfopen( &loc, "r", (i4)SI_RACC, sizeof( GCN_DB_REC0 ), 
            &srcFile );
        /*
        ** If the file exists but can't be opened, it's already optimized.
        */
        if (status == E_CL1904_SI_CANT_OPEN && ( LOexist( &loc ) == OK ) )
        {
            /*
            ** Open the existing file as "optimized" RACC.
            */
            status = SIfopen( &loc, "r", (i4)GCN_RACC_FILE, 
                sizeof( GCN_DB_REC0 ), &srcFile );
            if (status != OK)
            {
                SIprintf( "iicvtgcn: Error opening %s, status is %x\n",
                    srcbuf, status );
                continue;
            }
            if (verboseArg)
                SIprintf("%s is already optimized\n", srcbuf);
        }
        else if (status != OK)
        {
            SIprintf( "iicvtgcn: Error opening %s, status is %x\n",
                srcbuf, status );
            continue;
        }

        /*
        ** A successful open as SI_RACC means the file is not optimized.
        ** This file needs a rewrite.
        */
        else
        {
            if (verboseArg)
                SIprintf("Rewriting %s as optimized\n", srcbuf);
            writeOutput = TRUE;    
        }

        srcOpened = TRUE;

        while ( status == OK )
        {
            /*
            ** Read the source data and store in a queue for analysis.
            */
            status = SIread( srcFile, sizeof( GCN_DB_REC0 ),
                &count, (PTR)&tmp_rec );
            if ( status == ENDFILE )
                break;

            if ( status != OK )
            {
                SIprintf("iicvtgcn: Error reading %s, status is %x\n",
                    srcbuf, status);
                goto cvt_exit;
            }
            else if (tmp_rec.gcn_invalid && tmp_rec.gcn_tup_id != -1)
                continue;
            else
            {
                gcn_q = (GCN_QUEUE *)MEreqmem(0, sizeof(GCN_QUEUE),0,NULL);
                if (!gcn_q)
                {
                    SIprintf("iicvtgcn: Cannot allocate memory, exiting\n");
                    goto cvt_exit;
                }
                MEcopy((PTR)&tmp_rec, sizeof(GCN_DB_REC0), (PTR)&gcn_q->buf);
                QUinsert(&gcn_q->q, &gcn_qhead);
                /*
                ** EOF record found.
                */
                if (gcn_q->buf.gcn_tup_id == -1)
                {
                    gcn_q->buf.gcn_l_uid = 0;
                    gcn_q->buf.gcn_uid[0] = '\0';
                    gcn_q->buf.gcn_l_obj = 0;
                    gcn_q->buf.gcn_obj[0] = '\0';
                    gcn_q->buf.gcn_l_val = 0;
                    gcn_q->buf.gcn_val[0] = '\0';
                    gcn_q->buf.gcn_invalid = TRUE;
                    break;
                }
            }
        } /* while ( status == OK ) */

        /*
        ** Decrypt passwords for IILOGIN files.  If any V1 records are found, 
        ** the IILOGIN file will need to be rewritten.
        */
        isLogin = FALSE;
        for (q = gcn_qhead.q_prev; q != &gcn_qhead; q = q->q_prev)
        {
            gcn_q = (GCN_QUEUE *)q;

            /*
            ** EOF record found.
            */
            if (gcn_q->buf.gcn_tup_id == -1)
            {
                gcn_q->buf.gcn_invalid = TRUE;
                break;
            }

            if (i == IILOGIN)
            {
                isLogin = TRUE;
                MEcopy((PTR)&gcn_q->buf, sizeof(GCN_DB_REC0), (PTR)&tmp_rec);
                if (verboseArg)
                     SIprintf("\tEncoding vnode %s\n", gcn_q->buf.gcn_obj);

                if (unclusterArg)
                    status = gcn_recrypt( FALSE, local_mask, 
                        gcn_q->buf.gcn_val, &v1DecryptErr, &writeOutput);
                else if (clusterArg)
                    status = gcn_recrypt( TRUE, local_mask, 
                    gcn_q->buf.gcn_val, &v1DecryptErr, &writeOutput);
                else
                    status = gcn_recrypt( clustered, local_mask, 
                    gcn_q->buf.gcn_val, &v1DecryptErr, &writeOutput);

                if (status != OK)
                {
                    if (verboseArg)
                        SIprintf("Cannot decrypt password from " \
                            "vnode %s status %x\n", gcn_q->buf.gcn_obj,
                            status);
                    dcryptFail++;
                    MEcopy((PTR)&tmp_rec, sizeof(GCN_DB_REC0), 
                        (PTR)&gcn_q->buf);
                    continue;                
                }
                if (v1DecryptErr)
                {
                    if (verboseArg)
                        SIprintf("Cannot decrypt password from " \
                            "vnode %s\n", gcn_q->buf.gcn_obj);
                    dcryptFail++;
                    MEcopy((PTR)&tmp_rec, sizeof(GCN_DB_REC0), 
                        (PTR)&gcn_q->buf);
                    continue;
                }
            }  /* if (LOGIN) */

        } /* for (q = gcn_qhead.q_prev; q != &gcn_qhead; q = q->q_prev) */
        
        if (dcryptFail && verboseArg && isLogin)
        {
            if (clustered || unclusterArg )
                SIprintf("\n%d vnode(s) could not be decrypted.\n" \
                    "Probably some login entries were created on " \
                    "another node.\nTry executing iicvtgcn on another " \
                    "node to merge the other node's entries.\n\n", dcryptFail);
            else
                SIprintf("\n%d vnode(s) could not be decrypted.\n" \
                    "Probably the login file was created on " \
                    "another host.\nTry executing iicvtgcn on " \
                    "a different host.\n\n", dcryptFail);
        }

        if (!writeOutput)
        {
            if (srcOpened)
                SIclose(srcFile);
            srcOpened = FALSE;
            cleanup_queues();
            continue;
        }
   
        /*
        ** Open the destination file with special GCN_RACC_FILE flag, for 
        ** optimized writes.
        */
        if (clustered || clusterArg) 
        {
            if (named_file[i].add_cluster_node)
                STprintf( dstbuf, "II%s_%s", named_file[i].file, local_host);
            else
                STprintf(dstbuf, "II%s", named_file[i].file);
        }
        else
            STprintf( dstbuf, "II%s_%s", named_file[i].file, local_host);

        if (clusterArg && !named_file[i].add_cluster_node)
            rewrite = TRUE;

        LOfstfile( dstbuf, &loc );

        if (rewrite)
        {
            status = SIfopen( &loc, "rw", (i4)GCN_RACC_FILE, 
                sizeof( GCN_DB_REC0 ), &dstFile );
            if ( status != OK )
            {
                status = SIfopen( &loc, "w", (i4)GCN_RACC_FILE, 
                    sizeof( GCN_DB_REC0 ), &dstFile );
                if (status == OK)
                {
                    SIclose( dstFile);
                    status = SIfopen( &loc, "rw", (i4)GCN_RACC_FILE, 
                        sizeof( GCN_DB_REC0 ), &dstFile );
                }
            }
        }
        else
            status = SIfopen( &loc, "w", (i4)GCN_RACC_FILE, 
                sizeof( GCN_DB_REC0 ), &dstFile );

        if ( status != OK )
        {
            SIprintf( "iicvtgcn: Error opening %s, status is %x\n",dstbuf,
                status );
            goto cvt_exit;
        }

        dstOpened = TRUE;

        if (verboseArg)
            SIprintf("%s %s\n", rewrite ? "Rewriting " : "Writing ", dstbuf);

        /*
        ** If this is a merge operation (-c), login, attribute or
        ** node files may change the location of EOF, since the
        ** file to be merged may have different records than
        ** the destination file. 
        ** Before merging, the output file is read and fed into a queue.
        ** Then each merge record is compared to each output record.
        ** If the entire records match, nothing is done. 
        ** If a global login record matches only the vnode name
        ** global or private records will be added if not present;
        ** otherwise, nothing is done.
        ** Node or attribute records may be added if only one field
        ** fails to match.
        */
        status = SIfseek(dstFile, (i4)0, SI_P_START);
        if (rewrite)
        {
            while ( status == OK )
            {
                /*
                ** Read the source data and store in a queue for analysis.
                */
                status = SIread( dstFile, sizeof( GCN_DB_REC0 ),
                    &count, (PTR)&tmp_rec );
                if ( status == ENDFILE )
                    break;

                if ( status != OK )
                {
                    SIprintf("iicvtgcn: Error reading %s, status is %x\n",
                        dstbuf, status);
                    goto cvt_exit;
                }
                else if (tmp_rec.gcn_invalid && tmp_rec.gcn_tup_id != -1)
                    continue;
                else
                {
                    merge_q = (GCN_QUEUE *)MEreqmem(0, sizeof(GCN_QUEUE),0,NULL);
                    if (!merge_q)
                    {
                        SIprintf("iicvtgcn: Cannot allocate memory, exiting\n");
                        goto cvt_exit;
                    }
                    MEcopy((PTR)&tmp_rec, sizeof(GCN_DB_REC0), 
                        (PTR)&merge_q->buf);
                    QUinsert(&merge_q->q, &merge_qhead);
    
                    /*
                    ** EOF record found.
                    */
                    if (merge_q->buf.gcn_tup_id == -1)
                        break;
                }
                if ( status == ENDFILE )
                    break;

            } /* while ( status == OK ) */

            /*
            ** Go through the input queue.  Compare each record with
            ** the output (merge) queue.  If the record is invalid
            ** or doesn't match, it's ignored.
            */
            dcryptFail = 0;
            total_recs = 0;
            for (q = gcn_qhead.q_prev; q != &gcn_qhead; q = q->q_prev)
            {
                SYSTIME     timestamp;

                gcn_q = (GCN_QUEUE *)q;
                if (gcn_q->buf.gcn_tup_id == -1)
                    break;
                if ( !gcn_merge_rec( gcn_q, isLogin ) )
                    continue;
                if (isLogin)
                {
                    /*
                    ** Login passwords get encrypted as V0 in a cluster
                    ** environment.
                    */
                    MEcopy((PTR)&gcn_q->buf, sizeof(GCN_DB_REC0), 
                        (PTR)&tmp_rec);
                    status = gcn_recrypt( TRUE, local_mask, 
                        gcn_q->buf.gcn_val, &v1DecryptErr, &writeOutput);

                    if (status != OK)
                    {
                        if (verboseArg)
                            SIprintf("Cannot decrypt password from " \
                                "vnode %s status %x\n", gcn_q->buf.gcn_obj,
                                status);
                        dcryptFail++;
                        MEcopy((PTR)&tmp_rec, sizeof(GCN_DB_REC0), 
                            (PTR)&gcn_q->buf);
                        continue;                
                    }
                    if (v1DecryptErr)
                    {
                        if (verboseArg)
                            SIprintf("Cannot decrypt password from " \
                                "vnode %s\n", gcn_q->buf.gcn_obj);
                        dcryptFail++;
                        MEcopy((PTR)&tmp_rec, sizeof(GCN_DB_REC0), 
                            (PTR)&gcn_q->buf);
                        continue;
                    }
                }
                merge_q = (GCN_QUEUE *)MEreqmem(0, sizeof(GCN_QUEUE),0,NULL);
                if (!merge_q)
                {
                    SIprintf("iicvtgcn: Cannot allocate memory, exiting\n");
                    goto cvt_exit;
                }

                MEcopy((PTR)&gcn_q->buf, sizeof(GCN_DB_REC0), 
                    (PTR)&merge_q->buf);
                total_recs++;
              
                QUinsert(&merge_q->q, &merge_qhead);
            }

            if (dcryptFail && verboseArg && isLogin)
            {
                if (clustered || unclusterArg )
                    SIprintf("\n%d vnode(s) could not be decrypted.\n" \
                        "Probably some login entries were created on " \
                        "another node.\nTry executing iicvtgcn on another " \
                        "node to merge the other node's entries.\n\n", 
                        dcryptFail);
                    else
                        SIprintf("\n%d vnode(s) could not be decrypted.\n" \
                            "Probably the login file was created on " \
                            "another host.\nTry executing iicvtgcn on " \
                            "a different host.\n\n", dcryptFail);
            }
            if (verboseArg)
                SIprintf("Total records merged: %d\n", total_recs);

            /*
            ** If no records to merge, clean up and continue.
            */
            if (!total_recs)
            {
                cleanup_queues();
                continue;
            }

            status = SIfseek(dstFile, (i4)0, SI_P_START);
            active_rec = 0;
            for (q = merge_qhead.q_prev; q != &merge_qhead; q = q->q_prev)
            {
                merge_q = (GCN_QUEUE *)q;
                if (verboseArg)
                   SIprintf("Rewriting %s record vnode %s val %s\n", 
                       !STcasecmp("*", merge_q->buf.gcn_uid) ? "global" : 
                       "private", merge_q->buf.gcn_obj, merge_q->buf.gcn_val);
                if (merge_q->buf.gcn_tup_id == -1)
                    continue;
                status = SIwrite(sizeof( GCN_DB_REC0 ), 
                    (char *)&merge_q->buf, &count, dstFile );
                if ( status != OK)
                {
                    SIprintf( "iicvtgcn: Failed to write file %s, " \
                        "status is %x\n", srcbuf, status );
                    goto cvt_exit;
                }
                active_rec++;
            }
            /*
            ** Write new EOF record.
            */
            tmp_rec.gcn_tup_id = -1;
            tmp_rec.gcn_l_uid = 0;
            tmp_rec.gcn_uid[0] = '\0';
            tmp_rec.gcn_l_obj = 0;
            tmp_rec.gcn_obj[0] = '\0';
            tmp_rec.gcn_l_val = 0;
            tmp_rec.gcn_val[0] = '\0';
            tmp_rec.gcn_invalid = TRUE;
            offset = active_rec * sizeof(GCN_DB_REC0);
            status = SIfseek(dstFile, (i4)offset, SI_P_START);
            status = SIwrite(sizeof( GCN_DB_REC0 ), (PTR)&tmp_rec, 
                &count, dstFile );
        }
        else
        {
            for (q = gcn_qhead.q_prev; q != &gcn_qhead; q = q->q_prev)
            {
                gcn_q = (GCN_QUEUE *)q;
                gcn_q->buf.gcn_l_val = STlength(gcn_q->buf.gcn_val);
                if (verboseArg)
                   SIprintf("Writing %s record vnode %s val %s\n", 
                       !STcasecmp("*", gcn_q->buf.gcn_uid) ? "global" : 
                       "private", gcn_q->buf.gcn_obj, gcn_q->buf.gcn_val);
                status = SIwrite(sizeof( GCN_DB_REC0 ), (char *)&gcn_q->buf, 
                    &count, dstFile );
                if ( status != OK)
                {
                    SIprintf( "iicvtgcn: Failed to write file %s, " \
                        "status is %x\n", srcbuf, status );
                    goto cvt_exit;
                }
            }
        }  /* if (rewrite) */


        cleanup_queues();

        SIclose( srcFile );
        srcOpened = FALSE;
        SIclose( dstFile );
        dstOpened = FALSE;

    } /* for (i = 0; i < NBR_NAMED_FILES; i++ ) */

cvt_exit:

    cleanup_queues();

    if (srcOpened)
        SIclose(srcFile);
    if (dstOpened)
        SIclose(dstFile);
    PCexit( OK );
}