home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 11 Util
/
11-Util.zip
/
TIMEXSRC.ZIP
/
BA_REQ.C
< prev
next >
Wrap
C/C++ Source or Header
|
1990-03-29
|
16KB
|
567 lines
/* ba_req.c -- Request Processing
February 1990 Mark E. Mallett, Personal Workstation Magazine
This module contains routines to process requests made of the
background agent. Requests are made via the named pipe, whose handle
is RqpipeH. Routines in the module serve to process individual
requests.
Included are the following routines:
process_request Process a request from a client
*/
#define INCL_BASE
#include <stdio.h>
#include <malloc.h>
#include <string.h>
#include <sys/types.h>
#include <os2.h>
#include "errhand.h"
#include "timex.h"
#include "ba_timex.h"
#include "evpack.h"
/* Local definitions */
typedef /* Args for request processing */
struct {
TMXMSG *rp_reqP; /* Ptr to request buffer */
TMXMSG *rp_rspP; /* Ptr to response buffer */
} RP;
/* External data referenced */
extern HSEM Eventsem; /* Semaphore for event list */
extern PEVENT *PendingL; /* List of events */
extern HPIPE RqpipeH; /* Handle for the request pipe */
extern ERRLIST *Werlist; /* Wild condition list */
/* External routines used */
extern void db_write( void ); /* Write the database */
extern PEVENT *event_find( char *nameP );
extern void schedule( PEVENT *peventP );
/* Local data publicly available */
/* Local routines and forward declarations */
static void errresp( TMXRSP_ERR *rspP, int code, char *msgP );
static void return_event( TMXMSG *rspP, EVENT *eventP );
static void rq_add( RP *rpP );
static int rq_add1(RP *);
static void rq_del( RP *rpP );
static int rq_del1(RP *);
static void rq_get( RP *rpP );
static int rq_get1(RP *);
static void rq_getnext( RP *rpP );
static int rq_getnext1(RP *);
static void rq_modify( RP *rpP );
static int rq_mod1(RP *);
/* Private data */
static struct { /* Dispatch for request codes */
int rd_code; /* The code */
void (*rd_rtc)( /* Routine to call */
RP *rpP
);
}
Msgdisp[] = {
{ REQ_ADD, rq_add },
{ REQ_DEL, rq_del },
{ REQ_GET, rq_get },
{ REQ_GETNEXT, rq_getnext },
{ REQ_MODIFY, rq_modify },
{ 0, NULL }
};
/*
*//* process_request()
Process an incoming request
Accepts :
Returns :
Notes :
This routine is called when a connection has been made to the
request pipe (RqpipeH); that is, when a client has opened the
pipe. This routine is responsible for reading the request,
delegating its handling to the apppropriate routine, and
sending the response.
*/
void
process_request() {
int status;
int rdX; /* Request dispatch table index */
USHORT xferL; /* Transfer length */
TMXMSG *reqP; /* Ptr to request message */
TMXMSG *rspP; /* Ptr to response message */
RP rpblk; /* Request processing block */
char rcvbuf[512]; /* Request receive buffer */
char rspbuf[512]; /* Request response buffer */
/* Read the request. */
status = DosRead( RqpipeH, &rcvbuf[0], 512, &xferL );
if ( status != 0 ) {
warning( EC_NOTOK, "Pipe read failed (%d)", status );
return;
}
reqP = (TMXMSG *)&rcvbuf[0];
rspP = (TMXMSG *)&rspbuf[0];
if ( xferL != reqP->m_len )
errresp( (TMXRSP_ERR *)rspP, 0, "Request length mismatch." );
else {
/* Dispatch according to request type */
for( rdX = 0; Msgdisp[rdX].rd_rtc != NULL; ++rdX )
if ( reqP->m_code == Msgdisp[rdX].rd_code )
/* Found it */
break;
if ( Msgdisp[rdX].rd_rtc == NULL ) {
/* Invalid request; fill in response */
errresp( (TMXRSP_ERR *)rspP, 0, "Invalid request." );
}
else {
/* Hand off to dispatch. */
rpblk.rp_reqP = reqP;
rpblk.rp_rspP = rspP;
(*Msgdisp[rdX].rd_rtc)( &rpblk );
}
}
/* Send the response back. */
status = DosWrite( RqpipeH, &rspbuf[0], rspP->m_len, &xferL );
if ( status != 0 )
warning( EC_NOTOK, "Pipe write failed (%d)", status );
else if ( rspP->m_len != xferL )
warning( EC_NOTOK, "Pipe write incomplete" );
}
/*
*//* rq_add( rpP )
Process the REQ_ADD request: add an event
*/
static void
rq_add(
RP *rpP /* Ptr to request parm blk */
) {
int eval; /* Error value */
char *msgP; /* Ptr to error return */
/* Lock the event list so that we can manipulate it */
get_sem( "rq_add", "event list", Eventsem );
/* Catch errors here so real routine can work */
eval = handle_error( rq_add1, rpP, Werlist, &msgP );
/* Unlock the list */
rel_sem( "rq_add", "event list", Eventsem );
/* Throw back an error if there was one */
if ( eval != CXNONE )
return_error( el_cond( Werlist, eval ), msgP );
}
static int
rq_add1(
RP *rpP /* Ptr to request parm blk */
) {
TMXMSG *reqP; /* Ptr to request message */
TMXMSG *rspP; /* Ptr to response message */
EVENT *eventP; /* Event that we create */
PEVENT *newP; /* Ptr to new pevent */
reqP = rpP->rp_reqP;
rspP = rpP->rp_rspP;
/* Make the new event */
eventP = event_unpack( (char *)&reqP[1], reqP->m_len - sizeof(TMXMSG) );
/* Check for duplicate name */
if ( event_find( eventP->ev_nameP ) != NULL ) {
errresp( (TMXRSP_ERR *)rspP, 0, "Event already exists." );
free( eventP );
return( 0 );
}
/* Make new event */
newP = emalloc( "rq_add", "new event", sizeof( PEVENT ) );
newP->pe_eventP = eventP;
/* Schedule the new event */
schedule( newP );
/* Write out the new event database */
db_write();
/* Response is OK */
rspP->m_code = RSP_OK;
rspP->m_len = sizeof( TMXMSG );
return( 0 );
}
/*
*//* rq_del( rpP )
Process the REQ_DEL request: delete an event
*/
static void
rq_del(
RP *rpP /* Request parameter block */
) {
int eval; /* Error value */
char *msgP; /* Ptr to error return */
/* Lock the event list so that we can manipulate it */
get_sem( "rq_del", "event list", Eventsem );
/* Catch errors here so real routine can work */
eval = handle_error( rq_del1, rpP, Werlist, &msgP );
/* Unlock the list */
rel_sem( "rq_del", "event list", Eventsem );
/* Throw back an error if there was one */
if ( eval != CXNONE )
return_error( el_cond( Werlist, eval ), msgP );
}
static int
rq_del1(
RP *rpP /* Ptr to request parm blk */
) {
TMXREQ_DEL *reqP; /* Ptr to request message */
TMXMSG *rspP; /* Ptr to response message */
PEVENT *peventP; /* Event to delete */
reqP = (TMXREQ_DEL *)rpP->rp_reqP;
rspP = rpP->rp_rspP;
/* Attempt to find the event to delete */
peventP = event_find( &reqP->d_evname[0] );
if ( peventP == NULL )
errresp( (TMXRSP_ERR *)rspP, 0, "No such event." );
else {
/* Unhook the event. */
unschedule( peventP );
/* Get rid of it */
free( peventP->pe_eventP );
free( peventP );
/* Write out the new event database */
db_write();
/* Response is OK */
rspP->m_code = RSP_OK;
rspP->m_len = sizeof( TMXMSG );
}
return( 0 );
}
/*
*//* rq_get( rpP )
Process the REQ_GET request: Get an event's description
*/
static void
rq_get(
RP *rpP /* Request parameter block */
) {
int eval; /* Error value */
char *msgP; /* Ptr to error return */
/* Lock the event list so that we can manipulate it */
get_sem( "rq_get", "event list", Eventsem );
/* Catch errors here so real routine can work */
eval = handle_error( rq_get1, rpP, Werlist, &msgP );
/* Unlock the list */
rel_sem( "rq_get", "event list", Eventsem );
/* Throw back an error if there was one */
if ( eval != CXNONE )
return_error( el_cond( Werlist, eval ), msgP );
}
static int
rq_get1(
RP *rpP
) {
TMXREQ_GET *reqP; /* Receive message header */
TMXMSG *rspP; /* Response message header */
PEVENT *peventP; /* Ptr to pending event */
reqP = (TMXREQ_GET *)rpP->rp_reqP;
rspP = rpP->rp_rspP;
/* Look for the event */
peventP = event_find( &reqP->g_evname[0] );
/* Return the event */
if ( peventP == NULL )
errresp( (TMXRSP_ERR *)rspP, 0, "Event not found." );
else
return_event( rspP, peventP->pe_eventP );
return( 0 );
}
/*
*//* rq_getnext( rpP )
Process the REQ_GETNEXT request: Get the event after the
one specified.
*/
static void
rq_getnext(
RP *rpP /* Request parameter block */
) {
int eval; /* Error value */
char *msgP; /* Ptr to error return */
/* Lock the event list so that we can manipulate it */
get_sem( "rq_getnext", "event list", Eventsem );
/* Catch errors here so real routine can work */
eval = handle_error( rq_getnext1, rpP, Werlist, &msgP );
/* Unlock the list */
rel_sem( "rq_getnext", "event list", Eventsem );
/* Throw back an error if there was one */
if ( eval != CXNONE )
return_error( el_cond( Werlist, eval ), msgP );
}
static int
rq_getnext1(
RP *rpP
) {
TMXREQ_GET *reqP; /* Receive message header */
TMXMSG *rspP; /* Response message header */
PEVENT *peventP; /* Ptr to pending event */
PEVENT *retP; /* Ptr to the one to return */
reqP = (TMXREQ_GET *)rpP->rp_reqP;
rspP = rpP->rp_rspP;
/* Look for the event. Note that the list of events is not kept
in alphabetical order, so we'll have to search the whole list
for the one that is the best candidate. It would be possible
to also maintain a list of events by name, but I don't imagine
that there will be a whole lot of events in the system, so this
ought to suffice. Besides, name-order is only important when
responding to edit requests, not in the normal operation. */
retP = NULL;
for( peventP = PendingL; peventP != NULL; peventP = peventP->pe_nextP )
if ( stricmp( &reqP->g_evname[0],
peventP->pe_eventP->ev_nameP ) < 0 ) {
/* We have a candidate; choose between it and the one already
selected. */
if ( ( retP == NULL ) ||
( stricmp( peventP->pe_eventP->ev_nameP,
retP->pe_eventP->ev_nameP ) < 0 )
)
retP = peventP;
}
/* Return the event */
if ( retP == NULL ) {
rspP->m_code = RSP_OK;
rspP->m_len = sizeof( TMXMSG );
}
else
return_event( rspP, retP->pe_eventP );
return( 0 );
}
/*
*//* rq_modify( rpP )
Process the REQ_MODIFY request; modify an event.
This replaces an existing event with a new one.
*/
static void
rq_modify(
RP *rpP /* Ptr to request parm blk */
) {
int eval; /* Error value */
char *msgP; /* Ptr to error return */
/* Lock the event list so that we can manipulate it */
get_sem( "rq_modify", "event list", Eventsem );
/* Catch errors here so real routine can work */
eval = handle_error( rq_mod1, rpP, Werlist, &msgP );
/* Unlock the list */
rel_sem( "rq_modify", "event list", Eventsem );
/* Throw back an error if there was one */
if ( eval != CXNONE )
return_error( el_cond( Werlist, eval ), msgP );
}
static int
rq_mod1(
RP *rpP /* Ptr to request parm blk */
) {
char *nameP; /* Ptr to old name */
char *evbufP; /* Ptr to buffered event data */
TMXMSG *reqP; /* Ptr to request message */
TMXMSG *rspP; /* Ptr to response message */
EVENT *eventP; /* Event that we create */
PEVENT *peventP; /* Ptr to the current event */
reqP = rpP->rp_reqP;
rspP = rpP->rp_rspP;
/* Get the info */
nameP = (char *)&reqP[1]; /* Name of the event */
evbufP = nameP + strlen( nameP ) + 1;
eventP = event_unpack( evbufP,
reqP->m_len - ( evbufP - (char *)reqP ) );
/* Find the existing event */
peventP = event_find( nameP );
if ( peventP == NULL ) {
errresp( (TMXRSP_ERR *)rspP, 0, "No such event." );
free( eventP );
return( 0 );
}
/* Take it off the list. */
unschedule( peventP );
/* Check for illegal modify (to another existing name) */
if ( event_find( eventP->ev_nameP ) != NULL ) {
errresp( (TMXRSP_ERR *)rspP, 0, "Duplicate event name." );
free( eventP );
schedule( peventP );
return( 0 );
}
/* Replace the event info. */
free( peventP->pe_eventP );
peventP->pe_eventP = eventP;
/* Reschedule it. */
schedule( peventP );
/* Write out the new event database */
db_write();
/* OK return. */
rspP->m_code = RSP_OK;
rspP->m_len = sizeof( TMXMSG );
return( 0 );
}
/*
*//* return_event( rspP, eventP )
Formats an event-return message
Accepts :
rspP Ptr to response block
eventP Ptr to event block
Returns :
< nothing >
*/
static void
return_event(
TMXMSG *rspP, /* Ptr to response block */
EVENT *eventP /* Ptr to event to return */
) {
rspP->m_code = RSP_EVENT;
rspP->m_len = sizeof( TMXMSG );
rspP->m_len += event_pack( eventP, (char *)&rspP[1],
512 - sizeof(TMXMSG) );
}
/*
*//* errresp( msgP, errcode, errmsgP )
Fill in an error response message
Accepts :
msgP Ptr to message buffer
errcode Ptr to error code
errmsgP Ptr to error message string
Returns :
*rspLP Length of message
< message filled in >
*/
static void
errresp(
TMXRSP_ERR *msgP, /* Ptr to message buffer */
int errcode, /* Error code */
char *errmsgP /* Error message text */
) {
msgP->e_msghdr.m_code = RSP_ERROR;
msgP->e_msghdr.m_len = sizeof( TMXRSP_ERR ) + strlen( errmsgP );
msgP->e_code = errcode;
strcpy( &msgP->e_msg[0], errmsgP );
}