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-05,Westcott), approve(87-07-13,MCR7580),
 11      audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
 12      Created.
 13                                                    END HISTORY COMMENTS */
 14 
 15 /* PROCEDURE FUNCTION (execap):
 16 
 17 Sends a minor capability message to the specified major capability with the
 18 arguments provided.
 19 */
 20 
 21 #include <stdio.h>
 22 #include <ws.h>
 23 #include <alloc.h>
 24 #include <ws_mcb.h>
 25 #include <ws_error.h>
 26 #include <ws_func.h>
 27 #include <ws_dcls.h>
 28 #include <wsmincap.h>
 29 
 30 #define HEADER_LENGTH 6                /* Header information length */
 31 
 32 extern char local_system;              /* Identity of PC system */
 33 
 34 execap (p_major_num, p_minor_num, p_arg_ptr, p_arg_len, p_mcb_ptr)
 35 
 36 int  p_major_num;                      /* Destination major capability number */
 37 int  p_minor_num;                      /* Destination minor capability number */
 38 char *p_arg_ptr;                       /* Pointer to argument data */
 39 int  p_arg_len;                        /* Length of argument data */
 40 mcb  *p_mcb_ptr;                       /* Pointer to application's MCB */
 41 {
 42 struct xcap_struc xcap;
 43 char              *c1;
 44 char              *c2;
 45 char              *temp_p_arg_ptr;
 46 int               i;
 47 int               code;
 48 int               copylen;
 49 int               header_size;
 50 struct linklst    *new_msg_portion;
 51 struct linklst    *dead_buffer;
 52 struct linklst    *pending_msg_buffer;
 53 struct linklst    *pending_msg_link;
 54 struct linklst    *portion;
 55 struct linklst    *buffer_portion();
 56 int j;
 57 
 58    code = 0;
 59 
 60 /* Validate the mcb pointer */
 61 
 62    if (p_mcb_ptr == NULL)
 63       return (WSINVMCB);
 64 
 65 /* Move and validate the passed arguments into the execap structure */
 66 
 67    xcap.system =  (p_major_num >> 8);
 68    if ((xcap.system != WSIBMPC) && (xcap.system != WSMULTICS))
 69       return (WSINVSYS);
 70 
 71    xcap.major = (char) (0xff & p_major_num);
 72    if ((xcap.major < WSMAJCAP) || (xcap.major > MAX_CAPABILITY_NUMBER - 1))
 73       return (WSINVNUM);
 74 
 75 /* If there are any pending messages from the caller and the message to
 76    be sent is longer than on packet, then return WSBUFOVR because we can't
 77    have multiple long messages pending due to protocol */
 78 
 79    if ((p_arg_len > WSPAKSIZ) && (p_mcb_ptr -> outbuff != NULL))
 80       return (WSBUFOVR);
 81 
 82 /* Copy the argument string into the structure. If the string is longer than
 83    the maximum packet size, then copy the first portion of the string to the
 84    structure, and the remainder of the string into as many buffers as are
 85      required to contain the entire message. */
 86 
 87 /* Find end of buffer list */
 88 
 89    pending_msg_buffer = p_mcb_ptr -> outbuff;
 90    if (pending_msg_buffer != NULL)
 91        while (pending_msg_buffer->nextbuf != NULL)
 92           pending_msg_buffer = pending_msg_buffer -> nextbuf;
 93 
 94    pending_msg_link = NULL;
 95    temp_p_arg_ptr = p_arg_ptr;
 96 
 97 /* Split the message into portions */
 98 
 99    while (p_arg_len >= 0)
100    {  if (p_arg_len > (WSPAKSIZ - HEADER_LENGTH))
101       {  copylen = WSPAKSIZ - HEADER_LENGTH;
102          xcap.minor = PARTIAL_MESSAGE;
103          xcap.source_system = p_minor_num;
104          xcap.source_major = p_mcb_ptr->system_id;
105          xcap.xcapstr[0] = p_mcb_ptr->major_capability;
106          header_size = HEADER_LENGTH;
107       }
108       else
109       {  copylen = p_arg_len;
110          xcap.minor = p_minor_num;
111          xcap.source_system = p_mcb_ptr->system_id;
112          xcap.source_major = p_mcb_ptr->major_capability;
113          header_size = 5;
114          p_arg_len = -1;                                /* terminate loop */
115       }
116 
117 /* Copy data from user space into his message buffer space */
118 
119       new_msg_portion =
120          (struct linklst *) wsalloc (p_mcb_ptr -> outalloc, header_size+copylen+sizeof(struct linklst));
121 
122 /* Copy header information */
123 
124       if (new_msg_portion != NULL)
125       {  c1 = (char *) &xcap;
126          c2 = &(new_msg_portion -> lldata[0]);
127          for (i = 0; i < header_size; i++)
128             c2[i] = c1[i];
129 
130 /* Copy data information */
131 
132          c1 = temp_p_arg_ptr;
133          for (i = 0; i < copylen; i++)
134             c2[i + header_size] = c1[i];
135 
136          p_arg_len = p_arg_len - copylen;
137          temp_p_arg_ptr = &(c1[i]);
138 
139 /* Initialize link to hold portion of message */
140 
141          new_msg_portion->nextbuf = NULL;
142          new_msg_portion->nextlink = NULL;
143          new_msg_portion->linkused = copylen + header_size;
144 
145 
146 /* Insert buffer into linked list */
147 
148          if (pending_msg_buffer == NULL)              /* First in chain */
149          {  p_mcb_ptr->outbuff = new_msg_portion;
150             pending_msg_buffer = new_msg_portion;
151             pending_msg_link = new_msg_portion;
152          }
153          else
154          {  if (pending_msg_link == NULL)             /* Last in chain */
155             {  pending_msg_link = pending_msg_buffer;
156                while (pending_msg_link->nextlink != NULL)
157                   pending_msg_link = pending_msg_link->nextlink;
158             }
159             pending_msg_link->nextlink = new_msg_portion;
160             pending_msg_link = new_msg_portion;
161          }
162       }
163 
164 /* If can't copy into message buffer space then return all buffers back to
165        free queue */
166 
167       else
168       {  dead_buffer = p_mcb_ptr->outbuff;
169          while (dead_buffer != NULL)
170          {  pending_msg_buffer = dead_buffer->nextlink;
171             llpfree(p_mcb_ptr -> outalloc,&p_mcb_ptr->outbuff,dead_buffer);
172             dead_buffer = pending_msg_buffer;
173          }
174          return (WSBUFOVR);
175       }
176    }
177 
178 /* Extract the first portion of the message to send */
179 
180    portion = buffer_portion(p_mcb_ptr, pending_msg_buffer);
181    code = call_mowse_int (I$EXECAP, portion->lldata, portion->linkused);
182    wsfree (p_mcb_ptr -> outalloc, portion);
183    if (code)
184       llpfree (p_mcb_ptr -> outalloc, &(p_mcb_ptr -> outbuff), portion -> nextlink);
185    return (code);
186 }
187 
188 /* PROCEDURE FUNCTION (buffer_portion)
189 
190 Extract a portion of a message from the head of the pending portion queue.
191 */
192 
193 struct linklst *buffer_portion(p_mcb_ptr, p_buffer)
194 
195 mcb *p_mcb_ptr;
196 struct linklst *p_buffer;
197 {
198 struct linklst *portion;
199 struct linklst *msg_buffer_prev;
200 
201 /* If p_mcb_ptr is null then return */
202 
203    if (p_mcb_ptr == NULL)
204       return(NULL);
205 
206 /* If buffer is null then return */
207 
208    if (p_buffer == NULL)
209       return(NULL);
210 
211 /* Get portion of buffer to send */
212 
213    portion = p_buffer;
214 
215 /* Fix up chain from which portion was taken */
216 
217    msg_buffer_prev = p_mcb_ptr->outbuff;
218    if (msg_buffer_prev == NULL)
219       return(NULL);
220 
221 /* Search for either an equality to the current buffer, or NULL which signals
222    the trailing end of the message. */
223 
224    while (msg_buffer_prev->nextbuf != p_buffer)
225       if ((msg_buffer_prev = msg_buffer_prev->nextbuf) == NULL)
226          break;
227 
228    if (msg_buffer_prev == NULL)
229       p_mcb_ptr->outbuff = p_buffer->nextlink;
230    else
231    {  msg_buffer_prev->nextbuf = p_buffer->nextlink;
232       p_buffer->nextlink->nextbuf = p_buffer->nextbuf;
233    }
234 
235    return(portion);
236 }