1 /*============================================================================
2 FILE IPCaegis.c
3
4 MEMBER OF process XSPICE
5
6 Public Domain
7
8 Georgia Tech Research Corporation
9 Atlanta, Georgia 30332
10 PROJECT A-8503
11
12 AUTHORS
13
14 9/12/91 Steve Tynor
15
16 MODIFICATIONS
17
18 <date> <person name> <nature of modifications>
19
20 SUMMARY
21
22 Provides compatibility for the new XSPICE simulator to both the MSPICE user
23 interface and BCP via ATESSE v.1 style AEGIS mailboxes.
24
25 INTERFACES
26
27
28 REFERENCED FILES
29
30 None.
31
32 NON-STANDARD FEATURES
33
34 None.
35
36 ============================================================================*/
37
38 #ifdef IPC_AEGIS_MAILBOXES
39
40 #include <assert.h>
41 #include <apollo/base.h>
42 #include <apollo/mbx.h>
43 #include <apollo/error.h>
44 #include "ngspice/memory.h"
45
46 #include "ngspice/ipc.h"
47
48
49 typedef unsigned char Buffer_char_t;
50
51 static status_$t status;
52 typedef enum {
53 IPC_MBX_UNINITIALIZED,
54 IPC_MBX_INITIALIZED,
55 IPC_MBX_CONNECTED_TO_CLIENT,
56 } Ipc_Mbx_State_t;
57
58 static void *mbx_handle;
59 static Ipc_Mbx_State_t mbx_state = IPC_MBX_UNINITIALIZED;
60 static mbx_$server_msg_t mbx_send_msg_buf;
61 static mbx_$server_msg_t mbx_recieve_msg_buf;
62 static mbx_$server_msg_t *mbx_ret_ptr;
63 static int mbx_ret_len;
64 static short mbx_chan;
65
66 #include "ngspice/ipcproto.h"
67
68 /*---------------------------------------------------------------------------*/
69
70 /*
71 ipc_transport_initialize_server
72
73 This function creates an Aegis mailbox, and if successful,
74 calls ipc_get_line to wait for the first record sent which is
75 assumed to be the batch output filename.
76 */
77
78
79
ipc_transport_initialize_server(server_name,m,p,batch_filename)80 Ipc_Status_t ipc_transport_initialize_server (server_name, m, p,
81 batch_filename)
82 char *server_name; /* The mailbox pathname */
83 Ipc_Mode_t m; /* Mode - interactive or batch */
84 Ipc_Protocol_t p; /* Protocol type */
85 char *batch_filename; /* Batch filename returned */
86 {
87 int len;
88 /* extern void *malloc(); */
89
90 assert (p == IPC_PROTOCOL_V1);
91
92 mbx_$create_server (server_name, strlen (server_name), mbx_$serv_msg_max,
93 1, &mbx_handle, &status);
94
95 if (status.all != status_$ok) {
96 fprintf (stderr,
97 "ERROR: IPC: Error creating mailbox server \"%s\"\n",
98 server_name);
99 error_$print (status);
100 mbx_state = IPC_MBX_UNINITIALIZED;
101 return IPC_STATUS_ERROR;
102 } else {
103 mbx_state = IPC_MBX_INITIALIZED;
104 /*
105 * First record is the name of the batch filename - whether we're in
106 * batch mode or not:
107 */
108 return ipc_get_line (batch_filename, &len, IPC_WAIT);
109 }
110 /*
111 * shouldn't get here
112 */
113 assert (0);
114 return IPC_STATUS_ERROR;
115 }
116 /*---------------------------------------------------------------------------*/
extract_msg(str,len)117 Ipc_Status_t extract_msg (str, len)
118 char *str;
119 int *len;
120 {
121 *len = mbx_ret_len - mbx_$serv_msg_hdr_len;
122 assert (*len >= 0);
123
124 /*
125 * null terminate before copy:
126 */
127 mbx_ret_ptr->data [*len] = '\0';
128 strcpy (str, mbx_ret_ptr->data);
129
130 return IPC_STATUS_OK;
131 }
132
133 /*---------------------------------------------------------------------------*/
134
135 /*
136 ipc_transport_get_line
137
138 This function reads data sent by a client over the mailbox
139 channel. It also handles the initial opening of the
140 mailbox channel when requested by a client.
141 */
142
143
144
ipc_transport_get_line(str,len,wait)145 Ipc_Status_t ipc_transport_get_line (str, len, wait)
146 char *str; /* The string text read from IPC channel */
147 int *len; /* The length of str */
148 Ipc_Wait_t wait; /* Blocking or non-blocking */
149 {
150 if (mbx_state == IPC_MBX_UNINITIALIZED) {
151 fprintf (stderr,
152 "ERROR: IPC: Attempted to read from non-initialized mailbox\n");
153 return IPC_STATUS_ERROR;
154 }
155
156 assert ((mbx_state == IPC_MBX_CONNECTED_TO_CLIENT) ||
157 (mbx_state == IPC_MBX_INITIALIZED));
158
159 for (;;) {
160 if (wait == IPC_WAIT) {
161 mbx_$get_rec (mbx_handle, &mbx_recieve_msg_buf, mbx_$serv_msg_max,
162 &mbx_ret_ptr, &mbx_ret_len, &status);
163 } else {
164 mbx_$get_conditional (mbx_handle, &mbx_recieve_msg_buf,
165 mbx_$serv_msg_max, &mbx_ret_ptr, &mbx_ret_len,
166 &status);
167 if (status.all == mbx_$channel_empty) {
168 return IPC_STATUS_NO_DATA;
169 }
170 }
171
172 if (status.all != status_$ok) {
173 fprintf (stderr, "ERROR: IPC: Error reading from mailbox\n");
174 error_$print (status);
175 return IPC_STATUS_ERROR;
176 }
177
178 switch (mbx_ret_ptr->mt) {
179 case mbx_$channel_open_mt:
180 if (mbx_state == IPC_MBX_CONNECTED_TO_CLIENT) {
181 /*
182 * we're already connected to a client... refuse the connection
183 */
184 mbx_send_msg_buf.mt = mbx_$reject_open_mt;
185 } else {
186 mbx_send_msg_buf.mt = mbx_$accept_open_mt;
187 mbx_state = IPC_MBX_CONNECTED_TO_CLIENT;
188 }
189 mbx_send_msg_buf.cnt = mbx_$serv_msg_hdr_len;
190 mbx_chan = mbx_ret_ptr->chan;
191 mbx_send_msg_buf.chan = mbx_chan;
192
193 mbx_$put_rec (mbx_handle, &mbx_send_msg_buf, mbx_$serv_msg_hdr_len,
194 &status);
195
196 if (status.all != status_$ok) {
197 fprintf (stderr, "ERROR: IPC: Error writing to mailbox\n");
198 error_$print (status);
199 return IPC_STATUS_ERROR;
200 }
201
202 /*
203 * check to see if there was a message buried in the open request:
204 */
205 if (mbx_ret_len > mbx_$serv_msg_hdr_len) {
206 return extract_msg (str, len);
207 }
208 break;
209 case mbx_$eof_mt:
210 mbx_chan = mbx_ret_ptr->chan;
211 mbx_$deallocate(mbx_handle, mbx_chan, &status);
212
213 if (status.all != status_$ok) {
214 fprintf (stderr, "ERROR: IPC: Error deallocating mailbox\n");
215 error_$print (status);
216 return IPC_STATUS_ERROR;
217 }
218
219 mbx_state = IPC_MBX_INITIALIZED;
220 return IPC_STATUS_EOF;
221 break;
222 case mbx_$data_mt:
223 assert (mbx_state == IPC_MBX_CONNECTED_TO_CLIENT);
224 return extract_msg (str, len);
225 break;
226 case mbx_$data_partial_mt:
227 fprintf (stderr, "ERROR: IPC: Recieved partial data message - ignored\n");
228 break;
229 default:
230 fprintf (stderr, "ERROR: IPC: Bad message type (0x%x) recieved\n",
231 mbx_ret_ptr->mt);
232 }
233 }
234 return IPC_STATUS_ERROR;
235 }
236
237 /*---------------------------------------------------------------------------*/
238
239 /*
240 ipc_transport_terminate_server
241
242 This function calls ipc\_transport\_get\_line until it
243 receives an EOF from the client, which concludes the
244 communication.
245 */
246
247
ipc_transport_terminate_server()248 Ipc_Status_t ipc_transport_terminate_server ()
249 {
250 char buffer[300];
251 int len;
252 Ipc_Status_t status;
253
254 do {
255 status = ipc_transport_get_line (buffer, &len, IPC_WAIT);
256 } while ((status != IPC_STATUS_ERROR) &&
257 (status != IPC_STATUS_EOF));
258 return status;
259 }
260
261 /*---------------------------------------------------------------------------*/
262
263 /*
264 ipc_transport_send_line
265
266 This function sends a message to the current client through
267 the mailbox channel.
268 */
269
270
ipc_transport_send_line(str,len)271 Ipc_Status_t ipc_transport_send_line (str, len)
272 char *str; /* The bytes to send */
273 int len; /* The number of bytes from str to send */
274 {
275 long cnt;
276
277 if (mbx_state != IPC_MBX_CONNECTED_TO_CLIENT) {
278 fprintf (stderr,
279 "ERROR: IPC: Attempted to write to non-open mailbox\n");
280 return IPC_STATUS_ERROR;
281 }
282
283 mbx_send_msg_buf.mt = mbx_$data_mt;
284 if (mbx_$serv_msg_hdr_len + len > mbx_$serv_msg_max) {
285 fprintf (stderr,
286 "ERROR: IPC: send_line message too long - truncating\n");
287 len = mbx_$serv_msg_max - mbx_$serv_msg_hdr_len;
288 }
289
290 mbx_send_msg_buf.cnt = mbx_$serv_msg_hdr_len + len;
291 mbx_send_msg_buf.chan = mbx_chan;
292 memcpy (mbx_send_msg_buf.data, str, len);
293
294 cnt = mbx_send_msg_buf.cnt;
295 mbx_$put_rec (mbx_handle, &mbx_send_msg_buf, cnt, &status);
296
297 if (status.all != status_$ok) {
298 fprintf (stderr, "ERROR: IPC: Error writing to mailbox\n");
299 error_$print (status);
300 return IPC_STATUS_ERROR;
301 }
302 return IPC_STATUS_OK;
303 }
304
305 #else
306
307 int intDummy1;
308
309 #endif /* IPC_AEGIS_MAILBOXES */
310