Sample Implementation of rpc.rexd Client



next up previous contents
Next: About this document Up: Supporting Cryptographic Databases Previous: Key Management Service

Sample Implementation of rpc.rexd Client

  John Barkley

/****************************************************************************/
/*                                                                          */
/*  A sample implementation of the "on" command (a client for rpc.rexd)     */
/*   which does not require the default directory on the client to be       */
/*                       exported to the server                             */
/*                                                                          */
/*         this implementation was developed under SunOS 4.1.1              */
/****************************************************************************/

#include <stdio.h>
#include <signal.h>
#include <rpc/rpc.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/time.h>
#include <netdb.h>
#include "rex.h"

main (argc, argv)
int argc;
char **argv;
{
	extern char **environ;
	extern int errno;
	static rex_start rs ;			/* rpc argument pointer */
	static rex_result rr ;			/* rpc result pointer */
	static char nulstr[] = "";

	struct timeval total_timeout;
	int rpcsock = RPC_ANYSOCK;
	register CLIENT *client;
	enum clnt_stat clnt_stat;
/*           socket stuff                         */

	int sockin, sockout, length;
	struct sockaddr_in clientin, server;
	int msgsockin, msgsockout;
	static char buf[1024], *bp;
	int inc, outc, wc;
	int i, pid;

	if (argc < 3)  {
		fprintf (stderr, "usage: myon host command\n");
		exit (-1);
		}

	rs.rst_cmd.rst_cmd_len = argc-2;
        rs.rst_cmd.rst_cmd_val = &argv[2];
	rs.rst_host = &nulstr[0];
	rs.rst_fsname = &nulstr[0];
	rs.rst_dirwithin = &nulstr[0];
	for (i=0; environ[i] != 0; i++) 
	rs.rst_env.rst_env_len = i;
	rs.rst_env.rst_env_val = environ;
	rs.rst_flags = 0;

	/* Get a TCP CLIENT pointer */

	if ((client = clnt_create(argv[1], REXPROG, REXVERS,
	     			"tcp")) == NULL)  {
		clnt_pcreateerror ("clnttcp_create");
		exit (-1);
		}
/*      create input and output sockets for rpc.rexd to connect to       */

	sockin = socket(AF_INET, SOCK_STREAM, 0);
	if (sockin < 0 ) {perror("opening input stream socket"); exit(-1); };

	sockout = socket(AF_INET, SOCK_STREAM, 0);
	if (sockout < 0 ) {perror("opening output stream socket"); exit(-1); };

/*           name sockets             */
	clientin.sin_family = AF_INET;
	clientin.sin_addr.s_addr = INADDR_ANY;
	clientin.sin_port = 0;
	if (bind(sockout, (struct sockaddr *)&clientin, sizeof(clientin)) <0)
		{perror("getting client socket name"); exit(-1); };

	server.sin_family = AF_INET;
	server.sin_addr.s_addr = INADDR_ANY;
	server.sin_port = 0;
	if (bind(sockin, (struct sockaddr *)&server, sizeof(server)) <0)
		{perror("getting server socket name"); exit(-1); };

/*         get assigned port numbers      */
	length = sizeof(clientin);
	if( getsockname(sockout, (struct sockaddr *)&clientin, &length) < 0)
		{perror("getting client socket name"); exit(-1); };
	length = sizeof(server);
	if( getsockname(sockin, (struct sockaddr *)&server, &length) < 0)
		{perror("getting server socket name"); exit(-1); };
	rs.rst_port0 = ntohs(clientin.sin_port); 
	rs.rst_port1 = ntohs(server.sin_port);
	rs.rst_port2 = rs.rst_port1;

/*              start accepting connections           */
	listen(sockin, 5);
	listen(sockout, 5);

/*                     Set UNIX style authentication                         */
/*                                                                           */
/*  to use DES authentication, replace with a call to authdes_create()       */

	client->cl_auth = authunix_create_default();
/*             call rpc.rexd                     */

	total_timeout.tv_sec = 20;
	total_timeout.tv_usec = 0;
	clnt_stat = clnt_call (client, REXPROC_START, xdr_rex_start, &rs,
                               xdr_rex_result, &rr, total_timeout);

	if (clnt_stat != RPC_SUCCESS) {
		clnt_perror (client, "rpc");
		exit (-1);
	}
	if (rr.rlt_stat != 0){
		fprintf(stderr,rr.rlt_message);
		exit(-1);
	}
/*   create parent and child processes for sockout and sockin communications */
	pid = fork(); if(pid < 0){perror("fork"); exit(1); };
	if (pid == 0)
/*              the child  for sockout                             */
	{
	 close(sockin);
	 msgsockout = accept(sockout, (struct sockaddr *)0, (int *)0);
	 if( msgsockout == -1) {perror("accept sockout"); exit(1); };
	 inc = 1;
	 while (inc > 0)
	 {
	  errno = 0;
	  inc = read(0, buf, sizeof(buf));
	  if (inc < 0) perror("stdin read");
	  if (inc <= 0) continue;
	  bp = buf; outc = inc; 
	  while (outc > 0)
	   {
	    errno = 0;
	    wc = write(msgsockout, bp, outc);
	    if (wc <= 0) break;
	    outc = outc - wc; bp = bp + wc;
	    }
	   }
	 close(msgsockout);
	 close(sockout);
	 }
	    else
/*                the parent for sockin               */
	{
	  close(sockout);
	  msgsockin = accept(sockin, (struct sockaddr *)0, (int *)0);
	  if( msgsockin == -1) {perror("accept sockin"); exit(1); };
	  inc = 1;
	  while(inc !=0 )
	  { 
	   bzero(buf, sizeof(buf));
	   if( (inc = read(msgsockin, buf, sizeof(buf))) < 0)
			{perror("reading stream message"), exit(0); };
	   if (inc != 0) write(1, buf, inc);
            }
	  (void) kill(pid, SIGKILL);
	 } ;
	close(msgsockin);
	close(sockin);
}



John Barkley
Fri Oct 7 16:17:21 EDT 1994