/*{ ** Name: CXdecorate_file_name - Append node name to filename. ** ** Description: ** ** Append upper case node name to passed filename, keeping ** total filelength 36 chars or below. ** ** Inputs: ** filename - buffer holding filename. Must be > 36 chars in length. ** nodename - name to append, or if NULL, CXnode_name is used. ** ** Outputs: ** none. ** ** Returns: ** - Pointer to passed filename, so this can be used in-line ** to printf, etc. ** ** Exceptions: ** none ** ** Side Effects: ** none ** ** History: ** 26-sep-2002 (devjo01) ** Created. */ char * CXdecorate_file_name( char *filename, char *node ) { i4 len, extlen; len = STlength(filename); if ( NULL == node ) node = CXnode_name(NULL); if (len < DI_FILENAME_MAX) { *(filename + len++) = '_'; if (len < DI_FILENAME_MAX) { extlen = STlcopy(node, filename + len, DI_FILENAME_MAX - len); *(filename + len + extlen) = '\0'; CVupper(filename + len); } } return filename; }
/* ** Name: GClanman_async_thread ** Description: ** This thread handles all the asynchronous I/O for a protocol driver. ** It will be woken up when GClanman() places a request on it's input ** Q. Then, this thread will move the request from the input Q to its ** processing Q and continue to process the request until complete. ** When complete, the request is finally moved to the completion ** Q. ** History: ** 04-Nov-93 (edg) ** Written. ** 29-jun-2000 (somsa01) ** Use GCc_listen_port for the server ncb_name. Also, make sure ** that we update GCc_client_name if we need a unique one. ** 06-Aug-2009 (Bruce Lunsford) Sir 122426 ** Since _beginthreadex() is now used to start this thread, ** use _endthreadex() to end it. */ VOID GClanman_async_thread( VOID * parms) { int status = OK; char callname[NCBNAMSZ+1]; DWORD wait_stat; HANDLE hSave; int processing_requests = 0; int pending_requests = 0; QUEUE *q; SECURITY_ATTRIBUTES sa; iimksec (&sa); GCTRACE(4)("LMAN THREAD: started.\n"); top: /* ** Wait for a request to come in from the primary gcc thread.... */ GCTRACE(4)("LMAN THREAD: waiting for event ... \n"); wait_stat = WaitForSingleObject( hEventThreadInQ, INFINITE ); GCTRACE(3)("LMAN THREAD: wait returned %d, handle = %d\n", wait_stat, hEventThreadInQ ); /* ** If wait failed, chances are it's a major hosure. Continue on any ** way -- there's a possibility that something useful may get done. */ if (wait_stat == WAIT_FAILED) { GCTRACE(1)("LMAN THREAD: wait failed %d\n", GetLastError() ); } /* ** Now get get the incoming requests and add up how many requests ** we're processing. */ processing_requests = GCget_incoming_reqs( Tptr, hMutexThreadInQ ); GCTRACE(2)("LMAN THREAD: Got %d new requests to process\n", processing_requests); /* ** Loop until there's no more requests being processed. */ while( processing_requests ) { pending_requests = 0; /* ** Now loop thru the inprocess request list. */ for ( q = Tptr->process_head.q_next; q != &Tptr->process_head; q = q->q_next ) { REQUEST_Q *rq = (REQUEST_Q *)q; GCC_P_PLIST *parm_list = rq->plist; PCB *pcb = (PCB *)parm_list->pcb; parm_list->generic_status = OK; CLEAR_ERR(&parm_list->system_status); switch (parm_list->function_invoked) { /****************************************************** ** Handle CONNECT *******************************************************/ case GCC_CONNECT: GCTRACE(4)("LMAN THREAD: process CONNECT\n"); if ( pcb == NULL || pcb->state.conn == INITIAL ) { GCTRACE(3)("LMAN THREAD: initial CONNECT\n"); /* ** Allocate the protocol control block. */ pcb = (PCB *) malloc( sizeof(PCB) ); parm_list->pcb = (char *)pcb; if (pcb == NULL) { status = errno; SETWIN32ERR(&parm_list->system_status, status, ER_alloc); pcb->state.conn = COMPLETED; parm_list->generic_status = GC_CONNECT_FAIL; break; } memset( pcb, 0, sizeof( *pcb ) ); GCTRACE(3)("LMAN THREAD: CONNECT allocated pcb\n"); /* ** Create send/recv event handles for ncb. */ if ((pcb->s_ncb.ncb_event = CreateEvent( &sa, TRUE, FALSE, NULL ))== NULL) { status = GetLastError(); pcb->state.conn = COMPLETED; SETWIN32ERR(&parm_list->system_status, status, ER_create); parm_list->generic_status = GC_CONNECT_FAIL; break; } if ((pcb->r_ncb.ncb_event = CreateEvent( &sa, TRUE, FALSE, NULL ))== NULL) { status = GetLastError(); CloseHandle( pcb->s_ncb.ncb_event ); pcb->state.conn = COMPLETED; SETWIN32ERR(&parm_list->system_status, status, ER_create); parm_list->generic_status = GC_CONNECT_FAIL; break; } GCTRACE(3)("LMAN THREAD: CONNECT created events\n"); pcb->state.conn = INITIAL; } /* end if pcb NULL */ /* ** If the PCB state is not INITIAL, just break because ** we're just waiting for connect to complete. */ if ( pcb->state.conn != INITIAL ) break; /* ** Use the send ncb in pcb for the connect -- add name. */ pcb->s_ncb.ncb_command = NCBADDNAME; pcb->s_ncb.ncb_buffer = Dummy_Buf; pcb->s_ncb.ncb_length = sizeof(Dummy_Buf); pcb->s_ncb.ncb_lana_num = lana_num; for (;;) { STprintf( GCc_client_name, "%s%-d", MyName, GCc_client_count++ ); STcopy( GCc_client_name, pcb->s_ncb.ncb_name ); GCTRACE(3)("LMAN THREAD: CONNECT doing ADDNAME %s\n", pcb->s_ncb.ncb_name ); /* ** Copy to local NCB struct -- Netbios seems to fark ** up if we don't. */ memcpy( &Name_Ncb, &pcb->s_ncb, sizeof( Name_Ncb ) ); Netbios( &Name_Ncb ); if (Name_Ncb.ncb_retcode == NRC_GOODRET) break; else if (Name_Ncb.ncb_retcode == NRC_DUPNAME) continue; else { status = (STATUS)Name_Ncb.ncb_retcode; CloseHandle( Name_Ncb.ncb_event ); pcb->s_ncb.ncb_event = NULL; CloseHandle( pcb->r_ncb.ncb_event ); pcb->r_ncb.ncb_event = NULL; pcb->state.conn = COMPLETED; SETWIN32ERR(&parm_list->system_status, status, ER_netbios); parm_list->generic_status = GC_CONNECT_FAIL; break; } } if (parm_list->generic_status == GC_CONNECT_FAIL) break; /* ** just in case ... */ ResetEvent( pcb->s_ncb.ncb_event ); /* ** OK, now make the call */ hSave = pcb->s_ncb.ncb_event; /* save handle */ memset( &pcb->s_ncb, 0, sizeof(NCB) ); pcb->s_ncb.ncb_event = hSave; /* restore handle */ pcb->s_ncb.ncb_buffer = parm_list->buffer_ptr; pcb->s_ncb.ncb_length = (WORD)parm_list->buffer_lng; pcb->s_ncb.ncb_command = NCBCALL | ASYNCH; pcb->s_ncb.ncb_lana_num = lana_num; STcopy( GCc_client_name, pcb->s_ncb.ncb_name ); STpolycat( 3, parm_list->function_parms.connect.node_id, "_", parm_list->function_parms.connect.port_id, callname ); CVupper( callname ); /* ** Loopback check to prevent mangling the name (?) */ if ( STcompare( parm_list->function_parms.connect.port_id, GCc_listen_port ) == 0 ) { STcopy( GCc_listen_port, pcb->s_ncb.ncb_callname ); } else { STcopy( callname, pcb->s_ncb.ncb_callname ); } GCTRACE(3)("LMAN THREAD: CONNECT doing CALL to %s\n", pcb->s_ncb.ncb_callname ); if ( Netbios( &pcb->s_ncb ) != NRC_GOODRET ) { status = (STATUS)pcb->s_ncb.ncb_retcode; CloseHandle( pcb->s_ncb.ncb_event ); pcb->s_ncb.ncb_event = NULL; CloseHandle( pcb->r_ncb.ncb_event ); pcb->r_ncb.ncb_event = NULL; pcb->state.conn = COMPLETED; SETWIN32ERR(&parm_list->system_status, status, ER_netbios); parm_list->generic_status = GC_CONNECT_FAIL; break; } GCTRACE(3)("LMAN THREAD: Async CALL OK\n" ); pcb->state.conn = COMPLETING; break; /******************************************************* ** Handle SEND *******************************************************/ case GCC_SEND: GCTRACE(4)("LMAN THREAD: process SEND\n"); if ( pcb->state.send != INITIAL ) { break; } pcb->s_ncb.ncb_buffer = parm_list->buffer_ptr; pcb->s_ncb.ncb_length = (WORD)parm_list->buffer_lng; pcb->s_ncb.ncb_lana_num = lana_num; pcb->s_ncb.ncb_command = NCBSEND | ASYNCH; if ( Netbios( &pcb->s_ncb ) != NRC_GOODRET ) { status = (STATUS)pcb->s_ncb.ncb_retcode; pcb->state.send = COMPLETED; SETWIN32ERR(&parm_list->system_status, status, ER_netbios); parm_list->generic_status = GC_SEND_FAIL; } pcb->state.send = COMPLETING; break; /******************************************************* ** Handle RECEIVE *******************************************************/ case GCC_RECEIVE: GCTRACE(4)("LMAN THREAD: process RECEIVE\n"); if ( pcb->state.recv != INITIAL ) { pending_requests++; break; } pcb->r_ncb.ncb_buffer = parm_list->buffer_ptr; pcb->r_ncb.ncb_length = (WORD)parm_list->buffer_lng; pcb->r_ncb.ncb_lana_num = lana_num; pcb->r_ncb.ncb_command = NCBRECV | ASYNCH; if ( Netbios( &pcb->r_ncb ) != NRC_GOODRET ) { status = (STATUS)pcb->r_ncb.ncb_retcode; pcb->state.recv = COMPLETED; SETWIN32ERR(&parm_list->system_status, status, ER_netbios); parm_list->generic_status = GC_RECEIVE_FAIL; } pcb->state.recv = COMPLETING; break; /******************************************************* ** Handle DISCONNECT *******************************************************/ case GCC_DISCONNECT: GCTRACE(4)("LMAN THREAD: process DISCONNECT\n"); if ( pcb && pcb->state.disc == INITIAL ) { pcb->s_ncb.ncb_buffer = parm_list->buffer_ptr; pcb->s_ncb.ncb_length = (WORD)parm_list->buffer_lng; pcb->s_ncb.ncb_command = NCBHANGUP | ASYNCH; pcb->s_ncb.ncb_lana_num = lana_num; if ( pcb->s_ncb.ncb_lsn == 0 ) pcb->s_ncb.ncb_lsn = pcb->r_ncb.ncb_lsn; if ( Netbios( &pcb->s_ncb ) != NRC_GOODRET ) { status = (STATUS)pcb->s_ncb.ncb_retcode; pcb->state.disc = COMPLETED; SETWIN32ERR(&parm_list->system_status, status, ER_netbios); parm_list->generic_status = GC_DISCONNECT_FAIL; break; } pcb->state.disc = COMPLETING; } break; } /* end switch */ } /* end for process q loop */ /* ** Now go thru the inprocess Q and look for any requests that ** have been completed. This will be indicated by one of: ** parm_list->pcb == NULL (bad connect or after disconnect) or ** pcb->state == COMPLETED, or WaitForSingleObject indicates ** completion. */ GCTRACE(4)("LMAN THREAD: processing completed. . . \n"); q = Tptr->process_head.q_next; while( q != &Tptr->process_head ) { REQUEST_Q *rq = (REQUEST_Q *)q; GCC_P_PLIST *pl = rq->plist; PCB *pcb = (PCB *)pl->pcb; bool completed = FALSE; switch ( pl->function_invoked ) { case GCC_CONNECT: if ( pcb == NULL || pcb->state.conn == COMPLETED || WaitForSingleObject( pcb->s_ncb.ncb_event, 0) == WAIT_OBJECT_0 ) { if (pcb) { ResetEvent( pcb->s_ncb.ncb_event ); pcb->r_ncb.ncb_lsn = pcb->s_ncb.ncb_lsn; if ( pcb->s_ncb.ncb_lsn == 0 || pcb->s_ncb.ncb_retcode != NRC_GOODRET ) { pl->generic_status = GC_CONNECT_FAIL; status = (STATUS)pcb->s_ncb.ncb_retcode; SETWIN32ERR( &pl->system_status, status , ER_revent); CloseHandle( pcb->s_ncb.ncb_event ); CloseHandle( pcb->r_ncb.ncb_event ); free( pcb ); pl->pcb = NULL; } } completed = TRUE; } break; case GCC_SEND: if ( pcb == NULL || pcb->state.send == COMPLETED || WaitForSingleObject( pcb->s_ncb.ncb_event, 0) == WAIT_OBJECT_0 ) { ResetEvent( pcb->s_ncb.ncb_event ); if ( pcb->s_ncb.ncb_lsn == 0 || pcb->s_ncb.ncb_retcode != NRC_GOODRET ) { pl->generic_status = GC_SEND_FAIL; status = (STATUS)pcb->s_ncb.ncb_retcode; SETWIN32ERR( &pl->system_status, status , ER_revent); } else { GCTRACE(2)( "LMAN THREAD: Send COMP pl len %d pcb len %d\n", pl->buffer_lng, pcb->s_ncb.ncb_length); pl->buffer_lng = pcb->s_ncb.ncb_length; } completed = TRUE; } break; case GCC_RECEIVE: if ( pcb == NULL || pcb->state.recv == COMPLETED || WaitForSingleObject( pcb->r_ncb.ncb_event, 0) == WAIT_OBJECT_0 ) { ResetEvent( pcb->r_ncb.ncb_event ); if ( pcb->s_ncb.ncb_lsn == 0 || pcb->r_ncb.ncb_retcode != NRC_GOODRET ) { pl->generic_status = GC_RECEIVE_FAIL; status = (STATUS)pcb->r_ncb.ncb_retcode; SETWIN32ERR( &pl->system_status, status , ER_revent); } else { pl->buffer_lng = pcb->r_ncb.ncb_length; } completed = TRUE; } break; case GCC_DISCONNECT: if ( pcb == NULL || pcb->state.disc == COMPLETED || WaitForSingleObject( pcb->s_ncb.ncb_event, 0) == WAIT_OBJECT_0 ) { if (pcb) { if ( pcb->s_ncb.ncb_lsn == 0 || pcb->s_ncb.ncb_retcode != NRC_GOODRET ) { pl->generic_status = GC_DISCONNECT_FAIL; status = (STATUS)pcb->s_ncb.ncb_retcode; SETWIN32ERR( &pl->system_status, status , ER_revent); } pcb->s_ncb.ncb_command = NCBDELNAME; Netbios( &pcb->s_ncb ); CloseHandle( pcb->s_ncb.ncb_event ); CloseHandle( pcb->r_ncb.ncb_event ); free( pcb ); pl->pcb = NULL; } completed = TRUE; } break; } /* end switch */ if ( completed ) { QUEUE *nq = q->q_next; GCTRACE(3)("LMAN THREAD: Complete! PCB = %x PARM = %x \n", pcb, pl); GCcomplete_request( q ); q = nq; processing_requests--; GCTRACE(3)("LMAN THREAD: processed completed \n"); GCTRACE(3)(" : total now = %d \n", processing_requests); } /* end if req completed */ else { q = q->q_next; } } /* end for -- look for complete req */ /* ** Do a quick, non-blocking check to see if any new requests ** came in during processing. */ GCTRACE(4)("LMAN THREAD: quick look for new reqs \n"); if ( WaitForSingleObject( hEventThreadInQ, 0 ) == WAIT_OBJECT_0 ) { processing_requests += GCget_incoming_reqs( Tptr, hMutexThreadInQ ); } GCTRACE(4)("LMAN THREAD: process reqs now = %d\n", processing_requests); if (processing_requests && pending_requests == processing_requests) { i4 Sleeptime = 1; Sleep(Sleeptime); } } /* end while processing requests */ if (In_Shutdown) { _endthreadex(0); return; } /* ** we're done for now, go back to the top and sleep. */ GCTRACE(3)("LMAN THREAD: No more reqs, going back to top\n" ); goto top; }
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 ); }
/* ** Name: GClanman_init ** Description: ** LANMAN inititialization function. This routine is called from ** GCpinit() -- the routine GCC calls to initialize protocol drivers. ** ** This function does initialization specific to the protocol: ** Creates Events and Mutex's for the protocol ** Finds and saves a pointer to it's input event Q. ** Fires up the thread which will do asynch I/O ** History: ** 11-Nov-93 (edg) ** created. ** 15-jul-95 (emmag) ** Use a NULL Discretionary Access Control List (DACL) for ** security, to give implicit access to everyone. ** 23-Feb-1998 (thaal01) ** Make space for port_id, stops gcc crashing on startup, sometimes. ** 13-may-2004 (somsa01) ** Updated config.dat string used to retrieve port information such ** that we do not rely specifically on the GCC port. ** 06-Aug-2009 (Bruce Lunsford) Sir 122426 ** Change arglist pointer in _beginthreadex for async_thread from ** uninitialized "dummy" to NULL to eliminate compiler warning ** and possible startup problem. */ STATUS GClanman_init(GCC_PCE * pptr) { char *ptr, *host, *server_id, *port_id; char config_string[256]; char buffer[MAX_COMPUTERNAME_LENGTH + 1]; int real_name_size = MAX_COMPUTERNAME_LENGTH + 1; i4 i; int tid; HANDLE hThread; int status; SECURITY_ATTRIBUTES sa; char port_id_buf[8]; port_id = port_id_buf; iimksec (&sa); /* ** Look for trace variable. */ NMgtAt( "II_LANMAN_TRACE", &ptr ); if ( !(ptr && *ptr) && PMget("!.lanman_trace_level", &ptr) != OK ) { GCLANMAN_trace = 0; } else { GCLANMAN_trace = atoi( ptr ); } /* ** Create MUTEX and EVENT for the input queue of this protocol ** driver. */ if ( ( hMutexThreadInQ = CreateMutex(&sa, FALSE, NULL) ) == NULL ) { return FAIL; } GCTRACE(3)( "GClanman_init: MutexInQ Handle = %d\n", hMutexThreadInQ ); if ( ( hEventThreadInQ = CreateEvent(&sa, FALSE, FALSE, NULL)) == NULL ) { CloseHandle( hMutexThreadInQ ); return FAIL; } GCTRACE(3)( "GClanman_init: EventInQ Handle = %d\n", hEventThreadInQ ); GCTRACE(4)( "Start GClanman_init\n" ); /* ** Get set up for the PMget call. */ PMinit(); if( PMload( NULL, (PM_ERR_FUNC *)NULL ) != OK ) PCexit( FAIL ); /* ** Construct the network port identifier. */ host = PMhost(); server_id = PMgetDefault(3); if (!server_id) server_id = "*" ; STprintf( config_string, ERx("!.lanman.port"), SystemCfgPrefix, host, server_id); /* ** Search config.dat for a match on the string we just built. ** If we don't find it, then use the value for II_INSTALLATION ** failing that, default to II. */ PMget( config_string, &port_id ); if (port_id == NULL ) { NMgtAt("II_INSTALLATION", &ptr); if (ptr != NULL && *ptr != '\0') { STcopy(ptr, port_id); } else { STcopy(SystemVarPrefix, port_id); } } NMgtAt( "II_NETBIOS_NODE", &ptr ); if ( !ptr || !*ptr ) { /* ** Get Computer Name into buffer. */ *buffer = (char)NULL; GetComputerName( buffer, &real_name_size ); if ( !*buffer ) STcopy( "NONAME", buffer ); ptr = buffer; } /* ** MyName holds ID for outgoing connections. */ STpolycat( 2, ptr, "_", MyName ); /* ** Create listen port ID. */ STpolycat( 3, ptr, "_", port_id, GCc_listen_port ); CVupper( MyName ); CVupper( GCc_listen_port ); STcopy( GCc_listen_port, pptr->pce_port ); GCTRACE(2)("GClanman_init: port = %s\n", pptr->pce_port ); /* ** Go thru the the protocol threads event list and find the index ** of the lanman thread. Set the Global Tptr for easy reference ** to the event q's for this protocols thread. */ for ( i = 0; i < IIGCc_proto_threads.no_threads; i++ ) { THREAD_EVENTS *p = &IIGCc_proto_threads.thread[i]; if ( !STcompare( LANMAN_ID, p->thread_name ) ) { Tptr = p; break; } } if ( Tptr == NULL ) { CloseHandle( hEventThreadInQ ); CloseHandle( hMutexThreadInQ ); return FAIL; } /* ** Finally we start the asynchronous I/O thread */ hThread = (HANDLE)_beginthreadex(&sa, GC_STACK_SIZE, (LPTHREAD_START_ROUTINE) GClanman_async_thread, NULL, (unsigned long)NULL, &tid); if (hThread) { CloseHandle(hThread); } else { status = errno; GCTRACE(1)("GClanman_init: Couldn't create thread errno = %d '%s'\n", status, strerror(status) ); return FAIL; } return OK; }
static VOID gcn_nq_filename( char *type, char *host, char *filename ) { i4 len, plen, slen; char *onOff = NULL; bool clustered = FALSE; STATUS status; /* ** Filename template: II<type>[_<host>] */ plen = 2; len = STlength( type ); slen = (host && *host) ? STlength( host ) + 1 : 0; /* ** Adjust filename for platform limitations: ** drop prefix if type and suffix OK; ** drop suffix if prefix and type OK; ** otherwise, drop both prefix and suffix. */ if ( plen + len + slen > LO_NM_LEN ) if ( len + slen <= LO_NM_LEN ) plen = 0; else if ( plen + len <= LO_NM_LEN ) slen = 0; else plen = slen = 0; /* ** 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\n"); return; } PMsetDefault( 0, "ii" ); PMsetDefault( 1, host ); PMsetDefault( 2, ERx("gcn") ); status = PMget( ERx("!.cluster_mode"), &onOff); if (onOff && *onOff) clustered = !STncasecmp(onOff, "ON", STlength(onOff)); if (clustered && (!STncasecmp("LOGIN", type, STlength(type)) || !STncasecmp("NODE", type, STlength(type)) || !STncasecmp("ATTR", type, STlength(type)))) slen = 0; CVupper(type); STprintf( filename, "%s%s%s%s", plen ? "II" : "", type, slen ? "_" : "", slen ? host : "" ); /* ** Finally, truncate the filename if it is too long ** (hopefully this will never happen). */ if ( STlength( filename ) > LO_NM_LEN ) filename[ LO_NM_LEN ] = '\0'; return; }
int main( int argc, char **argv ) { EX_CONTEXT context; char name[ GCC_L_PORT + 1 ]; u_i2 apivers; PTR hndl; #ifdef LNX PCsetpgrp(); #endif MEadvise( ME_INGRES_ALLOC ); if ( EXdeclare( GCX_exit_handler, &context ) != OK ) { gcu_erlog( 0, 1, E_GC480F_EXCEPTION, NULL, 0, NULL ); PCexit( OK ); return( 0 ); } GChostname( GCD_global.host, sizeof( GCD_global.host ) ); gcu_erinit( GCD_global.host, GCD_LOG_ID, "" ); if ( initialize( argc, argv ) != OK ) gcd_exit(); gcd_init_mib(); if ( gcd_gca_init( ) != OK ) gcd_exit(); gcu_erinit( GCD_global.host, GCD_LOG_ID, GCD_global.gcd_lcl_id ); if ( gcd_adm_init() != OK ) gcd_exit(); apivers = gcd_msg_version( MSG_DFLT_PROTO ); if ( gcd_get_env( apivers, &hndl ) != OK ) gcd_exit(); if ( gcd_pool_init() != OK ) gcd_exit(); if ( gcd_gcc_init() != OK ) gcd_exit(); /* ** Log Server startup. */ { char server_flavor[256], server_type[32]; char *tmpbuf = PMgetDefault(3); ER_ARGUMENT erlist[2]; SIstd_write(SI_STD_OUT, "PASS\n"); if ( ! STbcompare( tmpbuf, 0, "*", 0, TRUE ) ) STcopy( "(DEFAULT)", server_flavor ); else STcopy( tmpbuf, server_flavor ); STcopy(PMgetDefault(2), server_type); CVupper(server_type); erlist[0].er_value = server_flavor; erlist[0].er_size = STlength(server_flavor); erlist[1].er_value = server_type; erlist[1].er_size = STlength(server_type); gcu_erlog( 0, GCD_global.language, E_GC4802_LOAD_CONFIG, NULL, 2, (PTR)&erlist ); gcu_erlog( 0, GCD_global.language, E_GC4800_STARTUP, NULL, 0, NULL ); } GCexec(); gcd_gcc_term(); gcd_pool_term(); gcd_rel_env(0); gcd_adm_term(); gcd_gca_term(); gcu_erlog( 0, GCD_global.language, E_GC4801_SHUTDOWN, NULL, 0, NULL ); EXdelete(); PCexit( OK ); return( 0 ); }
/*{ ** Name: RSdelete - propagate a DELETE row ** ** Description: ** Propagates a DELETE transaction row, either by calling a remote ** database procedure or by executing a remote DELETE. ** ** Inputs: ** row - row of data ** ** Outputs: ** none ** ** Returns: ** OK ** else - error */ STATUS RSdelete( RS_TARGET *target, RS_TRANS_ROW *row) { char *stmt=NULL; char *proc_name; STATUS err; bool collision_processed = FALSE; RS_TBLDESC *tbl = row->tbl_desc; II_INT2 nparams; IIAPI_DESCRIPTOR pdesc[DB_MAX_COLS+1]; IIAPI_DATAVALUE pdata[DB_MAX_COLS+1]; DB_DELIM_STR *pnames = NULL; RS_CONN *conn = &RSconns[target->conn_no]; II_LONG procRet; II_PTR stmtHandle; IIAPI_GETEINFOPARM errParm; IIAPI_GETQINFOPARM getQinfoParm; IIAPI_STATUS status; IIAPI_DESCRIPTOR *col; IIAPI_DESCRIPTOR *pds; i4 num_cols=tbl->num_regist_cols; i4 row_width=tbl->row_width; stmt = RSmem_allocate(row_width,num_cols,DB_MAXNAME+8,128); if (stmt == NULL) return (FAIL); messageit(5, 1268, row->rep_key.src_db, row->rep_key.trans_id, row->rep_key.seq_no, target->db_no); err = RScollision(target, row, tbl, &collision_processed); if (err || collision_processed) { MEfree((PTR)stmt); return (err); } /* For URO targets, delete the base row. */ if (target->type == TARG_UNPROT_READ) { char *where_list=NULL; char objname[DB_MAXNAME*2+3]; where_list = RSmem_allocate(row_width,tbl->num_key_cols,DB_MAXNAME+8,0); if (where_list == NULL) { MEfree((PTR)stmt); return (FAIL); } /* ** Iterate through key_desc and create the WHERE list and ** prepare the column descriptors. The data will come directly ** from key_data. */ *where_list = EOS; for (col = row->key_desc, pds = pdesc; col < row->key_desc + tbl->num_key_cols; ++col, ++pds) { if (col != row->key_desc) STcat(where_list, ERx(" AND ")); /* ** The following is special case code to allow existing ** customers in non-SQL92 installations to propagate to ** Gateway databases that use uppercase table and ** column names. */ if (conn->name_case == UI_UPPERCASE) { STcopy(col->ds_columnName, objname); CVupper(objname); STcat(where_list, objname); } else { STcat(where_list, col->ds_columnName); } STcat(where_list, ERx(" = ~V")); *pds = *col; /* struct */ pds->ds_columnType = IIAPI_COL_QPARM; } STcopy(tbl->dlm_table_name, objname); if (target->type == TARG_UNPROT_READ && conn->name_case == UI_UPPERCASE) CVupper(objname); STprintf(stmt, ERx("DELETE FROM %s.%s WHERE %s"), tbl->rem_table_owner, objname, where_list); status = IIsw_query(conn->connHandle, &conn->tranHandle, stmt, tbl->num_key_cols, pdesc, row->key_data, NULL, NULL, &stmtHandle, &getQinfoParm, &errParm); status = RSerror_check(1556, ROWS_SINGLE_ROW, stmtHandle, &getQinfoParm, &errParm, NULL, tbl->table_name); MEfree((PTR)where_list); if (status != OK) { MEfree((PTR)stmt); return (status); } } /* For FP and PRO targets, call the remote database procedure. */ else { pnames = (DB_DELIM_STR *)RSmem_allocate(0, DB_MAX_COLS+1, sizeof(*pnames),0); if (pnames == NULL) { MEfree((PTR)stmt); return (FAIL); } proc_name = pnames[0]; if (RPtblobj_name(tbl->table_name, row->table_no, TBLOBJ_REM_DEL_PROC, proc_name) != OK) { messageit(1, 1816, ERx("RSdelete"), tbl->table_name); RSmem_free(stmt, (char *)pnames, NULL, NULL, NULL); return (RS_INTERNAL_ERR); } if (RSpdp_PrepDbprocParams(proc_name, target, tbl, row, pnames, &nparams, pdesc, pdata) != OK) { RSmem_free(stmt, (char *)pnames, NULL, NULL, NULL); return (RS_INTERNAL_ERR); } status = IIsw_execProcedure(conn->connHandle, &conn->tranHandle, nparams, pdesc, pdata, &procRet, &stmtHandle, &getQinfoParm, &errParm); status = RSerror_check(1573, ROWS_DONT_CARE, stmtHandle, &getQinfoParm, &errParm, NULL, proc_name); if (status != OK) { RSmem_free(stmt, (char *)pnames, NULL, NULL, NULL); return (status); } if (procRet) { messageit(1, procRet, row->rep_key.src_db, row->rep_key.trans_id, row->rep_key.seq_no, target->db_no, tbl->table_name); RSmem_free(stmt, (char *)pnames, NULL, NULL, NULL); return (procRet); } } RSstats_update(target->db_no, tbl->table_no, RS_DELETE); if (target->type != TARG_UNPROT_READ) RSmonitor_notify(&RSconns[target->conn_no], RS_INC_DELETE, RSlocal_conn.db_no, tbl->table_name, tbl->table_owner); RSmonitor_notify(&RSlocal_conn, RS_OUT_DELETE, target->db_no, tbl->table_name, tbl->table_owner); RSmem_free(stmt, (char *)pnames, NULL, NULL, NULL); return (OK); }
static STATUS gcn_op_add ( char *msg_in, GCN_MBUF *mbout, char *user, char *gcn_type, GCN_TUP *masktup, i4 num_tuple, i4 opflags, i4 srv_flags ) { GCN_QUE_NAME *nq = NULL; i4 row_count, tup_count; STATUS status = OK; char flagbuf[ 9 ]; char valbuf[ 65 ]; char *newval = valbuf; /* ** Check that user has required privileges for operation requested. ** (These checks are bypassed if client is trusted.) */ if ( ! (opflags & GCN_OPFLAG_TRUST) ) { /* ** SERVER_CONTROL is required to add a server entry. */ if ( opflags & GCN_OPFLAG_SRV ) status = gca_chk_priv( user, GCA_PRIV_SERVER_CONTROL ); /* ** NET_ADMIN is required to add a global vnode entry. */ if ( opflags & GCN_OPFLAG_VNODE && opflags & GCN_OPFLAG_PUB ) status = gca_chk_priv( user, GCA_PRIV_NET_ADMIN ); if ( status != OK ) { gcn_error( status, NULL, user, mbout ); return( status ); } } /* Scan name list for given service class. */ if ( ! (nq = gcn_nq_find( gcn_type )) ) if ( ! (opflags & GCN_OPFLAG_SRV) ) { /* Can't find class. */ gcn_error( E_GC0100_GCN_SVRCLASS_NOTFOUND, NULL, gcn_type, mbout ); return( E_GC0100_GCN_SVRCLASS_NOTFOUND ); } else if ( ! (nq = gcn_nq_create( gcn_type )) ) { gcn_error( E_GC0121_GCN_NOMEM, NULL, gcn_type, mbout ); return( E_GC0121_GCN_NOMEM ); } /* ** Matching entries are deleted prior to adding new entries. ** When merging, only exact duplicates are deleted. Otherwise, ** matches depend on various tuple fields for different classes. */ if ( nq->gcn_transient ) { /* ** Registered servers match on listen address (value). ** UID is overloaded with formatted server flags. */ if ( ! (opflags & GCN_OPFLAG_MRG) ) masktup->obj = ""; masktup->uid = ""; CVlx( (long)srv_flags, flagbuf ); } else if ( opflags & GCN_OPFLAG_NODE ) { /* ** VNODE connection entries match on UID and VNODE (object). */ if ( ! (opflags & GCN_OPFLAG_MRG) ) masktup->val = ""; } else if ( opflags & GCN_OPFLAG_LOGIN ) { /* ** VNODE login entries match on UID and VNODE (object). ** Multiple values (merged entries) are not permitted. */ masktup->val = ""; } else if ( opflags & GCN_OPFLAG_ATTR ) { /* ** VNODE attribute entries match on UID, VNODE (object) ** and attribute name. */ if ( ! (opflags & GCN_OPFLAG_MRG) ) { /* ** Tuple value is attribute name and its value. ** Build match value to only have attribute name. */ char *pv[2]; i4 str_len = STlength( masktup->val ) + 1; if ( str_len > sizeof( valbuf ) ) { newval = (char *)MEreqmem( 0, str_len, FALSE, NULL ); if ( ! newval ) return( E_GC0121_GCN_NOMEM ); } (void)gcu_words( masktup->val, newval, pv, ',', 2 ); str_len = STlength( pv[0] ); pv[0][str_len] = ','; pv[0][str_len + 1] = '\0'; masktup->val = pv[0]; } } if ( gcn_nq_lock( nq, TRUE ) == OK ) { /* ** First delete any overlapping tuples and ** report that to the user. */ status = (row_count = gcn_nq_del( nq, masktup )) ? gcn_result( mbout, GCN_DEL, row_count ) : OK ; /* ** Insert the tuples into the name queue. */ for( row_count = tup_count = 0; status == OK && tup_count < num_tuple; tup_count++ ) { GCN_TUP tup; char buff[ 256 ]; char *login = buff; /* ** Get next tuple from user request. */ msg_in += gcu_get_str( msg_in, &gcn_type ); msg_in += gcn_get_tup( msg_in, &tup ); /* ** All tuples must have the same class. */ if ( ! gcn_type[0] ) gcn_type = IIGCn_static.svr_type; CVupper( gcn_type ); if ( STcompare( nq->gcn_type, gcn_type ) ) continue; /* ** Set user ID appropriately. */ if ( nq->gcn_transient ) tup.uid = flagbuf; else if ( opflags & GCN_OPFLAG_PUB ) tup.uid = GCN_GLOBAL_USER; else if ( ! (opflags & GCN_OPFLAG_UID) ) tup.uid = user; /* ** Login passwords are encrypted by the client ** and must be transformed into storage format. */ if ( opflags & GCN_OPFLAG_LOGIN ) { /* ** The encryption algorithm for storage produces ** a slightly longer string than the communication ** encryption. Ensure temp buffer is large enough. ** 50% larger is more than sufficient for current ** algorithm. */ i4 len = (STlength( tup.val ) * 3) / 2; if ( len >= sizeof( buff ) ) login = (char *)MEreqmem( 0, len + 1, FALSE, NULL ); if ( ! login ) status = E_GC0121_GCN_NOMEM; else { transform_login( tup.val, login ); tup.val = login; } } if ( status == OK ) { row_count += gcn_nq_add( nq, &tup ); if ( login != buff ) MEfree( (PTR)login ); } } if ( status == OK ) status = gcn_result( mbout, GCN_ADD, row_count ); else gcn_error( status, NULL, NULL, mbout ); gcn_nq_unlock( nq ); } else { status = E_GC0134_GCN_INT_NQ_ERROR; gcn_error( status, NULL, NULL, mbout ); } if ( newval != valbuf ) MEfree( (PTR)newval ); return( status ); }
STATUS gcn_oper_ns ( GCN_MBUF *mbin, GCN_MBUF *mbout, char *user, bool trusted ) { char *msg_in = mbin->data; char *tup_list; char *gcn_install; char *gcn_type; GCN_TUP tup; i4 opcode; i4 opflags = 0; i4 flags; i4 num_tuple; STATUS status = OK; CL_SYS_ERR sys_err; /* ** Retrieve GCN_NS_OPER message contents. */ msg_in += gcu_get_int( msg_in, &flags ); if ( trusted ) opflags |= GCN_OPFLAG_TRUST; /* Trusted */ if ( flags & GCN_PUB_FLAG ) opflags |= GCN_OPFLAG_PUB; /* Global */ if ( flags & GCN_UID_FLAG ) opflags |= GCN_OPFLAG_UID; /* Set UID */ if ( flags & GCN_MRG_FLAG ) opflags |= GCN_OPFLAG_MRG; /* Merge */ flags &= ~(GCN_MRG_FLAG | GCN_UID_FLAG); /* Remove internal flags */ msg_in += gcu_get_int( msg_in, &opcode ); msg_in += gcu_get_str( msg_in, &gcn_install ); msg_in += gcu_get_int( msg_in, &num_tuple ); if ( num_tuple > 0 ) { tup_list = msg_in; /* Tuple list needed for GCN_ADD */ msg_in += gcu_get_str( msg_in, &gcn_type ); msg_in += gcn_get_tup( msg_in, &tup ); /* Check for default server class */ if ( ! gcn_type[0] ) gcn_type = IIGCn_static.svr_type; CVupper( gcn_type ); if ( ! STcompare( gcn_type, GCN_NODE ) ) opflags |= GCN_OPFLAG_NODE; /* VNODE connection info */ else if ( ! STcompare( gcn_type, GCN_LOGIN ) ) opflags |= GCN_OPFLAG_LOGIN; /* VNODE login info */ else if ( ! STcompare( gcn_type, GCN_ATTR ) ) opflags |= GCN_OPFLAG_ATTR; /* VNODE attribute info */ else if ( ! STcompare( gcn_type, GCN_LTICKET ) || ! STcompare( gcn_type, GCN_RTICKET ) ) opflags |= GCN_OPFLAG_TICK; /* IP local/remote tickets */ else if ( ! STcompare( gcn_type, "SERVERS" ) ) opflags |= GCN_OPFLAG_SRVS; /* All registered servers */ else opflags |= GCN_OPFLAG_SRV; /* Anything else is a server */ /* ** Set user ID. IP tickets and public entries are user ** independent. In general, the client user ID is used ** (overwrites requested user ID) unless the Set UID flag ** has been specified (and client has NET_ADMIN privilege). */ if ( opflags & GCN_OPFLAG_TICK ) tup.uid = ""; else if ( opflags & GCN_OPFLAG_PUB ) tup.uid = GCN_GLOBAL_USER; else if ( ! (opflags & GCN_OPFLAG_UID) ) tup.uid = user; } /* ** Check that user has required privileges for operation requested. ** (These checks are bypassed if client is trusted.) */ if ( ! (opflags & GCN_OPFLAG_TRUST) ) { /* ** NET_ADMIN is required to access IP local/remote tickets. */ if ( opflags & GCN_OPFLAG_TICK ) status = gca_chk_priv( user, GCA_PRIV_NET_ADMIN ); /* ** NET_ADMIN is required to access another users's VNODE entry. */ if ( opflags & GCN_OPFLAG_VNODE && opflags & GCN_OPFLAG_UID ) status = gca_chk_priv( user, GCA_PRIV_NET_ADMIN ); /* ** SERVER_CONTROL is required to shutdown Name Server. */ if ( opcode == GCN_SHUTDOWN ) status = gca_chk_priv( user, GCA_PRIV_SERVER_CONTROL ); if ( status != OK ) { gcn_error( status, NULL, user, mbout ); return( status ); } } switch( opcode ) { case GCN_DEL : if ( num_tuple != 1 || opflags & GCN_OPFLAG_SRVS ) status = gcn_result( mbout, opcode, 0 ); /* Nothing to do... */ else status = gcn_op_del( mbout, user, gcn_type, &tup, opflags ); break; case GCN_ADD : if ( opflags & GCN_OPFLAG_SRVS ) status = gcn_result( mbout, opcode, 0 ); /* Nothing to do... */ else status = gcn_op_add( tup_list, mbout, user, gcn_type, &tup, num_tuple, opflags, flags ); break; case GCN_RET : if ( num_tuple != 1 ) status = gcn_result( mbout, opcode, 0 ); /* Nothing to do... */ else if ( opflags & GCN_OPFLAG_SRVS ) status = gcn_op_servers( mbout, &tup, opflags ); else status = gcn_op_get( mbout, gcn_type, &tup, opflags ); break; case GCN_SHUTDOWN: /* ** Deassign the nameserver listen logical */ GCnsid( GC_CLEAR_NSID, NULL, 0, &sys_err ); gcn_result( mbout, GCN_SHUTDOWN, 0 ); status = E_GC0152_GCN_SHUTDOWN; break; } return( status ); }
/* ** Name: main -main routine. ** ** Description: ** This routine is the main control routine for iirundbms. Starting an ** iidbms server consists of: ** 1) Opening and reading the PM data ** 2) Validating server arguments, converting to VMS internal format. ** 3) Creating mailbox for communication with server. ** 4) creating server processing. ** 5) Sending server process its commands. ** 6) Checking whether server startup succeeded or not. ** ** iirundbms command line format is: ** iirundbms <server type> <server flavor> ** where server type is something like "dbms", "recovery", "star", and ** server flavor is something like "public", "nonames", "benchmark". ** ** Inputs: ** argc - number of arguments (should be 1, 2 or 3) ** argv - argument array. ** ** Outputs: ** None ** ** Returns: ** a VMS status code is returned. ** ** History: ** 31-jan-1994 (bryanp) ** Added comment header. ** 21-Jan-1998 (horda03) Bug 68559 ** For GCC servers where a server flavour has been specified, ** command line to start the server must specify the server ** flavour in the form; "-instance=<server_flavor>" in order ** for the GCC to pickup the correct configuration details. ** 22-feb-1998 (chash01) ** RMCMD (Visual DBA backend server) startup takes two VMS CREPRC ** calls, one ihere, one in rmcmd.exe. When RMCMD server starts ** the PID returned by CREPRC in this module is no longer valid. ** WE have to first decode pid in the t_user_data field returned by ** RMCMD server in termination mailbox before print PID and ** server name to terminal. ** 31-Aug-2007 (ashco01) Bug #113490 & Bug #119021. ** Corrected detection of 'instance name' for GCB & GCD. ** 05-Dec-2007 (ashco01) Bug #119561. ** Ensure that all Ingres back-end detached processes define the ** SYS$SCRATCH logical as this is referenced via II_TEMPORARY ** when placing temporary DCL files. ** 10-Dec-2007 (ashco01) Bug #119561 ** Define SYS$SCRATCH within all detached processes. */ main( int argc, char **argv ) { static $DESCALLOC( prcnam ); unsigned int pqlcnt = 0; $DESCALLOC( uicdsc ); char *param; char prcbuf[16]; ACCDEF2 accmsg; unsigned int pid; unsigned short chan; unsigned short term; unsigned int mbxunt; int dviitem; char buf[128], tmp[128]; II_VMS_MASK_LONGWORD efc_state; char *log_start_commands; IOSB iosb; ER_ARGUMENT dummy_arg; i4 i; STATUS status; i4 gcc = 0; i4 gcc_instance = 0; i4 gcb = 0; i4 gcb_instance = 0; i4 gcd = 0; i4 gcd_instance = 0; /* ** setup the type and server_flavor parameters */ if ( argc >= 2 ) { server_type = argv[1]; /* Are we starting a GCB, GCC or GCD ? */ if (STbcompare( server_type, 3, "gcc", 3, TRUE ) == 0) gcc++; if (STbcompare( server_type, 3, "gcb", 3, TRUE ) == 0) gcb++; if (STbcompare( server_type, 3, "gcd", 3, TRUE ) == 0) gcd++; } if ( argc >= 3 ) { server_flavor = argv[2]; /* Need to precede server_flavor with "-instance=" ** if we're starting a GCB, GCC or GCD. */ gcc_instance = gcc; gcb_instance = gcb; gcd_instance = gcd; } /* ** initialize PM routines and setup the default ** search parameters for config.dat */ status = PMinit( ); if (status) { pmerr_func(status, 0, &dummy_arg); return (status); } switch( status = PMload((LOCATION *)NULL, pmerr_func) ) { case OK: /* Loaded sucessfully */ break; case PM_FILE_BAD: /* syntax error */ if (status != FAIL) /* As of Nov 1993, PM.H defines PM_FILE_BAD 1 */ pmerr_func(status, (i4)0, &dummy_arg); return (status); default: /* unable to open file */ if (status != FAIL) /* FAIL is a useless status to report... */ pmerr_func(status, (i4)0, &dummy_arg); return (status); } #ifdef EDBC PMsetDefault( 0, ERx( "ed" ) ); #else PMsetDefault( 0, ERx( "ii" ) ); #endif PMsetDefault( 1, PMhost( ) ); PMsetDefault( 2, server_type ); PMsetDefault( 3, server_flavor ); /* read and process pm parameters */ for ( i = 0; pm_option[i].PM_name != NULL; i++ ) { status = PMget( pm_option[i].PM_name, ¶m ); if ( status != OK ) continue; switch ( pm_option[i].type ) { unsigned int *target; case TYPE_CLRFLG: if ( STbcompare(param, 0, "off", 0, TRUE) != 0 && STbcompare(param, 0, "on", 0, TRUE) != 0 ) { SIprintf("IIRUNDBMS: %s value must be ON or OFF\n", pm_option[i].PM_name); SIflush(stdout); log_errmsg( "Must be ON or OFF", SS$_BADPARAM, 1 ); return (SS$_BADPARAM); } target = (unsigned int *)pm_option[i].target; if ( STbcompare(param, 0, pm_option[i].keyword, 0, TRUE) == 0) *target &= ~(int)pm_option[i].parameter; if ( msg_echo && (STscompare( pm_option[i].PM_name, 0, echo, 0 ) == 0) ) ERoptlog( pm_option[i].PM_name, param ); break; case TYPE_SETFLG: if ( STbcompare(param, 0, "off", 0, TRUE) != 0 && STbcompare(param, 0, "on", 0, TRUE) != 0 ) { SIprintf("IIRUNDBMS: %s value must be ON or OFF\n", pm_option[i].PM_name); SIflush(stdout); log_errmsg( "Must be ON or OFF", SS$_BADPARAM, 1 ); return (SS$_BADPARAM); } target = (unsigned int *)pm_option[i].target; if ( STbcompare(param, 0, pm_option[i].keyword, 0, TRUE) == 0) *target |= (int)pm_option[i].parameter; if ( msg_echo ) ERoptlog( pm_option[i].PM_name, param ); break; case TYPE_INT: target = (unsigned int *)pm_option[i].target; status = CVal( param, target ); if (status) { SIprintf("IIRUNDBMS: %s value must be an integer\n", pm_option[i].PM_name); SIflush(stdout); pmerr_func(status, 0, &dummy_arg); return (SS$_BADPARAM); } if ( msg_echo ) { STprintf( buf, "%d", *target ); ERoptlog( pm_option[i].PM_name, buf ); } break; case TYPE_UIC: { $DESCINIT( uicdsc, param ); status = iics_cvtuic( &uicdsc, (char *)pm_option[i].target ); if ( !(status & 1) ) { log_errmsg( "vms_uic invalid", status, 1 ); return (status); /* B56811 */ } if ( msg_echo ) { if ( *(unsigned int *)(pm_option[i].target) != 0 ) { STprintf( buf, "%s [%o,%o]", param, ((uic >> 16) & 0xffff), (uic & 0xffff) ); ERoptlog( pm_option[i].PM_name, buf ); } } break; } case TYPE_STR: if (STlength(param) > MAX_STRING_OPTION_LENGTH) { SIprintf("IIRUNDBMS: Max length for %s is %d\n", pm_option[i].PM_name, MAX_STRING_OPTION_LENGTH); SIflush(stdout); return (SS$_BADPARAM); } STcopy( param, (char *)pm_option[i].target ); if ( msg_echo ) ERoptlog( pm_option[i].PM_name, param ); break; case TYPE_PQL: /* ** build VMS process quota block */ quota[pqlcnt].name = (char)pm_option[i].parameter; status = CVal( param, "a[pqlcnt].value ); if (status) { SIprintf("IIRUNDBMS: %s value must be an integer\n", pm_option[i].PM_name); SIflush(stdout); pmerr_func(status, 0, &dummy_arg); return (SS$_BADPARAM); } pqlcnt++; if ( msg_echo ) ERoptlog( pm_option[i].PM_name, param ); break; case TYPE_PRIV: { char prvbuf[512]; char *p, *q; i4 j; /* ** Remove white space then ** convert the string to upper case, then ** remove leading and trailing parens */ if (STlength(param) >= sizeof(prvbuf)) { SIprintf("IIRUNDBMS: vms_privileges are too long\n"); SIprintf(" Actual length (%d) exceeds maximum (%d)\n", STlength(param), sizeof(prvbuf)); SIflush(stdout); return (SS$_BADPARAM); } STcopy( param, prvbuf); STtrmwhite( prvbuf ); CVupper( prvbuf ); /* ** Scan the comma seperated privilege list and set the ** privileges for each privileges keywork in the list. */ for ( p = prvbuf; p != 0 && *p != 0; p = q ) { if ( (q = STindex( p, ERx( "," ), 0 )) != NULL ) *q++ = '\0'; else if ( (q = STindex( p, ERx( ")" ), 0 )) != NULL ) *q++ = '\0'; if ( *p == '(' ) p++; for ( j = 0; prv_table[j].prv_name != NULL; j++ ) { if ( STscompare( p, 4, prv_table[j].prv_name, 4 ) == 0 ) { prvadr[0] |= prv_table[j].prv_code_low; prvadr[1] |= prv_table[j].prv_code_hi; if ( msg_echo ) ERoptlog( pm_option[i].PM_name, prv_table[j].prv_name ); break; } } if (prv_table[j].prv_name == NULL) { /* ** We failed to find privilege "p" in our table */ SIprintf("IIRUNDBMS: Syntax error in privilege list\n"); SIprintf(" Error near byte %d of string %s", p - prvbuf, param); SIflush(stdout); ERoptlog("Unrecognized privilege:", p); return (SS$_BADPARAM); } } break; } default: break; } }
i4 main( i4 argc, char **argv ) { STATUS generic_status = OK; CL_ERR_DESC system_status; EX_CONTEXT context; STATUS status; GCC_ERLIST erlist; STATUS (*call_list[7])(); i4 i, call_count; i4 cmd_args = 0; char usage[] = { "Usage: iigcb -from <protocol>" }; char usage1[] = { " -to <protocol> <hostname> < listen_address>" }; #ifdef LNX PCsetpgrp(); #endif MEfill( sizeof( system_status ), 0, (PTR)&system_status ); MEadvise( ME_INGRES_ALLOC ); EXdeclare( GCX_exit_handler, &context ); SIeqinit(); /* ** Parse command line. */ for( i = 1; i < argc; i++ ) if ( ! STcompare( argv[i], "-from" ) ) { if ( ++i >= argc ) { SIfprintf( stderr, "\n%s%s\n\n", usage, usage1 ); SIflush( stderr ); SIstd_write(SI_STD_OUT, "\nFAIL\n"); EXdelete(); PCexit( FAIL ); } STcopy( argv[i], gcb_from_addr.n_sel ); CVupper( gcb_from_addr.n_sel ); ++cmd_args; } else if ( ! STcompare( argv[ i ], "-to" ) ) { if ( (i + 3) >= argc ) { SIfprintf( stderr, "\n%s%s\n\n", usage, usage1 ); SIflush( stderr ); SIstd_write(SI_STD_OUT, "\nFAIL\n"); EXdelete(); PCexit( FAIL ); } STcopy( argv[ ++i ], gcb_to_addr.n_sel ); STcopy( argv[ ++i ], gcb_to_addr.node_id ); STcopy( argv[ ++i ], gcb_to_addr.port_id ); CVupper( gcb_to_addr.n_sel ); ++cmd_args; } if ( cmd_args ) if ( cmd_args == 2 ) gcb_pm_reso.cmd_line = TRUE; else { SIfprintf( stderr, "\n%s%s\n\n", usage, usage1 ); SIflush( stderr ); SIstd_write(SI_STD_OUT, "\nFAIL\n"); EXdelete(); PCexit( FAIL ); } /* ** Perform general initialization. The bridge may be run ** for async lines as a part of Ingres/Net. Otherwise, ** Bridge authorization is required. */ if ( gcb_pm_reso.cmd_line && ! STcasecmp( gcb_from_addr.n_sel, ERx("async") ) ) status = gcc_init( FALSE, CI_INGRES_NET, argc, argv, &generic_status, &system_status ); else { #ifdef CI_INGRES_BRIDGE status = gcc_init( FALSE, CI_INGRES_BRIDGE, argc, argv, &generic_status, &system_status ); #else generic_status = E_GC2A0F_NO_AUTH_BRIDGE; status = FAIL; #endif } if ( status != OK ) { gcc_er_log( &generic_status, &system_status, NULL, NULL ); generic_status = E_GC2A01_INIT_FAIL; gcc_er_log( &generic_status, NULL, NULL, NULL ); SIstd_write(SI_STD_OUT, "\nFAIL\n"); EXdelete(); PCexit( FAIL ); } /* ** Perform standalong Bridge Server initialization. */ IIGCc_global->gcc_flags |= GCC_STANDALONE; gcb_init_mib(); /* ** Initialize the protocol layers. */ call_list[0] = GCcinit; call_list[1] = gcb_alinit; call_list[2] = gcc_pbinit; call_count = 3; if ( gcc_call( &call_count, call_list, &generic_status, &system_status ) != OK ) { gcc_er_log( &generic_status, &system_status, NULL, NULL ); generic_status = E_GC2A01_INIT_FAIL; gcc_er_log( &generic_status, NULL, NULL, NULL ); SIstd_write(SI_STD_OUT, "\nFAIL\n"); } else { { /* ** Obtain and fix up the configuration name, then log it. */ char server_flavor[256], server_type[32]; char *tmpbuf = PMgetDefault(3); if (!STbcompare( tmpbuf, 0, "*", 0, TRUE )) STcopy("(DEFAULT)", server_flavor); else STcopy(tmpbuf, server_flavor); STcopy(PMgetDefault(2), server_type); CVupper(server_type); erlist.gcc_parm_cnt = 2; erlist.gcc_erparm[0].value = server_flavor; erlist.gcc_erparm[0].size = STlength(server_flavor); erlist.gcc_erparm[1].value = server_type; erlist.gcc_erparm[1].size = STlength(server_type); generic_status = E_GC2A10_LOAD_CONFIG; gcc_er_log( &generic_status, (CL_ERR_DESC *)NULL, (GCC_MDE *)NULL, &erlist); } erlist.gcc_parm_cnt = 1; erlist.gcc_erparm[0].size = STlength( IIGCc_rev_lvl ); erlist.gcc_erparm[0].value = IIGCb_rev_lvl; generic_status = E_GC2A03_STARTUP; gcc_er_log( &generic_status, NULL, NULL, &erlist ); /* ** Invoke GCexec to enter the main phase of Protocol bridge ** execution. GCexec does not return until bridge shutdown ** is initiated by invoking GCshut. */ GCexec(); generic_status = E_GC2A04_SHUTDOWN; gcc_er_log( &generic_status, &system_status, NULL, NULL ); } /* ** GCexec has returned. Bridge shutdown is in process. ** Initialize the call list to specify termination rotutines. ** Call in reverse order of initialization but don't call ** termination routines whose initialization routines were ** not called (call_count has the number of successful ** initialization calls). */ call_list[0] = gcb_alterm; call_list[1] = gcc_pbterm; call_list[2] = GCcterm; if ( gcc_call( &call_count, &call_list[ 3 - call_count ], &generic_status, &system_status ) ) gcc_er_log( &generic_status, &system_status, NULL, NULL ); /* ** Do general server termination. */ if ( gcc_term( &generic_status, &system_status ) != OK ) gcc_er_log( &generic_status, &system_status, NULL, NULL ); EXdelete(); PCexit( OK ); } /* end main */