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 >
C/C++ Source or Header  |  1990-02-08  |  19KB  |  709 lines

  1. /****************************************************\
  2. *                                                    *
  3. * ROBBS - Rexx Object Building Block System          *
  4. *                                                    *
  5. * sermod.c - the first building block in the series. *
  6. *                                                    *
  7. \****************************************************/
  8.  
  9. #include <libraries/dos.h>
  10. #include <devices/serial.h>
  11. #include <fcntl.h>
  12. #include <functions.h>
  13. #include <exec/types.h>
  14. #include <stdio.h>
  15. #include <exec/memory.h>
  16. #include <rexx/storage.h>
  17. #include <rexx/rxslib.h>
  18. #include <intuition/intuition.h>
  19. #include "Options.h"
  20. #include "SerialIO.h"
  21. #include "defs.h"
  22.  
  23. BOOL  DoPrefs  = TRUE;
  24. BOOL  KeepGoing;
  25.  
  26. char    portname[32]    = "NONE";
  27. char    macroport[32]   = "ROBBS_ctrl";
  28. char    command[10]     = "TEXT";
  29. char    translate       = '\x7f';
  30. char    status[100];
  31. char    sendstring[255];
  32. STRPTR  Token;
  33. STRPTR  CreateArgstring();
  34.  
  35. int  sendoffset;
  36. int  connected;
  37. int  outstanding_rexx_commands = 0;
  38.  
  39. unsigned  char  pattern[10][99];
  40. unsigned  char  table[10][100];
  41.  
  42. long  listening = 1,
  43.       talking   = 1,
  44.       sending   = 0,
  45.       scan     = 0;
  46.  
  47. struct  RexxLib  *RexxSysBase;
  48. struct  MsgPort  RexxPort;
  49. struct  RexxMsg  *rmptr, *OutMsg, *CreateRexxMsg();
  50.  
  51. void FreePort();
  52.  
  53. struct IntuitionBase *IntuitionBase = NULL;
  54.  
  55.  
  56. /* Defaults if no "Init.key" file. */
  57. static struct options Options =
  58.   {
  59.   /* Baud      */  300,
  60.   /* Xon       */  FALSE,
  61.   } ;
  62.  
  63. struct rx_mes
  64. {
  65. struct rx_mes *next;
  66. struct RexxMsg *mes;
  67. BYTE flag;
  68. };
  69.  
  70. struct rx_mes *mslist;
  71.  
  72. static char *validargs[] =
  73.   {
  74.   "RXD",    /* 0  */
  75.   "TXD",    /* 1  */
  76.   "SEND",    /* 2  */
  77.   "LSEND",    /* 3  */
  78.   "MATCH",    /* 4  */
  79.   "SCAN",    /* 5  */
  80.   "STATUS",  /* 6  */
  81.   "CONNECT",  /* 7  */
  82.   "CTRL",    /* 8 */
  83.   "COMM",    /* 9 */
  84.   "ABORT",    /* 10 */
  85.   "DIE",    /* 11 */
  86.   NULL
  87.   };
  88.  
  89. static  int    numcmds = 12;
  90. static  int    SerialIO;
  91. static  long    PrefBuf;
  92. static  struct  Preferences *Preferences;
  93. static  struct  IOExtSer *rd = NULL, *wr = NULL;
  94.  
  95. extern int Mode;
  96.  
  97. /*--------------------------------------------------------------*/
  98. /*      cleanup: all done so close up and prepare to exit       */
  99. /*--------------------------------------------------------------*/
  100.  
  101. static void cleanup()
  102.   {
  103.   if (RexxSysBase != NULL)
  104.     {
  105.     RemPort(&RexxPort);                   /* unlink it                     */
  106.     FreePort(&RexxPort);                  /* release the port resources    */
  107.     CloseLibrary(RexxSysBase);
  108.     }
  109.   if ( SerialIO != NULL )
  110.     CloseSerialIO();
  111.   if ( IntuitionBase != NULL )
  112.     CloseLibrary(IntuitionBase);
  113.   }
  114.  
  115. /*--------------------------------------------------------------*/
  116. /*      setdefaults: set defaults occording to current options. */
  117. /*--------------------------------------------------------------*/
  118.  
  119. static void setdefaults()
  120.   {
  121.  
  122.   /* set defaults */
  123.  
  124.   if (DoPrefs)
  125.     {
  126.     switch ( Preferences->BaudRate )
  127.       {
  128.       case 1:
  129.         Options.Baud = 300;
  130.         break;
  131.       case 2:
  132.         Options.Baud = 1200;
  133.         break;
  134.       case 3:
  135.         Options.Baud = 2400;
  136.         break;
  137.       case 4:
  138.         Options.Baud = 4800;
  139.         break;
  140.       case 5:
  141.         Options.Baud = 9600;
  142.         break;
  143.       case 6:
  144.         Options.Baud = 19200;
  145.         break;
  146.       case 7:
  147.         Options.Baud = MIDI;
  148.         break;
  149.       default:
  150.         Options.Baud = 300;
  151.         break;
  152.       }
  153.     }
  154.  
  155.     SetSerBaud( (int)Options.Baud);
  156.     SetXonMode( (BOOL)Options.Xon );
  157.     DoPrefs = FALSE;
  158.  
  159.   }
  160.  
  161. /*--------------------------------------------------------------*/
  162. /*      init: initialize Sermod - set defaults                  */
  163. /*--------------------------------------------------------------*/
  164.  
  165. static void init()
  166.   {
  167.  
  168.   IntuitionBase = (struct IntuitionBase *)
  169.     OpenLibrary("intuition.library", INTUITION_REV);
  170.   if( IntuitionBase == NULL )
  171.     {
  172.     puts("can't open intuition\n");
  173.     goto badopen;
  174.     }
  175.  
  176.   Preferences = GetPrefs (&PrefBuf, (long)sizeof(PrefBuf));
  177.  
  178.   if(( SerialIO = InitSerialIO(&rd, &wr) ) == NULL )
  179.     {
  180.     puts("Can't open the Serial Port.\n");
  181.     goto badopen;
  182.     }
  183.  
  184.   setdefaults();
  185.  
  186.   RexxSysBase = (struct RexxLib *)OpenLibrary("rexxsyslib.library",0L);
  187.   if (RexxSysBase == NULL)
  188.     {
  189.     printf("Can't open rexxsyslib.library.\n");
  190.     goto badopen;
  191.     }
  192.   InitPort(&RexxPort,"ROBBS_ser");    /* Initialize our message port   */
  193.   AddPort(&RexxPort);          /* Make the port public          */
  194.  
  195.   clearmatch();
  196.  
  197.   return;
  198.  
  199.   badopen:
  200.   cleanup();
  201.   exit( 4 );
  202.   }
  203.  
  204. /*--------------------------------------------------------------*/
  205. /*      clearmatch: clear all pattern strings and table         */
  206. /*--------------------------------------------------------------*/
  207.  
  208. clearmatch()
  209. {
  210.   int i, j;
  211.   for (j=0; j<NUM_MATCH; j++)  {
  212.     *pattern[j] = 0;
  213.     for (i=0; i<MAX_MATCH; i++)
  214.       table[j][i] = '\0';
  215.     }
  216. }
  217.  
  218. /*--------------------------------------------------------------*/
  219. /*      buildstatus: build status string from variables         */
  220. /*--------------------------------------------------------------*/
  221.  
  222. void buildstatus()
  223. {
  224. char serioports[20];
  225.  
  226.   sprintf(status, "%d ",(int)Options.Baud);
  227.  
  228.   if (Mode)
  229.     strcat(status, "NOECHO ");
  230.   else
  231.     strcat(status, "NOECHO ");
  232.   if ( (BOOL)Options.Xon )
  233.     strcat(status, "XENABLED ");
  234.   else
  235.     strcat(status, "XDISABLED ");
  236.   if (translate == '\x7f')
  237.     strcat(status, "TRANSLATE ");
  238.   else
  239.     strcat(status, "NOTRANSLATE ");
  240.   if (talking)
  241.     strcat(status, "TALKON ");
  242.   else
  243.     strcat(status, "TALKOFF ");
  244.   if (listening)
  245.     strcat(status, "LISTENON ");
  246.   else
  247.     strcat(status, "LISTENOFF ");
  248.   if (scan)
  249.     strcat(status, "SCANON ");
  250.   else
  251.     strcat(status, "SCANOFF ");
  252.   strcat(status, portname);
  253.   strcat(status, " ");
  254.   strcat(status, macroport);
  255.   sprintf(serioports, " %lx %lx", rd, wr);
  256.   strcat(status, serioports);
  257. }
  258.  
  259. /*-----------------------------------------------------------------*/
  260. /*  checkmatch(stringpointer): check for match in serial stream   */
  261. /*-----------------------------------------------------------------*/
  262.  
  263. checkmatch(s)
  264. char *s;
  265. {
  266. int  to, from,
  267.     matchflag,
  268.     killedflag,
  269.     offset,
  270.     patnum;
  271.  
  272.   while (*s) {
  273.     for (patnum=0; patnum<NUM_MATCH; patnum++)
  274.       {
  275.       matchflag = 0;  killedflag = 0;
  276.       if (*s == *pattern[patnum]) {
  277.         matchflag = 1;
  278.         if (*pattern[patnum]+1 == '\0') {
  279.           sendmatch( patnum );
  280.           matchflag = 0;
  281.           }
  282.         }
  283.       for(offset=0; offset<MAX_MATCH && table[patnum][offset]; offset++)
  284.         {
  285.         if (*s == pattern[patnum][ (table[patnum][offset]) ] )
  286.           {
  287.           table[patnum][offset]++;
  288.           if (pattern[patnum][ (table[patnum][offset]) ] == '\0')
  289.             sendmatch(patnum);
  290.           }
  291.         else
  292.           {
  293.           table[patnum][offset] = '\0';
  294.           killedflag = 1;
  295.           }
  296.         }
  297.  
  298.       if (matchflag)
  299.         table[patnum][offset] = '\1';
  300.  
  301.       if (killedflag)
  302.         {
  303.         to = 0;
  304.         while (table[patnum][to])
  305.           to++;
  306.       
  307.         for (from=to; from<MAX_MATCH; from++)
  308.           if (table[patnum][from] != 0)
  309.             {
  310.             table[patnum][to] = table[patnum][from];
  311.             to++;
  312.             table[patnum][from] = '\0';
  313.             }
  314.         }
  315.       }
  316.     s++;
  317.     }
  318. }
  319.  
  320. /*---------------------------------------------------------------*/
  321. /*  send_rexx_msg: send a message to a port                      */
  322. /*                 RexxPort is reply port. look for reply there  */
  323. /*---------------------------------------------------------------*/
  324.  
  325. send_rexx_msg(port, cmd, s)
  326. char *port;
  327. char *cmd;
  328. char *s;
  329.  
  330. {
  331.   struct MsgPort *localport;
  332.  
  333.   if ((OutMsg = CreateRexxMsg(&RexxPort, "robbs", "ROBBS" )) != NULL)
  334.     {
  335.     OutMsg->rm_Args[0] = CreateArgstring( cmd, (long) strlen( cmd ));
  336.     OutMsg->rm_Args[1] = CreateArgstring( s, (long) strlen( s ));
  337.     OutMsg->rm_Action = RXFUNC | 1;
  338.  
  339.     if( addmsglink( OutMsg ) ) {
  340.       Forbid();
  341.       if ((localport = FindPort(port)) != NULL)
  342.         PutMsg(localport, OutMsg);
  343.       else
  344.         freemsglink( OutMsg );
  345.       Permit();
  346.       }
  347.     else {
  348.      free_rexx_command(OutMsg);
  349.      }
  350.     }
  351.   return;
  352. }
  353.  
  354. /*-----------------------------------------------------------------*/
  355. /*  free_rexx_command: free the message we sent and decrement count */
  356. /*-----------------------------------------------------------------*/
  357.  
  358. free_rexx_command(rexxmsg)
  359. register struct RexxMsg *rexxmsg;
  360. {
  361.   /* delete the argument that we originally sent */
  362.  
  363.   DeleteArgstring(rexxmsg->rm_Args[0]);
  364.   DeleteArgstring(rexxmsg->rm_Args[1]);
  365.  
  366.   /* delete the extended message */
  367.  
  368.   DeleteRexxMsg( rexxmsg );
  369. }
  370.  
  371. /*-----------------------------------------------------------------*/
  372. /*  addmsglink: keep track of all outstanding Arexx messages sent  */
  373. /*-----------------------------------------------------------------*/
  374.  
  375. addmsglink( outmsg )
  376. struct RexxMsg *outmsg;
  377. {
  378. struct rx_mes *rxptr;
  379. register struct rx_mes *new;
  380.  
  381.  if( new = AllocMem((long)sizeof(struct rx_mes), MEMF_CLEAR) ) {
  382.   outstanding_rexx_commands++;
  383.   new->mes = outmsg;
  384.   if( !mslist ) {
  385.    mslist = new;
  386.   }
  387.   else {
  388.    rxptr = mslist;
  389.    while( rxptr->next )
  390.     rxptr = rxptr->next;
  391.    rxptr->next = new;
  392.   }
  393.   return TRUE;
  394.  }
  395.  return FALSE;
  396. }
  397.  
  398. /*-----------------------------------------------------------------*/
  399. /*  freemsglink: delete message from list of outstanding messages  */
  400. /*-----------------------------------------------------------------*/
  401.  
  402. freemsglink( outmsg )
  403. struct RexxMsg *outmsg;
  404. {
  405. register struct rx_mes *ptr, *next;
  406.  
  407.  ptr = mslist;                                 /* start at top of linked list    */
  408.  if( ptr->mes == outmsg ) {                    /* first see if it's the one      */
  409.   mslist = ptr->next;                          /* yes, reset top of list to next */
  410.   free_rexx_command( outmsg );                 /* free the rexx_message          */
  411.   FreeMem( ptr, (long)sizeof(struct rx_mes) ); /* free the link                  */
  412.   outstanding_rexx_commands--;                 /* adjust the (un-needed?) count  */
  413.   return;
  414.  }
  415.  while( ptr ) {                                /* else, start walking the list   */
  416.   next = ptr->next;                            /* get pointer to 'next' in list  */
  417.   if( next->mes == outmsg ) {                  /* is it the one ?                */
  418.    ptr->next = next->next;                     /* yes, get its 'next' pointer... */
  419.    free_rexx_command( outmsg );                /* ...before freeing it           */
  420.    FreeMem( next, (long)sizeof(struct rx_mes) );
  421.    outstanding_rexx_commands--;
  422.    return;
  423.   }
  424.   ptr = next;    /* nope, move on */
  425.  }
  426. }
  427.  
  428. /*-----------------------------------------------------------------*/
  429. /*  sendtext(portname, string): send text to connected port         */
  430. /*-----------------------------------------------------------------*/
  431.  
  432. sendtext(s)
  433. char *s;
  434. {
  435.   send_rexx_msg(portname, command, s);
  436. }
  437.  
  438. /*-----------------------------------------------------------------*/
  439. /*  sendmatch(number): inform of match in serial stream            */
  440. /*-----------------------------------------------------------------*/
  441.  
  442. sendmatch( num )
  443. int num;
  444. {
  445. char message[9];
  446.  
  447.  sprintf( message, "%d", num );
  448.  send_rexx_msg(macroport, "MATCH", message);
  449. }
  450.  
  451. /************* develop a string, then send it all at once **************
  452.  *
  453.  *  This function is designed to be used with Manx's format() function
  454.  *  Usage: format(PutFormat,format_string...);
  455.  *  Your calls must have one added character at the end
  456.  *  of the format_string-- 255 (-1). Use \xff.
  457.  *  This tells PutFormat to go print the string it has been building.
  458.  *  Make sure your format_string ends with '\xff', otherwise
  459.  *  the string won't print properly.
  460.  *
  461.  ***********************************************************************/
  462.  
  463. void PutFormat(character)
  464. register UBYTE character;
  465. {
  466. static int count;
  467. static UBYTE buffer[255];
  468.  
  469.   if ( (character == SQUIRTCHAR) || (count >= OUTSIZE - 3) ) {
  470.     buffer[count] = '\0';
  471.     if (connected)
  472.       sendtext( buffer );
  473.     if (scan) {
  474.       checkmatch(buffer);
  475.       }
  476.     count = 0;
  477.     }
  478.   else
  479.     buffer[count++] = character;
  480. }
  481.  
  482. /*-----------------------------------------------------------------*
  483.  *  nexttoken(): search for next space or NULL in token string     *
  484.  *-----------------------------------------------------------------*/
  485.  
  486. nexttoken()
  487. {
  488.   for ( ;(*Token != ' ' && *Token != '\0'); Token++ );
  489.   if (*Token == ' ')
  490.     Token++;
  491.   return;
  492. }
  493.  
  494. /******************************************************
  495.  *             Main Program                           *
  496.  ******************************************************/
  497.  
  498. main()
  499. {
  500. ULONG class, waitmask;
  501. int c, i, j, temp, code ;
  502. UBYTE character;
  503. struct rx_mes *mslist2;
  504.  
  505.   init();
  506.  
  507.   waitmask = (1L << rd->IOSer.io_Message.mn_ReplyPort->mp_SigBit)
  508.     |  (1L << wr->IOSer.io_Message.mn_ReplyPort->mp_SigBit)
  509.     |  (1L << RexxPort.mp_SigBit);
  510.  
  511.   KeepGoing = TRUE;
  512.   while( KeepGoing )
  513.     {
  514.  
  515.     if (( rmptr = (struct RexxMsg *) GetMsg(&RexxPort)) == NULL )
  516.       {
  517.       Wait( waitmask );
  518.       rmptr = (struct RexxMsg *) GetMsg(&RexxPort);
  519.       }
  520.     if (rmptr)
  521.       {
  522.       if (rmptr->rm_Node.mn_Node.ln_Type == NT_REPLYMSG )
  523.         freemsglink(rmptr);
  524.       else
  525.         {
  526.         Token = rmptr->rm_Args[0];
  527.         for (i=0; i < numcmds; i++)
  528.           if ( StrcmpN(rmptr->rm_Args[0], validargs[i], 3L) == NULL)
  529.             break;
  530.  
  531.         if (rmptr->rm_Action & 15L)
  532.           Token = rmptr->rm_Args[1];
  533.         else
  534.           nexttoken();
  535.  
  536.         /* these are set here, and only changed in case of error */
  537.         rmptr->rm_Result1 = 0;           /* return code      */
  538.         rmptr->rm_Result2 = 0;           /* secondary result */
  539.  
  540.         switch (i)
  541.           {
  542.           case 0:    /* RXD */
  543.             if (StrcmpN( Token, "ON", 2L) == NULL) {
  544.               listening = 1;
  545.               RestartSerIO();
  546.               }
  547.             else  if (StrcmpN( Token, "OFF", 3L) == NULL) {
  548.               listening = 0;
  549.               FlushSerIO();
  550.               }
  551.             else  rmptr->rm_Result1 = 18;
  552.             break;
  553.           case 1:    /* TXD */
  554.             if (strcmp( Token, "ON", 2L) == NULL) talking = 1;
  555.             else  if (strcmp( Token, "OFF") == NULL) talking = 0;
  556.             else  rmptr->rm_Result1 = 18;
  557.             break;
  558.           case 2:    /* SEND   */
  559.           case 3:    /* LSEND */
  560.             for (j=0; Token[j]; j++)
  561.               if (Token[j] == '\r')
  562.                 Token[j] = '\n';
  563.             strcpy(sendstring, Token);
  564.             if (i == 3) {
  565.               strcat(sendstring, "\n");
  566.               }
  567.             sending = 1; sendoffset = 0;
  568.             break;
  569.           case 4:    /* MATCH */
  570.             if (*Token == 'c' || *Token == 'C')
  571.               {
  572.               clearmatch();
  573.               break;
  574.               }
  575.             if (*Token >= '0' && *Token <= '9')
  576.               {
  577.               j = atoi(Token);
  578.               for (i=0; i<MAX_MATCH; i++)
  579.                 table[j][i] = '\0';
  580.               nexttoken();
  581.               strcpy(pattern [j], Token);
  582.               }
  583.             else
  584.               rmptr->rm_Result1 = 18;
  585.             break;
  586.           case 5:    /* SCAN */
  587.             if (strcmp( Token, "ON", 2L) == NULL) scan = 1;
  588.             else  if (strcmp( Token, "OFF") == NULL) scan = 0;
  589.             else  rmptr->rm_Result1 = 18;
  590.             break;
  591.           case 6:    /* STATUS */
  592.             buildstatus();
  593.             if (rmptr->rm_Action & (RXFF_RESULT))
  594.               rmptr->rm_Result2 = (long)CreateArgstring(status,
  595.                             (long)strlen(status));
  596.             break;
  597.           case 7:    /* CONNECT */
  598.             if (*Token) {
  599.               for (j = 0; Token[j] != ' '; j++) {
  600.                 portname[j] = Token[j];
  601.                 }
  602.               portname[j] = '\0';
  603.               nexttoken();
  604.               sprintf(command,"%s", Token);
  605.               connected = 1;
  606.               }
  607.             else {
  608.               portname[0] = '\0';
  609.               connected = 0;
  610.               }
  611.             break;
  612.           case 8:    /* CTRL */
  613.             if (*Token)
  614.               strcpy(macroport, Token);
  615.             break;
  616.           case 9:    /* COMM */
  617.             Options.Baud = atoi(Token);
  618.             nexttoken();
  619.             if (*Token == 'N')  {
  620.               Mode = NOECHO;
  621.               }
  622.             if (*Token == 'E')  {
  623.               Mode = MODEECHO;
  624.               }
  625.             nexttoken();
  626.             if (StrcmpN( Token, "XE", 2L) == NULL)
  627.               Options.Xon = 1;
  628.             if (StrcmpN( Token, "XD", 2L) == NULL)
  629.               Options.Xon = 0;
  630.             nexttoken();
  631.             if (*Token == 'T')
  632.               translate = '\x7f';
  633.             if (*Token == 'N')
  634.               translate = '\xff';
  635.             setdefaults();
  636.  
  637.           case 10:    /* ABORT */
  638.             sending = 0;
  639.             break;
  640.  
  641.           case 11:    /* DIE */
  642.             KeepGoing = FALSE;
  643.             break;
  644.  
  645.           default:
  646.             rmptr->rm_Result1 = 5;           /* return code      */
  647.             break;
  648.           }
  649.         ReplyMsg(rmptr);                 /* send it back     */
  650.         }
  651.       }
  652.  
  653.     /*-----  Send string out serial port  -------*/
  654.  
  655.     if (talking) {
  656.       while (sending) {
  657.         if (sendstring[sendoffset] == '\n')
  658.           sendstring[sendoffset] = '\r';
  659.         SerIOPut(sendstring[sendoffset++]);
  660.         if (sendstring[sendoffset] == 0)
  661.           sending = 0;
  662.         }
  663.       }
  664.      /*----- Drain the Serial Port Buffer-------------*/
  665.  
  666.     if (listening)
  667.       {
  668.       if ( temp = CheckSerIO() )
  669.       {
  670.         do
  671.           {
  672.           c = SerIOGet() & translate;
  673.           PutFormat(c);
  674.           } while( CheckSerIO() );
  675.         PutFormat((UBYTE)'\xff');  /* squirt out all received chars */
  676.         }
  677.       }
  678.     }          /* end while ( keepgoing )    */
  679.  
  680.   while (outstanding_rexx_commands)
  681.     {
  682.     printf("sermod: Outstanding commands: %d\n",outstanding_rexx_commands );
  683.     if (( rmptr = (struct RexxMsg *) GetMsg(&RexxPort)) == NULL )
  684.       {
  685.       Wait( 1L << RexxPort.mp_SigBit );
  686.       rmptr = (struct RexxMsg *) GetMsg(&RexxPort);
  687.       }
  688.       if (rmptr) {
  689.       if( rmptr->rm_Node.mn_Node.ln_Type == NT_REPLYMSG ) {
  690.         freemsglink(rmptr);
  691.         }
  692.       else {
  693.         if (StrcmpN( rmptr->rm_Args[0], "REALLY_DIE", 10L) == NULL)
  694.           while( mslist ) {
  695.             free_rexx_command( mslist->mes );
  696.             mslist2 = mslist->next;
  697.             FreeMem( mslist, (long)sizeof(struct rx_mes) );
  698.             mslist = mslist2;
  699.             }
  700.  
  701.           ReplyMsg(rmptr);
  702.           break;
  703.           }
  704.       }
  705.     }
  706.   cleanup();
  707.   exit( 0 );
  708. } /* end of main */
  709.