home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Club Amiga de Montreal - CAM
/
CAM_CD_1.iso
/
files
/
339.lha
/
SerMod
/
source
/
sermod.c
< prev
next >
Wrap
C/C++ Source or Header
|
1990-02-08
|
19KB
|
709 lines
/****************************************************\
* *
* ROBBS - Rexx Object Building Block System *
* *
* sermod.c - the first building block in the series. *
* *
\****************************************************/
#include <libraries/dos.h>
#include <devices/serial.h>
#include <fcntl.h>
#include <functions.h>
#include <exec/types.h>
#include <stdio.h>
#include <exec/memory.h>
#include <rexx/storage.h>
#include <rexx/rxslib.h>
#include <intuition/intuition.h>
#include "Options.h"
#include "SerialIO.h"
#include "defs.h"
BOOL DoPrefs = TRUE;
BOOL KeepGoing;
char portname[32] = "NONE";
char macroport[32] = "ROBBS_ctrl";
char command[10] = "TEXT";
char translate = '\x7f';
char status[100];
char sendstring[255];
STRPTR Token;
STRPTR CreateArgstring();
int sendoffset;
int connected;
int outstanding_rexx_commands = 0;
unsigned char pattern[10][99];
unsigned char table[10][100];
long listening = 1,
talking = 1,
sending = 0,
scan = 0;
struct RexxLib *RexxSysBase;
struct MsgPort RexxPort;
struct RexxMsg *rmptr, *OutMsg, *CreateRexxMsg();
void FreePort();
struct IntuitionBase *IntuitionBase = NULL;
/* Defaults if no "Init.key" file. */
static struct options Options =
{
/* Baud */ 300,
/* Xon */ FALSE,
} ;
struct rx_mes
{
struct rx_mes *next;
struct RexxMsg *mes;
BYTE flag;
};
struct rx_mes *mslist;
static char *validargs[] =
{
"RXD", /* 0 */
"TXD", /* 1 */
"SEND", /* 2 */
"LSEND", /* 3 */
"MATCH", /* 4 */
"SCAN", /* 5 */
"STATUS", /* 6 */
"CONNECT", /* 7 */
"CTRL", /* 8 */
"COMM", /* 9 */
"ABORT", /* 10 */
"DIE", /* 11 */
NULL
};
static int numcmds = 12;
static int SerialIO;
static long PrefBuf;
static struct Preferences *Preferences;
static struct IOExtSer *rd = NULL, *wr = NULL;
extern int Mode;
/*--------------------------------------------------------------*/
/* cleanup: all done so close up and prepare to exit */
/*--------------------------------------------------------------*/
static void cleanup()
{
if (RexxSysBase != NULL)
{
RemPort(&RexxPort); /* unlink it */
FreePort(&RexxPort); /* release the port resources */
CloseLibrary(RexxSysBase);
}
if ( SerialIO != NULL )
CloseSerialIO();
if ( IntuitionBase != NULL )
CloseLibrary(IntuitionBase);
}
/*--------------------------------------------------------------*/
/* setdefaults: set defaults occording to current options. */
/*--------------------------------------------------------------*/
static void setdefaults()
{
/* set defaults */
if (DoPrefs)
{
switch ( Preferences->BaudRate )
{
case 1:
Options.Baud = 300;
break;
case 2:
Options.Baud = 1200;
break;
case 3:
Options.Baud = 2400;
break;
case 4:
Options.Baud = 4800;
break;
case 5:
Options.Baud = 9600;
break;
case 6:
Options.Baud = 19200;
break;
case 7:
Options.Baud = MIDI;
break;
default:
Options.Baud = 300;
break;
}
}
SetSerBaud( (int)Options.Baud);
SetXonMode( (BOOL)Options.Xon );
DoPrefs = FALSE;
}
/*--------------------------------------------------------------*/
/* init: initialize Sermod - set defaults */
/*--------------------------------------------------------------*/
static void init()
{
IntuitionBase = (struct IntuitionBase *)
OpenLibrary("intuition.library", INTUITION_REV);
if( IntuitionBase == NULL )
{
puts("can't open intuition\n");
goto badopen;
}
Preferences = GetPrefs (&PrefBuf, (long)sizeof(PrefBuf));
if(( SerialIO = InitSerialIO(&rd, &wr) ) == NULL )
{
puts("Can't open the Serial Port.\n");
goto badopen;
}
setdefaults();
RexxSysBase = (struct RexxLib *)OpenLibrary("rexxsyslib.library",0L);
if (RexxSysBase == NULL)
{
printf("Can't open rexxsyslib.library.\n");
goto badopen;
}
InitPort(&RexxPort,"ROBBS_ser"); /* Initialize our message port */
AddPort(&RexxPort); /* Make the port public */
clearmatch();
return;
badopen:
cleanup();
exit( 4 );
}
/*--------------------------------------------------------------*/
/* clearmatch: clear all pattern strings and table */
/*--------------------------------------------------------------*/
clearmatch()
{
int i, j;
for (j=0; j<NUM_MATCH; j++) {
*pattern[j] = 0;
for (i=0; i<MAX_MATCH; i++)
table[j][i] = '\0';
}
}
/*--------------------------------------------------------------*/
/* buildstatus: build status string from variables */
/*--------------------------------------------------------------*/
void buildstatus()
{
char serioports[20];
sprintf(status, "%d ",(int)Options.Baud);
if (Mode)
strcat(status, "NOECHO ");
else
strcat(status, "NOECHO ");
if ( (BOOL)Options.Xon )
strcat(status, "XENABLED ");
else
strcat(status, "XDISABLED ");
if (translate == '\x7f')
strcat(status, "TRANSLATE ");
else
strcat(status, "NOTRANSLATE ");
if (talking)
strcat(status, "TALKON ");
else
strcat(status, "TALKOFF ");
if (listening)
strcat(status, "LISTENON ");
else
strcat(status, "LISTENOFF ");
if (scan)
strcat(status, "SCANON ");
else
strcat(status, "SCANOFF ");
strcat(status, portname);
strcat(status, " ");
strcat(status, macroport);
sprintf(serioports, " %lx %lx", rd, wr);
strcat(status, serioports);
}
/*-----------------------------------------------------------------*/
/* checkmatch(stringpointer): check for match in serial stream */
/*-----------------------------------------------------------------*/
checkmatch(s)
char *s;
{
int to, from,
matchflag,
killedflag,
offset,
patnum;
while (*s) {
for (patnum=0; patnum<NUM_MATCH; patnum++)
{
matchflag = 0; killedflag = 0;
if (*s == *pattern[patnum]) {
matchflag = 1;
if (*pattern[patnum]+1 == '\0') {
sendmatch( patnum );
matchflag = 0;
}
}
for(offset=0; offset<MAX_MATCH && table[patnum][offset]; offset++)
{
if (*s == pattern[patnum][ (table[patnum][offset]) ] )
{
table[patnum][offset]++;
if (pattern[patnum][ (table[patnum][offset]) ] == '\0')
sendmatch(patnum);
}
else
{
table[patnum][offset] = '\0';
killedflag = 1;
}
}
if (matchflag)
table[patnum][offset] = '\1';
if (killedflag)
{
to = 0;
while (table[patnum][to])
to++;
for (from=to; from<MAX_MATCH; from++)
if (table[patnum][from] != 0)
{
table[patnum][to] = table[patnum][from];
to++;
table[patnum][from] = '\0';
}
}
}
s++;
}
}
/*---------------------------------------------------------------*/
/* send_rexx_msg: send a message to a port */
/* RexxPort is reply port. look for reply there */
/*---------------------------------------------------------------*/
send_rexx_msg(port, cmd, s)
char *port;
char *cmd;
char *s;
{
struct MsgPort *localport;
if ((OutMsg = CreateRexxMsg(&RexxPort, "robbs", "ROBBS" )) != NULL)
{
OutMsg->rm_Args[0] = CreateArgstring( cmd, (long) strlen( cmd ));
OutMsg->rm_Args[1] = CreateArgstring( s, (long) strlen( s ));
OutMsg->rm_Action = RXFUNC | 1;
if( addmsglink( OutMsg ) ) {
Forbid();
if ((localport = FindPort(port)) != NULL)
PutMsg(localport, OutMsg);
else
freemsglink( OutMsg );
Permit();
}
else {
free_rexx_command(OutMsg);
}
}
return;
}
/*-----------------------------------------------------------------*/
/* free_rexx_command: free the message we sent and decrement count */
/*-----------------------------------------------------------------*/
free_rexx_command(rexxmsg)
register struct RexxMsg *rexxmsg;
{
/* delete the argument that we originally sent */
DeleteArgstring(rexxmsg->rm_Args[0]);
DeleteArgstring(rexxmsg->rm_Args[1]);
/* delete the extended message */
DeleteRexxMsg( rexxmsg );
}
/*-----------------------------------------------------------------*/
/* addmsglink: keep track of all outstanding Arexx messages sent */
/*-----------------------------------------------------------------*/
addmsglink( outmsg )
struct RexxMsg *outmsg;
{
struct rx_mes *rxptr;
register struct rx_mes *new;
if( new = AllocMem((long)sizeof(struct rx_mes), MEMF_CLEAR) ) {
outstanding_rexx_commands++;
new->mes = outmsg;
if( !mslist ) {
mslist = new;
}
else {
rxptr = mslist;
while( rxptr->next )
rxptr = rxptr->next;
rxptr->next = new;
}
return TRUE;
}
return FALSE;
}
/*-----------------------------------------------------------------*/
/* freemsglink: delete message from list of outstanding messages */
/*-----------------------------------------------------------------*/
freemsglink( outmsg )
struct RexxMsg *outmsg;
{
register struct rx_mes *ptr, *next;
ptr = mslist; /* start at top of linked list */
if( ptr->mes == outmsg ) { /* first see if it's the one */
mslist = ptr->next; /* yes, reset top of list to next */
free_rexx_command( outmsg ); /* free the rexx_message */
FreeMem( ptr, (long)sizeof(struct rx_mes) ); /* free the link */
outstanding_rexx_commands--; /* adjust the (un-needed?) count */
return;
}
while( ptr ) { /* else, start walking the list */
next = ptr->next; /* get pointer to 'next' in list */
if( next->mes == outmsg ) { /* is it the one ? */
ptr->next = next->next; /* yes, get its 'next' pointer... */
free_rexx_command( outmsg ); /* ...before freeing it */
FreeMem( next, (long)sizeof(struct rx_mes) );
outstanding_rexx_commands--;
return;
}
ptr = next; /* nope, move on */
}
}
/*-----------------------------------------------------------------*/
/* sendtext(portname, string): send text to connected port */
/*-----------------------------------------------------------------*/
sendtext(s)
char *s;
{
send_rexx_msg(portname, command, s);
}
/*-----------------------------------------------------------------*/
/* sendmatch(number): inform of match in serial stream */
/*-----------------------------------------------------------------*/
sendmatch( num )
int num;
{
char message[9];
sprintf( message, "%d", num );
send_rexx_msg(macroport, "MATCH", message);
}
/************* develop a string, then send it all at once **************
*
* This function is designed to be used with Manx's format() function
* Usage: format(PutFormat,format_string...);
* Your calls must have one added character at the end
* of the format_string-- 255 (-1). Use \xff.
* This tells PutFormat to go print the string it has been building.
* Make sure your format_string ends with '\xff', otherwise
* the string won't print properly.
*
***********************************************************************/
void PutFormat(character)
register UBYTE character;
{
static int count;
static UBYTE buffer[255];
if ( (character == SQUIRTCHAR) || (count >= OUTSIZE - 3) ) {
buffer[count] = '\0';
if (connected)
sendtext( buffer );
if (scan) {
checkmatch(buffer);
}
count = 0;
}
else
buffer[count++] = character;
}
/*-----------------------------------------------------------------*
* nexttoken(): search for next space or NULL in token string *
*-----------------------------------------------------------------*/
nexttoken()
{
for ( ;(*Token != ' ' && *Token != '\0'); Token++ );
if (*Token == ' ')
Token++;
return;
}
/******************************************************
* Main Program *
******************************************************/
main()
{
ULONG class, waitmask;
int c, i, j, temp, code ;
UBYTE character;
struct rx_mes *mslist2;
init();
waitmask = (1L << rd->IOSer.io_Message.mn_ReplyPort->mp_SigBit)
| (1L << wr->IOSer.io_Message.mn_ReplyPort->mp_SigBit)
| (1L << RexxPort.mp_SigBit);
KeepGoing = TRUE;
while( KeepGoing )
{
if (( rmptr = (struct RexxMsg *) GetMsg(&RexxPort)) == NULL )
{
Wait( waitmask );
rmptr = (struct RexxMsg *) GetMsg(&RexxPort);
}
if (rmptr)
{
if (rmptr->rm_Node.mn_Node.ln_Type == NT_REPLYMSG )
freemsglink(rmptr);
else
{
Token = rmptr->rm_Args[0];
for (i=0; i < numcmds; i++)
if ( StrcmpN(rmptr->rm_Args[0], validargs[i], 3L) == NULL)
break;
if (rmptr->rm_Action & 15L)
Token = rmptr->rm_Args[1];
else
nexttoken();
/* these are set here, and only changed in case of error */
rmptr->rm_Result1 = 0; /* return code */
rmptr->rm_Result2 = 0; /* secondary result */
switch (i)
{
case 0: /* RXD */
if (StrcmpN( Token, "ON", 2L) == NULL) {
listening = 1;
RestartSerIO();
}
else if (StrcmpN( Token, "OFF", 3L) == NULL) {
listening = 0;
FlushSerIO();
}
else rmptr->rm_Result1 = 18;
break;
case 1: /* TXD */
if (strcmp( Token, "ON", 2L) == NULL) talking = 1;
else if (strcmp( Token, "OFF") == NULL) talking = 0;
else rmptr->rm_Result1 = 18;
break;
case 2: /* SEND */
case 3: /* LSEND */
for (j=0; Token[j]; j++)
if (Token[j] == '\r')
Token[j] = '\n';
strcpy(sendstring, Token);
if (i == 3) {
strcat(sendstring, "\n");
}
sending = 1; sendoffset = 0;
break;
case 4: /* MATCH */
if (*Token == 'c' || *Token == 'C')
{
clearmatch();
break;
}
if (*Token >= '0' && *Token <= '9')
{
j = atoi(Token);
for (i=0; i<MAX_MATCH; i++)
table[j][i] = '\0';
nexttoken();
strcpy(pattern [j], Token);
}
else
rmptr->rm_Result1 = 18;
break;
case 5: /* SCAN */
if (strcmp( Token, "ON", 2L) == NULL) scan = 1;
else if (strcmp( Token, "OFF") == NULL) scan = 0;
else rmptr->rm_Result1 = 18;
break;
case 6: /* STATUS */
buildstatus();
if (rmptr->rm_Action & (RXFF_RESULT))
rmptr->rm_Result2 = (long)CreateArgstring(status,
(long)strlen(status));
break;
case 7: /* CONNECT */
if (*Token) {
for (j = 0; Token[j] != ' '; j++) {
portname[j] = Token[j];
}
portname[j] = '\0';
nexttoken();
sprintf(command,"%s", Token);
connected = 1;
}
else {
portname[0] = '\0';
connected = 0;
}
break;
case 8: /* CTRL */
if (*Token)
strcpy(macroport, Token);
break;
case 9: /* COMM */
Options.Baud = atoi(Token);
nexttoken();
if (*Token == 'N') {
Mode = NOECHO;
}
if (*Token == 'E') {
Mode = MODEECHO;
}
nexttoken();
if (StrcmpN( Token, "XE", 2L) == NULL)
Options.Xon = 1;
if (StrcmpN( Token, "XD", 2L) == NULL)
Options.Xon = 0;
nexttoken();
if (*Token == 'T')
translate = '\x7f';
if (*Token == 'N')
translate = '\xff';
setdefaults();
case 10: /* ABORT */
sending = 0;
break;
case 11: /* DIE */
KeepGoing = FALSE;
break;
default:
rmptr->rm_Result1 = 5; /* return code */
break;
}
ReplyMsg(rmptr); /* send it back */
}
}
/*----- Send string out serial port -------*/
if (talking) {
while (sending) {
if (sendstring[sendoffset] == '\n')
sendstring[sendoffset] = '\r';
SerIOPut(sendstring[sendoffset++]);
if (sendstring[sendoffset] == 0)
sending = 0;
}
}
/*----- Drain the Serial Port Buffer-------------*/
if (listening)
{
if ( temp = CheckSerIO() )
{
do
{
c = SerIOGet() & translate;
PutFormat(c);
} while( CheckSerIO() );
PutFormat((UBYTE)'\xff'); /* squirt out all received chars */
}
}
} /* end while ( keepgoing ) */
while (outstanding_rexx_commands)
{
printf("sermod: Outstanding commands: %d\n",outstanding_rexx_commands );
if (( rmptr = (struct RexxMsg *) GetMsg(&RexxPort)) == NULL )
{
Wait( 1L << RexxPort.mp_SigBit );
rmptr = (struct RexxMsg *) GetMsg(&RexxPort);
}
if (rmptr) {
if( rmptr->rm_Node.mn_Node.ln_Type == NT_REPLYMSG ) {
freemsglink(rmptr);
}
else {
if (StrcmpN( rmptr->rm_Args[0], "REALLY_DIE", 10L) == NULL)
while( mslist ) {
free_rexx_command( mslist->mes );
mslist2 = mslist->next;
FreeMem( mslist, (long)sizeof(struct rx_mes) );
mslist = mslist2;
}
ReplyMsg(rmptr);
break;
}
}
}
cleanup();
exit( 0 );
} /* end of main */