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(86-07-01,Westcott), approve(87-07-13,MCR7580),
 11      audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
 12      Created.
 13   2) change(86-11-15,Flegel), approve(87-07-13,MCR7580),
 14      audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
 15      Reimplementation of reset,resume,suspend,
 16      terminate.
 17   3) change(86-11-27,Flegel), approve(87-07-13,MCR7580),
 18      audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
 19      Empty buffers when a fail is returned.
 20                                                    END HISTORY COMMENTS */
 21 
 22 /* :  PROCEDURE FUNCTION (pe)
 23 
 24 pe (pre-entry) is the MOWSE routine which is forced into the application's
 25 address space and called before the application is called.  It is responsible
 26 for the following:
 27 
 28    1) packet assembly/disassembly
 29    2) specialized minor capability manipulations required to be done in the
 30       application's space
 31    3) call user application with data messages
 32 
 33 */
 34 
 35 #include <stdio.h>
 36 #include <ws.h>                        /* General constants */
 37 #include <ws_msg.h>                    /* Message structures */
 38 #include <wsmincap.h>                  /* Minor capability definitions */
 39 #include <ws_mcb.h>                    /* MOWSE Control BLock def */
 40 #include <ws_func.h>                   /* User interrupt MOWSE functions */
 41 #include <ws_error.h>                  /* Error codes */
 42 
 43 #define TRUE  1
 44 #define FALSE 0
 45 
 46 pe (p_mcb_ptr, p_minor_cap, p_bufseg, p_bufoff, p_buflen)
 47 
 48 mcb  *p_mcb_ptr;                       /* Capability's MCB */
 49 char p_minor_cap;                      /* Minor cap of message */
 50 int  p_bufseg;                         /* Segment address of message */
 51 int  p_bufoff;                         /* Offset of message within segment */
 52 int  p_buflen;                         /* Length of message */
 53 {
 54 int  link_info_size;
 55 int  msg_header_size;
 56 int  sender_major;
 57 int  code;
 58 struct more_msg more_message;          /* Message types for passed message */
 59 struct input_msg *message;
 60 
 61 /* : - if there is no handler for the message, ignore it */
 62 
 63    if (p_mcb_ptr -> mcb_flag & MCB_NULL_ROUTINE)
 64       return (0);
 65 
 66 /* : - copy message into user space. */
 67 
 68    msg_header_size = sizeof(more_message)-2;
 69    link_info_size = sizeof(struct linklst)-2;
 70    peek (p_bufseg,p_bufoff,&more_message, msg_header_size);
 71    message = (struct input_msg *) (&more_message);
 72 
 73 /* : - switch on the minor capability */
 74 
 75    switch ((int) p_minor_cap)
 76    {
 77       case CONTINUE_MESSAGE:
 78 
 79          return (handle_continue (p_mcb_ptr, &more_message));
 80 
 81       case PARTIAL_MESSAGE:
 82 
 83          return (handle_partial (p_mcb_ptr, p_buflen, p_bufseg, p_bufoff,
 84             msg_header_size, link_info_size, &more_message));
 85 
 86       case RESUME_APPLICATION:
 87 
 88          if (!(p_mcb_ptr -> mcb_flag & MCB_SUSPEND))
 89             return (WSNOSPND);
 90          p_mcb_ptr -> mcb_flag &= ~MCB_SUSPEND;
 91          code = forward (p_mcb_ptr, message -> minor, &(message -> msg_data[0]),
 92             p_buflen, message -> source_system, message -> source_major);
 93          return (code);
 94 
 95       case SUSPEND_APPLICATION:
 96 
 97          if (p_mcb_ptr -> mcb_flag & MCB_SUSPEND)
 98             return (WSSUSPND);
 99          code = forward (p_mcb_ptr, message -> minor, &(message -> msg_data[0]),
100             p_buflen, message -> source_system, message -> source_major);
101          p_mcb_ptr -> mcb_flag |= MCB_SUSPEND;
102          return (code);
103 
104       case RESET_APPLICATION:
105 
106          return (handle_reset (p_mcb_ptr, message, p_buflen));
107 
108       case FAIL_CAPABILITY:
109       case SYSTEM_ERROR:
110 
111          return (handle_fail (p_mcb_ptr, message, p_buflen));
112 
113       case TERMINATE_APPLICATION:
114 
115          code = forward (p_mcb_ptr, message -> minor, &(message -> msg_data[0]),
116             p_buflen, message -> source_system, message -> source_major);
117          return (code);
118 
119       default:
120 
121          return (handle_default (p_mcb_ptr, p_buflen, p_bufseg, p_bufoff, p_minor_cap,
122             msg_header_size, link_info_size, &more_message));
123    }
124 }
125 /*^L*/
126 /* : PROCEDURE FUNCTION (llpfree)
127 
128 Free the space occupied by the link list pointed to by llp.  The space that
129 is to be freed is a list that is trailing behind the the llp node:
130          -------------------
131 first ->|   |   |   |   |   |
132          -------------------
133           |
134           V
135          -------------------
136   llp ->|   |   |   |   |   |        <= free this list into core
137          -------------------
138           |
139           V
140          -------------------
141         |   |   |   |   |   |
142          -------------------
143 */
144 
145 llpfree (core,first,llp)
146 
147 struct allocstr *core;                 /* Where to free into */
148 struct linklst **first;                /* First node in list */
149 struct linklst *llp;                   /* Node to free */
150 {
151 struct linklst *llp1;                  /* Search node pointer */
152 
153 /* : Find the predecessor to the node to be freed and adjust the pointers
154      to go around the node to be freed */
155 
156    llp1 = *first;
157    if (llp1 == llp)
158       *first = llp1 -> nextbuf;
159    else
160    {  while (llp1 != NULL)
161       {  if (llp1->nextbuf == llp)
162          {  llp1->nextbuf = llp->nextbuf;
163             break;
164          }
165          llp1 = llp1->nextbuf;
166       }
167    }
168 
169 /* : Free all of the "sub-nodes" in the trailing list */
170 
171    while (llp != NULL)
172    {  llp1 = llp->nextlink;
173       wsfree(core,llp);
174       llp = llp1;
175    }
176 }
177 /*^L*/
178 /* : PROCEDURE FUNCTION (forward)
179 
180 Simply pass the message immediately to the application.  It shouldn't be
181 stored in the buffers as there is no need and the application needs immediate
182 knowledge.
183 */
184 
185 forward (p_mcb_ptr, p_minor, p_data, p_data_len, p_source_system, p_source_major)
186 
187 mcb  *p_mcb_ptr;
188 char p_minor;
189 char *p_data;
190 int  p_data_len;
191 char p_source_system;
192 char p_source_major;
193 {
194 int major_sender;
195 
196    major_sender = (p_source_system << 8) | p_source_major;
197 
198 /* : If suspended and not TERMINATE or RESUME, send FAIL_CAPABILITY to source */
199 
200    if ((p_mcb_ptr -> mcb_flag & MCB_SUSPEND) && (p_minor != TERMINATE_APPLICATION)
201       && (p_minor != RESUME_APPLICATION) && (p_minor != SUSPEND_APPLICATION))
202    {
203       return (execap (major_sender, FAIL_CAPABILITY, NULL, 0, p_mcb_ptr));
204    }
205 
206 /* : Else forward to application */
207 
208    (*p_mcb_ptr -> application_entry)
209       ((int)p_minor, major_sender, p_data, p_data_len,
210       p_mcb_ptr -> data_block_ptr, p_mcb_ptr);
211 
212    return (0);
213 }
214 /*^L*/
215 /* : PROCEDURE FUNCTION (handle_reset)
216 
217 Perform the operations necessary to handle resetting the application.
218 */
219 
220 /* : NOTES
221 
222 POTENTIAL BUG: reset clears out all of the applications input and output
223    buffers.  If there are partial long messages being sent/received, this
224    may cause problems in the assembly/dissasembly
225 */
226 
227 handle_reset (p_mcb_ptr, p_message, p_message_len)
228 
229 mcb  *p_mcb_ptr;
230 struct input_msg *p_message;
231 int p_message_len;
232 {
233 struct linklst *msg_buffer;
234 struct linklst *next_buf;
235 
236 /* : Clear out the applications input buffers */
237 
238    msg_buffer = p_mcb_ptr -> inbuff;
239    while (msg_buffer != NULL)
240    {  next_buf = msg_buffer -> nextbuf;
241       llpfree (p_mcb_ptr -> inalloc, &(p_mcb_ptr -> inbuff), msg_buffer);
242       msg_buffer = next_buf;
243    }
244    p_mcb_ptr -> inbuff = NULL;
245 
246 /* : Clear out the applications output buffers */
247 
248    msg_buffer = p_mcb_ptr -> outbuff;
249    while (msg_buffer != NULL)
250    {  next_buf = msg_buffer -> nextbuf;
251       llpfree (p_mcb_ptr -> outalloc, &(p_mcb_ptr -> outbuff), msg_buffer);
252       msg_buffer = next_buf;
253    }
254    p_mcb_ptr -> outbuff = NULL;
255 
256 /* : Pass the RESET_APPLICATION message to the capability */
257 
258    forward (p_mcb_ptr, p_message -> minor, &(p_message -> msg_data [0]),
259       p_message_len, p_message -> source_system, p_message -> source_major);
260 }
261 /*^L*/
262 /* : PROCEDURE FUNCTION (handle_fail)
263 
264 Perform the operations necessary to handle a fail capability,  this means
265 clearing out the applications output buffers.
266 */
267 
268 handle_fail (p_mcb_ptr, p_message, p_message_len)
269 
270 mcb  *p_mcb_ptr;
271 struct input_msg *p_message;
272 int p_message_len;
273 {
274 struct linklst *msg_buffer;
275 struct linklst *next_buf;
276 
277 /* : Clear out the applications output buffers */
278 
279    msg_buffer = p_mcb_ptr -> outbuff;
280    while (msg_buffer != NULL)
281    {  next_buf = msg_buffer -> nextbuf;
282       llpfree (p_mcb_ptr -> outalloc, &(p_mcb_ptr -> outbuff), msg_buffer);
283       msg_buffer = next_buf;
284    }
285    p_mcb_ptr -> outbuff = NULL;
286 
287 /* : Pass the FAIL_CAPABILITY message to the capability */
288 
289    forward (p_mcb_ptr, p_message -> minor, &(p_message -> msg_data [0]),
290       p_message_len, p_message -> source_system, p_message -> source_major);
291 }
292 /*^L*/
293 /* : PROCEDURE FUNCTION (handle_partial)
294 
295 Perform the necessary functions when a partial message for the application
296 arrives.
297 
298      -- header_format = system|major|CONTINUE|source_system|source_minor|minor
299 
300 */
301 
302 handle_partial (p_mcb_ptr, p_buflen, p_bufseg, p_bufoff, p_msg_hdr_size, p_link_info_size, p_more_message)
303 
304 mcb  *p_mcb_ptr;                       /* Capability's MCB */
305 int  p_bufseg;                         /* Segment address of message */
306 int  p_bufoff;                         /* Offset of message within segment */
307 int  p_buflen;                         /* Length of message */
308 int  p_msg_hdr_size;
309 int  p_link_info_size;
310 struct more_msg *p_more_message;
311 
312 {
313 int  found;
314 int  done;
315 int  buffer_size;
316 int  amount_to_copy;
317 int  major_sender;
318 int  i;
319 char *more_msg_header1;
320 char *more_msg_header2;
321 struct linklst *msg_buffer;
322 struct linklst *prev_msg_buffer;
323 struct linklst *new_msg_buffer;
324 
325 
326    msg_buffer = p_mcb_ptr->inbuff;
327    prev_msg_buffer = p_mcb_ptr->inbuff;
328 
329 /* : Find if this belongs to a message currently being built */
330 
331    found = done = FALSE;
332    while ((found == FALSE) && (done == FALSE))
333    {  if (msg_buffer == NULL)
334          done = TRUE;
335       else
336       {  more_msg_header1 = (char *) msg_buffer->lldata;
337          more_msg_header2 = (char *) p_more_message;
338 
339          if (!strncmp(more_msg_header1,more_msg_header2,p_msg_hdr_size))
340             found = done = TRUE;
341          else
342          {  prev_msg_buffer = msg_buffer;
343             msg_buffer = msg_buffer->nextbuf;
344          }
345       }
346    }
347 
348 /* : If done & !found then this is a new long message and allocate space */
349 
350    if (found == FALSE)
351    {  buffer_size = p_mcb_ptr->inbuff_length + p_link_info_size + p_msg_hdr_size;
352       new_msg_buffer = (struct linklst *) wsalloc(p_mcb_ptr->inalloc, buffer_size);
353 
354 /* : - if succeeded then copy the message in */
355 
356       if (new_msg_buffer != NULL)
357       {  new_msg_buffer->linksize = buffer_size;
358          amount_to_copy = min(buffer_size-p_link_info_size,p_buflen);
359          peek(p_bufseg,p_bufoff,new_msg_buffer->lldata,amount_to_copy);
360          new_msg_buffer->nextlink = NULL;
361          new_msg_buffer->nextbuf = NULL;
362          new_msg_buffer->linkused = amount_to_copy;
363 
364          if (prev_msg_buffer == p_mcb_ptr->inbuff)
365             p_mcb_ptr->inbuff = new_msg_buffer;
366          else
367             prev_msg_buffer->nextbuf = new_msg_buffer;
368       }
369 
370 /* : - else make a new message header for it for later */
371 
372       else
373       {  buffer_size = p_msg_hdr_size+p_link_info_size+1;
374          new_msg_buffer = (struct linklst *) wsalloc(p_mcb_ptr->inalloc,buffer_size);
375 
376          if (new_msg_buffer != NULL)
377          {  for (i=0; i<p_msg_hdr_size; i++)
378                new_msg_buffer->lldata[i] = *(((char *) p_more_message)+i);
379 
380             new_msg_buffer->nextlink = NULL;
381             new_msg_buffer->nextbuf = NULL;
382             new_msg_buffer->linkused = buffer_size;
383             new_msg_buffer->linksize = buffer_size;
384 
385             if (prev_msg_buffer == p_mcb_ptr->inbuff)
386                p_mcb_ptr->inbuff = new_msg_buffer;
387             else
388                prev_msg_buffer->nextbuf = new_msg_buffer;
389          }
390 
391 /* : -- if can't do that then send FAIL_CAPABILITY to the source */
392 
393          else
394          {  major_sender = p_more_message -> source_major;
395             major_sender = (major_sender << 8) | p_more_message -> minor;
396             return (execap(major_sender, FAIL_CAPABILITY, NULL, 0, p_mcb_ptr));
397          }
398       }
399    }
400 
401 /* : - If a buffer is found then add as much as possible to the buffer */
402 
403    if (found == TRUE)
404    {  amount_to_copy = min((p_buflen-p_msg_hdr_size),(msg_buffer->linksize-msg_buffer->linkused-p_link_info_size));
405       peek(p_bufseg,p_bufoff+p_msg_hdr_size,&(msg_buffer->lldata[msg_buffer->linkused]),
406          amount_to_copy);
407       msg_buffer->linkused += amount_to_copy;
408    }
409 
410 /* : - Send a <CONTINUE_MESSAGE> to the source of the message thus requesting
411         more data from the capability sending the long message. */
412 
413    major_sender = p_more_message -> source_major;
414    major_sender = (major_sender << 8) | p_more_message -> minor;
415    return (execap (major_sender, CONTINUE_MESSAGE,&(p_more_message -> source_system),1,p_mcb_ptr));
416 }
417 /*^L*/
418 /* : PROCEDURE FUNCTION (handle_continue)
419 
420 Handle the continue message for the capability.  This means extracting another
421 portion of the currently long message from the capability's outbuff.
422 
423 */
424 
425 handle_continue (p_mcb_ptr, p_more_message)
426 
427 mcb  *p_mcb_ptr;                       /* Capability's MCB */
428 struct more_msg *p_more_message;
429 
430 {
431 int  found;
432 int  done;
433 int  major_sender;
434 int  i;
435 int  code;
436 struct linklst *msg_buffer;
437 struct linklst *prev_msg_buffer;
438 struct more_msg *message;
439 
440 
441    code = 0;
442    msg_buffer = p_mcb_ptr->outbuff;
443    prev_msg_buffer = p_mcb_ptr->outbuff;
444    found = FALSE;
445    done = FALSE;
446 
447 /* : Look for a the message that is to be continued */
448 
449    while ((found == FALSE) && (done == FALSE))
450    {  if (msg_buffer == NULL)
451          done = TRUE;
452       else
453       {  message = (struct more_msg *) msg_buffer->lldata;
454          if ((message->system == p_more_message -> source_system)
455             && (message->major == p_more_message -> source_major)
456             && (message->source_system == p_more_message -> minor))
457          {
458             found = TRUE;
459             done = TRUE;
460          }
461          else if ((message->system == p_more_message -> source_system)
462             && (message->major == p_more_message -> source_major)
463             && (message->more_minor == p_more_message -> minor))
464          {
465             found = TRUE;
466             done = TRUE;
467          }
468          else
469          {  prev_msg_buffer = msg_buffer;
470             msg_buffer = msg_buffer->nextbuf;
471          }
472       }
473    }
474 
475 /* : If found then get the next portion and send it to the destination */
476 
477    if (found)
478    {  if (prev_msg_buffer == p_mcb_ptr->outbuff)      /* Head of list */
479       {  p_mcb_ptr->outbuff = msg_buffer->nextlink;
480          if (msg_buffer->nextlink != NULL)
481             p_mcb_ptr->outbuff->nextlink->nextbuf = msg_buffer->nextbuf;
482       }
483       else                                            /* Elsewhere in list */
484       {  prev_msg_buffer->nextbuf = msg_buffer->nextlink;
485          if (msg_buffer->nextlink != NULL)
486             msg_buffer->nextlink->nextbuf = msg_buffer->nextbuf;
487       }
488 
489 /* : - I$EXECAP knows what's going on with the messages, so call it */
490 
491       code = call_mowse_int(I$EXECAP,msg_buffer->lldata, msg_buffer->linkused);
492       wsfree(p_mcb_ptr->outalloc,msg_buffer);
493 
494    }
495 
496 /* : Otherwise we are trying to continue a message that does not exist so send
497      a FAIL_CAPABILITY to the application (this one is sending it) */
498 
499    else
500    {  code = forward (p_mcb_ptr, FAIL_CAPABILITY, NULL, 0, (char)WSIBMPC,
501          (char)WSMAJCAP);
502    }
503 
504    return (code);
505 }
506 /*^L*/
507 /* : PROCEDURE FUNCTION (handle_default)
508 
509 Handle passing the message on to the application.
510 */
511 
512 handle_default (p_mcb_ptr, p_buflen, p_bufseg, p_bufoff, p_minor_cap, p_msg_hdr_size, p_link_info_size, p_more_message)
513 
514 mcb  *p_mcb_ptr;                       /* Capability's MCB */
515 int  p_bufseg;                         /* Segment address of message */
516 int  p_bufoff;                         /* Offset of message within segment */
517 int  p_buflen;                         /* Length of message */
518 int  p_minor_cap;
519 int  p_msg_hdr_size;
520 int  p_link_info_size;
521 struct more_msg *p_more_message;
522 {
523 int  found;
524 int  done;
525 int  buffer_size;
526 int  amount_to_copy;
527 int  major_sender;
528 int  i;
529 int  all_copied;
530 int  start_of_message;
531 int  data_length;
532 char *more_msg_header1;
533 char *more_msg_header2;
534 struct input_msg *input_message;
535 struct linklst *msg_buffer;
536 struct linklst *prev_msg_buffer;
537 struct more_msg *message;
538 
539 /* : Look for a buffer containing previous portion of this message */
540 
541    msg_buffer = p_mcb_ptr->inbuff;
542    prev_msg_buffer = NULL;
543 
544    found = FALSE;
545    done = FALSE;
546    while ((found == FALSE) && (done == FALSE))
547    {  if (msg_buffer == NULL)
548          done = TRUE;
549       else
550       {  message = (struct more_msg *) msg_buffer->lldata;
551          if ((message->system == p_more_message -> system)
552             && (message->major == p_more_message -> major)
553             && (message->source_system == p_more_message -> more_minor))
554          {
555             found = TRUE;
556             done = TRUE;
557          }
558          else
559          {  prev_msg_buffer = msg_buffer;
560             msg_buffer = msg_buffer->nextbuf;
561          }
562       }
563    }
564 
565 /* : If one exists the copy as much of the current message into the buffer
566      located otherwise allocate a buffer and try to copy all of the message
567      into it. */
568 
569    if (found == TRUE)
570    {  amount_to_copy = min((p_buflen-p_msg_hdr_size+1),(msg_buffer->linksize - msg_buffer->linkused-p_link_info_size));
571 
572       if (amount_to_copy == (p_buflen-p_msg_hdr_size+1))
573       {  peek(p_bufseg,p_bufoff+p_msg_hdr_size-1,&(msg_buffer->lldata[msg_buffer->linkused]),
574             amount_to_copy);
575          msg_buffer->linkused += amount_to_copy;
576          data_length = msg_buffer->linkused - p_msg_hdr_size;
577          start_of_message = p_msg_hdr_size;
578          all_copied = TRUE;
579       }
580       else
581          all_copied = FALSE;
582    }
583    else
584    {  buffer_size = p_buflen+p_link_info_size;
585       msg_buffer = (struct linklst *) wsalloc(p_mcb_ptr->inalloc,buffer_size);
586 
587       if (msg_buffer != NULL)
588       {  peek(p_bufseg,p_bufoff,msg_buffer->lldata,p_buflen);
589          msg_buffer->nextlink = NULL;
590          msg_buffer->nextbuf = NULL;
591          msg_buffer->linkused = buffer_size;
592          msg_buffer->linksize = buffer_size;
593          data_length = p_buflen - (p_msg_hdr_size -1);
594          start_of_message = p_msg_hdr_size -1;
595          all_copied = TRUE;
596       }
597       else
598          all_copied = FALSE;
599    }
600 
601 
602 /* : If all of the current message was copied then call the application
603      with the information in the buffer and the minor specified otherwise,
604      call the application with the buffer and the minor = BUFFER_OVERFLOW. */
605 
606    major_sender = p_more_message -> source_system;
607    major_sender = (major_sender << 8) | p_more_message -> source_major;
608 
609    if (all_copied == TRUE)
610    {  input_message = (struct input_msg *) msg_buffer->lldata;
611       if (input_message->system != WSIBMPC)
612          return(-1);
613 
614 /* : - pass the message on to the application */
615 
616       forward (p_mcb_ptr, p_minor_cap, (&(msg_buffer -> lldata[start_of_message])),
617          data_length, p_more_message -> source_system, p_more_message -> source_major);
618    }
619    else
620    {  forward (p_mcb_ptr, WSOVRFLW, NULL, 0, (char)WSIBMPC, (char)WSMAJCAP);
621    }
622 
623 /* : Free the buffer just sent to the application if necessary. */
624 
625    if ((found == TRUE) && (msg_buffer != NULL))
626    {  if ((msg_buffer == p_mcb_ptr->inbuff) ||
627          (prev_msg_buffer == p_mcb_ptr->inbuff))
628       {
629          p_mcb_ptr->inbuff = msg_buffer->nextbuf;
630       }
631       else
632          prev_msg_buffer->nextbuf = msg_buffer->nextbuf;
633 
634       wsfree(p_mcb_ptr->inalloc,msg_buffer);
635    }
636    else
637    {  if (msg_buffer != NULL)
638          wsfree(p_mcb_ptr->inalloc,msg_buffer);
639    }
640 
641    return(0);
642 }
643 ^Z