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