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