3 * Revision 1.29 1994/08/18 19:55:04 markc
4 * Added ifdef for solaris.
6 * Revision 1.28 1994/08/17 18:25:25 markc
8 * Change RPC_make_arg_list to avoid leaving a hole at the head of the arg list
9 * Changed RPCProcessCreate to use the new version of arg list
10 * Changed the execl to execlp
12 * Revision 1.27 1994/07/28 22:22:04 krisna
13 * changed definitions of ReadFunc and WriteFunc to conform to prototypes
15 * Revision 1.26 1994/07/19 18:30:27 markc
16 * Made machineName default to zero as last parameter to RPC_make_arg_list.
17 * Added typecast to malloc call in RPC_make_arg_list.
19 * Added typecast to malloc call in RPC_make_arg_list.
21 * Revision 1.25 1994/07/18 19:08:25 hollings
22 * added extra arg to RPC_make_arg_list.
24 * Revision 1.24 1994/06/22 00:37:13 markc
25 * Fixed code to remove warnings.
27 * Revision 1.23 1994/06/02 23:36:58 markc
28 * Added support for igen error checking.
30 * Revision 1.22 1994/05/17 00:14:45 hollings
31 * added rcs log entry.
33 * Revision 1.21 1994/05/16 04:27:47 hollings
34 * Added inlcude of vfork.h on SUNS to prevent problem with optimizer.
36 * Revision 1.20 1994/05/12 18:47:51 jcargill
37 * Changed make args function to leave room for program name in arg_list[0],
38 * and added code to RPCprocessCreate to poke it in there before execv'ing.
40 * Revision 1.19 1994/04/21 23:23:49 hollings
41 * removed paradynd name from make args function.
43 * Revision 1.18 1994/04/06 22:46:12 markc
44 * Fixed bug in XDRrpc constructor that clobbered the fd value. Added feature
45 * to RPC_readReady to do blocking select.
47 * Revision 1.17 1994/04/01 20:05:27 hollings
48 * Removed kill of rsh process (not needed and it causes a race condition).
50 * Revision 1.16 1994/04/01 04:59:13 markc
51 * Put in support to encode NULL ptrs to strings in xdr_String.
53 * Revision 1.15 1994/03/31 22:59:08 hollings
54 * added well known port as a paramter to xdrRPC constructor.
56 * Revision 1.14 1994/03/31 22:45:04 markc
62 // This file defines a set of utility routines for RPC services.
66 // overcome malloc redefinition due to /usr/include/rpc/types.h declaring
72 /* prevents malloc from being redefined */
74 #define MALLOC_DEFINED_AS_VOID
77 #include "util/h/rpcUtil.h"
86 #include <netinet/in.h>
88 #include <sys/types.h>
94 #include <rpc/types.h>
98 // functions that g++-fixincludes missed
101 void bzero (char*, int);
102 int select (int, fd_set*, fd_set*, fd_set*, struct timeval*);
103 char *strdup (char*);
104 int gethostname(char*, int);
105 int socket(int, int, int);
106 int bind(int s, struct sockaddr *, int);
107 int getsockname(int, struct sockaddr*, int *);
108 int listen(int, int);
109 int connect(int s, struct sockaddr*, int);
110 int socketpair(int, int, int, int sv[2]);
112 int accept(int, struct sockaddr *addr, int *);
115 #include <sys/socket.h>
118 void bzero (char*, int);
119 int select (int, fd_set*, fd_set*, fd_set*, struct timeval*);
120 int socket(int, int, int);
121 int gethostname(char*, int);
122 int bind(int s, struct sockaddr *, int);
123 int getsockname(int, struct sockaddr*, int *);
124 int listen(int, int);
125 int connect(int s, struct sockaddr*, int);
126 int socketpair(int, int, int, int sv[2]);
127 int accept(int, struct sockaddr *addr, int *);
133 #define RSH_COMMAND "rsh"
135 int RPCdefaultXDRRead(const void* handle, char *buf, u_int len)
137 int fd = (int) handle;
141 ret = read(fd, buf, len);
142 } while (ret < 0 && errno == EINTR);
144 if (ret <= 0) return(-1);
148 int RPCdefaultXDRWrite(const void* handle, char *buf, u_int len)
150 int fd = (int) handle;
154 ret = write(fd, buf, len);
155 } while (ret < 0 && errno == EINTR);
167 fcntl (fd, F_SETFL, FNDELAY);
172 xdr_destroy (__xdrs__);
178 // prepare for RPC's to be done/received on the passed fd.
180 XDRrpc::XDRrpc(int f, xdrIOFunc readRoutine, xdrIOFunc writeRoutine, int nblock)
184 if (!readRoutine) readRoutine = (xdrIOFunc) RPCdefaultXDRRead;
185 if (!writeRoutine) writeRoutine = (xdrIOFunc) RPCdefaultXDRWrite;
186 (void) xdrrec_create(__xdrs__, 0, 0, (char *) fd, readRoutine,writeRoutine);
188 fcntl (fd, F_SETFL, FNDELAY);
192 // prepare for RPC's to be done/received on the passed fd.
194 XDRrpc::XDRrpc(char *machine,
197 xdrIOFunc readRoutine,
198 xdrIOFunc writeRoutine,
203 fd = RPCprocessCreate(&pid, machine, user, program, arg_list,
207 if (!readRoutine) readRoutine = (xdrIOFunc) RPCdefaultXDRRead;
208 if (!writeRoutine) writeRoutine = (xdrIOFunc) RPCdefaultXDRWrite;
209 (void) xdrrec_create(__xdrs__, 0, 0, (char *) fd,
210 readRoutine, writeRoutine);
212 fcntl (fd, F_SETFL, FNDELAY);
220 RPC_readReady (int fd, int timeout)
223 struct timeval tvptr, *the_tv;
225 tvptr.tv_sec = timeout; tvptr.tv_usec = 0;
226 if (fd < 0) return -1;
228 FD_SET (fd, &readfds);
230 // -1 timeout = blocking select
236 if (select (fd+1, &readfds, NULL, NULL, the_tv) == -1)
238 // if (errno == EBADF)
241 return (FD_ISSET (fd, &readfds));
245 RPC_undo_arg_list (int argc, char **arg_list, char **machine, int &family,
246 int &type, int &well_known_socket, int &flag)
252 for (loop=0; loop < argc; ++loop)
254 if (!strncmp(arg_list[loop], "-p", 2))
256 well_known_socket = (int) strtol (arg_list[loop] + 2, &ptr, 10);
257 if (ptr == (arg_list[loop] + 2))
261 else if (!strncmp(arg_list[loop], "-f", 2))
263 family = (int) strtol (arg_list[loop] + 2, &ptr, 10);
264 if (ptr == (arg_list[loop] + 2))
268 else if (!strncmp(arg_list[loop], "-t", 2))
270 type = (int) strtol (arg_list[loop] + 2, &ptr, 10);
271 if (ptr == (arg_list[loop] + 2))
275 else if (!strncmp(arg_list[loop], "-m", 2))
277 *machine = strdup (arg_list[loop] + 2);
278 if (!(*machine)) return -1;
281 else if (!strncmp(arg_list[loop], "-l", 2))
283 flag = (int) strtol (arg_list[loop] + 2, &ptr, 10);
284 if (ptr == (arg_list[loop] + 2))
289 if (sum == (16 + 8 + 4 + 2 + 1))
296 * Build an argument list starting at position 0.
297 * Note, this arg list will be used in an exec system call
298 * AND, the command name will have to be inserted at the head of the list
299 * But, a NULL space will NOT be left at the head of the list
301 char **RPC_make_arg_list(int family, int type, int well_known_socket,
302 int flag, char *machine_name)
308 arg_list = new char*[8];
309 sprintf(arg_str, "%s%d", "-p", well_known_socket);
310 arg_list[arg_count++] = strdup (arg_str); // 0
311 sprintf(arg_str, "%s%d", "-f", family);
312 arg_list[arg_count++] = strdup (arg_str); // 1
313 sprintf(arg_str, "%s%d", "-t", type);
314 arg_list[arg_count++] = strdup (arg_str); // 2
316 machine_name = (char *) malloc(50);
317 gethostname (machine_name, 49);
319 sprintf(arg_str, "%s%s", "-m", machine_name);
320 arg_list[arg_count++] = strdup (arg_str); // 3
321 sprintf(arg_str, "%s%d", "-l", flag);
322 arg_list[arg_count++] = strdup (arg_str); // 4
323 arg_list[arg_count++] = 0; // 5
327 // returns fd of socket that is listened on, or -1
329 RPC_setup_socket (int *sfd, // return file descriptor
330 int family, // AF_INET ...
331 int type) // SOCK_STREAM ...
333 struct sockaddr_in serv_addr;
337 if (gethostname(machine, 49) != 0)
340 if ((*sfd = socket(family, type, 0)) < 0)
343 memset ((char*) &serv_addr, 0, sizeof(serv_addr));
344 /* bzero ((char *) &serv_addr, sizeof(servaddr)); */
345 serv_addr.sin_family = (short) family;
346 serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
347 serv_addr.sin_port = htons(0);
349 length = sizeof(serv_addr);
351 if (bind(*sfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0)
354 if (getsockname (*sfd, (struct sockaddr *) &serv_addr, &length) < 0)
357 if (listen(*sfd, 5) < 0)
360 return (ntohs (serv_addr.sin_port));
364 // connect to well known socket
366 XDRrpc::XDRrpc(int family,
370 xdrIOFunc readRoutine,
371 xdrIOFunc writeRoutine,
373 // socket, connect using machine
375 struct sockaddr_in serv_addr;
376 struct hostent *hostptr = 0;
377 struct in_addr *inadr = 0;
381 if ( (hostptr = gethostbyname(machine)) == 0)
384 inadr = (struct in_addr *) hostptr->h_addr_list[0];
385 memset ((char*) &serv_addr, 0, sizeof(serv_addr));
386 /* bzero ((char *) &serv_addr, sizeof(serv_addr)); */
387 serv_addr.sin_family = family;
388 serv_addr.sin_addr = *inadr;
389 serv_addr.sin_port = htons(req_port);
391 if ( (fd = socket(family, type, 0)) < 0)
394 if (connect(fd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0)
398 if (!readRoutine) readRoutine = (xdrIOFunc) RPCdefaultXDRRead;
399 if (!writeRoutine) writeRoutine = (xdrIOFunc) RPCdefaultXDRWrite;
400 (void) xdrrec_create(__xdrs__, 0, 0, (char *) fd, readRoutine,writeRoutine);
402 fcntl (fd, F_SETFL, FNDELAY);
407 // prepare for RPC's to be done/received on the passed thread id.
409 THREADrpc::THREADrpc(int thread)
415 // This should never be called, it should be replaced by a virtual function
416 // from the derived class created by igen.
418 void RPCUser::verifyProtocolAndVersion()
424 // our version of string encoding that does malloc as needed.
426 bool_t xdr_String(XDR *xdrs, String *str)
429 unsigned char isNull=0;
431 // if XDR_FREE, str's memory is freed
432 switch (xdrs->x_op) {
435 len = strlen(*str)+1;
436 if (!xdr_u_char(xdrs, &isNull))
439 isNull = (unsigned char) 1;
440 if (!xdr_u_char(xdrs, &isNull))
445 return (xdr_string (xdrs, str, 65536));
448 if (!xdr_u_char(xdrs, &isNull))
453 return (xdr_string (xdrs, str, 65536));
455 // xdr_free (xdr_string, str);
464 // this should never occur
469 * arg_list should not have "command" at arg_list[0], it will
472 * if arg_list == NULL, command is the only argument used
474 int RPCprocessCreate(int *pid, char *hostName, char *userName,
475 char *command, char **arg_list, int portFd)
484 if (gethostname(local, 49))
488 !strcmp(hostName, "") ||
489 !strcmp(hostName, "localhost") ||
490 !strcmp(hostName, local)) {
491 ret = socketpair(AF_UNIX, SOCK_STREAM, 0, sv);
492 if (ret) return(ret);
499 execlp(command, command);
501 // how long is the arg_list?
502 for (al_len=0; arg_list[al_len]; al_len++)
505 new_al = new char*[al_len+2];
507 new_al[al_len+1] = 0;
508 for (i=0; i<al_len; ++i) {
509 new_al[i+1] = arg_list[i];
511 execvp(command, new_al);
516 } else if (*pid > 0 && !execlERROR) {
531 char *paradyndCommand;
533 total = strlen(command) + 2;
534 for (curr = arg_list; *curr; curr++) {
535 total += strlen(*curr) + 2;
537 paradyndCommand = (char *) malloc(total+2);
539 sprintf(paradyndCommand, "%s ", command);
540 for (curr = arg_list; *curr; curr++) {
541 strcat(paradyndCommand, *curr);
542 strcat(paradyndCommand, " ");
545 // need to rsh to machine and setup io path.
555 dup2(fd[1], 1); /* copy it onto stdout */
559 execlp(RSH_COMMAND, RSH_COMMAND, hostName, "-l",
560 userName, "-n", paradyndCommand, "-l0", NULL);
562 execlp(RSH_COMMAND, RSH_COMMAND, hostName, "-n",
563 paradyndCommand, "-l0", NULL);
566 } else if (shellPid > 0) {
572 pfp = fdopen(fd[0], "r");
574 ret = fgets(line, sizeof(line)-1, pfp);
575 if (ret && !strncmp(line, "PARADYND", strlen("PARADYND"))) {
576 // got the good stuff
577 sscanf(line, "PARADYND %d", pid);
579 retFd = RPC_getConnect(portFd);
582 // some sort of error message from rsh.
594 // wait for an expected RPC responce, but also handle upcalls while waiting.
595 // Should not be called directly !!!
597 void RPCUser::awaitResponce(int tag)
603 XDRrpc::setNonBlock()
606 fcntl (fd, F_SETFL, FNDELAY);
610 XDRrpc::readReady(int timeout)
612 return RPC_readReady (fd, timeout);
616 RPC_getConnect(int fd)
619 struct in_addr cli_addr;
625 clilen = sizeof(cli_addr);
627 if ((new_fd = accept (fd, (struct sockaddr *) &cli_addr, &clilen)) < 0)
633 RPCUser::RPCUser(int st)
638 RPCServer::RPCServer(int st)
644 * RPCgetArg - break a string into blank separated words
645 * Used to parse a command line.
647 * input --> a null terminated string, the command line
648 * argc --> returns the number of args found
649 * returns --> words (separated by blanks on command line)
650 * Note --> this allocates memory
652 char **RPCgetArg(int &argc, const char *input)
656 char **temp, **result;
657 const char *word_start;
658 int word_count = 0, temp_max, index, length, word_len;
662 return ((char **) 0);
664 length = strlen(input);
667 /* advance past blanks in input */
668 while ((index < length) && (input[index] == BLANK))
671 /* input is all blanks, or NULL */
672 if (index >= length) {
673 result = new char*[1];
674 if (!result) return ((char**) 0);
679 temp = new char*[30];
680 if (!temp) return temp;
684 /* the start of each string */
685 word_len = 0; word_start = input + index;
687 /* find the next BLANK and the WORD size */
688 while ((index < length) && (input[index] != BLANK)) {
693 temp[word_count] = new char[word_len+1];
694 strncpy(temp[word_count], word_start, word_len);
695 temp[word_count][word_len] = (char) 0;
698 /* skip past consecutive blanks */
699 while ((index < length) && (input[index] == BLANK))
702 /* no more room in temp, copy it to new_temp */
703 if (word_count > temp_max) {
707 /* new temp_max size */
708 nt_len = (temp_max+1) >> 1;
709 temp_max = nt_len - 1;
711 /* copy temp to new_temp */
712 new_temp = new char*[nt_len];
713 if (!new_temp) return ((char**) 0);
714 for (i=0; i<word_count; ++i)
715 new_temp[i] = temp[i];
720 } while (index < length);
723 /* null terminate the word list */
724 temp[word_count] = (char*) 0;