1 /* ***********************************************************
  2    *                                                         *
  3    * Copyright, (C) Honeywell Bull Inc., 1987                *
  4    *                                                         *
  5    * Copyright, (C) Honeywell Information Systems Inc., 1986 *
  6    *                                                         *
  7    *********************************************************** */
  8 
  9 /* HISTORY COMMENTS:
 10   1) change(85-12-22,Flegel), approve(87-07-13,MCR7580),
 11      audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
 12      Created.
 13   2) change(86-01-30,Flegel), approve(87-07-13,MCR7580),
 14      audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
 15      New parameter format.
 16   3) change(86-05-26,Westcott), approve(87-07-13,MCR7580),
 17      audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
 18      Suport for subchannels.
 19   4) change(86-08-27,Flegel), approve(87-07-13,MCR7580),
 20      audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
 21      Extracted queue insertion sections and FG
 22      buffer manipulations.
 23   5) change(86-08-29,Flegel), approve(87-07-13,MCR7580),
 24      audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
 25      Removed call to receive_byte.
 26   6) change(86-09-02,Flegel), approve(87-07-13,MCR7580),
 27      audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
 28      Extracted section for wakeup.
 29   7) change(86-10-10,Flegel), approve(87-07-13,MCR7580),
 30      audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
 31      Support for autoload.
 32   8) change(86-11-11,Flegel), approve(87-07-13,MCR7580),
 33      audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
 34      Call to external_mowse before wsexecap.
 35   9) change(86-12-09,Flegel), approve(87-07-13,MCR7580),
 36      audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
 37      Check on packetize_flag rather than packet_mode
 38      for autoload.
 39  10) change(86-12-11,Flegel), approve(87-07-13,MCR7580),
 40      audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
 41      Guaruntee a reply is sent to the source of a
 42      REQUEST_DISCONNECT message if the destination does not exist.
 43  11) change(87-01-06,Flegel), approve(87-07-13,MCR7580),
 44      audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
 45      Added guaruntee to send a status reply in the
 46      event that the specified capability does not exist for a status request.
 47                                                    END HISTORY COMMENTS */
 48 
 49 /* : PROCEDURE FUNCTION (rcvdata):
 50 
 51 Get a message from the Protocol Handler . If the message is from the foreground
 52 channel, then insert it into the foreground buffer (terminal_buf). If the
 53 message is from the background channel, then call message_parser to handle it.
 54 */
 55 
 56 #include <dos.h>
 57 #include <stdio.h>
 58 #include <ws.h>
 59 #include <alloc.h>
 60 #include <cat.h>
 61 #include <ws_fgb.h>
 62 #include <ws_dcls.h>
 63 #include <ws_buf.h>
 64 #include <ws_msg.h>
 65 #include <wsmincap.h>
 66 #include <ws_error.h>
 67 #include <ws_auto.h>
 68 
 69 extern struct fgbstr *lcbfptr;         /* First entry in application global buffer */
 70 extern struct fgbstr *lcblptr;         /* ... last */
 71 extern struct bstruc fg_buf;           /* Foreground intermediate buffer */
 72 extern struct allocstr *lcaptr;        /* Application global allocation area */
 73 
 74 extern int bg_in_use;                  /* Background active flag */
 75 extern int packetize_flag;             /* MOWSE protocol active flag */
 76 extern int mowse_terminating;          /* True when Multics MOWSE shutting down */
 77 extern int load_list_pending;          /* Whether there are autoloads to perform */
 78 
 79 extern char bg_sav_buf[];             /* Intermediate background message buffer */
 80 extern char mysystem;                 /* System id */
 81 
 82 extern local_cat *sleepq;             /* Sleeping application list */
 83 extern local_cat l_CAT[];             /* Local cat */
 84 
 85 /*^L*/
 86 
 87 rcvdata (p_dosflag)
 88 int  p_dosflag;                /* =1, if entry through int28 (DOS)  */
 89 {
 90 int loopflag;                  /* Determinas when we are done processing */
 91 int size;                      /* Size calculation space */
 92 int ecode;                     /* Error code */
 93 int i;                         /* Counter */
 94 int length;                    /* Length calculation space */
 95 int majorcap;                  /* Major capability number */
 96 int inpl;                      /* length of input message */
 97 
 98 struct input_msg *ip;          /* pointer to input message header structure  */
 99 
100 struct fgbstr *bufp;           /* Temporary buffer pointer */
101 struct fgbstr *fgbp1;          /* Capability buffer pointer */
102 
103 local_cat *catp;               /* pointer to a CAT entry */
104 
105 char *p1;                      /* Temporary pointers */
106 char *f1;
107 
108 char  *wsalloc();
109 int   rcvfgdat();
110 
111 
112 /* : Clear out input buffer */
113 
114    receive_byte();
115 
116 /* : while (more data available from protocol) */
117 
118    loopflag = 1;
119    while (loopflag) {
120       loopflag = 0;
121 
122 /* : - if room in foreground save buffer (empty) (buffer begins at bminor) */
123 
124       if (fg_buf.bin == fg_buf.bout) {
125          length = getdat(FG,&fg_buf.bminor);
126          if (length > 0) {
127             loopflag = 1;
128             fg_buf.bout = fg_buf.bfirst;
129             fg_buf.bin = fg_buf.bfirst + length - 1;
130          }
131       }
132 
133 /* : - if room in background save buffer */
134 
135       if (!bg_in_use)
136       {  bg_in_use = getdat(BG,&bg_sav_buf);
137          if (bg_in_use > 0)
138          {  loopflag = 1;
139             bufp = (struct fgbstr *)wsalloc (lcaptr,bg_in_use + 1 + sizeof(struct fgbstr));
140             if (bufp != NULL)
141 
142 /* : -- copy to local capability buffer */
143 
144             {  p1 = &bg_sav_buf[0];
145                f1 = &bufp -> fgb_char[0];
146                for (i = 0; i < bg_in_use; i++)
147                {  *f1++ = *p1++;
148                }
149                *f1++ = '\0';             /* terminate all messages with NULL */
150                bufp -> fgb_length = bg_in_use;
151                bufp -> fgb_next = NULL;
152                bg_in_use = 0;
153 
154 /* : -- link to previous local capability buffers */
155 
156                rcvmsg (bufp, &lcbfptr, &lcblptr);
157             }
158          }
159       }
160 
161 /* : - if foreground data available */
162 
163       if (fg_buf.bin != fg_buf.bout)
164          rcvfgdat (&fg_buf);
165 
166 /* : - if mowse terminating on Multics, dtm_mowse */
167 
168       if (mowse_terminating && !p_dosflag)
169       {  dtm_mowse ();
170          mowse_terminating = 0;
171       }
172 
173 /* : - if sleep queue is not empty and dos was NOT interrupted
174      -- call wakeup */
175 
176       if (sleepq != NULL && !p_dosflag)
177          wakeup ();
178 
179 /* : - if there are any autoloads pending then load them */
180 
181       if (!p_dosflag && load_list_pending && packetize_flag)
182       {  load_list_pending = 0;
183          autoload ();
184       }
185 
186 /* : - if background data available */
187 
188       if ((lcbfptr != 0) && (!p_dosflag) ) {
189          bufp = lcbfptr;
190          inpl = bufp -> fgb_length;
191          ip = (struct input_msg *) &bufp -> fgb_char[0];
192 
193 /* : -- if major_capability number = mowse major capability
194      --- call internal to parse and deal with the message */
195 
196          if (ip -> major == WSMAJCAP) {
197             internal_mowse(inpl,ip);
198          }
199 
200 /* : -- Else */
201 
202          else {
203             majorcap = ((int) ip -> major) - MIN_CAPABILITY_NUMBER;
204 
205 /* : --- if capability is not active (does not exist)
206      ---- send error message back to sender(FAIL_CAPABILITY) */
207 
208             if ((majorcap < 0) || (majorcap > NUMBER_OF_CAT_ENTRIES))
209                message_error (ip -> source_system, ip -> source_major, FAIL_CAPABILITY);
210             else if (l_CAT[majorcap].mcb_ptr == NULL)
211             {  if (ip -> minor == PARTIAL_MESSAGE)
212                   message_error (ip -> source_major, ip -> msg_data[0], FAIL_CAPABILITY);
213                else if (ip -> minor == REQUEST_DISCONNECT)
214                   message_error (ip -> source_system, ip -> source_major, RESPONSE_DISCONNECT);
215                else if (ip -> minor == GET_STATUS)
216                   message_error (ip -> source_system, ip -> source_major, STATUS_REPLY);
217                else
218                   message_error (ip -> source_system, ip -> source_major, FAIL_CAPABILITY);
219             }
220 
221 /* : --- else pass message to the application */
222 
223             else {
224                external_mowse (&l_CAT[majorcap],ip,inpl);
225             }
226          }
227          loopflag = 1;
228          lcbfptr = bufp -> fgb_next;
229          if (lcbfptr == NULL)
230             lcblptr = NULL;
231          wsfree (lcaptr,bufp);
232       }
233    }
234 }
235 
236 /*^L*/
237 
238 /* : PROCEDURE FUNCTION (message_error)
239 
240 Send the appropriate error to the source.
241 */
242 
243 message_error (p_system, p_major, p_minor)
244 
245 char p_system;                         /* Destination system of error */
246 char p_major;                          /* Destination major */
247 char p_minor;                          /* Minor to send */
248 {
249 struct input_msg exerep;               /* Message */
250 char   data;                           /* Message data */
251 struct putbg_struc status_msg;         /* Status reply message */
252 
253    exerep.system        = p_system;
254    exerep.major         = p_major;
255    exerep.minor         = p_minor;
256    exerep.source_major  = WSMAJCAP;
257    exerep.source_system = mysystem;
258 
259 /* : If minor was RESPONSE_DISCONNECT, then it failed */
260 
261    if (p_minor == RESPONSE_DISCONNECT)
262    {  data = WSREJECT;
263       send_i_mess(&exerep.system, sizeof(exerep) - 1, &data, 1);
264    }
265 
266 /* : Else if it was GET_STATUS, send an error message back */
267 
268    else if (p_minor == STATUS_REPLY)
269    {  status_msg.type = STATUS_REPLY;
270       status_msg.sender_major = (mysystem << 8) | WSMAJCAP;
271       strcpy (status_msg.bgmsg, "Capability does not exist.");
272       status_msg.length = strlen (status_msg.bgmsg);
273 
274       i_putbgm (&status_msg);
275    }
276 
277 /* : Else pass on the minor capability provided */
278 
279    else
280       send_i_mess(&exerep.system, sizeof(exerep) - 1,NULL,0);
281 }
282 ^Z