Changed args for RPC_undo_arg_list to reference types.
[dyninst.git] / common / src / rpcUtil.C
1
2 //
3 // This file defines a set of utility routines for RPC services.
4 //
5 //
6
7 // overcome malloc redefinition due to /usr/include/rpc/types.h declaring 
8 // malloc 
9
10 #ifdef MIPS
11 #define MALLOC_DEFINED_AS_VOID
12 #endif
13
14 #include "util/h/rpcUtil.h"
15
16 int RPCdefaultXDRRead(int handle, char *buf, u_int len)
17 {
18     int ret;
19
20     do {
21         ret = read(handle, buf, len);
22     } while (ret < 0 && errno == EINTR);
23
24     if (ret <= 0) return(-1);
25     return (ret);
26 }
27
28 int RPCdefaultXDRWrite(int handle, char *buf, u_int len)
29 {
30     int ret;
31
32     do {
33         ret = write(handle, buf, len);
34     } while (ret < 0 && errno == EINTR);
35     assert(ret == len);
36     return (ret);
37 }
38
39 XDRrpc::~XDRrpc()
40 {
41   if (fd >= 0)
42     {
43       fcntl (fd, F_SETFL, FNDELAY);
44       close(fd);
45     }
46   if (__xdrs__) 
47     {
48       xdr_destroy (__xdrs__);
49       delete (__xdrs__);
50     }
51 }
52
53 //
54 // prepare for RPC's to be done/received on the passed fd.
55 //
56 XDRrpc::XDRrpc(int f, xdrIOFunc readRoutine, xdrIOFunc writeRoutine, int nblock)
57 {
58     fd = f;
59     __xdrs__ = new XDR;
60     if (!readRoutine) readRoutine = RPCdefaultXDRRead;
61     if (!writeRoutine) writeRoutine = RPCdefaultXDRWrite;
62     (void) xdrrec_create(__xdrs__, 0, 0, (char *) fd, readRoutine,writeRoutine);
63     if (nblock)
64       fcntl (fd, F_SETFL, FNDELAY);
65 }
66
67 //
68 // prepare for RPC's to be done/received on the passed fd.
69 //
70 XDRrpc::XDRrpc(char *machine,
71                char *user,
72                char *program,
73                xdrIOFunc readRoutine, 
74                xdrIOFunc writeRoutine,
75                char **arg_list,
76                int nblock)
77 {
78     fd = RPCprocessCreate(&pid, machine, user, program, arg_list);
79     if (fd >= 0) {
80         __xdrs__ = new XDR;
81         if (!readRoutine) readRoutine = RPCdefaultXDRRead;
82         if (!writeRoutine) writeRoutine = RPCdefaultXDRWrite;
83         (void) xdrrec_create(__xdrs__, 0, 0, (char *) fd, 
84                 readRoutine, writeRoutine);
85         if (nblock)
86           fcntl (fd, F_SETFL, FNDELAY);
87     } else {
88         __xdrs__ = NULL;
89         fd = -1;
90     }
91 }
92
93 int
94 RPC_readReady (int fd)
95 {
96   fd_set readfds;
97   struct timeval tvptr;
98
99   tvptr.tv_sec = 0; tvptr.tv_usec = 0;
100   if (fd < 0) return -1;
101   FD_ZERO(&readfds);
102   FD_SET (fd, &readfds);
103   if (select (fd+1, &readfds, NULL, NULL, &tvptr) == -1)
104     {
105       // if (errno == EBADF)
106         return -1;
107     }
108   return (FD_ISSET (fd, &readfds));
109 }
110
111 int 
112 RPC_undo_arg_list (int argc, char **arg_list, char **machine, int &family,
113                    int &type, int &well_known_socket, int &flag)
114 {
115   int loop;
116   char *ptr;
117   int sum = 0;
118
119   for (loop=0; loop < argc; ++loop)
120     {
121       if (!strncmp(arg_list[loop], "-p", 2))
122         {
123           well_known_socket = (int) strtol (arg_list[loop] + 2, &ptr, 10);
124           if (!ptr)
125             return(-1);
126           sum |= 1;
127         }
128       else if (!strncmp(arg_list[loop], "-f", 2))
129         {
130           family = (int) strtol (arg_list[loop] + 2, &ptr, 10);
131           if (!ptr)
132             return(-1);
133           sum |= 2;
134         }
135       else if (!strncmp(arg_list[loop], "-t", 2))
136         {
137           type = (int) strtol (arg_list[loop] + 2, &ptr, 10);
138           if (!ptr)
139             return(-1);
140           sum |= 4;
141         }
142       else if (!strncmp(arg_list[loop], "-m", 2))
143         {
144           *machine = strdup (arg_list[loop] + 2);
145           if (!(*machine)) return -1;
146           sum |= 8;
147         }
148       else if (!strncmp(arg_list[loop], "-l", 2))
149         {
150           flag = (int) strtol (arg_list[loop] + 2, &ptr, 10);
151           if (!ptr)
152             return(-1);
153           sum |= 16;
154         }
155     }
156   if (sum == (16 + 8 + 4 + 2 + 1))
157         return 0;
158   else
159         return -1;
160 }
161
162 char **
163 RPC_make_arg_list (char *program, int family, int type, int well_known_socket,
164                    int flag)
165 {
166   char arg_str[100];
167   int arg_count = 0;
168   char **arg_list;
169   char machine_name[50];
170
171   arg_list = new char*[7];
172   arg_list[arg_count++] = strdup (program);
173   sprintf(arg_str, "%s%d", "-p", well_known_socket);
174   arg_list[arg_count++] = strdup (arg_str);
175   sprintf(arg_str, "%s%d", "-f", family);
176   arg_list[arg_count++] = strdup (arg_str);
177   sprintf(arg_str, "%s%d", "-t", type);
178   arg_list[arg_count++] = strdup (arg_str);
179   gethostname (machine_name, 49);
180   sprintf(arg_str, "%s%s", "-m", machine_name);
181   arg_list[arg_count++] = strdup (arg_str);
182   sprintf(arg_str, "%s%d", "-l", flag);
183   arg_list[arg_count++] = strdup (arg_str);
184   arg_list[arg_count++] = 0;
185   return arg_list;
186 }
187
188 // returns fd of socket that is listened on, or -1
189 int
190 RPC_setup_socket (int *sfd,   // return file descriptor
191                   int family, // AF_INET ...
192                   int type)   // SOCK_STREAM ...
193 {
194   struct sockaddr_in serv_addr;
195   int length;
196   char machine[50];
197
198   if (gethostname(machine, 49) != 0)
199     return -1;
200
201   if ((*sfd = socket(family, type, 0)) < 0)
202     return -1;
203   
204   bzero ((char *) &serv_addr, sizeof(serv_addr));
205   serv_addr.sin_family = (short) family;
206   serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
207   serv_addr.sin_port = htons(0);
208   
209   length = sizeof(serv_addr);
210
211   if (bind(*sfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0)
212     return -1;
213
214   if (getsockname (*sfd, (struct sockaddr *) &serv_addr, &length) < 0)
215     return -1;
216
217   if (listen(*sfd, 5) < 0)
218     return -1;
219
220   return (ntohs (serv_addr.sin_port));
221 }
222
223 //
224 // connect to well known socket
225 //
226 XDRrpc::XDRrpc(int family,            
227                int req_port,             
228                int type,
229                char *machine, 
230                xdrIOFunc readRoutine,
231                xdrIOFunc writeRoutine,
232                int nblock)
233      // socket, connect using machine
234 {
235   int fd = 0;
236
237   struct sockaddr_in serv_addr;
238   struct hostent *hostptr = 0;
239   struct in_addr *inadr = 0;
240
241   __xdrs__ = 0;
242
243   if ( (hostptr = gethostbyname(machine)) == 0)
244     { fd = -1; return; }
245
246   inadr = (struct in_addr *) hostptr->h_addr_list[0];
247   bzero ((char *) &serv_addr, sizeof(serv_addr));
248   serv_addr.sin_family = family;
249   serv_addr.sin_addr = *inadr;
250   serv_addr.sin_port = htons(req_port);
251
252   if ( (fd = socket(family, type, 0)) < 0)
253     { fd = -1; return; }
254
255   if (connect(fd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0)
256     { fd = -1; return; }
257
258     __xdrs__ = new XDR;
259     if (!readRoutine) readRoutine = RPCdefaultXDRRead;
260     if (!writeRoutine) writeRoutine = RPCdefaultXDRWrite;
261     (void) xdrrec_create(__xdrs__, 0, 0, (char *) fd, readRoutine,writeRoutine);
262     if (nblock)
263       fcntl (fd, F_SETFL, FNDELAY);
264
265 }
266
267 //
268 // prepare for RPC's to be done/received on the passed thread id.
269 //
270 THREADrpc::THREADrpc(int thread)
271 {
272     tid = thread;
273 }
274
275 //
276 // This should never be called, it should be replaced by a virtual function
277 //    from the derived class created by igen.
278 //
279 void RPCUser::verifyProtocolAndVersion()
280 {
281     abort();
282 }
283
284 //
285 // our version of string encoding that does malloc as needed.
286 //
287 bool_t xdr_String(XDR *xdrs, String *str)
288 {
289     int len;
290
291         // if XDR_FREE, str's memory is freed
292     switch (xdrs->x_op) {
293         case XDR_ENCODE:
294                 len = strlen(*str)+1;
295                 break;
296         case XDR_DECODE:
297                 *str = NULL;
298                 break;
299         case XDR_FREE:
300                 // xdr_free (xdr_string, str);
301                 if (*str)
302                   free (*str);
303                 *str = NULL;
304                 return (TRUE);
305                 // return(TRUE);
306                 // free the memory
307         default:
308                 assert(0);
309                 // this should never occur      
310     }
311     // should we have a better max length ???. 
312     // xdr_bytes(xdrs, str, &len, 65536*32768);
313     // return(TRUE);
314     return (xdr_string (xdrs, str, 65536));
315 }
316
317 int RPCprocessCreate(int *pid, char *hostName, char *userName,
318                      char *command, char **arg_list)
319 {
320     int ret;
321     int sv[2];
322     int execlERROR;
323
324     if (!hostName || !strcmp(hostName, "") || !strcmp(hostName, "localhost")) {
325         ret = socketpair(AF_UNIX, SOCK_STREAM, 0, sv);
326         if (ret) return(ret);
327         execlERROR = 0;
328         *pid = vfork();
329         if (*pid == 0) {
330             close(sv[0]);
331             dup2(sv[1], 0);
332             if (!arg_list)
333               execl(command, command);
334             else
335               execv(command, arg_list);
336             execlERROR = errno;
337             _exit(-1);
338         } else if (*pid > 0 && !execlERROR) {
339             close(sv[1]);
340             return(sv[0]);
341         } else {
342             return(-1);
343         }
344     } else {
345         // need to rsh to machine and setup io path.
346         printf("remote starts not implemented\n");
347         exit(-1);
348     }
349 }
350
351 //
352 // wait for an expected RPC responce, but also handle upcalls while waiting.
353 //    Should not be called directly !!!
354 //
355 void RPCUser::awaitResponce(int tag)
356 {
357     abort();
358 }
359
360 void
361 XDRrpc::setNonBlock()
362 {
363   if (fd >= 0)
364     fcntl (fd, F_SETFL, FNDELAY);
365 }
366
367 int
368 XDRrpc::readReady()
369 {
370   return RPC_readReady (fd);
371 }
372
373 int
374 RPC_getConnect(int fd)
375 {
376   int clilen;
377   struct in_addr cli_addr;
378   int new_fd;
379
380   if (fd == -1)
381     return -1;
382
383   clilen = sizeof(cli_addr);
384
385   if ((new_fd = accept (fd, (struct sockaddr *) &cli_addr, &clilen)) < 0)
386     return -1;
387   else
388     return new_fd;
389 }
390