Commit | Line | Data |
---|---|---|
b6ba6518 | 1 | /* Copyright 1993, 1998 Free Software Foundation, Inc. |
c906108c SS |
2 | |
3 | This file is part of GDB. | |
4 | ||
5 | This program is free software; you can redistribute it and/or modify | |
6 | it under the terms of the GNU General Public License as published by | |
7 | the Free Software Foundation; either version 2 of the License, or | |
8 | (at your option) any later version. | |
9 | ||
10 | This program is distributed in the hope that it will be useful, | |
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
13 | GNU General Public License for more details. | |
14 | ||
15 | You should have received a copy of the GNU General Public License | |
16 | along with this program; if not, write to the Free Software | |
17 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ | |
18 | ||
19 | static char udip2soc_c[]="@(#)udip2soc.c 2.11 Daniel Mann"; | |
20 | static char udip2soc_c_AMD[]="@(#)udip2soc.c 2.8, AMD"; | |
21 | /* | |
22 | * This module converts UDI Procedural calls into | |
23 | * UDI socket messages for UNIX. | |
24 | * It is used by DFE client processes | |
25 | ********************************************************************** HISTORY | |
26 | */ | |
27 | /* This is all unneeded on DOS machines. */ | |
28 | #ifndef __GO32__ | |
29 | ||
30 | #include <stdio.h> | |
31 | #include <string.h> | |
32 | ||
33 | /* Before sys/file.h for Unixware. */ | |
34 | #include <sys/types.h> | |
35 | ||
36 | #include <sys/file.h> | |
37 | ||
38 | /* This used to say sys/fcntl.h, but the only systems I know of that | |
39 | require that are old (pre-4.3, at least) BSD systems, which we | |
40 | probably don't need to worry about. */ | |
41 | #include <fcntl.h> | |
42 | ||
43 | #include <sys/wait.h> | |
44 | #include <sys/time.h> | |
45 | #include <sys/resource.h> | |
46 | #include <sys/socket.h> | |
47 | #include <netinet/in.h> | |
48 | #include <netdb.h> | |
49 | #include <signal.h> | |
50 | #include <sys/errno.h> | |
51 | #include "udiproc.h" | |
52 | #include "udisoc.h" | |
53 | ||
54 | extern int errno; | |
55 | extern int sys_nerr; | |
56 | extern int udr_errno; | |
57 | extern char* getenv(); | |
58 | ||
59 | /* local type decs. and macro defs. not in a .h file ************* MACRO/TYPE | |
60 | */ | |
61 | #define version_c 0x121 /* DFE-IPC version id */ | |
62 | #define TRUE -1 | |
63 | #define FALSE 0 | |
64 | #define PORT_NUM 7000 | |
65 | #define MAX_SESSIONS 5 /* maximum DFE-TIP connections */ | |
66 | #define SOC_BUF_SIZE 4* 1024 /* size of socket comms buffer */ | |
67 | #define SBUF_SIZE 500 /* size of string buffer */ | |
68 | #define ERRMSG_SIZE 500 /* size of error message buffer */ | |
69 | ||
70 | typedef struct connection_str /* record of connect session */ | |
71 | { | |
72 | int in_use; | |
73 | char connect_id[20]; /* connection identifier */ | |
74 | char domain_string[20]; /* dommaing for conection */ | |
75 | char tip_string[30]; /* TIP host name for AF_INET */ | |
76 | char tip_exe[80]; /* TIP exe name */ | |
77 | int dfe_sd; /* associated DFE socket */ | |
78 | int tip_pid; /* pid of TIP process */ | |
79 | struct sockaddr_in dfe_sockaddr; | |
80 | struct sockaddr_in tip_sockaddr_in; | |
81 | struct sockaddr tip_sockaddr; | |
82 | } connection_t; | |
83 | ||
84 | typedef struct session_str | |
85 | { | |
86 | int in_use; | |
87 | connection_t* soc_con_p; /* associated connection */ | |
88 | UDISessionId tip_id; /* associated TIP session ID */ | |
89 | } session_t; | |
90 | ||
91 | /* global dec/defs. which are not in a .h file ************* EXPORT DEC/DEFS | |
92 | */ | |
93 | UDIError dfe_errno; | |
94 | char dfe_errmsg[ERRMSG_SIZE];/* error string */ | |
95 | ||
96 | /* local dec/defs. which are not in a .h file *************** LOCAL DEC/DEFS | |
97 | */ | |
98 | LOCAL connection_t soc_con[MAX_SESSIONS]; | |
99 | LOCAL session_t session[MAX_SESSIONS]; | |
100 | LOCAL UDR udr; | |
101 | LOCAL UDR* udrs = &udr; /* UDR for current session */ | |
102 | LOCAL int current; /* int-id for current session */ | |
103 | LOCAL char sbuf[SBUF_SIZE]; /* String handler buffer */ | |
104 | LOCAL char config_file[80]; /* path/name for config file */ | |
105 | ||
106 | /***************************************************************** UDI_CONNECT | |
107 | * Establish a new FDE to TIP conection. The file "./udi_soc" or | |
108 | * "/etc/udi_soc" may be examined to obtain the conection information | |
109 | * if the "Config" parameter is not a completd "line entry". | |
110 | * | |
111 | * NOTE: the Session string must not start whith white-space characters. | |
112 | * Format of string is: | |
113 | * <session> <domain> <soc_name|host_name> <tip_exe|port> <pass to UDIconnect> | |
114 | * soc2cayman AF_INET cayman 7000 <not supported> | |
115 | * soc2tip AF_UNIX astring tip.exe ... | |
116 | */ | |
117 | UDIError | |
118 | UDIConnect(Config, Session) | |
119 | char *Config; /* in -- identification string */ | |
120 | UDISessionId *Session; /* out -- session ID */ | |
121 | { | |
122 | UDIInt32 service_id = UDIConnect_c; | |
123 | int domain; | |
124 | int cnt=0; | |
125 | int rcnt, pos, params_pos=0; | |
126 | char *tip_main_string; | |
127 | char *env_p; | |
128 | struct hostent *tip_info_p; | |
129 | FILE *fd; | |
130 | #if 0 | |
131 | FILE *f_p; | |
132 | #endif | |
133 | UDIUInt32 TIPIPCId; | |
134 | UDIUInt32 DFEIPCId; | |
135 | ||
136 | #if 0 /* This is crap. It assumes that udi_soc is executable! */ | |
137 | sprintf(sbuf, "which udi_soc"); | |
138 | f_p = popen(sbuf, "r"); | |
139 | if(f_p) | |
140 | { while( (sbuf[cnt++]=getc(f_p)) != EOF); | |
141 | sbuf[cnt-2]=0; | |
142 | } | |
143 | pclose(f_p); | |
144 | #endif | |
145 | ||
146 | for (rcnt=0; | |
147 | rcnt < MAX_SESSIONS && session[rcnt].in_use; | |
148 | rcnt++); | |
149 | ||
150 | if (rcnt >= MAX_SESSIONS) | |
151 | { | |
152 | sprintf(dfe_errmsg, "DFE-ipc ERROR: Too many sessions already open"); | |
153 | return UDIErrorIPCLimitation; | |
154 | } | |
155 | ||
156 | /* One connection can be multiplexed between several sessions. */ | |
157 | ||
158 | for (cnt=0; | |
159 | cnt < MAX_SESSIONS && soc_con[cnt].in_use; | |
160 | cnt++); | |
161 | ||
162 | if (cnt >= MAX_SESSIONS) | |
163 | { | |
164 | sprintf(dfe_errmsg, | |
165 | "DFE-ipc ERROR: Too many connections already open"); | |
166 | return UDIErrorIPCLimitation; | |
167 | } | |
168 | ||
169 | *Session = rcnt; | |
170 | session[rcnt].soc_con_p = &soc_con[cnt]; | |
171 | ||
172 | if (strchr(Config, ' ')) /* test if file entry given */ | |
173 | { | |
174 | soc_con[cnt].in_use = TRUE; | |
175 | sscanf(Config, "%s %s %s %s %n", | |
176 | soc_con[cnt].connect_id, | |
177 | soc_con[cnt].domain_string, | |
178 | soc_con[cnt].tip_string, | |
179 | soc_con[cnt].tip_exe, | |
180 | ¶ms_pos); | |
181 | tip_main_string = Config + params_pos; | |
182 | } | |
183 | else /* here if need to read udi_soc file */ | |
184 | { | |
185 | strcpy(config_file, "udi_soc"); | |
186 | env_p = getenv("UDICONF"); | |
187 | if (env_p) | |
188 | strcpy(config_file, env_p); | |
189 | ||
190 | fd = fopen(config_file, "r"); | |
191 | ||
192 | if (!fd) | |
193 | { | |
194 | sprintf(dfe_errmsg, "UDIConnect, can't open udi_soc file:\n%s ", | |
195 | strerror(errno)); | |
196 | dfe_errno = UDIErrorCantOpenConfigFile; | |
197 | goto tip_failure; | |
198 | } | |
199 | ||
200 | while (1) | |
201 | { | |
202 | if (fscanf(fd, "%s %s %s %s %[^\n]\n", | |
203 | soc_con[cnt].connect_id, | |
204 | soc_con[cnt].domain_string, | |
205 | soc_con[cnt].tip_string, | |
206 | soc_con[cnt].tip_exe, | |
207 | sbuf) == EOF) | |
208 | break; | |
209 | ||
210 | if (strcmp(Config, soc_con[cnt].connect_id) != 0) | |
211 | continue; | |
212 | ||
213 | soc_con[cnt].in_use = TRUE; /* here if entry found */ | |
214 | ||
215 | tip_main_string = sbuf; | |
216 | break; | |
217 | } | |
218 | ||
219 | fclose(fd); | |
220 | if (!soc_con[cnt].in_use) | |
221 | { | |
222 | sprintf(dfe_errmsg, | |
223 | "UDIConnect, can't find `%s' entry in udi_soc file", | |
224 | Config); | |
225 | dfe_errno = UDIErrorNoSuchConfiguration; | |
226 | goto tip_failure; | |
227 | } | |
228 | } | |
229 | /*----------------------------------------------------------- SELECT DOMAIN */ | |
230 | if (strcmp(soc_con[cnt].domain_string, "AF_UNIX") == 0) | |
231 | domain = AF_UNIX; | |
232 | else if (strcmp(soc_con[cnt].domain_string, "AF_INET") == 0) | |
233 | domain = AF_INET; | |
234 | else | |
235 | { | |
236 | sprintf(dfe_errmsg, "DFE-ipc ERROR: socket address family not known"); | |
237 | dfe_errno = UDIErrorBadConfigFileEntry; | |
238 | goto tip_failure; | |
239 | } | |
240 | ||
241 | /*---------------------------------------------------- MULTIPLEXED SOCKET ? */ | |
242 | /* If the requested session requires communication with | |
243 | a TIP which already has a socket connection established, | |
244 | then we do not create a new socket but multiplex the | |
245 | existing one. A TIP is said to use the same socket if | |
246 | socket-name/host-name and the domain are the same. | |
247 | */ | |
248 | for (rcnt=0; rcnt < MAX_SESSIONS; rcnt++) | |
249 | { | |
250 | if (soc_con[rcnt].in_use | |
251 | && rcnt != cnt | |
252 | && strcmp(soc_con[cnt].domain_string, | |
253 | soc_con[rcnt].domain_string) == 0 | |
254 | && strcmp(soc_con[cnt].tip_string, | |
255 | soc_con[rcnt].tip_string) == 0) | |
256 | { | |
257 | session[*Session].soc_con_p = &soc_con[rcnt]; | |
258 | soc_con[cnt].in_use = FALSE; /* don't need new connect */ | |
259 | goto tip_connect; | |
260 | } | |
261 | } | |
262 | /*------------------------------------------------------------------ SOCKET */ | |
263 | soc_con[cnt].dfe_sd = socket(domain, SOCK_STREAM, 0); | |
264 | if (soc_con[cnt].dfe_sd == -1) | |
265 | { | |
266 | sprintf(dfe_errmsg, "DFE-ipc ERROR, socket() call failed %s ", | |
267 | strerror (errno)); | |
268 | dfe_errno = UDIErrorUnknownError; | |
269 | goto tip_failure; | |
270 | } | |
271 | ||
272 | /*--------------------------------------------------------- AF_UNIX CONNECT */ | |
273 | if (domain == AF_UNIX) | |
274 | { | |
275 | if (strcmp(soc_con[cnt].tip_string, "*") == 0) | |
276 | { | |
277 | for (pos = 0; pos < 20; pos++) | |
278 | { | |
279 | int f; | |
280 | ||
281 | sprintf(soc_con[cnt].tip_string,"/tmp/U%d", getpid() + pos); | |
282 | f = open(soc_con[cnt].tip_string, O_CREAT); | |
283 | if (f == -1) | |
284 | continue; | |
285 | ||
286 | close(f); | |
287 | unlink(soc_con[cnt].tip_string); | |
288 | break; | |
289 | } | |
290 | ||
291 | if (pos >= 20) | |
292 | { | |
293 | sprintf(dfe_errmsg, | |
294 | "DFE-ipc ERROR, can't create random socket name"); | |
295 | dfe_errno = UDIErrorCantConnect; | |
296 | goto tip_failure; | |
297 | } | |
298 | } | |
299 | ||
300 | soc_con[cnt].tip_sockaddr.sa_family = domain; | |
301 | memcpy(soc_con[cnt].tip_sockaddr.sa_data, | |
302 | soc_con[cnt].tip_string, | |
303 | sizeof(soc_con[cnt].tip_sockaddr.sa_data)); | |
304 | if (connect(soc_con[cnt].dfe_sd, | |
305 | &soc_con[cnt].tip_sockaddr, | |
306 | sizeof(soc_con[cnt].tip_sockaddr))) | |
307 | { /* if connect() fails assume TIP not yet started */ | |
308 | /*------------------------------------------------------------ AF_UNIX EXEC */ | |
309 | int pid; | |
310 | int statusp; | |
311 | char *arg0; | |
312 | ||
313 | arg0 = strrchr(soc_con[cnt].tip_exe,'/'); | |
314 | ||
315 | if (arg0) | |
316 | arg0++; | |
317 | else | |
318 | arg0 = soc_con[cnt].tip_exe; | |
319 | ||
320 | pid = vfork(); | |
321 | ||
322 | if (pid == 0) /* Child */ | |
323 | { | |
324 | execlp(soc_con[cnt].tip_exe, | |
325 | arg0, | |
326 | soc_con[cnt].domain_string, | |
327 | soc_con[cnt].tip_string, | |
328 | NULL); | |
329 | _exit(1); | |
330 | } | |
331 | ||
332 | if (waitpid(pid, &statusp, WNOHANG)) | |
333 | { | |
334 | sprintf(dfe_errmsg, "DFE-ipc ERROR: can't exec the TIP"); | |
335 | dfe_errno = UDIErrorCantStartTIP; | |
336 | goto tip_failure; | |
337 | } | |
338 | ||
339 | pos = 3; | |
340 | for (pos = 3; pos > 0; pos--) | |
341 | { | |
342 | if (!connect(soc_con[cnt].dfe_sd, | |
343 | &soc_con[cnt].tip_sockaddr, | |
344 | sizeof(soc_con[cnt].tip_sockaddr))) | |
345 | break; | |
346 | sleep(1); | |
347 | } | |
348 | ||
349 | if (pos == 0) | |
350 | { | |
351 | sprintf(dfe_errmsg, "DFE-ipc ERROR, connect() call failed: %s", | |
352 | strerror (errno)); | |
353 | dfe_errno = UDIErrorCantConnect; | |
354 | goto tip_failure; | |
355 | } | |
356 | } | |
357 | } | |
358 | /*--------------------------------------------------------- AF_INET CONNECT */ | |
359 | else if (domain == AF_INET) | |
360 | { | |
361 | fprintf(stderr, | |
362 | "DFE-ipc WARNING, need to have first started remote TIP"); | |
363 | ||
364 | soc_con[cnt].tip_sockaddr_in.sin_family = domain; | |
365 | soc_con[cnt].tip_sockaddr_in.sin_addr.s_addr = | |
366 | inet_addr(soc_con[cnt].tip_string); | |
367 | if (soc_con[cnt].tip_sockaddr_in.sin_addr.s_addr == -1) | |
368 | { | |
369 | tip_info_p = gethostbyname(soc_con[cnt].tip_string); | |
370 | if (tip_info_p == NULL) | |
371 | { | |
372 | sprintf(dfe_errmsg,"DFE-ipc ERROR, No such host %s", | |
373 | soc_con[cnt].tip_string); | |
374 | dfe_errno = UDIErrorNoSuchConnection; | |
375 | goto tip_failure; | |
376 | } | |
377 | memcpy((char *)&soc_con[cnt].tip_sockaddr_in.sin_addr, | |
378 | tip_info_p->h_addr, | |
379 | tip_info_p->h_length); | |
380 | } | |
381 | soc_con[cnt].tip_sockaddr_in.sin_port | |
382 | = htons(atoi(soc_con[cnt].tip_exe)); | |
383 | ||
384 | if (connect(soc_con[cnt].dfe_sd, | |
385 | (struct sockaddr *) &soc_con[cnt].tip_sockaddr_in, | |
386 | sizeof(soc_con[cnt].tip_sockaddr_in))) | |
387 | { | |
388 | sprintf(dfe_errmsg, "DFE-ipc ERROR, connect() call failed %s ", | |
389 | strerror (errno)); | |
390 | dfe_errno = UDIErrorCantConnect; | |
391 | goto tip_failure; | |
392 | } | |
393 | } | |
394 | /*------------------------------------------------------------- TIP CONNECT */ | |
395 | if (cnt == 0) udr_create(udrs, soc_con[cnt].dfe_sd, SOC_BUF_SIZE); | |
396 | ||
397 | tip_connect: | |
398 | current = cnt; | |
399 | session[*Session].in_use = TRUE; /* session id is now in use */ | |
400 | ||
401 | udr_errno = 0; | |
402 | udrs->udr_op = UDR_ENCODE; /* send all "in" parameters */ | |
403 | udr_UDIInt32(udrs, &service_id); | |
404 | ||
405 | DFEIPCId = (company_c << 16) + (product_c << 12) + version_c; | |
406 | udr_UDIUInt32(udrs, &DFEIPCId); | |
407 | ||
408 | udr_string(udrs, tip_main_string); | |
409 | ||
410 | udr_sendnow(udrs); | |
411 | ||
412 | udrs->udr_op = UDR_DECODE; /* recv all "out" parameters */ | |
413 | udr_UDIUInt32(udrs, &TIPIPCId); | |
414 | if ((TIPIPCId & 0xfff) < version_c) | |
415 | sprintf(dfe_errmsg, "DFE-ipc: Obsolete TIP Specified"); | |
416 | ||
417 | udr_UDIInt32(udrs, &soc_con[cnt].tip_pid); | |
418 | ||
419 | udr_UDISessionId(udrs, &session[*Session].tip_id); | |
420 | ||
421 | udr_UDIError(udrs, &dfe_errno); | |
422 | if (dfe_errno > 0) UDIKill(*Session, 0); | |
423 | ||
424 | return dfe_errno; | |
425 | ||
426 | tip_failure: | |
427 | ||
428 | soc_con[cnt].in_use = FALSE; | |
429 | session[*Session].in_use = FALSE; | |
430 | /* XXX - Should also close dfe_sd, but not sure what to do if muxed */ | |
431 | return dfe_errno; | |
432 | } | |
433 | ||
434 | /************************************************************** UDI_Disconnect | |
435 | * UDIDisconnect() should be called before exiting the | |
436 | * DFE to ensure proper shut down of the TIP. | |
437 | */ | |
438 | UDIError UDIDisconnect(Session, Terminate) | |
439 | UDISessionId Session; | |
440 | UDIBool Terminate; | |
441 | { | |
442 | int cnt; | |
443 | UDIInt32 service_id = UDIDisconnect_c; | |
444 | if(Session < 0 || Session > MAX_SESSIONS) | |
445 | { | |
446 | sprintf(dfe_errmsg," SessionId not valid (%d)", Session); | |
447 | return UDIErrorNoSuchConfiguration; | |
448 | } | |
449 | udr_errno = 0; | |
450 | udrs->udr_op = UDR_ENCODE; /* send all "in" parameters */ | |
451 | udr_UDIInt32(udrs, &service_id); | |
452 | udr_UDISessionId(udrs, &session[Session].tip_id); | |
453 | udr_UDIBool(udrs, &Terminate); | |
454 | udr_sendnow(udrs); | |
455 | ||
456 | session[Session].in_use = FALSE; /* session id is now free */ | |
457 | for (cnt=0; cnt < MAX_SESSIONS; cnt++) | |
458 | if(session[cnt].in_use | |
459 | && session[cnt].soc_con_p == session[Session].soc_con_p | |
460 | ) break; | |
461 | if(cnt >= MAX_SESSIONS) /* test if socket not multiplexed */ | |
462 | if(shutdown(session[Session].soc_con_p->dfe_sd, 2)) | |
463 | { | |
464 | sprintf(dfe_errmsg, "DFE-ipc WARNING: socket shutdown failed"); | |
465 | return UDIErrorIPCInternal; | |
466 | } | |
467 | else | |
468 | session[Session].soc_con_p->in_use = 0; | |
469 | ||
470 | udrs->udr_op = UDR_DECODE; /* receive all "out" parameters */ | |
471 | udr_UDIError(udrs, &dfe_errno); /* get any TIP error */ | |
472 | return dfe_errno; | |
473 | } | |
474 | ||
475 | /******************************************************************** UDI_KILL | |
476 | * UDIKill() is used to send a signal to the TIP. | |
477 | * This is a private IPC call. | |
478 | */ | |
479 | UDIError UDIKill(Session, Signal) | |
480 | UDISessionId Session; | |
481 | UDIInt32 Signal; | |
482 | { | |
483 | int cnt; | |
484 | UDIInt32 service_id = UDIKill_c; | |
485 | if(Session < 0 || Session > MAX_SESSIONS) | |
486 | { | |
487 | sprintf(dfe_errmsg," SessionId not valid (%d)", Session); | |
488 | return UDIErrorNoSuchConfiguration; | |
489 | } | |
490 | udr_errno = 0; | |
491 | udrs->udr_op = UDR_ENCODE; /* send all "in" parameters */ | |
492 | udr_UDIInt32(udrs, &service_id); | |
493 | udr_UDISessionId(udrs, &session[Session].tip_id); | |
494 | udr_UDIInt32(udrs, &Signal); | |
495 | udr_sendnow(udrs); | |
496 | ||
497 | session[Session].in_use = FALSE; /* session id is now free */ | |
498 | for (cnt=0; cnt < MAX_SESSIONS; cnt++) | |
499 | if(session[cnt].in_use | |
500 | && session[cnt].soc_con_p == session[Session].soc_con_p | |
501 | ) break; | |
502 | if(cnt < MAX_SESSIONS) /* test if socket not multiplexed */ | |
503 | if(shutdown(session[Session].soc_con_p->dfe_sd, 2)) | |
504 | { | |
505 | sprintf(dfe_errmsg, "DFE-ipc WARNING: socket shutdown failed"); | |
506 | return UDIErrorIPCInternal; | |
507 | } | |
508 | else | |
509 | session[Session].soc_con_p->in_use = 0; | |
510 | ||
511 | udrs->udr_op = UDR_DECODE; /* receive all "out" parameters */ | |
512 | udr_UDIError(udrs, &dfe_errno); /* get any TIP error */ | |
513 | return dfe_errno; | |
514 | } | |
515 | ||
516 | /************************************************** UDI_Set_Current_Connection | |
517 | * If you are connected to multiple TIPs, you can change | |
518 | * TIPs using UDISetCurrentConnection(). | |
519 | */ | |
520 | UDIError UDISetCurrentConnection(Session) | |
521 | UDISessionId Session; | |
522 | { | |
523 | UDIInt32 service_id = UDISetCurrentConnection_c; | |
524 | ||
525 | if(Session < 0 || Session > MAX_SESSIONS) | |
526 | return UDIErrorNoSuchConfiguration; | |
527 | if(!session[Session].in_use) /* test if not in use yet */ | |
528 | return UDIErrorNoSuchConnection; | |
529 | ||
530 | current = Session; | |
531 | /* change socket or multiplex the same socket */ | |
532 | udrs->sd = session[Session].soc_con_p->dfe_sd; | |
533 | ||
534 | udr_errno = 0; | |
535 | udrs->udr_op = UDR_ENCODE; /* send all "in" parameters */ | |
536 | udr_UDIInt32(udrs, &service_id); | |
537 | udr_UDISessionId(udrs, &session[Session].tip_id); | |
538 | udr_sendnow(udrs); | |
539 | if(udr_errno) return udr_errno; | |
540 | ||
541 | udrs->udr_op = UDR_DECODE; /* receive all "out" parameters */ | |
542 | udr_UDIError(udrs, &dfe_errno); /* get any TIP error */ | |
543 | return dfe_errno; | |
544 | } | |
545 | ||
546 | /************************************************************ UDI_Capabilities | |
547 | * The DFE uses UDICapabilities() to both inform the TIP | |
548 | * of what services the DFE offers and to inquire of the | |
549 | * TIP what services the TIP offers. | |
550 | */ | |
551 | UDIError UDICapabilities(TIPId, TargetId, DFEId, DFE, TIP, DFEIPCId, | |
552 | TIPIPCId, TIPString) | |
553 | UDIUInt32 *TIPId; /* out */ | |
554 | UDIUInt32 *TargetId; /* out */ | |
555 | UDIUInt32 DFEId; /* in */ | |
556 | UDIUInt32 DFE; /* in */ | |
557 | UDIUInt32 *TIP; /* out */ | |
558 | UDIUInt32 *DFEIPCId; /* out */ | |
559 | UDIUInt32 *TIPIPCId; /* out */ | |
560 | char *TIPString; /* out */ | |
561 | { | |
562 | UDIInt32 service_id = UDICapabilities_c; | |
563 | int size; | |
564 | ||
565 | udr_errno = 0; | |
566 | udrs->udr_op = UDR_ENCODE; /* send all "in" parameters */ | |
567 | udr_UDIInt32(udrs, &service_id); | |
568 | udr_UDIInt32(udrs, &DFEId); | |
569 | udr_UDIInt32(udrs, &DFE); | |
570 | udr_sendnow(udrs); | |
571 | if(udr_errno) return udr_errno; | |
572 | ||
573 | udrs->udr_op = UDR_DECODE; /* receive all "out" paramters */ | |
574 | udr_UDIInt32(udrs, TIPId); | |
575 | udr_UDIInt32(udrs, TargetId); | |
576 | udr_UDIInt32(udrs, TIP); | |
577 | udr_UDIInt32(udrs, DFEIPCId); | |
578 | *DFEIPCId = (company_c << 16) + (product_c << 12) + version_c; | |
579 | udr_UDIInt32(udrs, TIPIPCId); | |
580 | udr_string(udrs, sbuf); | |
581 | udr_UDIError(udrs, &dfe_errno); /* get any TIP error */ | |
582 | size = strlen(sbuf); | |
583 | if(size +1 > 80) return -1; /* test if sufficient space */ | |
584 | strcpy(TIPString, sbuf); | |
585 | return dfe_errno; | |
586 | } | |
587 | ||
588 | /********************************************************** UDI_Enumerate_TIPs | |
589 | * Used by the DFE to enquire about available TIP | |
590 | * connections. | |
591 | */ | |
592 | UDIError UDIEnumerateTIPs(UDIETCallback) | |
593 | int (*UDIETCallback)(); /* In -- function to callback */ | |
594 | { | |
595 | FILE *fp; | |
596 | ||
597 | fp = fopen(config_file, "r"); | |
598 | if(fp == NULL) | |
599 | return UDIErrorCantOpenConfigFile; | |
600 | while(fgets( sbuf, SBUF_SIZE, fp)) | |
601 | if(UDIETCallback( sbuf) == UDITerminateEnumeration) | |
602 | break; | |
603 | fclose( fp); | |
604 | return UDINoError; /* return success */ | |
605 | } | |
606 | ||
607 | /*********************************************************** UDI_GET_ERROR_MSG | |
608 | * Some errors are target specific. They are indicated | |
609 | * by a negative error return value. The DFE uses | |
610 | * UDIGetErrorMsg() to get the descriptive text for | |
611 | * the error message which can then be displayed to | |
612 | * the user. | |
613 | */ | |
614 | UDIError UDIGetErrorMsg(error_code, msg_len, msg, CountDone) | |
615 | UDIError error_code; /* In */ | |
616 | UDISizeT msg_len; /* In -- allowed message space */ | |
617 | char* msg; /* Out -- length of message*/ | |
618 | UDISizeT *CountDone; /* Out -- number of characters */ | |
619 | { | |
620 | UDIInt32 service_id = UDIGetErrorMsg_c; | |
621 | int size; | |
622 | ||
623 | udr_errno = 0; | |
624 | udrs->udr_op = UDR_ENCODE; /* send all "in" parameters */ | |
625 | udr_UDIInt32(udrs, &service_id); | |
626 | udr_UDIError(udrs, &error_code); | |
627 | udr_UDISizeT(udrs, &msg_len); | |
628 | udr_sendnow(udrs); | |
629 | if(udr_errno) return udr_errno; | |
630 | ||
631 | udrs->udr_op = UDR_DECODE; /* receive all "out" parameters */ | |
632 | udr_string(udrs, sbuf); | |
633 | udr_UDISizeT(udrs, CountDone); | |
634 | udr_UDIError(udrs, &dfe_errno); /* get any TIP error */ | |
635 | size = strlen(sbuf); | |
636 | if(size +1 > msg_len) return -1; /* test if sufficient space */ | |
637 | strcpy(msg, sbuf); | |
638 | return dfe_errno; | |
639 | } | |
640 | ||
641 | /******************************************************* UDI_GET_TARGET_CONFIG | |
642 | * UDIGetTargetConfig() gets information about the target. | |
643 | */ | |
644 | UDIError UDIGetTargetConfig(KnownMemory, NumberOfRanges, ChipVersions, | |
645 | NumberOfChips) | |
646 | UDIMemoryRange KnownMemory[]; /* Out */ | |
647 | UDIInt *NumberOfRanges; /* In and Out */ | |
648 | UDIUInt32 ChipVersions[]; /* Out */ | |
649 | UDIInt *NumberOfChips; /* In and Out */ | |
650 | { | |
651 | UDIInt32 service_id = UDIGetTargetConfig_c; | |
652 | int cnt; | |
653 | int MaxOfRanges = *NumberOfRanges; | |
654 | ||
655 | udr_errno = 0; | |
656 | udrs->udr_op = UDR_ENCODE; /* send all "in" parameters */ | |
657 | udr_UDIInt32(udrs, &service_id); | |
658 | udr_UDIInt(udrs, NumberOfRanges); | |
659 | udr_UDIInt(udrs, NumberOfChips); | |
660 | udr_sendnow(udrs); | |
661 | if(udr_errno) return udr_errno; | |
662 | ||
663 | udrs->udr_op = UDR_DECODE; /* receive all "out" paramters */ | |
664 | for(cnt=1; cnt <= MaxOfRanges; cnt++) | |
665 | udr_UDIMemoryRange(udrs, &KnownMemory[cnt-1]); | |
666 | udr_UDIInt(udrs, NumberOfRanges); | |
667 | udr_UDIInt(udrs, NumberOfChips); | |
668 | for(cnt=1; cnt <= *NumberOfChips; cnt++) | |
669 | udr_UDIUInt32(udrs, &ChipVersions[cnt -1]); | |
670 | udr_UDIError(udrs, &dfe_errno); /* get any TIP error */ | |
671 | return dfe_errno; | |
672 | } | |
673 | ||
674 | /********************************************************** UDI_CREATE_PRCOESS | |
675 | * UDICreateProcess() tells the target OS that a | |
676 | * process is to be created and gets a PID back unless | |
677 | * there is some error. | |
678 | */ | |
679 | UDIError UDICreateProcess(pid) | |
680 | UDIPId *pid; /* out */ | |
681 | { | |
682 | UDIInt32 service_id = UDICreateProcess_c; | |
683 | ||
684 | udr_errno = 0; | |
685 | udrs->udr_op = UDR_ENCODE; /* send all "in" parameters */ | |
686 | udr_UDIInt32(udrs, &service_id); | |
687 | udr_sendnow(udrs); | |
688 | if(udr_errno) return udr_errno; | |
689 | ||
690 | udrs->udr_op = UDR_DECODE; /* receive all "out" parameters */ | |
691 | udr_UDIPId(udrs, pid); | |
692 | udr_UDIError(udrs, &dfe_errno); /* get any TIP error */ | |
693 | return dfe_errno; | |
694 | } | |
695 | ||
696 | /***************************************************** UDI_Set_Current_Process | |
697 | * UDISetCurrentProcess uses a pid supplied by | |
698 | * UDICreateProcess and sets it as the default for all | |
699 | * udi calls until a new one is set. A user of a | |
700 | */ | |
701 | UDIError UDISetCurrentProcess (pid) | |
702 | UDIPId pid; /* In */ | |
703 | { | |
704 | UDIInt32 service_id = UDISetCurrentProcess_c; | |
705 | ||
706 | udr_errno = 0; | |
707 | udrs->udr_op = UDR_ENCODE; /* send all "in" parameters */ | |
708 | udr_UDIInt32(udrs, &service_id); | |
709 | udr_UDIPId(udrs, &pid); | |
710 | udr_sendnow(udrs); | |
711 | if(udr_errno) return udr_errno; | |
712 | ||
713 | udrs->udr_op = UDR_DECODE; /* receive all "out" parameters */ | |
714 | udr_UDIError(udrs, &dfe_errno); /* get any TIP error */ | |
715 | return dfe_errno; | |
716 | } | |
717 | ||
718 | /****************************************************** UDI_INITIALISE_PROCESS | |
719 | * UDIInitializeProcess() prepare process for | |
720 | * execution. (Reset processor if process os processor). | |
721 | */ | |
722 | UDIError UDIInitializeProcess( ProcessMemory, NumberOfRanges, EntryPoint, | |
723 | StackSizes, NumberOfStacks, ArgString) | |
724 | UDIMemoryRange ProcessMemory[]; /* In */ | |
725 | UDIInt NumberOfRanges; /* In */ | |
726 | UDIResource EntryPoint; /* In */ | |
727 | CPUSizeT *StackSizes; /* In */ | |
728 | UDIInt NumberOfStacks; /* In */ | |
729 | char *ArgString; /* In */ | |
730 | { | |
731 | UDIInt32 service_id = UDIInitializeProcess_c; | |
732 | int cnt; | |
733 | ||
734 | udr_errno = 0; | |
735 | udrs->udr_op = UDR_ENCODE; /* send all "in" parameters */ | |
736 | udr_UDIInt32(udrs, &service_id); | |
737 | udr_UDIInt(udrs, &NumberOfRanges); | |
738 | for(cnt = 0; cnt < NumberOfRanges; cnt++) | |
739 | udr_UDIMemoryRange(udrs, &ProcessMemory[cnt] ); | |
740 | udr_UDIResource(udrs, &EntryPoint); | |
741 | udr_UDIInt(udrs, &NumberOfStacks); | |
742 | for(cnt = 0; cnt < NumberOfStacks; cnt++) | |
743 | udr_CPUSizeT(udrs, &StackSizes[cnt]); | |
744 | udr_string(udrs, ArgString); | |
745 | udr_sendnow(udrs); | |
746 | if(udr_errno) return udr_errno; | |
747 | ||
748 | udrs->udr_op = UDR_DECODE; /* receive all "out" parameters */ | |
749 | udr_UDIError(udrs, &dfe_errno); /* get any TIP error */ | |
750 | return dfe_errno; | |
751 | } | |
752 | ||
753 | /********************************************************* UDI_DESTROY_PROCESS | |
754 | * UDIDestroyProcess() frees a process resource | |
755 | * previously created by UDICreateProcess(). | |
756 | */ | |
757 | UDIError UDIDestroyProcess(pid) | |
758 | UDIPId pid; /* in */ | |
759 | { | |
760 | UDIInt32 service_id = UDIDestroyProcess_c; | |
761 | ||
762 | udr_errno = 0; | |
763 | udrs->udr_op = UDR_ENCODE; /* send all "in" parameters */ | |
764 | udr_UDIInt32(udrs, &service_id); | |
765 | udr_UDIPId(udrs, &pid); | |
766 | udr_sendnow(udrs); | |
767 | if(udr_errno) return udr_errno; | |
768 | ||
769 | udrs->udr_op = UDR_DECODE; /* receive all "out" parameters */ | |
770 | udr_UDIError(udrs, &dfe_errno); /* get any TIP error */ | |
771 | return dfe_errno; | |
772 | } | |
773 | ||
774 | /****************************************************************** UDI_READ | |
775 | * UDIRead() reads a block of objects from a target | |
776 | * address space to host space. | |
777 | */ | |
778 | ||
779 | UDIError UDIRead (from, to, count, size, count_done, host_endian) | |
780 | UDIResource from; /* in - source address on target */ | |
781 | UDIHostMemPtr to; /* out - destination address on host */ | |
782 | UDICount count; /* in -- count of objects to be transferred */ | |
783 | UDISizeT size; /* in -- size of each object */ | |
784 | UDICount *count_done; /* out - count actually transferred */ | |
785 | UDIBool host_endian; /* in -- flag for endian information */ | |
786 | { | |
787 | UDIInt32 service_id = UDIRead_c; | |
788 | int byte_count; | |
789 | ||
790 | udr_errno = 0; | |
791 | udrs->udr_op = UDR_ENCODE; /* send all "in" parameters */ | |
792 | udr_UDIInt32(udrs, &service_id); | |
793 | udr_UDIResource(udrs, &from); | |
794 | udr_UDICount(udrs, &count); | |
795 | udr_UDISizeT(udrs, &size); | |
796 | udr_UDIBool(udrs, &host_endian); | |
797 | udr_sendnow(udrs); | |
798 | if(udr_errno) return udr_errno; | |
799 | ||
800 | udrs->udr_op = UDR_DECODE; /* receive all "out" paramters */ | |
801 | udr_UDICount(udrs, count_done); | |
802 | byte_count = (*count_done) * size; | |
803 | if(*count_done > 0 && *count_done <= count) | |
804 | udr_bytes(udrs, to, byte_count); | |
805 | if(udr_errno) return udr_errno; | |
806 | udr_UDIError(udrs, &dfe_errno); /* get any TIP error */ | |
807 | return dfe_errno; | |
808 | } | |
809 | ||
810 | /****************************************************************** UDI_WRITE | |
811 | * UDIWrite() writes a block of objects from host | |
812 | * space to a target address+space. | |
813 | */ | |
814 | UDIError UDIWrite( from, to, count, size, count_done, host_endian ) | |
815 | UDIHostMemPtr from; /* in -- source address on host */ | |
816 | UDIResource to; /* in -- destination address on target */ | |
817 | UDICount count; /* in -- count of objects to be transferred */ | |
818 | UDISizeT size; /* in -- size of each object */ | |
819 | UDICount *count_done; /* out - count actually transferred */ | |
820 | UDIBool host_endian; /* in -- flag for endian information */ | |
821 | { | |
822 | UDIInt32 service_id = UDIWrite_c; | |
823 | int byte_count = count * size; | |
824 | ||
825 | udr_errno = 0; | |
826 | udrs->udr_op = UDR_ENCODE; /* send all "in" parameters */ | |
827 | udr_UDIInt32(udrs, &service_id); | |
828 | udr_UDIResource(udrs, &to); | |
829 | udr_UDICount(udrs, &count); | |
830 | udr_UDISizeT(udrs, &size); | |
831 | udr_UDIBool(udrs, &host_endian); | |
832 | udr_bytes(udrs, from, byte_count); | |
833 | udr_sendnow(udrs); | |
834 | if(udr_errno) return udr_errno; | |
835 | ||
836 | udrs->udr_op = UDR_DECODE; /* receive all "out" paramters */ | |
837 | udr_UDICount(udrs, count_done); | |
838 | udr_UDIError(udrs, &dfe_errno); /* get any TIP error */ | |
839 | return dfe_errno; | |
840 | } | |
841 | ||
842 | /******************************************************************** UDI_COPY | |
843 | * UDICopy() copies a block of objects from one target | |
844 | * get address/space to another target address/space. | |
845 | */ | |
846 | UDIError UDICopy(from, to, count, size, count_done, direction ) | |
847 | UDIResource from; /* in -- destination address on target */ | |
848 | UDIResource to; /* in -- source address on target */ | |
849 | UDICount count; /* in -- count of objects to be transferred */ | |
850 | UDISizeT size; /* in -- size of each object */ | |
851 | UDICount *count_done; /* out - count actually transferred */ | |
852 | UDIBool direction; /* in -- high-to-low or reverse */ | |
853 | { | |
854 | UDIInt32 service_id = UDICopy_c; | |
855 | ||
856 | udr_errno = 0; | |
857 | udrs->udr_op = UDR_ENCODE; /* send all "in" parameters */ | |
858 | udr_UDIInt32(udrs, &service_id); | |
859 | udr_UDIResource(udrs, &from); | |
860 | udr_UDIResource(udrs, &to); | |
861 | udr_UDICount(udrs, &count); | |
862 | udr_UDISizeT(udrs, &size); | |
863 | udr_UDIBool(udrs, &direction); | |
864 | udr_sendnow(udrs); | |
865 | if(udr_errno) return udr_errno; | |
866 | ||
867 | udrs->udr_op = UDR_DECODE; /* receive all "out" parameters */ | |
868 | udr_UDICount(udrs, count_done); | |
869 | udr_UDIError(udrs, &dfe_errno); /* get any TIP error */ | |
870 | return dfe_errno; | |
871 | } | |
872 | ||
873 | /***************************************************************** UDI_EXECUTE | |
874 | * UDIExecute() continues execution of the default | |
875 | * process from the current PC. | |
876 | */ | |
877 | UDIError UDIExecute() | |
878 | { | |
879 | UDIInt32 service_id = UDIExecute_c; | |
880 | ||
881 | udr_errno = 0; | |
882 | udrs->udr_op = UDR_ENCODE; /* send all "in" parameters */ | |
883 | udr_UDIInt32(udrs, &service_id); | |
884 | udr_sendnow(udrs); | |
885 | if(udr_errno) return udr_errno; | |
886 | ||
887 | udrs->udr_op = UDR_DECODE; /* receive all "out" parameters */ | |
888 | udr_UDIError(udrs, &dfe_errno); /* get any TIP error */ | |
889 | return dfe_errno; | |
890 | } | |
891 | ||
892 | /******************************************************************** UDI_STEP | |
893 | * UDIStep() specifies a number of "instruction" | |
894 | * steps to make. | |
895 | */ | |
896 | UDIError UDIStep(steps, steptype, range) | |
897 | UDIUInt32 steps; /* in -- number of steps */ | |
898 | UDIStepType steptype; /* in -- type of stepping to be done */ | |
899 | UDIRange range; /* in -- range if StepInRange is TRUE */ | |
900 | { | |
901 | UDIInt32 service_id = UDIStep_c; | |
902 | ||
903 | udr_errno = 0; | |
904 | udrs->udr_op = UDR_ENCODE; /* send all "in" parameters */ | |
905 | udr_UDIInt32(udrs, &service_id); | |
906 | udr_UDIInt32(udrs, &steps); | |
907 | udr_UDIStepType(udrs, &steptype); | |
908 | udr_UDIRange(udrs, &range); | |
909 | udr_sendnow(udrs); | |
910 | if(udr_errno) return udr_errno; | |
911 | ||
912 | udrs->udr_op = UDR_DECODE; /* receive all "out" parameters */ | |
913 | udr_UDIError(udrs, &dfe_errno); /* get any TIP error */ | |
914 | return dfe_errno; | |
915 | } | |
916 | ||
917 | /******************************************************************** UDI_STOP | |
918 | * UDIStop() stops the default process | |
919 | */ | |
920 | UDIVoid UDIStop() | |
921 | { | |
922 | if (strcmp(session[current].soc_con_p->domain_string, "AF_UNIX") == 0) | |
923 | kill(session[current].soc_con_p->tip_pid, SIGINT); | |
924 | else | |
925 | udr_signal(udrs); | |
926 | ||
927 | /* XXX - should clean up session[] and soc_con[] structs here as well... */ | |
928 | ||
929 | return; | |
930 | } | |
931 | ||
932 | /******************************************************************** UDI_WAIT | |
933 | * UDIWait() returns the state of the target procesor. | |
934 | */ | |
935 | UDIError UDIWait(maxtime, pid, stop_reason) | |
936 | UDIInt32 maxtime; /* in -- maximum time to wait for completion */ | |
937 | UDIPId *pid; /* out -- pid of process which stopped if any */ | |
938 | UDIUInt32 *stop_reason; /* out -- PC where process stopped */ | |
939 | { | |
940 | UDIInt32 service_id = UDIWait_c; | |
941 | ||
942 | udr_errno = 0; | |
943 | udrs->udr_op = UDR_ENCODE; /* send all "in" parameters */ | |
944 | udr_UDIInt32(udrs, &service_id); | |
945 | udr_UDIInt32(udrs, &maxtime); | |
946 | udr_sendnow(udrs); | |
947 | if(udr_errno) return udr_errno; | |
948 | ||
949 | udrs->udr_op = UDR_DECODE; /* receive all "out" parameters */ | |
950 | udr_UDIPId(udrs, pid); | |
951 | udr_UDIUInt32(udrs, stop_reason); | |
952 | udr_UDIError(udrs, &dfe_errno); /* get any TIP error */ | |
953 | return dfe_errno; | |
954 | } | |
955 | ||
956 | /********************************************************** UDI_SET_BREAKPOINT | |
957 | * UDISetBreakpoint() sets a breakpoint at an adress | |
958 | * and uses the passcount to state how many | |
959 | * times that instruction should be hit before the | |
960 | * break occurs. | |
961 | */ | |
962 | UDIError UDISetBreakpoint (addr, passcount, type, break_id) | |
963 | UDIResource addr; /* in -- where breakpoint gets set */ | |
964 | UDIInt32 passcount; /* in -- passcount for breakpoint */ | |
965 | UDIBreakType type; /* in -- breakpoint type */ | |
966 | UDIBreakId *break_id; /* out - assigned break id */ | |
967 | { | |
968 | UDIInt32 service_id = UDISetBreakpoint_c; | |
969 | ||
970 | udr_errno = 0; | |
971 | udrs->udr_op = UDR_ENCODE; /* send all "in" parameters */ | |
972 | udr_UDIInt32(udrs, &service_id); | |
973 | udr_UDIResource(udrs, &addr); | |
974 | udr_UDIInt32(udrs, &passcount); | |
975 | udr_UDIBreakType(udrs, &type); | |
976 | udr_sendnow(udrs); | |
977 | if(udr_errno) return udr_errno; | |
978 | ||
979 | udrs->udr_op = UDR_DECODE; /* receive all "out" parameters */ | |
980 | udr_UDIBreakId(udrs, break_id); | |
981 | udr_UDIError(udrs, &dfe_errno); /* get any TIP error */ | |
982 | return dfe_errno; | |
983 | } | |
984 | ||
985 | /******************************************************** UDI_QUERY_BREAKPOINT | |
986 | */ | |
987 | UDIError UDIQueryBreakpoint (break_id, addr, passcount, type, current_count) | |
988 | UDIBreakId break_id; /* in -- assigned break id */ | |
989 | UDIResource *addr; /* out - where breakpoint was set */ | |
990 | UDIInt32 *passcount; /* out - trigger passcount for breakpoint */ | |
991 | UDIBreakType *type; /* out - breakpoint type */ | |
992 | UDIInt32 *current_count; /* out - current count for breakpoint */ | |
993 | { | |
994 | UDIInt32 service_id = UDIQueryBreakpoint_c; | |
995 | ||
996 | udr_errno = 0; | |
997 | udrs->udr_op = UDR_ENCODE; /* send all "in" parameters */ | |
998 | udr_UDIInt32(udrs, &service_id); | |
999 | udr_UDIBreakId(udrs, &break_id); | |
1000 | udr_sendnow(udrs); | |
1001 | if(udr_errno) return udr_errno; | |
1002 | ||
1003 | udrs->udr_op = UDR_DECODE; /* receive all "out" parameters */ | |
1004 | udr_UDIResource(udrs, addr); | |
1005 | udr_UDIInt32(udrs, passcount); | |
1006 | udr_UDIBreakType(udrs, type); | |
1007 | udr_UDIInt32(udrs, current_count); | |
1008 | udr_UDIError(udrs, &dfe_errno); /* get any TIP error */ | |
1009 | return dfe_errno; | |
1010 | } | |
1011 | ||
1012 | /******************************************************** UDI_CLEAR_BREAKPOINT | |
1013 | * UDIClearBreakpoint() is used to clear a breakpoint. | |
1014 | */ | |
1015 | UDIError UDIClearBreakpoint (break_id) | |
1016 | UDIBreakId break_id; /* in -- assigned break id */ | |
1017 | { | |
1018 | UDIInt32 service_id = UDIClearBreakpoint_c; | |
1019 | ||
1020 | udr_errno = 0; | |
1021 | udrs->udr_op = UDR_ENCODE; /* send all "in" parameters */ | |
1022 | udr_UDIInt32(udrs, &service_id); | |
1023 | udr_UDIBreakId(udrs, &break_id); | |
1024 | udr_sendnow(udrs); | |
1025 | if(udr_errno) return udr_errno; | |
1026 | ||
1027 | udrs->udr_op = UDR_DECODE; /* receive all "out" parameters */ | |
1028 | udr_UDIError(udrs, &dfe_errno); /* get any TIP error */ | |
1029 | return dfe_errno; | |
1030 | } | |
1031 | ||
1032 | /************************************************************** UDI_GET_STDOUT | |
1033 | * UDIGetStdout() is called when a call to | |
1034 | * UDIWait() indicates there is STD output data ready. | |
1035 | */ | |
1036 | UDIError UDIGetStdout(buf, bufsize, count_done) | |
1037 | UDIHostMemPtr buf; /* out -- buffer to be filled */ | |
1038 | UDISizeT bufsize; /* in -- buffer size in bytes */ | |
1039 | UDISizeT *count_done; /* out -- number of bytes written to buf */ | |
1040 | { | |
1041 | UDIInt32 service_id = UDIGetStdout_c; | |
1042 | ||
1043 | udr_errno = 0; | |
1044 | udrs->udr_op = UDR_ENCODE; /* send all "in" parameters */ | |
1045 | udr_UDIInt32(udrs, &service_id); | |
1046 | udr_UDISizeT(udrs, &bufsize); | |
1047 | udr_sendnow(udrs); | |
1048 | if(udr_errno) return udr_errno; | |
1049 | ||
1050 | udrs->udr_op = UDR_DECODE; /* receive all "out" parameters */ | |
1051 | udr_UDISizeT(udrs, count_done); | |
1052 | udr_bytes(udrs, buf, *count_done); | |
1053 | udr_UDIError(udrs, &dfe_errno); /* get any TIP error */ | |
1054 | return dfe_errno; | |
1055 | } | |
1056 | ||
1057 | /************************************************************** UDI_GET_STDERR | |
1058 | * UDIGetStderr() is called when a call to | |
1059 | * UDIWait() indicates there is STDERR output data ready | |
1060 | */ | |
1061 | UDIError UDIGetStderr(buf, bufsize, count_done) | |
1062 | UDIHostMemPtr buf; /* out -- buffer to be filled */ | |
1063 | UDISizeT bufsize; /* in -- buffer size in bytes */ | |
1064 | UDISizeT *count_done; /* out -- number of bytes written to buf */ | |
1065 | { | |
1066 | UDIInt32 service_id = UDIGetStderr_c; | |
1067 | ||
1068 | udr_errno = 0; | |
1069 | udrs->udr_op = UDR_ENCODE; /* send all "in" parameters */ | |
1070 | udr_UDIInt32(udrs, &service_id); | |
1071 | udr_UDISizeT(udrs, &bufsize); | |
1072 | udr_sendnow(udrs); | |
1073 | if(udr_errno) return udr_errno; | |
1074 | ||
1075 | udrs->udr_op = UDR_DECODE; /* receive all "out" parameters */ | |
1076 | udr_UDISizeT(udrs, count_done); | |
1077 | udr_bytes(udrs, buf, *count_done); | |
1078 | udr_UDIError(udrs, &dfe_errno); /* get any TIP error */ | |
1079 | return dfe_errno; | |
1080 | } | |
1081 | ||
1082 | /*************************************************************** UDI_PUT_STDIN | |
1083 | * UDIPutStdin() is called whenever the DFE wants to | |
1084 | * deliver an input character to the TIP. | |
1085 | */ | |
1086 | UDIError UDIPutStdin (buf, count, count_done) | |
1087 | UDIHostMemPtr buf; /* in -- buffer to be filled */ | |
1088 | UDISizeT count; /* in -- buffer size in bytes */ | |
1089 | UDISizeT *count_done; /* out - number of bytes written to buf */ | |
1090 | { | |
1091 | UDIInt32 service_id = UDIPutStdin_c; | |
1092 | ||
1093 | udr_errno = 0; | |
1094 | udrs->udr_op = UDR_ENCODE; /* send all "in" parameters */ | |
1095 | udr_UDIInt32(udrs, &service_id); | |
1096 | udr_UDISizeT(udrs, &count); | |
1097 | udr_bytes(udrs, buf, count); | |
1098 | udr_sendnow(udrs); | |
1099 | if(udr_errno) return udr_errno; | |
1100 | ||
1101 | udrs->udr_op = UDR_DECODE; /* receive all "out" parameters */ | |
1102 | udr_UDISizeT(udrs, count_done); | |
1103 | udr_UDIError(udrs, &dfe_errno); /* get any TIP error */ | |
1104 | return dfe_errno; | |
1105 | } | |
1106 | ||
1107 | /************************************************************** UDI_STDIN_MODE | |
1108 | * UDIStdinMode() is used to change the mode that chazcters | |
1109 | * are fetched from the user. | |
1110 | */ | |
1111 | UDIError UDIStdinMode(mode) | |
1112 | UDIMode *mode; /* out - */ | |
1113 | { | |
1114 | UDIInt32 service_id = UDIStdinMode_c; | |
1115 | ||
1116 | udr_errno = 0; | |
1117 | udrs->udr_op = UDR_ENCODE; /* send all "in" parameters */ | |
1118 | udr_UDIInt32(udrs, &service_id); | |
1119 | udr_sendnow(udrs); | |
1120 | if(udr_errno) return udr_errno; | |
1121 | ||
1122 | udrs->udr_op = UDR_DECODE; /* receive all "out" parameters */ | |
1123 | udr_UDIMode(udrs, mode); | |
1124 | udr_UDIError(udrs, &dfe_errno); /* get any TIP error */ | |
1125 | return dfe_errno; | |
1126 | } | |
1127 | ||
1128 | /*************************************************************** UDI_PUT_TRANS | |
1129 | * UDIPutTrans() is used to feed input to the passthru mode. | |
1130 | */ | |
1131 | UDIError UDIPutTrans (buf, count, count_done) | |
1132 | UDIHostMemPtr buf; /* in -- buffer address containing input data */ | |
1133 | UDISizeT count; /* in -- number of bytes in buf */ | |
1134 | UDISizeT *count_done; /* out-- number of bytes transfered */ | |
1135 | { | |
1136 | UDIInt32 service_id = UDIPutTrans_c; | |
1137 | ||
1138 | udr_errno = 0; | |
1139 | udrs->udr_op = UDR_ENCODE; /* send all "in" parameters */ | |
1140 | udr_UDIInt32(udrs, &service_id); | |
1141 | udr_UDISizeT(udrs, &count); | |
1142 | udr_bytes(udrs, buf, count); | |
1143 | udr_sendnow(udrs); | |
1144 | if(udr_errno) return udr_errno; | |
1145 | ||
1146 | udrs->udr_op = UDR_DECODE; /* receive all "out" parameters */ | |
1147 | udr_UDISizeT(udrs, count_done); | |
1148 | udr_UDIError(udrs, &dfe_errno); /* get any TIP error */ | |
1149 | return dfe_errno; | |
1150 | } | |
1151 | ||
1152 | /*************************************************************** UDI_GET_TRANS | |
1153 | * UDIGetTrans() is used to get output lines from the | |
1154 | * passthru mode. | |
1155 | */ | |
1156 | UDIError UDIGetTrans (buf, bufsize, count_done) | |
1157 | UDIHostMemPtr buf; /* out -- buffer to be filled */ | |
1158 | UDISizeT bufsize; /* in -- size of buf */ | |
1159 | UDISizeT *count_done; /* out -- number of bytes in buf */ | |
1160 | { | |
1161 | UDIInt32 service_id = UDIGetTrans_c; | |
1162 | ||
1163 | udr_errno = 0; | |
1164 | udrs->udr_op = UDR_ENCODE; /* send all "in" parameters */ | |
1165 | udr_UDIInt32(udrs, &service_id); | |
1166 | udr_UDISizeT(udrs, &bufsize); | |
1167 | udr_sendnow(udrs); | |
1168 | if(udr_errno) return udr_errno; | |
1169 | ||
1170 | udrs->udr_op = UDR_DECODE; /* receive all "out" parameters */ | |
1171 | udr_UDISizeT(udrs, count_done); | |
1172 | udr_bytes(udrs, buf, *count_done); | |
1173 | udr_UDIError(udrs, &dfe_errno); /* get any TIP error */ | |
1174 | return dfe_errno; | |
1175 | } | |
1176 | ||
1177 | /************************************************************** UDI_Trans_Mode | |
1178 | * UDITransMode() is used to change the mode that the | |
1179 | * transparent routines operate in. | |
1180 | */ | |
1181 | UDIError UDITransMode(mode) | |
1182 | UDIMode *mode; /* out -- selected mode */ | |
1183 | { | |
1184 | UDIInt32 service_id = UDITransMode_c; | |
1185 | ||
1186 | udr_errno = 0; | |
1187 | udrs->udr_op = UDR_ENCODE; /* send all "in" parameters */ | |
1188 | udr_UDIInt32(udrs, &service_id); | |
1189 | udr_UDIMode(udrs, mode); | |
1190 | udr_sendnow(udrs); | |
1191 | if(udr_errno) return udr_errno; | |
1192 | ||
1193 | udrs->udr_op = UDR_DECODE; /* receive all "out" parameters */ | |
1194 | udr_UDIError(udrs, &dfe_errno); | |
1195 | return dfe_errno; | |
1196 | } | |
1197 | ||
1198 | /******************************************************************** UDI_TEST | |
1199 | */ | |
1200 | UDIError UDITest( cnt, str_p, array) | |
1201 | UDISizeT cnt; | |
1202 | UDIHostMemPtr str_p; | |
1203 | UDIInt32 array[]; | |
1204 | { | |
1205 | UDIInt32 service_id = UDITest_c; | |
1206 | UDIInt16 scnt = cnt; | |
1207 | UDISizeT r_cnt; | |
1208 | char buf[256]; | |
1209 | ||
1210 | udr_errno = 0; | |
1211 | udrs->udr_op = UDR_ENCODE; /* send all "in" parameters */ | |
1212 | udr_UDIInt32(udrs, &service_id); | |
1213 | ||
1214 | printf("send cnt=%d scnt=%d\n", cnt, scnt); | |
1215 | udr_UDISizeT(udrs, &cnt); | |
1216 | udr_UDIInt16(udrs, &scnt); | |
1217 | printf(" array[0]=0x%x array[1]=0x%x array[2]=0x%x array[3]=0x%x\n", | |
1218 | array[0], array[1], array[2], array[3]); | |
1219 | udr_bytes(udrs, (char*)array, 4*sizeof(UDIInt32)); | |
1220 | printf(" string=%s\n", str_p); | |
1221 | udr_string(udrs, str_p); | |
1222 | udr_sendnow(udrs); | |
1223 | if(udr_errno) | |
1224 | { fprintf(stderr, " DFE-ipc Send ERROR\n"); | |
1225 | return udr_errno; | |
1226 | } | |
1227 | ||
1228 | udrs->udr_op = UDR_DECODE; /* receive all "out" parameters */ | |
1229 | printf("recv "); | |
1230 | udr_UDISizeT(udrs, &r_cnt); | |
1231 | udr_UDIInt16(udrs, &scnt); | |
1232 | printf(" rcnt=%d scnt=%d\n", r_cnt, scnt); | |
1233 | udr_bytes(udrs, (char*)array, 4*sizeof(UDIInt32)); | |
1234 | ||
1235 | printf(" array[0]=0x%x array[1]=0x%x array[2]=0x%x array[3]=0x%x\n", | |
1236 | array[0], array[1], array[2], array[3]); | |
1237 | udr_string(udrs, str_p); | |
1238 | printf(" string=%s\n", str_p); | |
1239 | ||
1240 | udr_UDIError(udrs, &dfe_errno); | |
1241 | return dfe_errno; | |
1242 | } | |
1243 | ||
1244 | ||
1245 | ||
1246 | UDIUInt32 UDIGetDFEIPCId() | |
1247 | { | |
1248 | return ((company_c << 16) + (product_c << 12) + version_c); | |
1249 | } | |
1250 | #endif /* __GO32__ */ |