/*{ ** 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); }
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 ); }
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 ); }
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 ); }
/*{ ** 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; }
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 ); }
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 ); }
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 ); }
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 ); }
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; }
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 ); }