home *** CD-ROM | disk | FTP | other *** search
/ Garbo / Garbo.cdr / mac / source / layers.zoo / layers.2 / protocol.c < prev   
Encoding:
C/C++ Source or Header  |  1990-06-11  |  24.9 KB  |  870 lines

  1. /*             Copyright (C) 1989 by David W. Trissel 
  2.  *
  3.  *              Not derived from licensed software.
  4.  *
  5.  * Permission is granted to freely use, copy, modify, and redistribute
  6.  * this software, provided that no attempt is made to gain profit from it,
  7.  * the author is not construed to be liable for any results of using the
  8.  * software, alterations are clearly marked as such, and this notice is
  9.  * not modified.
  10.  *
  11.  */
  12.  
  13. #include    <stdio.h>
  14. #include    <signal.h>
  15. #include    <errno.h>
  16. #include    "layers.h"
  17.  
  18.                 /* protocol.c - BSD MacLayers protocol driver */
  19.  
  20. /*    This module handles all interaction with the Macintosh MacLayers
  21. **    program. Services provided are:
  22. **
  23. **        InitLink()    - initialize link to MacLayers
  24. **
  25. **        TopChannel() - return highest prority channel
  26. **
  27. **        SendNew()    - request new layer channel of MacLayers
  28. **
  29. **        SendTitle() - change window title to given string (NOT IMPLENTED YET)
  30. **
  31. **        SendDelete()- tell MacLayers indicated layer has died
  32. **
  33. **        SendQuit()    - order MacLayers to terminate layers mode
  34. **
  35. **        SendData()    - send output to indicated channel's window
  36. **
  37. **        SendReshape() - send Shape structure to MacLayers
  38. **
  39. **        ProcessStreamin() - data is ready to be processed from MacLayers
  40. **
  41. */
  42.  
  43. #define DUMPALL
  44. #undef    DUMPALL
  45.  
  46. /* C library calls */
  47. unsigned alarm();                /* alarm system call */
  48.  
  49. static int        GetData();
  50. static void        Packet();
  51. static void        Parse();
  52. static void        AwaitInput();
  53. static void        asciishape();
  54. static void        fill4();
  55. static void        fill2();
  56. static void        fill1();
  57. static int        parseshape();
  58. static unsigned    get4();
  59. static unsigned    get2();
  60. static unsigned    get1();
  61.  
  62. static char        inbuff[IOSIZE];        /* input buffer from MacLayers */
  63. static char     *inpos;                /* current input position in buffer */
  64. static int        insize = 0;            /* characters left to process */
  65. static int        Outstream = -1;        /* current output stream channel */
  66. static int        Instream = -1;        /* current input stream channel */
  67.  
  68. static struct Shape    SNshape;        /* SendNew() shape response */
  69. static int        SNresp = 0;            /* SendNew() reponse poll flag */
  70. static int        SNchan = 0;            /* SendNew() channel return */
  71. #define SN_WAITING    -1000            /* SendNew() waiting response value */
  72.  
  73. #define ATTRSIZE    15                /* size of window attribute string */
  74.  
  75. #define FLUSH    fflush(stdout)
  76.  
  77.  
  78.                 /* Initlink() - initialize link with MacLayers */
  79.  
  80. /* Returns:
  81. **                0 - linkup failed
  82. **                1 - linkup successful, Maclayers now in protocol mode
  83. */
  84.  
  85. int
  86. Initlink()
  87. {
  88.     int Outstream = -1;                /* no default stream yet */
  89.     int    Instream = -1;                /* no default stream yet */
  90.     int        num1, num2, num3;        /* scanf item result */
  91.     int        err;                    /* error code */
  92.  
  93. #define WAITTIME    10                /* second wait response time */
  94. #define INITTIME    2                /* wait time after succesful startup */
  95.  
  96.     /* we must non-buffer input since all input must be immediate */
  97.     setbuf(stdin, NULL);            /* non-buffer all input */
  98.  
  99.     /* send intitial request for terminal type and version number */
  100.     DO DEBUG("write: ESC [ c\n");
  101.     if ((err=printf("\033[c")) < 0)
  102.       {
  103.         DO DEBUG(" printf() error code %d\n", err);
  104.         return ( 0 );                /* problem with stdout */
  105.       }
  106.     FLUSH;                            /* force output buffer */
  107.  
  108.     /* attempt to read "ESC [ ? 8 ; typedigits ; versiondigits c" */
  109.     num1 = num2 = num3 = -1;        /* default to unsupplied values */
  110.     (void) alarm(WAITTIME);            /* set timeout */
  111.     DO DEBUG(" doing first scanf\n");
  112.     (void) scanf("\033[?%d;%d;%dc", &num1, &num2, &num3);
  113.     (void) alarm(0);                /* cancel alarm */
  114.     DO DEBUG("read ESC [ ? %d ; %d; %d c\n", num1, num2, num3);
  115.     if (num1 != 8 || num2 != 10)
  116.         return ( 0 );                /* not correct response or layers term ID */
  117.  
  118.     /* ask terminal if ENC_ENABLE is to be forced */
  119.     DO DEBUG("write: ESC [ F\n");
  120.     (void) printf("\033[F");
  121.     FLUSH;                            /* force output buffer */
  122.     (void) alarm(WAITTIME);            /* set timeout */
  123.  
  124.     /* attempt to read "ESC [ flag F" (flag indicates ENC_ENABLE status) */
  125.     num1 = -1;                        /* default to invalid response */
  126.     (void) scanf("\033[%dF", &num1);
  127.     (void) alarm(0);                /* cancel alarm */
  128.     DO DEBUG("read ESC [ %d F\n", num1);
  129.     if (num1 != 2 && num1 != 0)
  130.         return ( 0 );                /* something's wrong */
  131.  
  132.     /* now startup packet mode in non ENC_ENABLE processing */
  133.     DO DEBUG("write: ESC [ 2 ; 0 v\n");
  134.     (void) printf("\033[2;0v");        /* "ESC [ 2 ; 0 v" */
  135.     FLUSH;                            /* force output buffer */
  136.  
  137.     /* we are now in packet mode */
  138.     sleep( INITTIME );                /* let Macintosh keep up with us */
  139.     return ( 1 );                    /* return successful startup */
  140.  
  141. } /* Initlink() */
  142.  
  143.  
  144.             /* TopChannel() - return highest prority channel */
  145.  
  146. int
  147. TopChannel()
  148. {
  149.     return ( Instream );
  150.  
  151. } /* TopChannel() */
  152.  
  153.  
  154.     /*
  155.     ** WARNING: Most of the following functions may be recursively called
  156.     **            as control commands are processed from the input stream
  157.     */
  158.  
  159.  
  160.             /* ProcessStreamin() - MacLayers has input to process */
  161.  
  162. void
  163. ProcessStreamin()
  164. {
  165.     int        c;                        /* input character being processed */
  166.  
  167.     DO DEBUG("ProcessStreamin()\n");
  168.  
  169.     GetData(0);                        /* read some and don't timeout */
  170.  
  171.     while (insize > 0)                /* while more data to process ... */
  172.         Parse();                    /* process next chuck of data */
  173.  
  174. } /* ProcessStreamin() */
  175.  
  176.  
  177.         /* SendNew() - request new layer channel from MacLayers */
  178.  
  179. /*    This command is unique in that it returns a response from MacLayers.
  180. **    To do this we continue processing the input stream until we get
  181. **    our return. (This leads to recursive conditions.) The variables
  182. **    'SNresp', 'SNshape' and 'SNchan' are set when our reply is received.
  183. */
  184. int
  185. SendNew(shape)
  186. struct Shape    *shape;                /* shape to use for new window */
  187. {
  188.     int            i;                    /* attribute count variable */
  189.     char        astring[ATTRSIZE];    /* copy of attribute string */
  190.  
  191.     DO DEBUG("SendNew() new layer requested: '~%cA'\n", '1'+ATTRSIZE);
  192.  
  193.     /* check for a recursive call */
  194.     if (SNresp == SN_WAITING)
  195.       {    DO DEBUG("return 0 - recursive call\n");
  196.         return ( 0 );                /* return failure */
  197.       }
  198.  
  199.     putchar(ESCAPE);                /* send start of control packet char */
  200.     putchar('1' + ATTRSIZE);        /* send command size */
  201.     putchar('A');                    /* send command */
  202.     asciishape(shape, astring);        /* convert shape to string */
  203.     for (i=0; i < ATTRSIZE; i++)
  204.         putchar(astring[i]);        /* send next attribute digit */
  205.     FLUSH;
  206.  
  207.     /* now stay here and process the input stream until we see our response */
  208. /**** THIS SHOULD BE ENHANCED TO TIMEOUT WITH GetData() AND REISSUE REQUEST */
  209.     SNresp = SN_WAITING;            /* indicate we are waiting a response */
  210.     while (SNresp == SN_WAITING)
  211.       { DO DEBUG(" while (SNresp %d == %d)\n", SNresp, SN_WAITING);
  212.         AwaitInput();                /* wait till input from MacLayers arrives */
  213.         ProcessStreamin();            /* process available input */
  214.       }
  215.  
  216.     if (SNresp == -1)                /* if Maclayers rejected request */
  217.         SNchan = 0;                    /* return failure channel of zero */
  218.     else
  219.         *shape = SNshape;            /* else update shape structure */
  220.  
  221.     DO DEBUG("SendNew() returning channel %d\n", SNchan);
  222.  
  223.     return ( SNchan );                /* return the indicated channel */
  224.  
  225. } /* SendNew() */
  226.  
  227.  
  228.             /* SendReshape() - send to shape to MacLayers */
  229.  
  230. void
  231. SendReshape(chan, shape)
  232. int                chan;                /* channel shape belongs to */
  233. struct Shape    *shape;                /* shape to use for new window */
  234. {
  235.     int            i;                    /* attribute count variable */
  236.     char        astring[ATTRSIZE];    /* copy of attribute string */
  237.  
  238.     DO DEBUG("SendReshape() reshape: '~%cA'\n", '2'+ATTRSIZE);
  239.  
  240.     if (chan <= 0 || chan > MAXPCHAN)
  241.       {    DO DEBUG("BAD CHANNEL!!!\n");
  242.         return;                        /* ignore request */
  243.       }
  244.  
  245.     putchar(ESCAPE);                /* send start of control packet char */
  246.     putchar('2' + ATTRSIZE);        /* send command size */
  247.     putchar('R');                    /* send command */
  248.     putchar(chan + '0');            /* send channel */
  249.     asciishape(shape, astring);        /* convert shape to string */
  250.     DO DEBUG("shape: %.*s\n", ATTRSIZE, astring);
  251.     for (i=0; i < ATTRSIZE; i++)
  252.         putchar(astring[i]);        /* send next attribute digit */
  253.     FLUSH;
  254.  
  255. } /* SendReshape() */
  256.  
  257.  
  258.             /* SendTitle() - set layer's window title */
  259.  
  260. void
  261. SendTitle(chan, buff, cnt)
  262. int            chan;                    /* layer window ID */
  263. char        *buff;                    /* new title string */
  264. int            cnt;                    /* count of title length */
  265. {
  266.     int        i;                        /* work variable */
  267.  
  268.     DO DEBUG("SendTitle(chan%d, len %d, '%.*s')\n", chan, cnt, cnt, buff);
  269.  
  270.     if (chan <= 0 || chan > MAXPCHAN)
  271.       {    DO DEBUG("BAD CHANNEL!!!\n");
  272.         return;                        /* ignore request */
  273.       }
  274.  
  275.     if (cnt < 0)
  276.       {    DO DEBUG("BAD COUNT!!!\n");
  277.         return;                        /* ignore request */
  278.       }
  279.  
  280.     /* for now chop title size to 29 chars since that's MacLayer's limit */
  281.     if (cnt > 29)
  282.         cnt = 29;                    /* due to packet size limit */
  283.  
  284.     /* we must guarantee that the size will not appear to be another ESCAPE */
  285.     if ('2' + cnt == ESCAPE)
  286.         cnt--;                        /* truncate to avoid ESCAPE ESCAPE */
  287.     
  288.     putchar(ESCAPE);                /* send start of control packet char */
  289.     putchar('2' + cnt);                /* send size of packet */
  290.     putchar('T');                    /* send command */
  291.     putchar(chan + '0');            /* send channel ID */
  292.     for (i=0; i<cnt; i++)
  293.         putchar(buff[i]);            /* send out title */
  294.     FLUSH;
  295.  
  296. } /* SendTitle() */
  297.  
  298.  
  299.             /* SendDelete() - tell Maclayers layer died */
  300.  
  301. void
  302. SendDelete(chan)
  303. int        chan;                        /* dead channel ID */
  304. {
  305.     DO DEBUG("SendDelete(%d) '~2D%d'\n", chan, chan);
  306.  
  307.     if (chan <= 0 || chan > MAXPCHAN) /* check channel ID */
  308.       {    DO DEBUG("BAD CHANNEL!!!\n");
  309.         return;                        /* ignore request */
  310.       }
  311.  
  312.     putchar(ESCAPE);                /* send control packet start char */
  313.     putchar('2');                    /* send command size */
  314.     putchar('D');                    /* send command character */
  315.     putchar(chan + '0');            /* channel ID in ascii */
  316.     FLUSH;
  317.  
  318. } /* SendDelete() */
  319.  
  320.  
  321.             /* SendQuit() - order MacLayers to end layers mode */
  322.  
  323. void
  324. SendQuit(chan)
  325. int        chan;                        /* dead channel ID */
  326. {
  327.     DO DEBUG("SendQuit() '~1E'\n");
  328.  
  329.     putchar(ESCAPE);                /* send control packet start char */
  330.     putchar('1');                    /* send command size */
  331.     putchar('E');                    /* send command */
  332.     FLUSH;
  333.  
  334. } /* SendQuit() */
  335.  
  336.  
  337.             /* SendData() - send output to layer's window */
  338.  
  339. void
  340. SendData(chan, buff, cnt)
  341. int            chan;                    /* layer window ID */
  342. unsigned char *buff;                /* new title string */
  343. int            cnt;                    /* count of title length */
  344. {
  345.     unsigned c;                        /* output character being sent */
  346.  
  347.     DO
  348.       {    int        dcnt;
  349.  
  350.         DEBUG("SendData(chan %d, len %d, '", chan, cnt, cnt, buff);
  351.         for (dcnt=0; dcnt<cnt; dcnt++)
  352.             DEBUG("%c", buff[dcnt]); /* dump each char so null doesn't stop */
  353.         DEBUG("')\n");
  354.       }
  355.  
  356.     if (chan <= 0 || chan > MAXPCHAN)
  357.       {    DO DEBUG("BAD CHANNEL!!!\n");
  358.         return;                        /* ignore request */
  359.       }
  360.  
  361.     /* if new output channel stream then prefix redirect command */
  362.     if (chan != Outstream)
  363.       {    DO DEBUG("Redirecting output to %d '~2O%d'\n", chan, chan);
  364.         putchar(ESCAPE);            /* start of command sequence */
  365.         putchar('2');                /* send command size */
  366.         putchar('O');                /* send command */
  367.         putchar(chan + '0');        /* put out channel in ASCII */
  368.         Outstream = chan;            /* new output stream set */
  369.       }
  370.  
  371.     /* transmit the buffer converting the ESCAPE sequence to double ESCAPE */
  372.     while (cnt--)
  373.       {    c = *buff++;                /* get next output character */
  374. #ifdef DUMPALL
  375.         DO DEBUG("outchar %c 0x%x\n", c, c);
  376. #endif
  377.         if (c == ESCAPE || c == (ESCAPE + 0x80))
  378.           {    putchar(c);                /* put it out twice */
  379. #ifdef DUMPALL
  380.             DO DEBUG(" Doubled Escape!\n");
  381. #endif
  382.           }
  383.         putchar(c);                    /* write character out */
  384.       }
  385.  
  386.     FLUSH;                            /* force out queued output characters */
  387.         
  388. } /* SendData() */
  389.  
  390.  
  391.             /* Parse() - process next chunk of input stream */
  392.  
  393. static void
  394. Parse()
  395. {
  396. #define    ST_NULL        0                /* not primed for next state yet */
  397. #define    ST_STREAM    1                /* processing default stream input */
  398. #define    ST_PKT        2                /* processing packet data */
  399.  
  400.     int        c;                        /* input character being processed */
  401.  
  402.     static    int state = ST_NULL;    /* current input state */
  403.     static    int psize = 0;            /* packet size */
  404.     static    int    rempsize = 0;        /* remembered packet size */
  405.     static    char pdata[MAXSTR];        /* area for packet data */
  406.     static    char *ppos;                /* packet read insert position */
  407.     static    int escapemode = 0;        /* processing escape character */
  408.     static    int    escapechar;            /* escape character being processed */
  409.     static    pchan = -1;                /* packet input stream channel */
  410.  
  411.     while (insize-- > 0)            /* while more data */
  412.       {    c = *inpos++;                /* get next character */
  413.         switch (state)                /* process according to state */
  414.         { case ST_NULL:                /* prepare for new packet */
  415.             DO DEBUG("ST_NULL\n");
  416.             psize = 0;                /* clear packet size */
  417.             ppos = pdata;            /* start fill at data position */
  418.             pchan = Instream;        /* packet channel is current input stream */
  419.             state = ST_STREAM;        /* default is stream processing */
  420.  
  421.           case ST_STREAM:
  422.             /* stream keyboard input for layer */
  423.             /* check for escape char with possible high bit on */
  424. #ifdef DUMPALL
  425.             DO DEBUG("ST_STREAM %x/%x esc %d insz %d\n",
  426.                         c, c & 0x7f, escapemode, insize);
  427. #endif
  428.             if (c == ESCAPE || c == (ESCAPE | 0x80))
  429.               {    if (escapemode && c == escapechar) /* previous was ESCAPE */
  430.                 /* this is really a single ESCAPE character */
  431.                     escapemode = 0;        /* back out of ESCAPE mode */
  432.                 else
  433.                     /* what do we do with back to back esc esc+0x80 ? */
  434.                   {    /* flag in escape mode */
  435.                     escapemode++;
  436.                     escapechar = c;        /* remember character used for escape */
  437.                     continue;            /* and continue scan */
  438.                   }
  439.               }
  440.             else
  441.             if (escapemode)
  442.               { /* this is the start of a control packet */
  443.                 if (psize)                /* if we have previous data packet */
  444.                     Packet(pchan, psize, pdata); /* finish up previous pkt */
  445.                 /* process packet size */
  446.                 psize = (c & 0x7f) - '0'; /* save size byte */
  447.                 if (psize <= 0 || psize > MAXSTR)
  448.                   {    /* bad size */
  449.                     DO DEBUG("Bad pkt size %d\n", psize);
  450.                     break;                /* trash this packet */
  451.                   }
  452.                 rempsize = psize;        /* remember this size for later */
  453. #if 0
  454.                 ptimo = rtimo;            /* start receive timeout */                
  455. #endif
  456.                 escapemode = 0;            /* escape mode now off */
  457.                 ppos = pdata;            /* initialize data store pointer */
  458.                 state = ST_PKT;            /* expect packet data next */
  459.                 continue;                /* continue scan */
  460.               }
  461.                   
  462.             /* process standard data output character for current stream */
  463.             
  464.             *ppos++ = c;                /* save next data character */
  465.                 
  466.             if (++psize >= MAXSTR)        /* if packet full ... */
  467.               {    Packet(pchan, psize, pdata); /* process this packet */
  468.                 break;                    /* end packet processing */
  469.               }                  
  470.             continue;                    /* continue scan */
  471.                                                 
  472.           case ST_PKT:
  473.             /* process next paket data byte */
  474.             *ppos++ = c & 0x7f;        /* store next data byte */
  475. #ifdef DUMPALL
  476.             DO DEBUG("ST_PKT: %x sz %d\n", c & 0x7f, psize);
  477. #endif
  478.             if (--psize != 0)
  479.                 continue;
  480. #if 0
  481.             if (crc((unsigned char *) &rpkt, rpkt.pkt.HEADER_DSIZE+2))
  482.                 STATS(Scrcerr);            /* communications error */
  483.             else
  484. #endif
  485.             Packet(0, rempsize, pdata); /* process it */
  486.                 
  487.             } /* end build packet switch */
  488.             
  489. #if 0
  490.         ptimo = 0;                        /* no more receive timeout */
  491. #endif
  492.         state = ST_NULL;                /* no more receive packet in progress */
  493.             
  494.       } /* end while (insize) */
  495.           
  496.     if (state == ST_STREAM && psize )    /* if we have some data ... */
  497.       {    Packet(Instream, psize, pdata); /* process this data */
  498. #if 0
  499.         ptimo = 0;                        /* no more receive timeout */
  500. #endif
  501.         state = ST_NULL;                /* no more receive packet in progress */
  502.       }
  503.  
  504. } /* Parse() */
  505.  
  506.  
  507.         /* Packet() - prcess next input data string or control packet */
  508. static void
  509. Packet(chan, size, buff)
  510. int            chan;                        /* channel (0 if control packet) */
  511. int            size;                        /* amount of data */
  512. char        *buff;                        /* pointer to packet data */
  513. {
  514.     static struct Shape shape;            /* Shape structure */
  515.  
  516.     DO DEBUG("Packet(chan %d, size %d, '%.*s')\n", chan, size, size, buff);
  517.  
  518.     /* verify channel */
  519.     if (chan < 0 || chan > MAXPCHAN)
  520.       {    DO DEBUG("BAD CHANNEL!!\n");
  521.         return;                            /* ignore bad channel */
  522.       }
  523.  
  524.     /* if data packet (chan>0) feed data to server */
  525.     if (chan > 0)
  526.       {    ReceiveData(chan, buff, size);
  527.         return;                            /* we are through */
  528.       }
  529.  
  530.     /* control packet (channel 0) */
  531.     chan = buff[1] - '0';                /* assume channel specified */
  532.     if (chan < 0 || chan > MAXPCHAN)    /* if invalid ... */
  533.         chan = 0;                        /* set to zero */
  534.  
  535.     switch (buff[0])
  536.     { case 'I':        /* redirect stream */
  537.         DO DEBUG("CMD 'I' redirect stream to %c\n", buff[1]);
  538.         if (size != 2)                    /* verify size */
  539.             break;                        /* break if bad */
  540.         if (chan == 0)                    /* verify channel */
  541.             break;                        /* break if bad */
  542.         Instream = chan;                /* new instream channel */
  543.         return;                            /* we are through */
  544.  
  545.       case 'A':        /* returned A_NEWLAYER packet */
  546.         DO DEBUG("CMD 'A' A_NEWLAYER response %c newchan %c SNresp %d\n",
  547.                     buff[2], buff[1], SNresp);
  548.         if (size != 3 + ATTRSIZE)
  549.             break;                        /* break if bad */
  550.  
  551.         /* if SendNew() not waiting for a response this is invalid */
  552.         if (SNresp != SN_WAITING)
  553.             break;                        /* break if bad */
  554.  
  555.         if (buff[2] == '1')                /* if response is "failed" ... */
  556.             SNresp = -1;                /* show -1 response */
  557.         else
  558.         if (buff[2] == '0')                /* if response is "success" ... */
  559.           {    if (chan == 0)                /* if invalid channel */
  560.                 break;                    /* break if bad */
  561.             /* build shape structure for SendNew() */
  562.             if (parseshape(&SNshape, &buff[3]) == -1)
  563.                 break;                    /* if invalid data then bad packet */
  564.             SNresp = 0;                    /* show good response */
  565.             SNchan = chan;                /* indicate channel returned */
  566.           }
  567.         else
  568.             break;                        /* break if bad */
  569.  
  570.         DO DEBUG("SNresp = %d, SNchan = %d\n", SNresp, SNchan);
  571.         return;                            /* we are through */
  572.         
  573.       case 'N':        /* new layer creation */
  574.         DO DEBUG("CMD 'N' new layer creation newchan %c\n", buff[1]);
  575.         if (size != 2 + ATTRSIZE)        /* verify size */
  576.             break;                        /* break if bad */
  577.         if (chan == 0)                    /* verify channel */
  578.             break;                        /* break if bad */
  579.         /* build shape structure */
  580.         if (parseshape(&shape, &buff[2]) == -1)
  581.             break;                        /* if invalid data then bad packet */
  582.         ReceiveNew(chan, &shape);        /* pass to server */
  583.         return;                            /* packet is done */
  584.  
  585.       case 'D':        /* deleted layer */
  586.         DO DEBUG("CMD 'D' deleted layer %c\n", buff[1]);
  587.         if (size != 2)                    /* verify size */
  588.             break;                        /* break if bad */
  589.         if (chan == 0)                    /* verify channel */
  590.             break;                        /* break if bad */
  591.         ReceiveDelete(chan);            /* pass on to server */
  592.         return;                            /* packet is done */
  593.  
  594.       case 'E':        /* exit - awaiting shutdown */
  595.         DO DEBUG("CMD 'E' exit MacLayers awaiting shutdown msg\n");
  596.         if (size != 1)                    /* verify size */
  597.             break;                        /* break if bad */
  598.         ReceiveQuit();                    /* pass to server */
  599.         /* NOT REACHED*/
  600.         return;                            /* ?? should never reach here */
  601.  
  602.       case 'R':        /* reshaped */
  603.         DO DEBUG("CMD 'R' reshape chan %c\n", buff[1]);
  604.  
  605.         if (size != 2 + ATTRSIZE)        /* verify size */
  606.             break;                        /* break if bad */
  607.  
  608.         if (chan == 0)                    /* verify channel */
  609.             break;                        /* break if bad */
  610.  
  611.         /* build shape structure */
  612.         if (parseshape(&shape, &buff[2]) == -1)
  613.             break;                        /* if invalid data then bad packet */
  614.  
  615.         ReceiveReshape(chan, &shape);     /* tell server about shape */
  616.         return;                            /* packet processed */
  617.  
  618.       case 'S':        /* signal */
  619.         DO DEBUG("CMD 'S' SIGNAL chan %c sig %c\n", buff[1], buff[2]);
  620.         if (size != 3)                    /* verify size */
  621.             break;                        /* break if bad */
  622.         if (chan == 0)
  623.             break;                        /* break if bad */
  624.  
  625.         if (buff[2] == '0')                /* if SIGINT */
  626.             size = SIGINT;                /* yes */
  627.         else
  628.         if (buff[2] == '1')                /* if SIGHUP */
  629.             size = SIGHUP;                /* yes */
  630.         else
  631.             break;                        /* invalid signal */
  632.             
  633.         ReceiveSignal(chan, size);        /* pass to server */
  634.         return;                            /* packet processed */
  635.  
  636.       default:
  637.         DO DEBUG("ILLEGAL CONTROL PACKET!!!\n");
  638.         return;                            /* ignore bad packet */
  639.  
  640.     } /* end command packet switch */
  641.  
  642.     /* switch falls out if bad size or channel for given command */
  643.     DO DEBUG("Invalid size or channel!!!\n");    /* dump error */
  644.     return;                                /* ignore packet */
  645.  
  646. } /* Packet() */
  647.  
  648.  
  649.             /* GetData() - read next input from MacLayers stream */
  650.  
  651. /*    An input timout parameter can indicate that we return if nothing
  652. **    is read within a certain amount of seconds. The return code is:
  653. **
  654. **        0 - timeout occured and no data was read
  655. **
  656. **        1 - no timeout occured, data read
  657. */
  658. static int
  659. GetData(timeout)
  660. int            timeout;                /* timeout in seconds (or zero) */
  661. {
  662.     int        result;                    /* return from read() */
  663.  
  664.     DO DEBUG("GetData(timout %d)\n", timeout);
  665.  
  666.     /* if buffer still has data simply return (SHOULD NOT OCCUR?) */
  667.     if (insize > 0)
  668.         return ( 1 );                /* act as through data read */
  669.     inpos = inbuff;                    /* next get will start at beginning */
  670.     insize = 0;                        /* default insize back to zero */
  671.  
  672.     /* set timeout if we are to do so */
  673.     if (timeout)
  674.         (void) alarm(timeout);        /* set timeout in seconds */
  675.  
  676.     /* do the read from stdin */
  677.     result = read(0, inbuff, IOSIZE);
  678.  
  679.     /* if alarm was set cancel it now */
  680.     if (timeout)
  681.         (void) alarm(0);            /* cancel alarm */
  682.  
  683.     /* check for timeout or error */
  684.     /* EWOULDBLOCK for no data avail -(but we should not see this) */
  685.     /* EINTR if signal stopped the read -(rare but could happen) */
  686.     if (result <= 0)
  687.         return ( 0 );                /* return nothing read */
  688.  
  689.     /* return with fresh buffer data */
  690.     insize = result;
  691.     DO DEBUG("read %d bytes\n", insize);
  692.     return ( 1 );                    /* return OK code */
  693.  
  694. } /* GetData() */
  695.  
  696.  
  697.             /* AwaitInput() - wait for more input from MacLayers */
  698.  
  699. static void
  700. AwaitInput()
  701. {
  702.     int        r;                        /*  read descriptor bits */
  703.  
  704.     DO DEBUG("AwaitInput()\n");
  705.  
  706.     do
  707.       {    r = 1<<0;                    /* wait for read from input device */
  708.         if (select(32, &r, NULL, NULL, NULL) == -1)    /* if problem waiting ... */
  709.           {    if (errno != EINTR)            /* if not simply signal taken ... */
  710.               {    /* SHOULD NOT OCCUR - shutdown layers */
  711.                 DO DEBUG("AwaitInput: select error %d\n", errno);
  712.                 printf("layers: AwaitInput: bad select %d\n", errno);
  713.                 FQuit();                    /* shutdown layers */
  714.                 /* NOT REACHED */
  715.               }
  716.           }
  717.       } while ((r & 1<<0) == 0);
  718.         
  719. } /* AwaitInput() */
  720.  
  721.                 /* asciishape() - convert Shape structure to ASCII */
  722. static void
  723. asciishape(shape, loc)
  724. struct Shape    *shape;                        /* Shape structure for channel */
  725. char            *loc;                        /* location to start filling result */
  726. {
  727.     char        *origloc;                    /* (for debuggin) */
  728.  
  729.     origloc = loc;                            /* remember start of string */
  730.     fill4(&loc, shape->worigh);                /* origin h */
  731.     fill4(&loc, shape->worigv);                /* origin v */
  732.     fill2(&loc, shape->wlines);                /* lines high */
  733.     fill2(&loc, shape->wchars);                /* chars wide */
  734.     fill1(&loc, shape->wfont);                /* font size */
  735.     fill2(&loc, shape->wattr);                /* attributes */
  736.  
  737.     DO DEBUG("asciishape(): %.*s\n", ATTRSIZE, origloc);
  738.  
  739. } /* asciishape() */
  740.  
  741.  
  742.                     /* fill4() - convert parameter to ASCII */
  743.  
  744. static void
  745. fill4(loc, valu)
  746. char        **loc;                            /* pointer to fill area pointer */
  747. unsigned    valu;                            /* value to use */
  748. {
  749.     fill2(loc, valu>>8);                    /* fill high half word */
  750.     fill2(loc, valu & 0xff);                /* fill low half word */
  751.  
  752. } /* fill4() */
  753.  
  754.  
  755.                     /* fill2() - convert parameter to ASCII */
  756.  
  757. static void
  758. fill2(loc, valu)
  759. char        **loc;                            /* pointer to fill area pointer */
  760. unsigned    valu;                            /* value to use */
  761. {
  762.     fill1(loc, valu>>4);                    /* fill high byte */
  763.     fill1(loc, valu & 0xf);                    /* fill low byte */
  764.     
  765. } /* fill2() */
  766.  
  767.  
  768.                     /* fill1() - convert parameter to ASCII */
  769.  
  770. static void
  771. fill1(loc, valu)
  772. char        **loc;                            /* pointer to fill area pointer */
  773. unsigned    valu;                            /* value to use */
  774. {
  775.     *(*loc)++ = "0123456789ABCDEF"[valu & 0xf]; /* return hex value */
  776.  
  777. } /* fill1() */
  778.  
  779.  
  780.             /* parseshape() - convert ASCII image to Shape structure */
  781.                 
  782. static int    Badconvert;                        /* indicates bad conversion */
  783.  
  784. static int
  785. parseshape(shape, loc)
  786. struct Shape    *shape;                        /* Shape structure for channel */
  787. char            *loc;                        /* location to start parsing */
  788. {
  789.     Badconvert = 0;                            /* clear bad characters indicator */
  790.     shape->worigh = get4(&loc);                /* origin h */
  791.     shape->worigv = get4(&loc);                /* origin v */
  792.     shape->wlines = get2(&loc);                /* lines high */
  793.     shape->wchars = get2(&loc);                /* chars wide */
  794.     shape->wfont = get1(&loc);                /* font size */
  795.     shape->wattr = get2(&loc);                /* attributes */
  796.  
  797.     DO DEBUG("ParseShape(): origv %d, origh %d, lines %d, chars %d\n",
  798.                 shape->worigv, shape->worigh, shape->wlines, shape->wchars);
  799.     DO DEBUG("   font %d, attr 0x%x, badconv %d\n",
  800.                     shape->wfont, shape->wattr, Badconvert);
  801.  
  802.     return ( Badconvert ? -1 : 0 );            /* return conversion code */
  803.  
  804. } /* parseshape() */
  805.  
  806.  
  807.                     /* get4() - convert ASCII to parameter */
  808.  
  809. static unsigned
  810. get4(loc)
  811. char        **loc;                            /* pointer to fill area pointer */
  812. {
  813.     unsigned    hi;                            /* high portion */
  814.     unsigned    low;                        /* low portion */
  815.  
  816.     hi = get2(loc);                            /* get high byte */
  817.     low = get2(loc);                        /* get low byte */
  818.  
  819.     return ( (hi<<8) + low );                /* return word value */
  820.  
  821. } /* get4() */
  822.  
  823.  
  824.                     /* get2() - convert ASCII to parameter */
  825.  
  826. static unsigned
  827. get2(loc)
  828. char        **loc;                            /* pointer to fill area pointer */
  829. {
  830.     unsigned    hi;                            /* high portion */
  831.     unsigned    low;                        /* low portion */
  832.  
  833.     hi = get1(loc);                            /* get high half */
  834.     low = get1(loc);                        /* get low half */
  835.  
  836.     return ( (hi<<4) + low );                /* return byte value */
  837.     
  838. } /* get2() */
  839.  
  840.  
  841.                     /* get1() - convert ASCII to parameter */
  842.  
  843. /*    This function sets 'Badconvert' if an invalid character is detected */
  844.  
  845. static unsigned
  846. get1(loc)
  847. char        **loc;                            /* pointer to fill area pointer */
  848. {
  849.     int            c;                            /* character to convert */
  850.     
  851.     c = *(*loc)++;                            /* fetch character */
  852.     
  853.     if (c >= '0' && c <= '9')
  854.         /* zero through nine */
  855.         return ( c - '0' );                    /* return it's binary value */
  856.     
  857.     if (c >= 'a' && c <= 'f')
  858.         /* lower case hex */
  859.         return ( c - 'a' + 10);                /* return it's binary value */
  860.         
  861.     if (c >= 'A' && c <= 'F')
  862.         /* upper case hex */
  863.         return ( c - 'A' + 10);                /* return it's binary value */
  864.         
  865.     /* invalid digit! */
  866.     Badconvert++;                            /* set bad character flag */
  867.     return ( 0 );                            /* return a zero */
  868.  
  869. } /* get1() */
  870.