Exemple #1
0
/*{
** 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;
}
Exemple #2
0
/*
** 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;
}
Exemple #3
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 );
}
Exemple #4
0
/*
** 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;
}
Exemple #5
0
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;
}
Exemple #6
0
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 );
}
Exemple #7
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);
}
Exemple #8
0
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 );
}
Exemple #9
0
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 );
}
Exemple #10
0
/*
** 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, &param );
	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, &quota[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;
	}
    }
Exemple #11
0
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 */