Exemple #1
0
/* decode semaphore error */
void
semerr(
i4 rv,
CS_SEMAPHORE *sp,
char *msg)
{
    MY_SCB *scb;
#ifdef EX_DEBUG
    EX_CONTEXT context;

    if (EXdeclare(ex_handler, &context) != OK) {
	/* some exception was raised */
	SIfprintf( stderr,"Error: unexpected exception in semerr()...");
	EXdelete();
	return;
    }
#endif

    CSget_scb( (CS_SCB **)&scb );
    SIfprintf(stderr, "%s %p returned %d (%s)\n", msg, sp, rv, maperr(rv) );
    SIfprintf(stderr, "\tPhilosopher %d, scb %p\n", scb->phil, scb );
    SIfprintf(stderr, "\t%p->cs_value %d\n", sp, sp->cs_value );
    SIfprintf(stderr, "\t%p->cs_count %d\n", sp, sp->cs_count );
    SIfprintf(stderr, "\t%p->cs_owner %x\n", sp, sp->cs_owner );
    SIfprintf(stderr, "\t%p->cs_list %p\n", sp, sp->cs_list );
    SIfprintf(stderr, "\t%p->cs_next %p\n", sp, sp->cs_next );

#ifdef EX_DEBUG
    EXdelete();
#endif
}
Exemple #2
0
/*
** Name: ascs_avformat	- Show info on the current thread during an AV
**
** Description:
**	This routine calls scs_iformat to show what thread was running
**	when the server got an AV.
**
** Inputs:
**	None.
**
** Outputs:
**	Returns:
**	    STATUS
**	Exceptions:
**	    none
**
** Side Effects:
**	    none
**
** History:
**	27-feb-1992 (rog)
**	    Created.
**	29-Jun-1993 (daveb)
**	    correctly cast arg to CSget_scb().
**	02-Jul-1993 (daveb)
**	    prototyped.
**	07-jul-1993 (rog)
**	    Changed the message from saying a fatal error occurred to just
**	    saying that an error occurred.
[@history_template@]...
*/
STATUS
ascs_avformat(void)
{
	STATUS		ret_val;
	EX_CONTEXT	ex;

    if (EXdeclare(ascs_fhandler, &ex) != OK)
    {
	ret_val = FAIL;
    }
    else
    {
	SCD_SCB		*scb;
	i4		err_code;
	char 		*msg_buffer;
	i4		msg_length;

	msg_buffer = "An error occurred in the following session:";
	msg_length = STlength(msg_buffer);

	CSget_scb((CS_SCB **)&scb);
	ule_format(0, 0, ULE_MESSAGE, 0, msg_buffer, msg_length,0,&err_code,0);
	ret_val = ascs_iformat(scb, 1, 0, 1);
    }

    EXdelete();
    return(ret_val);
}
Exemple #3
0
void
logger(
i4 errnum, i4 arg1, i4 arg2)
{
    char buf[ ER_MAX_LEN ];
#ifdef EX_DEBUG
    EX_CONTEXT context;

    if (EXdeclare(ex_handler, &context) != OK) {
	/* some exception was raised */
	Psem( &SIsem );
	SIfprintf( stderr,"Error: unexpected exception in logger()...");
	Vsem( &SIsem );

	EXdelete();
	return;
    }
#endif

    Psem( &SIsem );
    if( ERreport( errnum, buf ) == OK )
    	SIfprintf(stderr, "%s\n", buf);
    else
	SIfprintf(stderr, "ERROR %d (%x), %s %d\n", 
		errnum, errnum, arg1, arg2 );
    Vsem( &SIsem );

#ifdef EX_DEBUG
    EXdelete();
#endif
    if(errnum != E_CS0018_NORMAL_SHUTDOWN)
	PCexit(FAIL);
    PCexit(OK);
}
Exemple #4
0
/* Observe that philosopher n is eating */
void
eats(
i4 n)
{
#ifdef EX_DEBUG
    EX_CONTEXT context;

    if (EXdeclare(ex_handler, &context) != OK) {
	/* some exception was raised */
	Psem( &SIsem );
	SIfprintf( stderr,"Error: unexpected exception in eats()...");
	Vsem( &SIsem );

	EXdelete();
	return;
    }
#endif
 
    if( Noisy )
    {
	Psem( &SIsem );
	SIfprintf(stderr, "%d (%s) eats...\n", n, Names[ n ] );
	Vsem( &SIsem );
    }
    CSswitch();

#ifdef EX_DEBUG
    EXdelete();
#endif
}
Exemple #5
0
char *
maperr(
STATUS rv)
{
    char *ret_val;

#ifdef EX_DEBUG
    EX_CONTEXT context;

    if (EXdeclare(ex_handler, &context) != OK) {
	/* some exception was raised */
	SIfprintf( stderr,"Error: unexpected exception in maperr()...");
	EXdelete();
	return "";
    }
#endif

    switch( rv )
    {
    case E_CS0017_SMPR_DEADLOCK:
	ret_val = "E_CS0017_SMPR_DEADLOCK";
	break;

    case E_CS000F_REQUEST_ABORTED:
	ret_val = "E_CS000F_REQUEST_ABORTED";
	break;

    case E_CS000A_NO_SEMAPHORE:
        ret_val = "E_CS000A_NO_SEMAPHORE";
	break;

    case OK:
	ret_val = "";
	break;

    default:
	ret_val = "Unknown exception";
	break;
    }

#ifdef EX_DEBUG
    EXdelete();
#endif
    return ret_val;
}
Exemple #6
0
/*
**	Setup global variables and add threads for each philosopher.
**	Called by CSinitialize before threads are started
*/
STATUS
hello(
CS_INFO_CB *csib)
{
    i4 i;
    STATUS stat;
    CL_ERR_DESC	err;
#ifdef EX_DEBUG
    EX_CONTEXT context;

    if (EXdeclare(ex_handler, &context) != OK) {
	/* some exception was raised */
	SIfprintf( stderr,"Error: unexpected exception in hello()...");
	EXdelete();
	return FAIL;
    }
#endif

    SIsem.cs_value = 0;
    SIsem.cs_count = 0;
    SIsem.cs_owner = NULL;
    SIsem.cs_list = NULL;
    SIsem.cs_next = NULL;

    Freesem.cs_value = 0;
    Freesem.cs_count = 0;
    Freesem.cs_owner = NULL;
    Freesem.cs_list = NULL;
    Freesem.cs_next = NULL;

    for( i = 0, stat = OK; i < n_phils && stat == OK; i++ )
    {
	Freesticks[ i ] = 2;
	stat = CSadd_thread( 0, (PTR)NULL, i + 1, (CS_SID*)NULL, &err );
    }

    /* no semaphore needed, called before CSdispatch */
    if( Noisy )
	SIfprintf(stderr, "World begins, philosophers wonder why.\n" );

#ifdef EX_DEBUG
    EXdelete();
#endif
    return( stat );
}
Exemple #7
0
/* Called when all thread functions return from the TERMINATE state */
STATUS
bye()
{
#ifdef EX_DEBUG
    EX_CONTEXT context;

    if (EXdeclare(ex_handler, &context) != OK) {
	/* some exception was raised */
	SIfprintf( stderr,"Error: unexpected exception in bye()...");
	EXdelete();
	return FAIL;
    }
#endif

    /* no semaphore needed, called when all threads are dead */
    if( Noisy )
	SIfprintf(stderr, "All philosophers are dead.  World ends.\n");

#ifdef EX_DEBUG
    EXdelete();
#endif
    return( OK );
}
Exemple #8
0
/* Observe that philosopher n is thinking */
void
thinks(
i4 n)
{
#ifdef EX_DEBUG
    EX_CONTEXT context;

    if (EXdeclare(ex_handler, &context) != OK) {
	/* some exception was raised */
	Psem( &SIsem );
	SIfprintf( stderr,"exception raised while thinking, OK...\n");
	Vsem( &SIsem );

	EXdelete();
	return;
    }
#endif

    if( Noisy )
    {
	Psem( &SIsem );
	SIfprintf(stderr, "%d (%s) thinks...\n", n, Names[ n ] );
	Vsem( &SIsem );

    }
    CSswitch();

#ifdef EX_DEBUG
    EXsignal(not_handled, 0);

    Psem( &SIsem );
    SIfprintf( stderr,"Error: should not be reached in thinks()...");
    Vsem( &SIsem );

    EXdelete();
#endif
}
Exemple #9
0
/* release a semaphore */
STATUS
Vsem(
CS_SEMAPHORE *sp)
{
    STATUS rv;
#ifdef EX_DEBUG
    EX_CONTEXT context;

    if (EXdeclare(ex_handler, &context) != OK) {
	/* some exception was raised */
	SIfprintf( stderr,"Error: unexpected exception in Vsem()...");
	EXdelete();
	return FAIL;
    }
#endif

    if( rv = CSv_semaphore( sp ) )
	semerr( rv, sp, "Vsem" );

#ifdef EX_DEBUG
    EXdelete();
#endif
    return( rv );
}
Exemple #10
0
/* release sticks held by philosopher n */
void
freesticks(
i4 n)
{
#ifdef EX_DEBUG
    EX_CONTEXT context;

    if (EXdeclare(ex_handler2, &context) != OK) {
	/* free_exc error should never be EX_DECLARE'd. */
	Psem( &SIsem );
	SIfprintf( stderr,"Error: unexpected exception in freesticks()...");
	Vsem( &SIsem );

	EXdelete();
	return;
    }
#endif

    Psem( &Freesem );

#ifdef EX_DEBUG
    EXsignal(free_exc, 1, n);
#endif

    Freesticks[ n ] += 2;
    ++Freesticks[ LEFT( n ) ];
    ++Freesticks[ RIGHT( n ) ];

    CSswitch();	    /* gratuitous, tests semaphores */

    Vsem( &Freesem );

#ifdef EX_DEBUG
    EXdelete();
#endif
}
Exemple #11
0
STATUS
ERslookup(
    i4		    msg_number,
    CL_ERR_DESC	    *clerror,
    i4		    flags,
    char	    *sqlstate,
    char	    *msg_buf,
    i4		    msg_buf_size,
    i4		    language,
    i4		    *msg_length,
    CL_ERR_DESC	    *err_code,
    i4		    num_param,
    ER_ARGUMENT	    *param )
{
    i4			erindex;	/* index of ERmulti table */
    i4		status;
    i4			length = 0;
    ER_ARGUMENT		*p;
    ER_ARGUMENT		hidden[CLE_INFO_ITEMS];	/* to access info in clerror */
    char		tempbuf[ER_MAX_LEN+ER_MAX_NAME+2];
    i4			templen;
    char		*p_msg_buf;
    char		*p_tempbuf;
    SYSTIME		stime;
    char		langbuf[ER_MAX_LANGSTR];
    EX_CONTEXT		context;
    ER_SEMFUNCS		*sems;

#define			    D_WIDTH	    23
#define			    F_WIDTH	    20
#define			    X_WIDTH	    18


    /*	Validate the parameters. */

    if (msg_buf == 0 || msg_buf_size == 0 || msg_length == 0)
    {
	return (ER_BADPARAM);
    }
    if (language != -1 && ERlangstr(language,langbuf) != OK)
    {
	return (ER_BADLANGUAGE);
    }
 
    if (!(flags & ER_NAMEONLY))
    {
        EXdump(msg_number,0);
    }
 

    /*	Insert timestamp if requested. */

    if (flags & ER_TIMESTAMP)
    {
	if (msg_buf_size < 21)
	{
	    return (ER_TOOSMALL);
	}
	TMnow(&stime);
	TMstr(&stime,msg_buf);

	length = (i4)STlength(msg_buf);	
	msg_buf[length++] = ' ';
    }

    /*
    **    if (clerror && msg_number)
    **        look up msg_number, optional parameters in clerror->moreinfo
    **    else if (clerror)
    **    {
    **        if (clerror->intern)
    **            look up clerror.intern, optional params in clerror->moreinfo
    **        if (clerror->callid)
    **            look up system error message
    **    }
    */
    if (clerror)
    {
	if (msg_number)	/* Look up message after system error */
	{
	    /*
	    ** Set up an ER_ARGUMENT that references system-dependent
	    ** information in `clerror', and point `param' at it.
	    */
	    i4  i;

	    for (i = 0; i < CLE_INFO_ITEMS; ++i)
	    {
	        /* "...all of whose members begin at offset 0..." (K&R) */

	        hidden[i].er_value = (PTR)&clerror->moreinfo[i].data._i4;
	        hidden[i].er_size = clerror->moreinfo[i].size;
	    }

	    param = &hidden[0];
	    num_param = CLE_INFO_ITEMS;
	}
        else		/* retrieve system-dependent error messages */
	{
	    i4	        len;
	    ER_ARGUMENT	argv[3];

	    if (clerror->intern)    /* look up internal CL error */
	    {
	        i4  i;

	        for (i = 0; i < CLE_INFO_ITEMS; ++i)
	        {
	            argv[i].er_value = (PTR)&clerror->moreinfo[i].data._i4;
	            argv[i].er_size = clerror->moreinfo[i].size;
	        }

	        /*
	        ** Don't timestamp on recursive call, since it's been done
	        ** already (if requested).
	        */
	        if ((status = ERslookup((i4) clerror->intern,
		    (CL_ERR_DESC*) NULL, flags & ~ER_TIMESTAMP | ER_TEXTONLY,
		    NULL, &msg_buf[length], msg_buf_size-length, language, &len,
		    err_code, CLE_INFO_ITEMS, argv)) != OK)
	        {
	            return (status);
	        }
	        length += len;

		if (clerror->callid)
		    msg_buf[length++] = '\n';
	    }

	    if (clerror->callid)    /* look up system error message text */
	    {
                DESCRIPTOR	msg_desc;

    	        msg_desc.desc_length = sizeof(tempbuf) - 1;
	        msg_desc.desc_value = tempbuf;
	        if ((status = cer_sysgetmsg(clerror, &len, &msg_desc, err_code))
		    != OK)
	        {
	            return(status);
	        }

	        argv[0].er_size = argv[1].er_size = argv[2].er_size =
		    ER_PTR_ARGUMENT;

	        argv[0].er_value = (PTR)&clerror->errnum;
	        argv[1].er_value = (PTR)ERNAME((i4) clerror->callid);
	        argv[2].er_value = (PTR)tempbuf;

	        if ((status = ERslookup(ER_UNIXERROR, (CL_ERR_DESC*) NULL,
	                flags & ~ER_TIMESTAMP | ER_TEXTONLY, NULL,
			&msg_buf[length], msg_buf_size - length, language,
			&len,err_code, 3, argv))
		    != OK)
	        {
	            return (status);
	        }
	        length += len;
	    }

	    msg_buf[*msg_length = length] = EOS;
	    return (OK);
        }
    }


    /*
    **	Check if error message file is already opened or not yet. 
    **  First see if the language is initialized.  If not, initialize
    **  it and the message files.
    **	If it is already opened, cer_fndindex function returns the index of
    **	ERmulti table that internal language code is parameter 'language'.
    **  If not yet, it returns '-1'.
    */

    if (cer_issem(&sems))
    {
	if (((sems->sem_type & MU_SEM) ?
	    (*sems->er_p_semaphore)(&sems->er_mu_sem) :
	    (*sems->er_p_semaphore)(1, &sems->er_sem)) != OK)
	{
	    sems = NULL;
	}
    }

    if ((erindex = cer_fndindex(language)) == -1)
    {
	if ((status = cer_nxtindex(language,&erindex)) != OK)
	{   /* Error in initializing the language */
	    if (sems)
	    {
		if (sems->sem_type & MU_SEM)
		    _VOID_ (*sems->er_v_semaphore)(&sems->er_mu_sem);
		else
		    _VOID_ (*sems->er_v_semaphore)(&sems->er_sem);
	    }
	    return (status);
	}
    }

    /*  If the error message file is not opened, open the message file. */

    if (!cer_isopen(erindex,ER_SLOWSIDE))
    {
        if ((status = cer_sinit(language,msg_number,erindex,err_code)) != OK)
        {
	    if (sems)
	    {
		if (sems->sem_type & MU_SEM)
		    _VOID_ (*sems->er_v_semaphore)(&sems->er_mu_sem);
		else
		    _VOID_ (*sems->er_v_semaphore)(&sems->er_sem);
	    }
            return (status);
        }
    }

    /*	If not open then just return. */
    if (!cer_isopen(erindex,ER_SLOWSIDE))
    {
	if (sems)
	{
	    if (sems->sem_type & MU_SEM)
		_VOID_ (*sems->er_v_semaphore)(&sems->er_mu_sem);
	    else
		_VOID_ (*sems->er_v_semaphore)(&sems->er_sem);
	}
	/*
	**  As internal file id is '0', openning file will fail.
	**  In her,return status 'ER_BADOPEN' to show open fail.
	*/
	return (ER_BADOPEN);
    }
	
    /*
    **  Search message string from file and set to buffer.
    **	Error status on system call set to 'err_code'.
    */

    status = cer_sstr(msg_number, sqlstate, tempbuf,
			msg_buf_size - length, erindex, err_code,
			flags & ER_TEXTONLY? ER_GET : ER_LOOKUP);
    if (sems)
    {
	if (sems->sem_type & MU_SEM)
	    _VOID_ (*sems->er_v_semaphore)(&sems->er_mu_sem);
	else
	    _VOID_ (*sems->er_v_semaphore)(&sems->er_sem);
    }

    if (status != OK)
    {
	return (status);
    }

    /*
    **	Format the text with parameters into the callers buffer.
    **  The message is truncated if it will not fit.
    */

    /*  Insert part of name from temporary buffer to buffer */

    status = OK;
    templen = (i4)STlength(tempbuf);
    p_msg_buf = &msg_buf[length];
    p_tempbuf = tempbuf;
    if (!(flags & ER_TEXTONLY))
    {
        while(*p_tempbuf != '\t')
        {
	    CMcpyinc(p_tempbuf,p_msg_buf);
        }
        CMcpyinc(p_tempbuf,p_msg_buf);
    }
    

    /* ============================================ */
    /* Copy text to message substituting arguments. */
    /* -------------------------------------------- */
    /* (But first, declare an exception handler to  */
    /*  catch bad params that may access violate.)  */
    /* ============================================ */

    if (EXdeclare(er_exhandler, &context))
    {
	u_i4	res_len;
	u_i4	bytes_left_in_buf;

	bytes_left_in_buf = (u_i4)(msg_buf_size - (p_msg_buf - msg_buf));
	res_len = STlen( STncpy(p_msg_buf,
   ERx("*** ERslookup() ERROR: Missing or bad parameter for this message. ***"),
	bytes_left_in_buf ));
	p_msg_buf[ bytes_left_in_buf - 1 ] = EOS;
	p_msg_buf += res_len;
	*msg_length = (i4)(p_msg_buf - msg_buf);
	EXdelete();
	return (OK);
    }


    for( ;p_tempbuf - tempbuf < templen; CMnext(p_tempbuf))
    {
        long		number;
        u_long    	unumber;
        double		fnumber;
	i4		i;
	i4		pnum;
 
	if ( (*p_tempbuf != '%') || (flags & ER_NOPARAM) )
	{
	    if ((p_msg_buf - msg_buf) >= msg_buf_size)
		break;
	    CMcpychar(p_tempbuf,p_msg_buf);
	    CMnext(p_msg_buf);
	    continue;
	}
	if (p_tempbuf - tempbuf + 2 >= templen)
	    continue;
	CMnext(p_tempbuf);
	if (*p_tempbuf == '!')
	{
	    if ((p_msg_buf - msg_buf) + 3 >= msg_buf_size)
		continue;
	    CMcpychar(ERx("\r"),p_msg_buf);
	    CMnext(p_msg_buf);
	    CMcpychar(ERx("\n"),p_msg_buf);
	    CMnext(p_msg_buf);
	    CMcpychar(ERx("\t"),p_msg_buf);
	    CMnext(p_msg_buf);
	    continue;
	}
	/*
	** Only works for up to 10 parameters, and makes character set
	** assumptions - should be fixed.
	*/
	if ( *p_tempbuf < '0' || *p_tempbuf > '9' )
	{
	    /* treat any other character as a literal */
	    if ((p_msg_buf - msg_buf) >= msg_buf_size)
		break;
	    if ( *p_tempbuf != '%' )
	    {
	        CMcpychar("%",p_msg_buf);
	        CMnext(p_msg_buf);
	    }
	    CMcpychar(p_tempbuf,p_msg_buf);
	    CMnext(p_msg_buf);
	    continue;
	}
	pnum = *p_tempbuf - '0';
	if (pnum >= num_param)
	{
		EXdelete();
		return(ER_BADPARAM);
	}
	p = &param[pnum];
	CMnext(p_tempbuf);
	switch (*p_tempbuf)
	{
	  case 'd':
	    /* Convert an integer into the buffer with width D_WIDTH */

	    if (p->er_size == ER_PTR_ARGUMENT) /* this is ptr to i4 */
		number = *(i4 *)p->er_value;
	    else if (p->er_size == 0)   /* this is a i4 */
		number = (i4)(SCALARP)p->er_value;
	    else if (p->er_size == 1)
		number = *(i1 *)p->er_value;
	    else if (p->er_size == 2)
		number = *(i2 *)p->er_value;
	    else if (p->er_size == 4)
		number = *(i4 *)p->er_value;
	    else if (p->er_size == 8)
		number = *(i8 *)p->er_value;
	    else
		continue;

	    if (p_msg_buf - msg_buf + D_WIDTH >= msg_buf_size)
	        continue;

	    if (p->er_size == 8)
	    {
	        CVla8(number, p_msg_buf);
	    }
	    else
	    {
	        CVla((i4)number, p_msg_buf);
	    }
	    while (*p_msg_buf)
		CMnext(p_msg_buf);
	    continue;

	  case 'u':
	    /* Convert an integer into the buffer with width D_WIDTH */

	    if (p->er_size == ER_PTR_ARGUMENT) /* this is ptr to u_i4 */
		number = *(u_i4 *)p->er_value;
	    else if (p->er_size == 0)   /* this is a u_i4 */
		number = (u_i4)(SCALARP)p->er_value;
	    else if (p->er_size == 1)
		number = *(u_i1 *)p->er_value;
	    else if (p->er_size == 2)
		number = *(u_i2 *)p->er_value;
	    else if (p->er_size == 4)
		number = *(u_i4 *)p->er_value;
	    else if (p->er_size == 8)
		number = *(u_i8 *)p->er_value;
	    else
		continue;

	    if (p_msg_buf - msg_buf + D_WIDTH >= msg_buf_size)
	        continue;

	    if (p->er_size == 8)
	    {
	        CVula8(number, p_msg_buf);
	    }
	    else
	    {
	        CVula((u_i4)number, p_msg_buf);
	    }
	    while (*p_msg_buf)
		CMnext(p_msg_buf);
	    continue;

	  case 'f':
	  {
	    i2	    res_width;

	    /* Convert a float into the buffer with width F_WIDTH */

	    if (p->er_size == ER_PTR_ARGUMENT) /* Pointer to a double */
		fnumber = *(double *)p->er_value;
	    else if (p->er_size == 4)
		fnumber = *(f4 *)p->er_value;
	    else if (p->er_size == 8)
		fnumber = *(f8 *)p->er_value;
	    else
		continue;

	    if (p_msg_buf - msg_buf + F_WIDTH >= msg_buf_size)
		continue;

	    /* Always convert to 'e' format. */

	    CVfa(fnumber, (i4) 20, (i4) 5, 'e', '.', p_msg_buf, &res_width);
	    p_msg_buf += F_WIDTH;
	    continue;
	  }
	  case 'c':
	    /* Convert a character array into buffer. */

	    if (p->er_value == 0)
		p->er_value = (PTR)ERx("<missing>");
	    if ((p->er_size == 0) || (p->er_size == ER_PTR_ARGUMENT))
	    {
		for (i = 0; ((char *)p->er_value)[i]; i++)
		    ;
		p->er_size = i;
	    }
             
	    if (p_msg_buf - msg_buf + p->er_size >= msg_buf_size)
		continue;

	    if (p->er_size > msg_buf_size - (p_msg_buf - msg_buf))
		p->er_size = (i4)(msg_buf_size - (p_msg_buf - msg_buf));
/*	    p->er_size=STtrmwhite(p_msg_buf);*/
	    MEcopy(p->er_value, p->er_size, p_msg_buf);
	    p->er_size = (i4)STtrmnwhite(p_msg_buf, p->er_size);
	    p_msg_buf += p->er_size;
	    continue;

	  case 'x':
	    /* Convert an integer into the buffer with width D_WIDTH */

	    if (p->er_size == ER_PTR_ARGUMENT)
		unumber = *(u_i4 *)p->er_value;
	    else if (p->er_size == 0)
		unumber = (u_i4)(SCALARP)p->er_value;
	    else if (p->er_size == 1)
		unumber = *(u_i1 *)p->er_value;
	    else if (p->er_size == 2)
		unumber = *(u_i2 *)p->er_value;
	    else if (p->er_size == 4)
		unumber = *(u_i4 *)p->er_value;
	    else if (p->er_size == 8)
		unumber = *(u_i8 *)p->er_value;

	    if (p_msg_buf - msg_buf + X_WIDTH >= msg_buf_size)
		continue;

	    for (i = 8; --i >= 0; )
	    {
		/* {@fix_me@}
		** This is *NOT* machine independent.  This relys on an
		** ASCII-like character set, where the digits '0'-'9' are
		** contiguous and sequential, and the characters 'A'-'F'
		** are contiguous and sequential.  Both ASCII and EBCDIC
		** happen to be this way.
		*/
		if ((*(p_msg_buf + i) = (unumber & 0x0f) + '0') > '9')
		    *(p_msg_buf + i) += 'A' - '9' - 1;
		unumber >>= 4;
	    }
	    p_msg_buf += 8;
	    continue;

	default:
	    continue;
	}
    }
    *msg_length = (i4)(p_msg_buf - msg_buf);
    *p_msg_buf = EOS;
    EXdelete();
    return (OK);
}
Exemple #12
0
/* A philosopher thread function, called out of CSdispatch */
STATUS
philosopher(
i4 mode,
MY_SCB *scb,
i4 *next_mode)
{
    i4 bites = 0;

#ifdef EX_DEBUG
    EX_CONTEXT context;

    if (EXdeclare(ex_handler, &context) != OK) {
	/* some exception was raised */
	Psem( &SIsem );
	SIfprintf( stderr,"Error: unexpected exception in philosopher()...");
	Vsem( &SIsem );

	EXdelete();
	return FAIL;
    }
#endif

    switch( mode )
    {
    case CS_INITIATE:	/* A new philsopher is born */

	scb->phil = Threads++;
	status[scb->phil] = mode;
	while( bites < NBITES )
	{
	    getsticks( scb->phil );
	    eats( scb->phil );
	    bites++;
	    freesticks( scb->phil );
	    thinks( scb->phil );
	}

	/* fall into: */

    default:
	*next_mode = CS_TERMINATE;
	break;

    case CS_TERMINATE:
	if( Noisy )
	{
# ifdef EX_SIG_DEBUG
	    signal(SIGUSR1, intfunc);
	    if (scb->phil == 1) {
		SIfprintf(stderr, "Send a signal #%d to process #%d\n",
			SIGUSR1, getpid());
		pause();
	    }
# endif /* EX_SIG_DEBUG */
	    Psem( &SIsem );
	    SIfprintf(stderr, "%d (%s) dies, RIP.\n",
			scb->phil, Names[ scb->phil ] );
	    if ( status[scb->phil]  == mode )
	    {
		SIfprintf(stderr, "Oops this philosopher is already dead?\n");
		SIfprintf(stderr, "\t\t CS code is non-functional\n");
	    }
	    Vsem( &SIsem );

	}

	*next_mode = CS_TERMINATE;

	/* If no more threads, shutdown */
	status[scb->phil] = mode;

	if( --Threads == 0 ) {
	    /* Everyone else should be dead, no semaphore needed. */
	    SIflush( stderr );

	    CSterminate( CS_KILL, (i4 *)NULL );
	}

	break;
    }

#ifdef EX_DEBUG
    EXdelete();
#endif
    return( OK );
}
Exemple #13
0
/*{
** Name: sxf_call	- The main SXF entry point.
**
** Description:
**      The routine checks that the arguments to sxf_call look reasonable.
**	The implementing function is then called and operation completion
**	status is returned to the caller.
**
** Inputs:
**      op_code			The SXF operation code.
**      rcb			The SXF request control block for the operation.
**
** Outputs:
**	Returns:
**	    DB_STATUS
**	Exceptions:
**	    none
**
** Side Effects:
**	    none
**
** History:
**	9-July-1992 (markg)
**	    Initial creation.
**	03-sep-1992 (pholman)
**	    Give calls NULL functionlaity for initial integration
**	20-oct-1992 (markg)
**	    Updated to have entry points for all SXF operations.
*/
DB_STATUS
sxf_call(
    SXF_OPERATION	op_code, 
    SXF_RCB		*rcb)
{
    DB_STATUS	    	status = E_DB_OK;
    EX_CONTEXT	    	context;
    i4	    	error;
	
    CLRDBERR(&rcb->sxf_error);

    /*	Make a cursury check for bad parameters. */
    if (op_code < SXF_MIN_OPCODE 
     || op_code > SXF_MAX_OPCODE 
     || rcb->sxf_cb_type != SXFRCB_CB 
     || rcb->sxf_length != sizeof (SXF_RCB) 
     || (Sxf_svcb == NULL && op_code != SXC_STARTUP))
    {
	/*  Figure out the error in more detail. */
	if (op_code < SXF_MIN_OPCODE || op_code > SXF_MAX_OPCODE)
	    SETDBERR(&rcb->sxf_error, 0, E_SX0001_BAD_OP_CODE);
	else if (rcb->sxf_cb_type != SXFRCB_CB)
	    SETDBERR(&rcb->sxf_error, 0, E_SX0002_BAD_CB_TYPE);
	else if (rcb->sxf_length != sizeof (SXF_RCB))
	{
	    TRdisplay("Bad SXF CB length. Input length %d expected %d\n",
		rcb->sxf_length, sizeof(SXF_RCB));
	    SETDBERR(&rcb->sxf_error, 0, E_SX0003_BAD_CB_LENGTH);
	}
	else
	    SETDBERR(&rcb->sxf_error, 0, E_SX000F_SXF_NOT_ACTIVE);

	return (E_DB_ERROR);
    }

    if (EXdeclare(ex_handler, &context) == OK 
     && (Sxf_svcb == NULL || (Sxf_svcb->sxf_svcb_status & SXF_CHECK) == 0))
    {
	switch (op_code)
	{
	/* Control operations. */
	case SXC_STARTUP:
	    status = sxc_startup(rcb);
	    break;

	case SXC_SHUTDOWN:
	    status = sxc_shutdown(rcb);
	    break;

	case SXC_BGN_SESSION:
	    status = sxc_bgn_session(rcb);
	    break;

	case SXC_END_SESSION:
	    status = sxc_end_session(rcb);
	    break;
	
	case SXC_ALTER_SESSION:
	    status = sxc_alter_session(rcb);
	    break;

	case SXC_AUDIT_THREAD:
	    status = sxac_audit_thread(rcb);
	    break;

	case SXC_AUDIT_WRITER_THREAD:
	    status = sxac_audit_writer_thread(rcb);
	    break;

	/* Audit file oerations */
	case SXA_OPEN:
	    status = sxaf_open(rcb);
	    break;

	case SXA_CLOSE:
	    status = sxaf_close(rcb);
	    break;

	/* Audit record operations */
	case SXR_WRITE:
	    status = sxar_write(rcb);
	    break;

	case SXR_POSITION:
	    status = sxar_position(rcb);
	    break;

	case SXR_READ:
	    status = sxar_read(rcb);
	    break;

	case SXR_FLUSH:
	    status = sxar_flush(rcb);
	    break;

	/* Audit state operations */
	case SXS_ALTER:
	    status = sxas_alter(rcb);
	    break;

	case SXS_SHOW:
	    status = sxas_show(rcb);
	    break;
	}

	EXdelete();
        return (status);
    }

    /*
    ** If exception handler declares or the SXF_SVCB has already been 
    ** marked inconsistent, this is a server fatal condition. In most 
    ** cases it is sufficient to return a server fatal error, and let the 
    ** caller handle the rest. 
    **
    ** However, if this is an audit record write operation we have to 
    ** nuke the server ourselves. The reason for this is that if the
    ** client code does not handle the return status correctly the 
    ** security of the system could be compromised.
    */
    EXdelete();

    if (op_code == SXR_WRITE)
    {
	_VOID_ ule_format(E_SX0005_INTERNAL_ERROR, NULL, ULE_LOG,
			NULL, NULL, 0L, NULL, &error, 0);
	_VOID_ ule_format(E_SX1048_SERVER_TERMINATE, NULL, ULE_LOG,
			NULL, NULL, 0L, NULL, &error, 0);
	_VOID_ CSterminate(CS_KILL, NULL);
    }

    SETDBERR(&rcb->sxf_error, 0, E_SX0005_INTERNAL_ERROR);
    return (E_DB_FATAL);
}
Exemple #14
0
/*{
** Name: opn_ceval	- evaluate the cost of the join operator tree
**
** Description:
**      Entry point for routines which evaluate cost of a join operator tree.
**      Contains checks for timeouts within the optimizer.
**
** Inputs:
**      subquery                        ptr to subquery being analyzed
**          ->ops_estate.opn_sroot      ptr to root of join operator tree
**
** Outputs:
**      subquery->ops_bestco            ptr to best plan found
**      subquery->ops_cost              cost of best plan found
**	Returns:
**	    VOID
**	Exceptions:
**	    none
**
** Side Effects:
**	    none
**
** History:
**	11-jun-86 (seputis)
**          initial creation from costeval
**	2-nov-88 (seputis)
**          changed CSstatistics interface
**	2-nov-88 (seputis)
**          add trace flag to timeout on number of plans being evaluated
**	15-aug-89 (seputis)
**	    add trace flag to adjust timeout factor which converts cost to time
**	    used to help isolate early timeout problems
**	16-may-90 (seputis)
**	    - b21582, move timeout checking to opn_timeout routine so it can be
**	    called from opn_arl
**	17-oct-90 (seputis)
**	    - b33386 - print error is no qep is found
**	22-apr-91 (seputis)
**	    - fix floating point exception handling problems
**	19-nov-99 (inkdo01)
**	    Changes to remove EXsignal from opn_exit processing.
**	18-oct-02 (inkdo01)
**	    Changes to enable new enumeration.
**	30-mar-2004 (hayke02)
**	    Call opn_exit() with a FALSE longjump.
**	30-Jun-2006 (kiria01) b116309
**	    Capture memory exhaustion error to errlog.log. 
**	11-Mar-2008 (kschendel) b122118
**	    Remove unused ops_tempco.  Fix up bfexception stuff so that we
**	    stop calling recover pointlessly at the start of every query.
[@history_line@]...
*/
OPN_STATUS
opn_ceval(
	OPS_SUBQUERY       *subquery)
{
    EX_CONTEXT	    excontext;		/* context block for exception 
                                        ** handler*/
    OPN_SUBTREE     *opn_ssubtp;        /* dummy var ignored at this level
                                        ** - list of subtrees with possible cost
                                        ** orderings (including reformats)
                                        ** - all element in the list have same
                                        ** relations but in different order or
                                        ** use a different tree structure.
                                        */
    OPN_RLS         *opn_srlmp;         /* dummy var ignored at this level
                                        ** - list of list of subtrees, with a
                                        ** different set of relations for each
                                        ** OPN_RLS element
                                        */
    OPN_EQS         *opn_seqp;          /* dummy var ignored at this level
                                        ** - used to create a list of different
                                        ** OPN_SUBTREE (using indexes) if
                                        ** an index exists.
                                        */
    OPN_STATUS	    sigstat = OPN_SIGOK;

    if ( EXdeclare(opn_mhandler, &excontext) == EX_DECLARE ) /* set
				    ** up exception handler to 
				    ** recover from out of memory
				    ** errors */
    {
	/* this point will only be reached if the enumeration processing has
	** run out of memory.  The optimizer will try to continue by copying 
	** the best CO tree found so far, out of enumeration memory, and  
	** reinitializing the enumeration stream, and continuing.  
	** The out-of-memory error will be reported if a complete pass of 
	** cost evaluation cannot be completed. */
	(VOID)EXdelete();		    /* cancel exception handler prior
					    ** to exiting routine */
	if (subquery->ops_global->ops_gmask & OPS_FLINT)
	{
	    subquery->ops_global->ops_gmask &= ~OPS_FLINT; /* reset exception
					    ** indicator */
	    return(OPN_SIGOK);		    /* skip this plan if a float
					    ** or integer exception has occurred
					    ** during processing */
	}
	if ( EXdeclare(opn_mhandler, &excontext) == EX_DECLARE ) /* set
				    ** exception handler to catch case in
				    ** which no progress is made */
	{
	    (VOID)EXdelete();		    /* cancel exception handler prior
					    ** to exiting routine */
	    if (subquery->ops_bestco)
		opx_verror(E_DB_WARN, E_OP0400_MEMORY, (OPX_FACILITY)0); /* report 
					    ** warning message to caller */
	    else
	    {
		opx_lerror(E_OP0400_MEMORY, 0); /* Output to errlog.log as well kiria01-b116309 */
		opx_error(E_OP0400_MEMORY); /* exit with a user error if the query
					    ** cannot find at least one acceptable
					    ** query plan */
	    }
	    opn_exit(subquery, FALSE);		    /* exit with current query plan */
	    return(OPN_SIGEXIT);
	}
	opn_recover(subquery);              /* routine will copy best CO tree 
					    ** and reinitialize memory stream
					    */
    }

    subquery->ops_global->ops_gmask &= (~OPS_FPEXCEPTION); /* reset fp exception
					    ** indicator before evaluating
					    ** plan */
    if (subquery->ops_global->ops_gmask & OPS_BFPEXCEPTION
      && subquery->ops_bestco != NULL)
	opn_recover(subquery);		    /* if the current best plan occurred with
					    ** exceptions then enumeration memory needs
					    ** to be flushed, so that subsequent plans
					    ** do not use subtrees which may have
					    ** been created with exceptions, this means
					    ** that the OPF cache of sub-trees is not
					    ** used if one exception has occurred and
					    ** the current best plan was created with
					    ** exceptions */
    

    (VOID) opn_nodecost (  subquery, 
		    subquery->ops_global->ops_estate.opn_sroot,
		    (subquery->ops_mask & OPS_LAENUM) ? subquery->ops_laeqcmap :
		    	&subquery->ops_eclass.ope_maps.opo_eqcmap, 
		    &opn_ssubtp,
		    &opn_seqp,
		    &opn_srlmp, &sigstat);

    if (sigstat != OPN_SIGEXIT && 
	!(subquery->ops_mask & OPS_LAENUM) &&
	opn_timeout(subquery))    	    /* check for timeout (but only for 
					    ** old style enumeration) */
    {
	(VOID)EXdelete();		    /* cancel exception handler prior
					    ** to exiting routine, call after
					    ** opn_timeout in case out of memory
					    ** errors occur */
	opn_exit(subquery, FALSE);	    /* at this point we 
					    ** return the subquery->opn_bestco
					    ** tree, this
					    ** could also happen in freeco
					    ** and enumerate */
	return(OPN_SIGEXIT);
    }
    (VOID)EXdelete();			    /* cancel exception handler prior
					    ** to exiting routine */
    return(sigstat);
}
Exemple #15
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 #16
0
/*
** Name: PCexec_suid - Execute a command as the ingres user.
**
** Description:
**	This procedure works with the Ingres service to run the given
**	command as the ingres user. It mimicks the "setuid" bit in UNIX.
**
** Inputs:
**	cmdbuf - command to execute as the ingres user
**
** Outputs:
**	none
**
** Returns:
**	OK
**	FAIL
**
** Side Effects:
**	none
**
** History:
**	08-jan-1998 (somsa01)
**	    Created.
**	19-feb-1998 (somsa01)
**	    We need to pass to the service the current working directory
**	    as well.  (Bug #89006)
**	25-feb-1998 (somsa01)
**	    We now have an input file for the process' stdin which
**	    runs through the OpenIngres service.
**	19-jun-1998 (somsa01)
**	    Use SYSTEM_PRODUCT_NAME for the name of the service.
**	10-jul-1998 (kitch01)
**		Bug 91362. If user is 'system' run through OpenIngres service
**		despite having access to server shared memory 'system' does not
**		have required privilege to access semaphores/mutexes.
**	11-jun-1999 (somsa01)
**	    If the command is a startup command, then it is always run through
**	    the Ingres service.
**	03-nov-1999 (somsa01)
**	    A failure from ControlService() should be treated as a severe
**	    error which should not let us continue.
** 	22-jan-2000 (somsa01)
**	    Return the exit code of the spawned process. Also, if the
**	    files exist, truncate them. The service name is now keyed off
**	    of II_INSTALLATION.
**	05-jun-2000 (somsa01)
**	    The Ingres installation may be started as the SYSTEM account,
**	    in which the 'ingres' user will not automatically have access
**	    to the shared memory segments. Therefore, even if the real
**	    user is 'ingres', check to see if he has access.
**	24-oct-2000 (somsa01)
**	    Removed the check on shared memory access. Access to the shared
**	    memory segment does not necessarily mean that the user running
**	    the process does not need to run the specified process as the
**	    Ingres owner. Also, generalized the check of the user with
**	    IDname_service().
**	18-dec-2000 (somsa01)
**	    Modified the cases to run the command "as is" without the Ingres
**	    service.
**	20-mar-2002 (somsa01)
**	    If all is well, return the exit code of the child process that
**	    was executed.
**	29-mar-2002 (somsa01)
**	    Properly return the child process exit code.
**	11-apr-2003 (somsa01)
**	    While waiting for "pending" to not be set, give some CPU back
**	    to the OS.
**      29-Jul-2005 (drivi01)
**	    Allow user to run the command if he/she owns a shared
**	    segment and ingres is not running as a service.
**	06-Dec-2006 (drivi01)
**	    Adding support for Vista, Vista requires "Global\" prefix for
**	    shared objects as well.  Replacing calls to GVosvers with 
**	    GVshobj which returns the prefix to shared objects.
**	    Added PCadjust_SeDebugPrivilege to allow quering of 
**	    System processes.
**	25-Jul-2007 (drivi01)
**		On Vista, PCexec_suid is unable to use SE_DEBUG Privilege
**	    to query process status and retireve its exit code.
**		The routine for monitoring a process and retrieving 
**	    its exit code has been moved to Ingres Service.
**	05-Nov-2009 (wanfr01) b122847
**	    Don't do a PCsleep unless you are waiting for more input
*/
STATUS
PCexec_suid(char *cmdbuf)
{
    EX_CONTEXT		context;
    SERVICE_STATUS	ssServiceStatus;
    LPSERVICE_STATUS	lpssServiceStatus = &ssServiceStatus;
    struct SETUID	setuid;
    DWORD		ProcID;
    HANDLE		SaveStdout;
    SECURITY_ATTRIBUTES	sa;
    CHAR		szRealUserID[25] = "";
    CHAR		*pszRealUserID = szRealUserID;
    CHAR		szServiceUserID[25] = "";
    CHAR		*pszServiceUserID = szServiceUserID;
    DWORD		BytesWritten, BytesRead = 0;
    CHAR		*inst_id;
    CHAR		SetuidShmName[64];
    CHAR		*temp_loc;
    CHAR		InBuf[256], OutBuf[256];
    static CHAR		SetuidPipeName[32];
    CL_ERR_DESC		err_code;
    CHAR		ServiceName[255];
    DWORD		ExitCode = 0;
    CHAR		tchII_INSTALLATION[3];
    BOOL		SetuidDbCmd = FALSE, ServiceCommand = FALSE;
    int			i, cmdlen;
    char		*ObjectPrefix;
	u_i4		drType;
    SC_HANDLE		schSCManager, OpIngSvcHandle;
    BOOL		bServiceStarted = FALSE;

    if (EXdeclare(ex_handler, &context) != OK)
    {
	EXdelete();
	PCexit(FAIL);
    }
    NMgtAt("II_INSTALLATION", &inst_id);
    STcopy(inst_id, tchII_INSTALLATION);

    /*
    ** See if this is a command that MUST be run through the Ingres
    ** service.
    */
    cmdlen = (i4)STlength(cmdbuf);
    for (i = 0; ServiceCommands[i] ; i++)
    {
	if (STbcompare( cmdbuf, cmdlen, ServiceCommands[i],
			(i4)STlength(ServiceCommands[i]), FALSE ) == 0)
	{
	    ServiceCommand = TRUE;
	    break;
	}
    }

    /*
    ** If the user is the same as the user who started the Ingres
    ** service, just spawn the command.
    */
    if (!ServiceCommand)
    {
	IDname(&pszRealUserID);
	if (!IDname_service(&pszServiceUserID) &&
	    STcompare(pszServiceUserID, pszRealUserID) == 0 && 
		PCisAdmin())
	{
	    /*
	    ** Attempt to just execute the command.
	    */
	    return( PCcmdline( (LOCATION *) NULL, cmdbuf, PC_WAIT,
		    (LOCATION *) NULL, &err_code) );
	}
	else
	{
	    /*
	    ** If current user is not the same as service user and ingres is not
	    ** running as a service, check if shared memory segment is owned
	    ** by current user, if user has access to shared segment allow him
	    ** to run the command.
	    */
	    PTR	shmem;
	    SIZE_TYPE	allocated_pages=0;
	    STATUS status;

	    if((status = MEget_pages(ME_MSHARED_MASK, 1, "lglkdata.mem",
	                 &shmem, &allocated_pages, &err_code)) == OK)
	    {
	        STprintf(ServiceName, "%s_Database_%s", SYSTEM_SERVICE_NAME, 
		tchII_INSTALLATION);
	        if ((schSCManager = OpenSCManager(NULL, NULL, 
					SC_MANAGER_CONNECT)) != NULL)
	        {
		    if ((OpIngSvcHandle = OpenService(schSCManager, ServiceName,
					SERVICE_QUERY_STATUS)) != NULL)
		    {
		       if (QueryServiceStatus(OpIngSvcHandle,lpssServiceStatus))
		       {
		    	if (ssServiceStatus.dwCurrentState != SERVICE_STOPPED)
			     bServiceStarted = TRUE;
		        }
		    }
	        }	
	        if (!bServiceStarted)
		    return(PCcmdline( (LOCATION *) NULL, cmdbuf, PC_WAIT,
			(LOCATION *) NULL, &err_code) );
	    }

	}

	/*
	** See if this command is an Ingres command which needs to interact
	** with at least one database.
	*/
	for (i = 0; validSetuidDbCmds[i] ; i++)
	{
	    if (STbcompare( cmdbuf, cmdlen, validSetuidDbCmds[i],
			    (i4)STlength(validSetuidDbCmds[i]), FALSE ) == 0)
	    {
		SetuidDbCmd = TRUE;
		break;
	    }
	}

	/*
	** If the user has access to the Ingres shared memory segment,
	** just spawn the command provided that it is not in the
	** validSetuidDbCmds list.
	*/
	if (!SetuidDbCmd)
	{
	    PTR	shmem;
	    SIZE_TYPE	allocated_pages=0;
	    STATUS	status;

	    if (((status = MEget_pages(ME_MSHARED_MASK, 1, "lglkdata.mem",
		&shmem,
		&allocated_pages, &err_code)) == OK) ||
		(status == ME_NO_SUCH_SEGMENT))
	    {
		if (status != ME_NO_SUCH_SEGMENT)
		    MEfree_pages(shmem, allocated_pages, &err_code);
		
		return( PCcmdline( (LOCATION *) NULL, cmdbuf, PC_WAIT,
			(LOCATION *) NULL, &err_code) );
	    }
	}
    }

    /*
    ** We must run the command through the Ingres service.
    */

    if ( STstrindex(cmdbuf, "-silent", 0, FALSE ) )
	SilentMode = TRUE;

    iimksec(&sa);


	GVshobj(&ObjectPrefix);
	STprintf(SetuidShmName, "%s%sSetuidShm", ObjectPrefix, tchII_INSTALLATION);

    if ( (SetuidShmHandle = OpenFileMapping(FILE_MAP_READ | FILE_MAP_WRITE,
					    FALSE,
					    SetuidShmName)) == NULL )
    {
	error_exit(GetLastError());
	return(FAIL);
    }
    if ( (SetuidShmPtr = MapViewOfFile(SetuidShmHandle,
				       FILE_MAP_WRITE | FILE_MAP_READ,
				       0,
				       0,
				       sizeof(struct SETUID_SHM))) == NULL )
    {
	error_exit(GetLastError());
	return(FAIL);
    }

    /* Set up the information to send to the service. */
    STcopy(cmdbuf, setuid.cmdline);
    GetCurrentDirectory(sizeof(setuid.WorkingDirectory),
			setuid.WorkingDirectory);
	NMgtAt("II_TEMPORARY", &temp_loc);
	drType = GetDriveType(NULL);
	if (drType == DRIVE_REMOTE)
	{
		STcopy(temp_loc, setuid.WorkingDirectory);
	}
    SaveStdout = GetStdHandle(STD_OUTPUT_HANDLE);
    CVla(GetCurrentProcessId(), setuid.ClientProcID);
    STprintf(SetuidPipeName, "\\\\.\\PIPE\\INGRES\\%s\\SETUID", inst_id);

    /* Set up the stdout file for the command. */
    STprintf(OutfileName, "%s\\%sstdout.tmp", temp_loc, setuid.ClientProcID);
    if ( (OutFile = CreateFile(OutfileName,
			       GENERIC_READ | GENERIC_WRITE,
			       FILE_SHARE_READ | FILE_SHARE_WRITE,
			       &sa,
			       CREATE_ALWAYS,
			       FILE_ATTRIBUTE_NORMAL,
			       NULL)) == INVALID_HANDLE_VALUE )
    {
	error_exit(GetLastError());
	return(FAIL);
    }

    /* Set up the stdin file for the command. */
    STprintf(InfileName, "%s\\%sstdin.tmp", temp_loc, setuid.ClientProcID);
    if ( (InFile = CreateFile(InfileName,
			      GENERIC_READ | GENERIC_WRITE,
			      FILE_SHARE_READ | FILE_SHARE_WRITE,
			      &sa,
			      CREATE_ALWAYS,
			      FILE_FLAG_WRITE_THROUGH,
			      NULL)) == INVALID_HANDLE_VALUE )
    {
	error_exit(GetLastError());
	return(FAIL);
    }

    /* Wait until the service is ready to process our request. */
    while (SetuidShmPtr->pending == TRUE)
	PCsleep(100);
    SetuidShmPtr->pending = TRUE;

    /* Trigger the "setuid" event of the service. */
    if ( (schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT)) == NULL)
    {
	error_exit(GetLastError());
	return(FAIL);
    }

    STprintf(ServiceName, "%s_Database_%s", SYSTEM_SERVICE_NAME,
	     tchII_INSTALLATION );
	OpIngSvcHandle = OpenService(schSCManager, ServiceName,
						SERVICE_USER_DEFINED_CONTROL);
	if (OpIngSvcHandle == NULL)
	{
		STprintf(ServiceName, "%s_DBATools_%s", SYSTEM_SERVICE_NAME,
	     tchII_INSTALLATION );
		OpIngSvcHandle = OpenService(schSCManager, ServiceName,
						SERVICE_USER_DEFINED_CONTROL);
	}
    if ( OpIngSvcHandle == NULL)
    {
	error_exit(GetLastError());
	return(FAIL);
    }
    if (!ControlService(OpIngSvcHandle, RUN_COMMAND_AS_INGRES,
			lpssServiceStatus))
    {
	error_exit(GetLastError());
	CloseServiceHandle(schSCManager);
	return(FAIL);
    }

    WaitNamedPipe(SetuidPipeName, NMPWAIT_WAIT_FOREVER);

    /* Send the information to the service. */
    if ( (Setuid_Handle = CreateFile(SetuidPipeName,
				     GENERIC_READ|GENERIC_WRITE,
				     FILE_SHARE_READ|FILE_SHARE_WRITE,
				     &sa,
				     OPEN_EXISTING,
				     FILE_ATTRIBUTE_NORMAL,
				     NULL)) == INVALID_HANDLE_VALUE )
    {
	error_exit(GetLastError());
	return(FAIL);
    }
    if (!WriteFile(Setuid_Handle, &setuid, sizeof(struct SETUID),
		   &BytesWritten, NULL))
    {
	error_exit(GetLastError());
	return(FAIL);
    }

    /*
    ** Retrieve information back from the service, and then
    ** disconnect from the pipe.
    */
    if (!ReadFile(Setuid_Handle, &setuid, sizeof(struct SETUID),
		  &BytesRead, NULL))
    {
	error_exit(GetLastError());
	return(FAIL);
    }

    ProcID = setuid.CreatedProcID;
    SetuidShmPtr->pending = FALSE;

    UnmapViewOfFile(SetuidShmPtr);
    SetuidShmPtr = NULL;
    CloseHandle(SetuidShmHandle);

    if ( (ProcID != -1) && (ProcID != -2) )
    {
	/*
	** Wait for the "spawned" process to exit, reading its output
	** from the stdout file.
	*/
	for (;;)
	{
	    if ( ((!ReadFile(OutFile, OutBuf, sizeof(OutBuf), &BytesRead, NULL)
		  || (BytesRead == 0)) && setuid.ExitCode != STILL_ACTIVE ))
		break;

	    if ( BytesRead &&
		 (!WriteFile(SaveStdout, OutBuf, BytesRead, &BytesWritten,
		  NULL)) && setuid.ExitCode != STILL_ACTIVE)
		break;
	    else if (BytesRead < sizeof(OutBuf))
		PCsleep(200);

	    /*
	    ** Currently, the only DBA program which can require
	    ** user input is verifydb. Therefore, when it spits out
	    ** the appropriate messages asking for user input, get
	    ** it from the end user and pass it along to the spawned
	    ** process.
	    */
	    if ( (STrstrindex(OutBuf, "S_DU04FF_CONTINUE_PROMPT", 0, FALSE)
			!= NULL) ||
		 (STrstrindex(OutBuf, "S_DU0300_PROMPT", 0, FALSE) != NULL) )
	    {
		SIflush(stdout);
		MEfill(sizeof(OutBuf), ' ', &OutBuf);
		MEfill(sizeof(InBuf), ' ', &InBuf);
		SIgetrec(InBuf, 255, 0);
		WriteFile(InFile, InBuf, sizeof(OutBuf), &BytesWritten, NULL);
	    }
	}

	ExitCode = setuid.ExitCode;
	CloseHandle(Setuid_Handle);
	CloseHandle(InFile);
	DeleteFile(InfileName);
	CloseHandle(OutFile);
	DeleteFile(OutfileName);
	CloseServiceHandle(OpIngSvcHandle);
	CloseServiceHandle(schSCManager);
        return(ExitCode);
    }
    else
    {
	error_exit(GetLastError());
	return(FAIL);
    }
}
Exemple #17
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 */