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