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