Ejemplo n.º 1
0
bool
adu_1monthcheck(
char    *input,
i4	*output)
{
    i4			    month;

    /* month can be an integer, or an alphanumeric code */

    if (CVal(input, &month) == OK)
    {
        *output = month;
        return (month < 1 || month > MONTHS_PER_YR);
    }
    else
    {
	const ADU_DATENAME *d;

        _VOID_ CVlower(input);

	d = adu_monthname_lookup(input,STlength(input));
	if (d == NULL)
	{
	    *output = 0;
	    return 1;
	}

	*output = d->d_value; 
	return (d->d_class != 'm'); /* TWISTED LOGIC! */
    }
}
Ejemplo n.º 2
0
static II_BOOL
ns_param_marker( API_PARSE *parse, i4  fld, i4  *index )
{
    II_BOOL	marker = FALSE;
    i4	value;

    if ( parse->fields[ fld ][0] == '~'  &&  parse->fields[ fld ][1] == 'V' )
    {
	/*
	** Was an explicit parameter index
	** included with the marker?
	*/
	if ( parse->fields[ fld ][2]  &&
	     CVal( &parse->fields[ fld ][2], &value ) == OK )
	    *index = value;

	/*
	** Convert field from text to parameter.
	*/
	parse->parameter[ fld ] = *index;	/* Parameter index */
	parse->fields[ fld ][0] = EOS;		/* Parameter value */
	(*index)++;				/* Next default index */
	marker = TRUE;
    }

    return( marker );
}
Ejemplo n.º 3
0
Archivo: sort.c Proyecto: NavamiK/C5.0
void Quicksort(CaseNo Fp, CaseNo Lp, Attribute Att)
/*   ---------  */
{
    CaseNo	i, Middle, High;
    ContValue	Thresh, Val;

    if ( Fp < Lp )
    {
	Thresh = CVal(Case[(Fp+Lp) / 2], Att);

	/*  Divide cases into three groups:
		Fp .. Middle-1: values < Thresh
		Middle .. High: values = Thresh
		High+1 .. Lp:   values > Thresh  */

	for ( Middle = Fp ; CVal(Case[Middle], Att) < Thresh ; Middle++ )
	    ;

	for ( High = Lp ; CVal(Case[High], Att) > Thresh ; High-- )
	    ;

	for ( i = Middle ; i <= High ; )
	{
	    if ( (Val = CVal(Case[i], Att)) < Thresh )
	    {
		Swap(Middle, i);
		Middle++;
		i++;
	    }
	    else
	    if ( Val > Thresh )
	    {
		Swap(High, i);
		High--;
	    }
	    else
	    {
		i++;
	    }
	}

	/*  Sort the first and third groups  */

	Quicksort(Fp, Middle-1, Att);
	Quicksort(High+1, Lp, Att);
    }
}
Ejemplo n.º 4
0
void Quicksort(CaseNo Fp, CaseNo Lp, Attribute Att)
/*   ---------  */
{
    CaseNo i;

    ForEach(i, Fp, Lp)
    {
	Pair[i].C = CVal(Case[i], Att);
	Pair[i].D = Case[i];
    }
Ejemplo n.º 5
0
/*{
** Name: CS_map_sys_segment()	- Map the system control segment to this process
**
** Description:
**	Maps the system control block to this process.  This must happen before
**	any other action can be taken on shared memory (with the exception of
**	CS_create_sys_segment()).
**
**	Upon successful exectution of this routine CS may manipulate the system
**	control data structure CS_SMCNTRL (taking care to use proper semaphore
**	techniques which take into account that the data structure is shared
**	across processes).
**
**	This call is internal to CS is meant only to be called by CS, and may
**	only exist on unix systems supporting shared memory.
**
** Inputs:
**	none.
**
** Outputs:
**      cssm_segment			ptr to the CS_SMCNTRL data structure.
**      err_code			system dependent error information.
**
**	Returns:
**	    E_DB_OK
**
**	Exceptions:
**	    none
**
** Side Effects:
**	    none
**
** History:
**      08-Sep-88 (mmm)
**          First Version
**	12-jun-89 (rogerk)
**	    Added allocated_pages argument to MEget_pages calls.
**	    Changed shared memory key from a LOCATIONN pointer to a character
**	    string.
**      26-aug-89 (rexl)
**          Added calls to protect page allocator.
**	18-oct-1993 (bryanp)
**	    Issue trace messages in failure cases. Simply returning FAIL doesnt
**		help the diagnosis process very much, while the trace messages
**		can help (if the caller has done a TRset_file by this point).
**	14-Oct-1998 (jenjo02)
**	    CS_map_sys_segment(): Don't initialize css_spinlock. That was done 
**	    when the shared segment was created. Reinitializing it may 
**	    effectively destroy a holding process's lock!
**	21-May-2004 (wanfr01)
**	    INGSRV2835, Bug 112371
**	    As per the Jon Jensen's last update, removed the invalid initialize
**	    of css_spinlock.
**	5-Apr-2006 (kschendel)
**	    Use generated css version instead of constant.
** 12-aug-2008 (stephenb)
**		previous change is too strict if programs not shipped with Ingres
**		try to connect to the system segment because the checked version
**		goes right down to the build number. allow some latitude using
**		II_SYSSEG_VERS. If this is set to the current major Ingres 
**		version we will allow the connection. This is an interim 
**		solution to Golden Gate's issue.
*/
STATUS
CS_map_sys_segment(CL_ERR_DESC *err_code)
{
    STATUS	status = OK;
    PTR		address;
    SIZE_TYPE	alloc_pages;

    /* map segment into first available address and then initialize it */
    /* Use "sysseg.mem" as shared memory key. */
    address = 0;
    status = MEget_pages(ME_SSHARED_MASK, 0, "sysseg.mem", &address,
                         &alloc_pages, err_code);

    if (status)
    {
#ifdef xDEBUG
	TRdisplay("CS_map_sys_segment: unable to attach to sysseg.mem (%x)\n",
			status);
#endif
	/* Unable to attach allocated shared memory segment. */
	/* status = FAIL; This isn't a useful error return code! */
    }
    else
    {
    	char	*segvers;
    	i4		segint;
    	
    	Cs_sm_cb = (CS_SMCNTRL *) address;
    	/* 
    	** check if segment version has been provided, if so we'll
    	** deem it O.K. if it matches the current major version
    	*/
    	NMgtAt("II_SYSSEG_VERS", &segvers);
    	if (segvers != (char *)NULL && *segvers != EOS && 
    			CVal(segvers, &segint) == OK && segint == GV_MAJOR)
    		status = OK;
    	else
    	{
    		i4 id = make_css_version();
	
			if (Cs_sm_cb->css_version != id)
			{
			    TRdisplay(
		"CS_map_sys_segment: sysseg.mem is version %x (%d). We need version %x (%d)\n",
				Cs_sm_cb->css_version, Cs_sm_cb->css_version,
				id, id);
			    SETCLERR(err_code, 0, 0);
			    status = FAIL;
			}
    	}
    }

    return(status);
}
Ejemplo n.º 6
0
static STATUS
my_dynamic_index(i4 msg,
		 PTR cdata,
		 i4  linstance,
		 char *instance, 
		 PTR *instdata )
{
    STATUS stat = OK;
    i4 ival;
    char buf[ 20 ];

    switch( msg )
    {
    case MO_GET:
	*instdata = (PTR)instance;
	break;

    case MO_GETNEXT:
	if( *instance == EOS )
	    ival = 0;

	stat = CVal( instance, &ival ); /* value is the instance */
	if( stat != OK )
	    break;
	
	if( ival > 9 )		/* validate this instance */
	    stat = MO_NO_INSTANCE;
	else if( ++ival > 9 ) /* validate next */
	    stat = MO_NO_NEXT;

	if( stat != OK )
	    break;

	CVla( ival, buf );
	
	/* assumes caller doesn't blast instance before passing
	   it to a get/set method.  Otherwise hard to handle,
	   because we don't want to allocate memory here to
	   be freed in the get or set routine. */

	*instdata = (PTR)instance;
	
	STncpy( instance, buf, linstance );
	instance [ linstance ] = EOS;
	if( STlength( buf ) != STlen ( instance ))
	    stat = MO_INSTANCE_TRUNCATED;

	break;

    default:
	stat = MO_BAD_MSG;
    }
    return( stat );
}
Ejemplo n.º 7
0
static STATUS
myintset( i4  offset,
	 i4  luserbuf,
	 char *userbuf,
	 i4  objsize,
	 PTR object )
{
    STATUS stat;
    i4 tval;

    stat = CVal( userbuf, &tval );
    if( stat == OK )
	private_num = tval;
    
    return( stat );
}
Ejemplo n.º 8
0
/*{
** Name: get_value()	- get value 
**
** Description:
**	Return value of symbol input.  If symbol is not set in the environment
**	then return "default_value".
**
** Inputs:
**	symbol		The string representation of the symbol (ie. "II_SYM")
**	default_value	An integer default value to be returned if symbol not
**			found in the environment.
** Outputs:
**	none.
**
**
**	Returns:
**	      value of the symbol if set in environment, else returns
**	      whatever "default_value" was input.
**
** History:
**      06-apr-92 (mikem)
**         Created.
*/
static i4
get_value(char *symbol, i4 default_value)
{
    i4		value = default_value; 
    char	*string;
    i4	env_value;
    
    NMgtAt(symbol, &string);
    if (string                &&
	*string               &&
	(!CVal(string, &env_value)))
    {
	/* user override of default */
	value = env_value;
    }

    return(value);
}
Ejemplo n.º 9
0
STATUS
gca_ns_init( VOID )
{
#ifdef GCF_EMBEDDED_GCN

    char	*ptr, host[ 50 ];
    char	*pm_default[ PM_MAX_ELEM ];
    i4		count;
    STATUS	status = OK;

    /*
    ** We do not want to initialize the embedded Name Server
    ** interface if this is the actual Name Server.  The Name
    ** Server initializes the interface before initializing
    ** GCA, so check to see if IIGCn_static is initialized,
    ** indicating that gcn_init() has already been called.
    */
    if ( IIGCn_static.maxsessions )  return( OK );

    /*
    ** Check to see if tracing of Name Server code
    ** is enabled (for whoever we are) before resetting
    ** PM for the Name Server.
    */
    gcu_get_tracesym( "II_GCN_TRACE", "!.gcn_trace_level", &ptr );
    if ( ptr  &&  *ptr )  CVal( ptr, &IIGCn_static.trace );

    /*
    ** Save current PM defaults and set up for Name Server.
    */
    for( count = 0; count < PM_MAX_ELEM; count++ )
	pm_default[ count ] = PMgetDefault( count );

    PMsetDefault( 0, SystemCfgPrefix );	/* Name Server defaults */
    PMsetDefault( 1, PMhost() );
    PMsetDefault( 2, ERx( "gcn" ) );

    for( count = 3; count < PM_MAX_ELEM; count++ )
	PMsetDefault( count, NULL );

    /*
    ** Initialize embedded Name Server.
    */
    GChostname( host, sizeof( host ) );
    if ( gcn_srv_init() != OK  ||  gcn_srv_load( host, NULL ) != OK )
	status = E_GC0013_ASSFL_MEM;

    /*
    ** Reset PM defaults.
    */
    for( count = 0; count < PM_MAX_ELEM; count++ )
	PMsetDefault( count, pm_default[ count ] );


    return( status );

#else /* GCA_EMBEDDED_GCN */

    return( OK );

#endif /* GCA_EMBEDDED_GCN */
}
Ejemplo n.º 10
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 );
}
Ejemplo n.º 11
0
/*{
** Name: LGK_initialize()	-  initialize the lg/lk shared mem segment.
**
** Description:
**	This routine is called by the LGinitialize or LKinitialize routine.  IT
**	assumes that a previous caller has allocated the shared memory segment.
**
**	If it discovers that the shared memory segment has not yet been
**	initialized, it calls the LG and LK initialize-memory routines to do so.
**
** Inputs:
**	flag		- bit mask of:
**			  LOCK_LGK_MEMORY to lock the shared data segment
**			  LGK_IS_CSP if process is CSP process this node.
**
** Outputs:
**	sys_err		- place for system-specific error information.
**
**	Returns:
**	    OK	- success
**	    !OK - failure (CS*() routine failure, segment not mapped, ...)
**	
**  History:
**	Summer, 1992 (bryanp)
**	    Working on the new portable logging and locking system.
**	19-oct-1992 (bryanp)
**	    Check memory version number when attaching.
**	22-oct-1992 (bryanp)
**	    Change LGLKDATA.MEM to lglkdata.mem.
**	23-Oct-1992 (daveb)
**	    name the semaphore too.
**	13-feb-1993 (keving)
**	    Remove support for II_LGK_MEMORY_SIZE. If II_LG_MEMSIZE
**	    is not set then calculate memory size from PM values. 
**	24-may-1993 (bryanp)
**	    If the shared memory is the wrong version, don't install the
**	    at_exit handlers (the rundown routines won't be able to interpret
**	    the memory properly).
**	26-jul-1993 (jnash)
**	    Add 'flag' param lock the LGK data segment.
**	20-sep-1993 (bryanp)
**	    In addition to calling PCatexit, call (on VMS) sys$dclexh, since
**		there are some situations (image death and image rundown without
**		process rundown) which are caught neither by PCatexit (since
**		PCexit isn't run) nor by check-dead threads (since process
**		rundown never happened). This fixes a hole where an access-
**		violating ckpdb or auditdb command never got cleaned up.
**	31-jan-1994 (bryanp)
**	    Back out a few "features" which are proving countereffective:
**	    1) Don't bother checking mem_creator_pid to see if the previous
**		creator of the shared memory has died. This was an attempt to
**		gracefully re-use sticky shared memory following a system crash,
**		but it is suspected as being the culprit in a series of system
**		failures by re-initializing the shared memory at inopportune
**		times.
**	    2) Don't complain if the shared memory already exists but is of a
**		different size than you expected. Just go ahead and try to use
**		it anyway.
**	21-feb-1994 (bryanp)
**	    Reverse item (1) of the above 31-jan-1994 change and re-enable the
**		graceful re-use of shared memory. People weren't happy with
**		having to run ipcclean and csinstall all the time.
**	23-may-1994 (bryanp)
**	    On VMS, disable ^Y for LG/LK-aware processes. We don't want to allow
**		^Y because you might interrupt the process right in the middle
**		of an LG or LK operation, while holding the shared memory
**		semaphore, and this would then wedge the whole installation.
**          
**      17-May-1994 (daveb) 59127
**          Attach lgk_mem semaphore if we're attaching to the segment.
**      30-jan-1995 (lawst01) bug 61984
**          Use memory needed calculation from the 'lgk_calculate_size'
**          function to determine the size of the shared memory pool for
**          locking and locking. If the II_LG_MEMSIZE variable is specified
**          with a value larger than needed use the supplied value. If
**          lgk_calculate_size is unable to calculate a size then use the
**          magic number of 400000.  In addition issue a warning message
**          and continue executing in the event the number of pages
**          allocated is less than the number requested. 
**	24-apr-1997 (nanpr01)
**	    Reinstate Bryanp's change. In the process of fixing bug 61984
**	    by Steve Lawrence and subsequent undo of Steve's fix by Nick
**	    Ireland on 25-jun-96 (nick) caused the if 0 code removed.
**	    Part of the Steve's change was not reinstated such as not returning
**	    the status and exit and continue.
**	    1. Don't complain if the shared memory already exists but is of a
**	    different size than you expected. Just go ahead and try to use
**	    it.
**     18-aug-1998 (hweho01)
**          Reclaim the kernel resource if LG/LK shared memory segment is  
**          reinitialized. If the shared segment is re-used (the previous creator 
**          of the shared segment has died), the cross-process semaphores get 
**          initialized more than once at the same locations. That cause the
**          kernel resource leaks on DG/UX (OS release 4.11MU04). To fix the 
**          problem, CS_cp_sem_cleanup() is called to destroy all the 
**          semaphores before LG/LK shraed segment get recreated. 
**          CS_cp_sem_cleanup() is made dependent on xCL_NEED_SEM_CLEANUP and
**          OS_THREADS_USED, it returns immediately for most platforms.  
**	27-Mar-2000 (jenjo02)
**	    Added test for crossed thread types, refuse connection
**	    to LGK memory with E_DMA811_LGK_MT_MISMATCH.
**	18-apr-2001 (devjo01)
**	    s103715 (Portable cluster support)
**	    - Add CX mem requirement calculations.
**	    - Add LGK_IS_CSP flag to indicate that LGK memory is being
**	      initialized for a CSP process.
**	    - Add basic CX initialization.
**      19-sep-2002 (devjo01)
**          If running NUMA clustered allocate memory out of local RAD.
**	30-Apr-2003 (jenjo02)
**	    Rearchitected to silence long-tolerated race conditions.
**	    BUG 110121.
**	27-feb-2004 (devjo01)
**	    Rework allocation of CX shared memory to be compatible
**	    with race condition fix introduced for bug 110121.
**	29-Dec-2008 (jonj)
**	    If lgk_calculate_size() returns FAIL, the total memory
**	    needed exceeds MAX_SIZE_TYPE and we can't continue, but
**	    tell what we can about the needs of the various bits of
**	    memory before quitting.
**	06-Aug-2009 (wanfr01)
**	    Bug 122418 - Return E_DMA812 if LOCK_LGK_MUST_ATTACH is
**	    is passed in and memory segment does not exist
**      20-Nov-2009 (maspa05) bug 122642
**          In order to synchronize creation of UUIDs across servers added
**          a semaphore and a 'last time' variable into LGK memory. 
**      14-Dec-2009 (maspa05) bug 122642
**          #ifdef out the above change for Windows. The rest of the change
**          does not apply to Windows so the variables aren't defined.
*/
STATUS
LGK_initialize(
i4	  	flag,
CL_ERR_DESC	*sys_err,
char		*lgk_info)
{
    PTR		ptr;
    SIZE_TYPE	memleft;
    SIZE_TYPE	size;
    STATUS	ret_val;
    STATUS	mem_exists;
    char	mem_name[15];
    SIZE_TYPE	allocated_pages;
    i4		me_flags;
    i4		me_locked_flag;
    SIZE_TYPE	memory_needed;
    char	*nm_string;
    SIZE_TYPE	pages;
    LGK_MEM	*lgk_mem;
    i4		err_code;
    SIZE_TYPE   min_memory;
    i4		retries;
    i4		i;
    i4		attached;
    PID		*my_pid_slot;
    i4		clustered;
    u_i4	nodes;
    SIZE_TYPE	cxmemreq;
    PTR		pcxmem;
    LGLK_INFO	lgkcount;
    char	instid[4];

    CL_CLEAR_ERR(sys_err);

    /*
    ** if LGK_base is set then this routine has already been called.  It is
    ** set up so that both LGiniitalize and LKinitialize calls it, but only
    ** the first call does anything.
    */

    if (LGK_base.lgk_mem_ptr)
	return(OK);

    PCpid( &LGK_my_pid );

    memory_needed = 0;
    NMgtAt("II_LG_MEMSIZE", &nm_string);
    if (nm_string && *nm_string)
#if defined(LP64)
	if (CVal8(nm_string, (long*)&memory_needed))
#else
	if (CVal(nm_string, (i4 *)&memory_needed))
#endif /* LP64 */
	    memory_needed = 0;

    /* Always calculate memory needed from PM resource settings  */
    /* and compare with supplied value, if supplied value is less */
    /* than minimum then use minimum                             */

    min_memory = 0;
    if ( OK == lgk_get_counts(&lgkcount, FALSE))
    {
	if ( lgk_calculate_size(FALSE, &lgkcount, &min_memory) )
	{
	    /*
	    ** Memory exceeds MAX_SIZE_TYPE, can't continue.
	    ** 
	    ** Do calculation again, this time with "wordy"
	    ** so user can see allocation bits, then quit.
	    */
	    lgk_calculate_size(TRUE, &lgkcount, &min_memory);
	    return (E_DMA802_LGKINIT_ERROR); 
	}
    }
    if (min_memory)
       memory_needed = (memory_needed < min_memory) ? min_memory
                                                    : memory_needed;
    else
       memory_needed = (memory_needed < 400000 ) ? 400000 
                                                 : memory_needed;

    clustered = (i4)CXcluster_enabled();
    cxmemreq = 0;
    if ( clustered )
    {

	if ( OK != CXcluster_nodes( &nodes, NULL ) )
	    nodes = 0;
	cxmemreq = CXshm_required( 0, nodes, lgkcount.lgk_max_xacts,
		    lgkcount.lgk_max_locks, lgkcount.lgk_max_resources );
	if ( MAX_SIZE_TYPE - memory_needed < cxmemreq )
	{
	    /*
	    ** Memory exceeds MAX_SIZE_TYPE, can't continue.
	    ** 
	    ** Do calculation again, this time with "wordy"
	    ** so user can see allocation bits, then quit.
	    */
	    SIprintf("Total LG/LK/CX allocation exceeds max of %lu bytes by %lu\n"
	    	     "Adjust logging/locking configuration values and try again\n",
		         MAX_SIZE_TYPE, cxmemreq - (MAX_SIZE_TYPE - memory_needed));
	    lgk_calculate_size(TRUE, &lgkcount, &min_memory);
	    return (E_DMA802_LGKINIT_ERROR); 
	}
	memory_needed += cxmemreq;
    }

    if ( memory_needed < MAX_SIZE_TYPE - ME_MPAGESIZE )
	pages = (memory_needed + ME_MPAGESIZE - 1) / ME_MPAGESIZE;
    else
        pages = memory_needed / ME_MPAGESIZE;

    /*
    ** Lock the LGK segment if requested to do so
    */
    if (flag & LOCK_LGK_MEMORY)
	me_locked_flag = ME_LOCKED_MASK;
    else
	me_locked_flag = 0;

    me_flags = (me_locked_flag | ME_MSHARED_MASK | ME_IO_MASK | 
		ME_CREATE_MASK | ME_NOTPERM_MASK | ME_MZERO_MASK);
    if (CXnuma_user_rad())
        me_flags |= ME_LOCAL_RAD;

    STcopy("lglkdata.mem", mem_name);

    /*
    ** In general, we just want to attach to the shared memory and detect if
    ** we are the first process to do so. However, there are ugly race
    ** conditions to consider, as well as complications because the shared
    ** memory may be left around following a system crash.
    **
    ** First we attempt to create the shared memory. Usually it already exists,
    ** so we check for and handle the case of "already exists".
    */

    /*
    ** (jenjo02)
    **
    ** Restructured to better handle all those ugly race conditions
    ** which are easily reproduced by running two scripts, one that
    ** continuously executes "lockstat" while the other is starting
    ** and stopping Ingres.
    **
    ** For example,
    **
    **		lockstat A	acquires and init's the memory
    **		RCP		attaches to "A" memory
    **		lockstat A	terminates normally
    **		lockstat B	attaches to "A" memory, sees that
    **				"A"s pid is no longer alive, and
    **				reinitializes the memory, much to
    **				the RCP's chagrin.
    ** or (more commonly)
    **
    **		lockstat A	acquires and begins to init the mem
    **		RCP		attaches to "A" memory which is
    **				still being zero-filled by lockstat,
    **				checks the version number (zero),
    **				and fails with a E_DMA434 mismatch.
    **
    ** The fix utilizes the mem_ext_sem to synchronize multiple
    ** processes; if the semaphore hasn't been initialized or
    ** if mem_version_no is zero, we'll wait one second and retry,
    ** up to 60 seconds before giving up. This gives the creating
    ** process time to complete initialization of the memory.
    **
    ** Up to LGK_MAX_PIDS are allowed to attach to the shared
    ** memory. When a process attaches it sets its PID in the
    ** first vacant slot in lgk_mem->mem_pid[]; if there are
    ** no vacant slots, the attach is refused. When the process
    ** terminates normally by calling LGK_rundown(), it zeroes
    ** its PID slot.
    **
    ** When attaching to an existing segment, we check if  
    ** there are any live processes still using the memory;
    ** if so, we can't destroy it (no matter who created it).
    ** If there are no live processes attached to the memory,
    ** we destroy and reallocate it (based on current config.dat
    ** settings).
    */

    for ( retries = 0; ;retries++ )
    {
	LGK_base.lgk_mem_ptr = (PTR)NULL;
	
	/* Give up if unable to get memory in one minute */
#if defined(conf_CLUSTER_BUILD)
        if (retries > 1)
#else
	if ( retries )
#endif
	{
	    if ( retries < 60 )
		PCsleep(1000);
	    else
	    {
		/* Another process has it blocked way too long */
		uleFormat(NULL, E_DMA800_LGKINIT_GETMEM, (CL_ERR_DESC *)NULL,
				ULE_LOG, NULL, NULL, 0, NULL, &err_code, 0);
		/* Unable to attach allocated shared memory segment. */
		return (E_DMA802_LGKINIT_ERROR); 
	    }
	}

	ret_val = MEget_pages(me_flags,
				pages, mem_name, (PTR*)&lgk_mem,
				&allocated_pages, sys_err);

	if ( mem_exists = ret_val )
	{
	    if (ret_val == ME_ALREADY_EXISTS)
	    {
		ret_val = MEget_pages((me_locked_flag | 
				       ME_MSHARED_MASK | ME_IO_MASK),
				      pages, mem_name, (PTR*)&lgk_mem,
				      &allocated_pages, sys_err);
#if defined(conf_CLUSTER_BUILD)
                if (ret_val && !retries)
                    continue;  /* try one more time */
#endif
	    }
	    if (ret_val)
	    {
		uleFormat(NULL, ret_val, sys_err,
				ULE_LOG, NULL, NULL, 0, NULL, &err_code, 0);
		uleFormat(NULL, E_DMA800_LGKINIT_GETMEM, (CL_ERR_DESC *)NULL,
				ULE_LOG, NULL, NULL, 0, NULL, &err_code, 0);
		/* Unable to attach allocated shared memory segment. */
		return (E_DMA802_LGKINIT_ERROR); 
	    }
	}
	else if (flag & LOCK_LGK_MUST_ATTACH)
	{	
	    /* Do not use the shared segment you just allocated */
	    MEfree_pages((PTR)lgk_mem, allocated_pages, sys_err);
	    return (E_DMA812_LGK_NO_SEGMENT); 
	}

	size = allocated_pages * ME_MPAGESIZE;

	/* Expose this process to the memory */
	LGK_base.lgk_mem_ptr = (PTR)lgk_mem;

	if ( mem_exists )
	{
	    /*
	    ** Memory exists.
	    **
	    ** Try to acquire the semaphore. If it's
	    ** uninitialzed, retry from the top.
	    **
	    ** If the version is zero, then another
	    ** process is initializing the memory;
	    ** keep retrying until the version is 
	    ** filled in.
	    **
	    */
	    if ( ret_val = CSp_semaphore(1, &lgk_mem->mem_ext_sem) )
	    {
		if ( ret_val != E_CS000A_NO_SEMAPHORE )
		{
		    uleFormat(NULL, ret_val, sys_err,
				ULE_LOG, NULL, NULL, 0, NULL, &err_code, 0);
		    ret_val = E_DMA802_LGKINIT_ERROR;
		    break;
		}
		continue;
	    }

	    /* Retry if still being init'd by another process */
	    if ( !lgk_mem->mem_version_no )
	    {
		CSv_semaphore(&lgk_mem->mem_ext_sem);
		continue;
	    }

	    /*
	    ** Check pids which appear to be attached to
	    ** the memory:
	    **
	    ** If any process is still alive, then we
	    ** assume the memory is consistent and use it.
	    **
	    ** If a process is now dead, it terminated
	    ** without going through LGK_rundown
	    ** to zero its PID slot, zero it now.
	    **
	    ** If there are no live PIDs attached to 
	    ** the memory, we destroy and recreate it.
	    */
	    my_pid_slot = (PID*)NULL;
	    attached = 0;

	    for ( i = 0; i < LGK_MAX_PIDS; i++ )
	    {
		if ( lgk_mem->mem_pid[i] && 
		     PCis_alive(lgk_mem->mem_pid[i]) )
		{
		    attached++;
		}
		else
		{
		    /* Vacate the slot */
		    if (lgk_mem->mem_pid[i])
		    {
			uleFormat(NULL, E_DMA499_DEAD_PROCESS_INFO, (CL_ERR_DESC *)NULL,
				ULE_LOG, NULL, NULL, 0, NULL, &err_code, 2,
				0, lgk_mem->mem_pid[i],
				0, lgk_mem->mem_info[i].info_txt);
		    }
		    lgk_mem->mem_pid[i] = (PID)0;
		    lgk_mem->mem_info[i].info_txt[0] = EOS;

		    /* Use first vacant slot for this process */
		    if ( !my_pid_slot )
		    {
			my_pid_slot = &lgk_mem->mem_pid[i];
			LGK_base.lgk_pid_slot = i;
		    }
		}
		/* Quit when both questions answered */
		if ( attached && my_pid_slot )
		    break;
	    }

	    /* If no living pids attached, destroy/reallocate */
	    if ( !attached )
	    {
		CSv_semaphore(&lgk_mem->mem_ext_sem);
		if ( LGK_destroy(allocated_pages, sys_err) )
		{
		    ret_val = E_DMA802_LGKINIT_ERROR;
		    break;
		}
		continue;
	    }

	    /* All attached pids alive? */
	    if ( !my_pid_slot )
	    {
		/* ... then there's no room for this process */
		uleFormat(NULL, E_DMA80A_LGK_ATTACH_LIMIT, (CL_ERR_DESC *)NULL,
		    ULE_LOG, NULL, NULL, 0, NULL, &err_code, 1,
		    0, attached);
	        ret_val = E_DMA802_LGKINIT_ERROR;
	    }
	    else if (lgk_mem->mem_version_no != LGK_MEM_VERSION_CURRENT)
	    {
		uleFormat(NULL, E_DMA434_LGK_VERSION_MISMATCH, (CL_ERR_DESC *)NULL,
		    ULE_LOG, NULL, NULL, 0, NULL, &err_code, 2,
		    0, lgk_mem->mem_version_no, 0, LGK_MEM_VERSION_CURRENT);
		ret_val = E_DMA435_WRONG_LGKMEM_VERSION;
	    }
	    /*
	    ** Don't allow mixed connections of MT/non-MT processes.
	    ** Among other things, the mutexing mechanisms are 
	    ** incompatible!
	    */
	    else if ( (CS_is_mt() && (lgk_mem->mem_status & LGK_IS_MT) == 0) ||
		     (!CS_is_mt() &&  lgk_mem->mem_status & LGK_IS_MT) )
	    {
		uleFormat(NULL, E_DMA811_LGK_MT_MISMATCH, (CL_ERR_DESC *)NULL,
		    ULE_LOG, NULL, NULL, 0, NULL, &err_code, 2,
		    0, (lgk_mem->mem_status & LGK_IS_MT) ? "OS"
							 : "INTERNAL",
		    0, (CS_is_mt()) ? "OS"
				    : "INTERNAL");
		ret_val = E_DMA802_LGKINIT_ERROR;
	    }
	    else
	    {
		/*
		** CX memory (if any) will lie immediately past LGK header.
		*/
		pcxmem = (PTR)(lgk_mem + 1);
		pcxmem = (PTR)ME_ALIGN_MACRO(pcxmem, sizeof(ALIGN_RESTRICT));

		LGK_base.lgk_lkd_ptr = (char *)LGK_base.lgk_mem_ptr +
					lgk_mem->mem_lkd;
		LGK_base.lgk_lgd_ptr = (char *)LGK_base.lgk_mem_ptr +
					lgk_mem->mem_lgd;
		
		/* Stuff our pid in first vacant slot */
		*my_pid_slot = LGK_my_pid;
		STlcopy(lgk_info, lgk_mem->mem_info[i].info_txt, LGK_INFO_SIZE-1);
	    }

#if defined(VMS) || defined(UNIX)
	    /* set up pointers to reference the uuid mutex and last time
	     * variable */

	    if (!ID_uuid_sem_ptr)
           	ID_uuid_sem_ptr=&lgk_mem->id_uuid_sem;

	    if (!ID_uuid_last_time_ptr)
                ID_uuid_last_time_ptr=&lgk_mem->uuid_last_time;

	    if (!ID_uuid_last_cnt_ptr)
                ID_uuid_last_cnt_ptr=&lgk_mem->uuid_last_cnt;
#endif

	    CSv_semaphore(&lgk_mem->mem_ext_sem);
	}
	else
	{

	    /* Memory did not exist */
	    /* Zero the version to keep other processes out */
	    lgk_mem->mem_version_no = 0;

#if defined(VMS) || defined(UNIX)
	    /* set up the uuid mutex and last time pointers to
	     * reference the objects in shared memory */

	    {
	        STATUS id_stat;

	        ID_uuid_sem_ptr=&lgk_mem->id_uuid_sem;
                ID_uuid_last_time_ptr=&lgk_mem->uuid_last_time;
                ID_uuid_last_cnt_ptr=&lgk_mem->uuid_last_cnt;
	        *ID_uuid_last_cnt_ptr=0;
	        ID_UUID_SEM_INIT(ID_uuid_sem_ptr,CS_SEM_MULTI,"uuid sem",
				&id_stat);
	    }
#endif

	    /* ... then initialize the mutex */
	    CSw_semaphore(&lgk_mem->mem_ext_sem, CS_SEM_MULTI,
	    			    "LGK mem ext sem" );

	    /* Record if memory created for MT or not */
	    if ( CS_is_mt() )
		lgk_mem->mem_status = LGK_IS_MT;

	    /*
	    ** memory is as follows:
	    **
	    **	-----------------------------------------------------------|
	    **	| LGK_MEM struct (keep track of this mem)	           |
	    **	|							   |
	    **	-----------------------------------------------------------|
	    **	| If a clustered installation memory reserved for CX       |
	    **	|							   |
	    **	------------------------------------------------------------
	    **	| LKD - database of info for lk system			   |
	    **	|							   |
	    **	------------------------------------------------------------
	    **	| LGD - database of info for lg system			   |
	    **	|							   |
	    **	------------------------------------------------------------
	    **	| memory manipulated by LGKm_* routines for structures used |
	    **	| by both the lk and lg systems.			   |
	    **	|							   |
	    **	------------------------------------------------------------
	    */

	    /* put the LGK_MEM struct at head of segment leaving ptr pointing 
	    ** at next aligned piece of memory
	    */

	    /*
	    ** CX memory (if any) will lie immediately past LGK header.
	    */
	    pcxmem = (PTR)(lgk_mem + 1);
	    pcxmem = (PTR)ME_ALIGN_MACRO(pcxmem, sizeof(ALIGN_RESTRICT));

	    LGK_base.lgk_lkd_ptr = pcxmem + cxmemreq;
	    LGK_base.lgk_lkd_ptr = (PTR) ME_ALIGN_MACRO(LGK_base.lgk_lkd_ptr,
						sizeof(ALIGN_RESTRICT));
	    lgk_mem->mem_lkd = (i4)((char *)LGK_base.lgk_lkd_ptr -
					 (char *)LGK_base.lgk_mem_ptr);

	    LGK_base.lgk_lgd_ptr = (PTR) ((char *) LGK_base.lgk_lkd_ptr +
					    sizeof(LKD));
	    LGK_base.lgk_lgd_ptr = (PTR) ME_ALIGN_MACRO(LGK_base.lgk_lgd_ptr,
						sizeof(ALIGN_RESTRICT));
	    lgk_mem->mem_lgd = (i4)((char *)LGK_base.lgk_lgd_ptr -
					 (char *)LGK_base.lgk_mem_ptr);

	    /* now initialize the rest of memory for allocation */

	    /* how much memory is left? */

	    ptr = ((char *)LGK_base.lgk_lgd_ptr + sizeof(LGD));
	    memleft = size - (((char *) ptr) - ((char *) LGK_base.lgk_mem_ptr));

	    if ( (ret_val = lgkm_initialize_mem(memleft, ptr)) == OK &&
		 (ret_val = LG_meminit(sys_err)) == OK &&
		 (ret_val = LK_meminit(sys_err)) == OK )
	    {
		/* Clear array of attached pids and pid info */
		for ( i = 0; i < LGK_MAX_PIDS; i++ )
		{
		    lgk_mem->mem_pid[i] = (PID)0;
		    lgk_mem->mem_info[i].info_txt[0] = EOS;
		}

		/* Set the creator pid */
		LGK_base.lgk_pid_slot = 0;
		lgk_mem->mem_creator_pid = LGK_my_pid;

		/* Set the version, releasing other processes */
		lgk_mem->mem_version_no = LGK_MEM_VERSION_CURRENT;
	    }
	    else
	    {
		uleFormat(NULL, ret_val, (CL_ERR_DESC *)NULL,
			    ULE_LOG, NULL, NULL, 0, NULL, &err_code, 0);
		ret_val = E_DMA802_LGKINIT_ERROR;

		/* Destroy the shared memory */
		LGK_destroy(allocated_pages, sys_err);
	    }
	}

	if ( ret_val == OK )
	{
	    PCatexit(LGK_rundown);

	    if ( clustered )
	    {
		/*
		** Perform preliminary cluster connection and CX memory init.
		*/

		/* Get installation code */
		NMgtAt("II_INSTALLATION", &nm_string);
		if ( nm_string )
		{
		    instid[0] = *(nm_string);
		    instid[1] = *(nm_string+1);
		}
		else
		{
		    instid[0] = 'A';
		    instid[1] = 'A';
		}
		instid[2] = '\0';
		ret_val = CXinitialize( instid, pcxmem, flag & LGK_IS_CSP );
		if ( ret_val )
		{
		    /* Report error returned from CX */
		    uleFormat(NULL, ret_val, (CL_ERR_DESC *)NULL,
			ULE_LOG, NULL, NULL, 0, NULL, &err_code, 0 );
		    break;
		}
	    }

#ifdef VMS
	    {
	    static $EXHDEF	    exit_block;
	    i4			ctrl_y_mask = 0x02000000;

	    /*
	    ** On VMS, programs like the dmfjsp and logstat run as images in
	    ** the shell process. That is, the system doesn't start and stop
	    ** a process for each invocation of the program, it just starts
	    ** and stops an image in the same process. This means that if
	    ** the program should die, the image may be rundown but the process
	    ** will remain, which means that the check-dead threads of other
	    ** processes in the installation will not feel that they need to
	    ** rundown this process, since it's still alive.
	    **
	    ** By declaring an exit handler, which will get a chance to run
	    ** even if PCexit isn't called, we improve our chances of getting
	    ** to perform rundown processing if we should die unexpectedly.
	    **
	    ** Furthermore, we ask DCL to disable its ^Y processing, which
	    ** lessens the chance that the user will interrupt us while we
	    ** are holding the semaphore.
	    */
	    exit_block.exh$g_func = LGK_rundown;
	    exit_block.exh$l_argcount = 1;
	    exit_block.exh$gl_value = &exit_block.exh$l_status;

	    if (sys$dclexh(&exit_block) != SS$_NORMAL)
		ret_val = FAIL;

	    lib$disable_ctrl(&ctrl_y_mask, 0);
	    }
#endif
	}
	break;
    }

    if ( ret_val )
	LGK_base.lgk_mem_ptr = NULL;

    return(ret_val);
}
Ejemplo n.º 12
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;
	}
    }
