added pid to xdr class.
[dyninst.git] / pdutil / src / rpcUtil.C
1
2 //
3 // This file defines a set of utility routines for RPC services.
4 //
5 //
6 #include <stdlib.h>
7 #include <unistd.h>
8 #include <errno.h>
9 #include <assert.h>
10 #include <sys/types.h>
11 #include <sys/socket.h>
12
13 extern "C" {
14 #include <rpc/types.h>
15 #include <rpc/xdr.h>
16 }
17 #include "util/h/rpcUtil.h"
18
19 int RPCdefaultXDRRead(int handle, char *buf, u_int len)
20 {
21     int ret;
22
23     do {
24         ret = read(handle, buf, len);
25     } while (ret < 0 && errno == EINTR);
26
27     if (ret <= 0) return(-1);
28     return (ret);
29 }
30
31 int RPCdefaultXDRWrite(int handle, char *buf, u_int len)
32 {
33     int ret;
34
35     do {
36         ret = write(handle, buf, len);
37     } while (ret < 0 && errno == EINTR);
38     assert(ret == len);
39     return (ret);
40 }
41
42 //
43 // prepare for RPC's to be done/received on the passed fd.
44 //
45 XDRrpc::XDRrpc(int f, xdrIOFunc readRoutine, xdrIOFunc writeRoutine)
46 {
47     fd = f;
48     __xdrs__ = (XDR *) malloc(sizeof(XDR));
49     if (!readRoutine) readRoutine = RPCdefaultXDRRead;
50     if (!writeRoutine) writeRoutine = RPCdefaultXDRWrite;
51     (void) xdrrec_create(__xdrs__, 0, 0, (char *) fd, readRoutine,writeRoutine);
52 }
53
54
55 //
56 // prepare for RPC's to be done/received on the passed fd.
57 //
58 XDRrpc::XDRrpc(char *machine,
59                char *user,
60                char *program,
61                xdrIOFunc readRoutine, 
62                xdrIOFunc writeRoutine)
63 {
64     fd = RPCprocessCreate(&pid, machine, user, program);
65     if (fd >= 0) {
66         __xdrs__ = (XDR *) malloc(sizeof(XDR));
67         if (!readRoutine) readRoutine = RPCdefaultXDRRead;
68         if (!writeRoutine) writeRoutine = RPCdefaultXDRWrite;
69         (void) xdrrec_create(__xdrs__, 0, 0, (char *) fd, 
70                 readRoutine, writeRoutine);
71     } else {
72         __xdrs__ = NULL;
73         fd = -1;
74     }
75 }
76
77 //
78 // prepare for RPC's to be done/received on the passed thread id.
79 //
80 THREADrpc::THREADrpc(int thread)
81 {
82     tid = thread;
83 }
84
85 //
86 // This should never be called, it should be replaced by a virtual function
87 //    from the derived class created by igen.
88 //
89 void RPCUser::verifyProtocolAndVersion()
90 {
91     abort();
92 }
93
94 //
95 // our version of string encoding that does malloc as needed.
96 //
97 bool_t xdr_String(XDR *xdrs, String *str)
98 {
99     int len;
100
101     if (xdrs->x_op == XDR_ENCODE) {
102         len = strlen(*str)+1;
103     } else {
104         *str = NULL;
105     }
106     // should we have a better max length ???. 
107     xdr_bytes(xdrs, str, &len, 65536*32768);
108     return(TRUE);
109 }
110
111 int RPCprocessCreate(int *pid, char *hostName, char *userName, char *command)
112 {
113     int ret;
114     int sv[2];
115     int execlERROR;
116
117     if (!hostName || !strcmp(hostName, "") || !strcmp(hostName, "localhost")) {
118         ret = socketpair(AF_UNIX, SOCK_STREAM, 0, sv);
119         if (ret) return(ret);
120         execlERROR = 0;
121         *pid = vfork();
122         if (*pid == 0) {
123             close(sv[0]);
124             dup2(sv[1], 0);
125             execl(command, command);
126             execlERROR = errno;
127             _exit(-1);
128         } else if (*pid > 0 && !execlERROR) {
129             close(sv[1]);
130             return(sv[0]);
131         } else {
132             return(-1);
133         }
134     } else {
135         // need to rsh to machine and setup io path.
136         printf("remote starts not implemented\n");
137         exit(-1);
138     }
139 }
140
141 //
142 // wait for an expected RPC responce, but also handle upcalls while waiting.
143 //    Should not be called directly !!!
144 //
145 void RPCUser::awaitResponce(int tag)
146 {
147     abort();
148 }