/****************************************************************************/ /* */ /* 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); }