Ejemplo n.º 13
0
static STATUS
ADFmo_fi_index(
    i4	    msg,
    PTR	    cdata,
    i4	    linstance,
    char    *instance,
    PTR	    *instdata)
{
    ADI_FI_DESC *fi;
    STATUS	    status;
    i4	    ix;
    i4         maxix = Adf_globs->Adi_num_fis;

    CVal(instance, &ix);

    switch (msg)
    {
	case MO_GET:
	    if (ix < 1 || ix > maxix )
	    {
		  status = MO_NO_INSTANCE;
		  break;
	    }
	    fi = &Adf_globs->Adi_fis[ix];
	    if ((fi == NULL) ||
		(fi->adi_finstid < 1))
	    {
		  status = MO_NO_INSTANCE;
		  break;
	    }

	    *instdata = (PTR)fi;
	    status = OK;

	    break;

	case MO_GETNEXT:
	    while (++ix <= maxix)
	    {
	      fi = &Adf_globs->Adi_fis[ix];
	      if ((fi == NULL) ||
	          (fi->adi_finstid < 1))
	      {
	        continue;
	      }
	      else
	      {
	        *instdata = (PTR)fi;
	        status = MOlongout( MO_INSTANCE_TRUNCATED,
					(i8)ix,
					linstance, instance);
	        break;
	      }
	    }
	    if (ix > maxix)
		status = MO_NO_INSTANCE;
		
	    break;

	default:
	    status = MO_BAD_MSG;
	    break;
    }

    return (status);
}
Ejemplo n.º 14
0
static STATUS
ADFmo_op_index(
    i4	    msg,
    PTR	    cdata,
    i4	    linstance,
    char    *instance,
    PTR	    *instdata)
{
    ADI_OPRATION *op;
    STATUS	    status;
    i4	    ix;
    i4         maxix = (Adf_globs->Adi_op_size) / sizeof(ADI_OPRATION);

    CVal(instance, &ix);

    switch(msg)
    {
	case MO_GET:
	    if (ix < 1 || ix > maxix )
	    {
		  status = MO_NO_INSTANCE;
		  break;
	    }
	    op = &Adf_globs->Adi_operations[ix];
	    if ((op == NULL) ||
		(op->adi_opid < 1))
	    {
		  status = MO_NO_INSTANCE;
		  break;
	    }

	    *instdata = (PTR)op;
	    status = OK;

	    break;

	case MO_GETNEXT:
	    while (++ix <= maxix)
	    {
	      op = &Adf_globs->Adi_operations[ix];
	          if ((op == NULL) ||
		      (op->adi_opid < 1))
		  {
		    continue;
		  }
		  else
		  {
		    *instdata = (PTR)op;
		    status = MOlongout( MO_INSTANCE_TRUNCATED,
					(i8)ix,
					linstance, instance);
		    break;
		  }
	    }
	    if (ix > maxix)
		status = MO_NO_INSTANCE;
		
	    break;

	default:
	    status = MO_BAD_MSG;
	    break;
    }

    return (status);
}
Ejemplo n.º 15
0
static STATUS
ADFmo_dt_index(
    i4	    msg,
    PTR	    cdata,
    i4	    linstance,
    char    *instance,
    PTR	    *instdata)
{
    ADI_DATATYPE *dt;
    STATUS	    status;
    i4	    ix;
    i4	    maxix = (Adf_globs->Adi_dt_size) / sizeof(ADI_DATATYPE);

    CVal(instance, &ix);

    switch(msg)
    {
	case MO_GET:
	    if (ix < 1 || ix > maxix )
	    {
		  status = MO_NO_INSTANCE;
		  break;
	    }
	    dt = &Adf_globs->Adi_datatypes[ix];
	    if ((dt == NULL) ||
		(dt->adi_dtid < 1))
	    {
		  status = MO_NO_INSTANCE;
		  break;
	    }

	    *instdata = (PTR)dt;
	    status = OK;

	    break;

	case MO_GETNEXT:
	    while (++ix <= maxix)
	    {
	      dt = &Adf_globs->Adi_datatypes[ix];
	          if ((dt == NULL) ||
		      (dt->adi_dtid < 1))
		  {
		    continue;
		  }
		  else
		  {
		    *instdata = (PTR)dt;
		    status = MOlongout( MO_INSTANCE_TRUNCATED,
					(i8)ix,
					linstance, instance);
		    break;
		  }
	    }
	    if (ix > maxix)
		status = MO_NO_INSTANCE;
		
	    break;

	default:
	    status = MO_BAD_MSG;
	    break;
    }

    return (status);
}
Ejemplo n.º 16
0
STATUS
ERsend(i4 flag, char *message, i4 msg_length, CL_ERR_DESC *err_code)
{
# ifdef NT_GENERIC
    static bool		er_init = FALSE;
    static bool		is_w95 = FALSE;
# else /* !NT_GENERIC */
    static int		er_ifi = -2;
    static int          ar_ifi = -2;
# endif /* !NT_GENERIC */
    STATUS		status;
    char                tmp_buf[ER_MAX_LEN];
    char*               logmsg = message;

    /*	Check for bad paramters. */

    CL_CLEAR_ERR( err_code );

    if ((message == 0 || msg_length == 0) && flag != ER_AUDIT_MSG)
        return (ER_BADPARAM);

    if ((flag != ER_ERROR_MSG) && (flag != ER_AUDIT_MSG) &&
        ( flag != ER_OPER_MSG))
        return (ER_BADPARAM);

# ifndef NT_GENERIC
    if (flag & ER_AUDIT_MSG)
    {
        key_t msg_key;
        char  *ipc_number;
        struct
        {
            long    mtype;
            char    mtext[ER_MAX_LEN];
        }   msg;

        if (ar_ifi == -2)
        {
            NMgtAt("II_AUDIT_IPC", &ipc_number);
            if (ipc_number && ipc_number[0])
            {
                CVal(ipc_number, &msg_key);
                ar_ifi = msgget(msg_key, 0);
                if (ar_ifi == -1)
                {
                    SETCLERR(err_code, 0, ER_open);
                    return(ER_NO_AUDIT);
                }
            }
            else
            {
                SETCLERR(err_code, 0, ER_open);
                return(ER_NO_AUDIT);
            }

        }
 
        /*  Handle special case to connect only but not send message. */
 
        if (msg_length == 0 && message == 0)
                return (OK);

        MEcopy(message, msg_length, msg.mtext);
        msg.mtype = 1;
        if (msgsnd(ar_ifi, &msg, msg_length, 0))
        {
            SETCLERR(err_code, 0, ER_open);
            return(ER_BADSEND);
        }
        return (OK);
    }
    else
# endif /* ! NT_GENERIC */
    if (flag & ER_OPER_MSG)
    {
        char    hostname[GL_MAXNAME];
        STATUS  status;
 
        message[msg_length] = EOS;
        TRdisplay("ER Operator:\"%s\"\n",message);
	if (!ERsysinit)
	    ERinitsyslog();
# ifdef NT_GENERIC
        {
        wchar_t *wmessage = NULL;

        /*
        ** Update the ReportEvent to report information in the event log.
        */
        if ( ReportEvent( EventLog,
                        (WORD) EVENTLOG_INFORMATION_TYPE,
                        (WORD) 0,             /* event category */
                        (DWORD) I_ING_INFO,   /* event identifier */
                        (PSID) NULL,
                        (WORD) 1,             /* number of strings */
                        (DWORD) 0,
                        &message,
                        NULL ) == FALSE)   
                status = GetLastError();
	if ( !er_init )
	{
	    char		VersionString[256];
	    FUNC_EXTERN BOOL	GVosvers(char *OSVersionString);

	    GVosvers(VersionString);
	    is_w95 = ( STstrindex(VersionString, "Microsoft Windows 9",
				  0, FALSE) != NULL ) ? TRUE : FALSE;

	    if ( !is_w95 ) /* netapi32 only on NT */
	    {
		HANDLE hDll;
                if ((hDll = LoadLibrary(TEXT("netapi32.dll"))) != NULL)
                {
                    pNetMessageNameAdd = 
		     (NET_API_STATUS (*)(LPCWSTR,LPCWSTR))
		     GetProcAddress(hDll, TEXT("NetMessageNameAdd"));
                    pNetMessageNameDel = 
		     (NET_API_STATUS (*)(LPCWSTR,LPCWSTR))
		     GetProcAddress(hDll, TEXT("NetMessageNameDel"));
                    pNetMessageBufferSend = 
		      (NET_API_STATUS (*)(LPCWSTR,LPCWSTR,LPCWSTR,LPBYTE,DWORD))
		      GetProcAddress(hDll, TEXT("NetMessageBufferSend"));
		}
		/* if any problem, pretend we don't support it */
		if ( pNetMessageNameAdd == NULL ||
		     pNetMessageNameDel == NULL ||
		     pNetMessageBufferSend == NULL )
		    is_w95 = TRUE;
	    }
	}

	if ( !is_w95 )
	{
	    /*
	    ** Now, send the message to the server console,
	    ** putting up a message box (if the messenger service
	    ** is running.  Everything must be in Unicode.
	    */

	    if ( whostname[0] == 0 )
	    {
		unsigned int len = sizeof(hostname);
                /* 
		** get the hostname in Unicode format for use 
		** by messenger service 
		*/
                GetComputerName( (char *)hostname, &len );
		MultiByteToWideChar( GetACP(), 0,
				     hostname, sizeof(hostname),
				     whostname, sizeof(whostname) );
	    }
            /* initialize the messenger service */
            status = (*pNetMessageNameAdd)( whostname, msgname );
            if ( status != NERR_Success )
	        status = GetLastError();

	    /* Allocate a buffer for the Unicode */
	    wmessage = (wchar_t *) MEreqmem( 0, msg_length * sizeof(wchar_t), 
				             TRUE, &status );
	    if ( wmessage )
	    {
	        /* copy the message to the Unicode buffer */
		MultiByteToWideChar( GetACP(), 0,
				     message, msg_length,
				     wmessage, msg_length * sizeof(wchar_t) );
                status = (*pNetMessageBufferSend)( whostname, 
					       msgname, 
					       NULL, 
				               (LPBYTE) wmessage, 
					       msg_length*sizeof(wchar_t) );
                if ( status != NERR_Success )
	            status = GetLastError();
	        MEfree( (PTR)wmessage );
	    }

            /* re-initialize the messenger service */
            status = (*pNetMessageNameDel)( whostname, msgname );
            if ( status != NERR_Success )
	        status = GetLastError();

	}
	}
# elif defined(OS_THREADS_USED) && defined(any_aix)
	syslog_r( LOG_ALERT|LOG_ERR, message );
# else
	syslog( LOG_ALERT|LOG_ERR, message );
# endif /* NT_GENERIC */
    }

    if (flag & ER_OPER_MSG)
    {
        i4 msglen = 0;
	char* host = PMhost();

        MEfill( ER_MAX_LEN, 0, tmp_buf );

        /*
        ** Format the message string for the event log.  As the source is
        ** not known a fixed string of INGSYSLOG is used.
        */
        TRformat( NULL, 0, tmp_buf, ER_MAX_LEN - 1,
            "%8.8t::[INGSYSLOG         , 00000000]: %@ ", STlength(host),
            host );
        msglen = STlength(tmp_buf);
        STcat( tmp_buf, message );  /* append original message */
        msg_length += msglen;
        logmsg = tmp_buf;
    }
    status = ERlog( logmsg, msg_length, err_code );
    return( status );
}
Ejemplo n.º 17
0
/*{
** Name: CXcluster_nodes	- Retrun information about configured nodes.
**
** Description:
**
**	Function will return information about the nodes configured
**	in this installation.
**
** Inputs:
**	
**	pnodecnt	- Pointer to u_i4 to hold node count, or NULL.
**
**	hconfig		- Address of pointer to be filled with pointer
**			  to an initialized CX_CONFIGURATION, or NULL.
**			  DO NOT alter the contents of the cached
**			  CX_CONFIGURATION through the returned address!
**
** Outputs:
**
**	*pnodecnt	- Filled in with # nodes.
**
**	*hconfig	- Holds pointer to cached CX_CONFIGURATION.
**
**	Returns:
**		OK		- Normal successful completion.
**		FAIL		- Problem with configuration found.
**		
**	Exceptions:
**	    none
**
** Side Effects:
**	    none.
**
** History:
**	18-apr-2001 (devjo01)
**	    Created. (Much of code lifted from DMFCSP)
**	15-Apr-2005 (fanch01)
**	    Modified cx_nodes array references to be valid from element zero.
*/
STATUS
CXcluster_nodes( u_i4 *pnodecnt, CX_CONFIGURATION **hconfig )
{
    static		 i4			 config_valid = 0;
    static		 CX_CONFIGURATION	 config = { 0 };

    STATUS		 status = OK;
    u_i4		 nodecnt;
    PM_SCAN_REC 	 scanrec;
    char		*resname;
    char		*resvalue;
    char		*nodename;
    i4			 nodename_l;
    i4			 clusterid;
    CX_NODE_INFO	*pni;
    i4			 i, rad;
    char		 param[80];

    if ( !config_valid )
    {
	status = PMinit();
	if ( OK == status )
	{
	    status = PMload( (LOCATION *)NULL, (PM_ERR_FUNC *)0);
	}
	else if ( PM_DUP_INIT == status )
	{
	    status = OK;
	}
	if ( status == OK )
	{
	    nodecnt = 0;

	    /*
	    ** Start the scan
	    */
	    status = PMscan( "^II\\.[^.]*\\.CONFIG\\.CLUSTER\\.ID$",
			     &scanrec, (char *) NULL,
			     &resname, &resvalue );

	    while ( status == OK )
	    {
		/*
		** Extract out node name and convert value to integer
		*/
		nodename = PMgetElem( 1, resname );
		nodename_l = STlength(nodename);

		CVal( resvalue, &clusterid );

		/* Ignore entries with zero cluster id. */
		if ( 0 != clusterid )
		{
		    /*
		    ** Check id is withing range
		    */
		    if ( (clusterid > CX_MAX_NODES) ||
			 (clusterid < 0) )
		    {
			TRdisplay( ERx( \
"%@ CSP node config: Node %s has an invalid id: %d, valid range (0 - %d)\n"),
			     nodename, clusterid, CX_MAX_NODES );
			status = FAIL;
			break;
		    }

		    /*
		    ** Adjust clusterid so array references are zero based.
		    */
		    clusterid--;

		    /*
		    ** Check that specified id is not already used.
		    */
		    if ( config.cx_nodes[clusterid].cx_node_name_l != 0 )
		    {
			/*
			** Location is already being used issue a message 
			** accordingly
			*/
			if (STxcompare( nodename, nodename_l, 
			    config.cx_nodes[clusterid].cx_node_name,
			    config.cx_nodes[clusterid].cx_node_name_l,
			    TRUE, FALSE) == 0)
			{
			    TRdisplay(
ERx("%@ Cluster configuration: Node %~t already exists in correct location.\n"),
			     nodename_l, nodename );
			}
			else
			{
			    TRdisplay(
ERx("%@ Cluster configuration: Node %~t has same id as Node %~t.\n"),
			     nodename_l, nodename,
			     config.cx_nodes[clusterid].cx_node_name_l,
			     config.cx_nodes[clusterid].cx_node_name );
			}
			status = FAIL;
			break;
		    }

		    /*
		    ** Make sure nodename is unique
		    */
		    for (i = 1; i <= nodecnt; i++)
		    {
			if (STxcompare(
			     config.cx_nodes[config.cx_xref[i]].cx_node_name,
			     config.cx_nodes[config.cx_xref[i]].cx_node_name_l,
			     nodename, nodename_l, TRUE, FALSE) == 0)
			{
			    TRdisplay( 
		 ERx("%@ Cluster configuration: Node %s already exists.\n"),
			     nodename );
			    status = FAIL;
			    break;
			}
		    }

		    /*
		    ** Add to configuration
		    */
		    nodecnt++;
		    config.cx_xref[nodecnt] = clusterid;
		    pni = &config.cx_nodes[clusterid];
		    STmove( nodename, '\0', CX_MAX_NODE_NAME_LEN,
		     pni->cx_node_name );
		    pni->cx_node_name_l = 
		     STnlength(CX_MAX_NODE_NAME_LEN,
		     pni->cx_node_name );
		    pni->cx_node_number = clusterid + 1;
		    pni->cx_host_name_l = pni->cx_rad_id = 0;

		    STprintf(param,"ii.%s.gcn.local_vnode", nodename);
		    if ( OK == PMget(param, &resvalue) )
		    {
			STmove( resvalue, '\0', CX_MAX_HOST_NAME_LEN,
				 pni->cx_host_name );
			pni->cx_host_name_l = STnlength( CX_MAX_HOST_NAME_LEN,
			 pni->cx_host_name );
		    }

		    STprintf(param,"ii.%s.config.numa.rad", nodename);
		    if ( OK == PMget(param, &resvalue) &&
			 OK == CVan(resvalue, &rad) && rad > 0 )
		    {
			pni->cx_rad_id = rad;
		    }

		    /*
		    ** Find next element
		    */
		    status = PMscan( (char *) NULL, &scanrec, (char *) NULL,
			     &resname, &resvalue );
		}
	    }

	    /*
	    ** End condition 
	    */
	    if ( status == PM_NOT_FOUND )
		status = OK;
	}

	if (status != OK )    
	{
	    TRdisplay( ERx("%@ Cluster configuration Error\n") );
	    return (FAIL);
	}
	config.cx_node_cnt = nodecnt;
	config_valid = 1;

    }
    if ( pnodecnt )
	*pnodecnt = config.cx_node_cnt;
    if ( hconfig )
	*hconfig = &config;
    
    return OK;
} /*CXcluster_nodes*/
Ejemplo n.º 18
0
/******************************************************************************
** Name: CSoptions() - fetch a pile of options using PMget()
**
** Description:
**      Calls PMget() for each option in the option table, converts the
**      value appropriately, and distributes the value into the right
**	spot in the CS_SYSTEM block.
**
**	Note special cruddiness surrounding CSO_SERVER_CLASS: the CL
**	fetches this only to set cs_isstar, used by CSinitiate() to 
**	calculate the file descriptor fluff factors: STAR uses more of 'em.
******************************************************************************/
STATUS
CSoptions( CS_SYSTEM *cssb )
{
	i4  echo = 1;
	struct CSO_OPTIONS *csopt;
	i4  failures = 0;

	for( csopt = cso_opttab; csopt->cso_name; csopt++ )
	{
	    char	*cs_svalue;
	    i4		cs_value = 0;
	    STATUS	status = OK;

	    /* 
	     * Get option's value using PMget() 
	     */

	    if( PMget( csopt->cso_name, &cs_svalue ) != OK )
		continue;

	    if( echo )
		ERoptlog( csopt->cso_name, cs_svalue );

	    /* 
	     * Convert & check the option's value, according to argtype 
	     */

	    switch( csopt->cso_argtype )
	    {
	    case 'g':
		/* String option */
		break;

	    case 'm':
		/* numeric option or the word "max"

		if( !STcompare( cs_svalue, "max" ) )
		{
		    cs_value = -1;
		    break;
		}
		/* fall through */

	    case 'o':
	    case 'n':
		/* set a numeric option */

		if( CVal( cs_svalue, &cs_value ) != OK )
		{
		    status = E_CS0025_NUMERIC_ARG;
		}
		else if( csopt->cso_argtype == 'o' && cs_value < 0 )
		{
		    status = E_CS0026_POSITIVE_VALUE;
		}
		break;

	    case 't':
		/* set a switch option: on = true */

		if( STbcompare( cs_svalue, 0, "on", 0, TRUE ) )
		    continue;
		break;
		    
	    case 'z':
		/* clear a switch option */

		if( !STbcompare( cs_svalue, 0, "on", 0, TRUE ) )
		    continue;
		break;
	    }

	    if( status )
	    {
		(*cssb->cs_elog)( status, (CL_ERR_DESC *)0, 1,
			    STlength( csopt->cso_name ), csopt->cso_name );
		failures++;
		break;
	    }

	    /*
	     * Distribute option value, according to index
	     */

	    switch( csopt->cso_index )
	    {
	    case CSO_ECHO:
		/* echo: off */
		echo = 0;
		break;

	    case CSO_ACT_SESSION:
		cssb->cs_max_active = cs_value;
		break;

	    case CSO_CON_SESSION:
		cssb->cs_max_sessions = cs_value;
		break;

	    case CSO_MAXLDB_CON:
//		cssb->cs_max_ldb_connections = cs_value;
		break;

	    case CSO_MAX_WS:

# if defined( xCL_034_GETRLIMIT_EXISTS) && defined( RLIMIT_RSS )
		{
		    struct rlimit rlim;
		    getrlimit( RLIMIT_RSS, &rlim );

		    rlim.rlim_cur = cs_value;

		    if( cs_value < 0 || cs_value > rlim.rlim_max )
			rlim.rlim_cur = rlim.rlim_max;

		    setrlimit( RLIMIT_RSS, &rlim );
		}
#endif
		break;

	    case CSO_PRIORITY:
		/* Process priority */

# ifdef xCL_033_SETPRIORITY_EXISTS
//		setpriority( PRIO_PROCESS, 0, cs_value );
# else
//		nice( cs_value );
# endif
		break;

	    case CSO_QUANTUM:
//		cssb->cs_quantum = cs_value;
		break;

	    case CSO_SESS_ACCTNG:
		cssb->cs_mask |= CS_ACCNTING_MASK;
		cssb->cs_mask |= CS_CPUSTAT_MASK;
		break;
		
	    case CSO_CPUSTATS:
		cssb->cs_mask |= CS_CPUSTAT_MASK;
		break;

	    case CSO_STK_SIZE:
		cssb->cs_stksize = cs_value;
		break;

	    case CSO_SERVER_CLASS:
//		cssb->cs_isstar = !STcompare( cs_svalue, "STAR" ); /* cheesy */
		break;

	    case CSO_DEFINE:
		cssb->cs_define = TRUE;
		break;
	    }
	}
    return (OK);
}