#include <stdio.h>
#include <rpc/rpc.h>
#include <netdb.h>
#include <sys/socket.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "librpc01.h"
int program = 2000333;
int version = 10;
char *server = NULL;
char *file_name = NULL;
char host_name[100];
long host_address;
void do_compare(int, char *, struct data *, char *);
void usage_error(char *program_name);
int main(int argc, char *argv[])
{
struct hostent *hp;
struct data buffer, *return_buffer;
int i, n, rc;
FILE *fp;
struct stat stat_buffer;
char *p;
CLIENT *clnt;
struct sockaddr_in server_sin;
int sock;
struct timeval timeout;
for (i = 1; i < argc; i++) {
if (!strcmp(argv[i], "-s")) {
if (++i >= argc) {
fprintf(stderr, "-s requires a host name\n");
usage_error(argv[0]);
}
server = argv[i];
continue;
}
if (!strcmp(argv[i], "-f")) {
if (++i >= argc) {
fprintf(stderr, "-h requires a file name\n");
usage_error(argv[0]);
}
file_name = argv[i];
continue;
}
if (!strcmp(argv[i], "-p")) {
if (++i >= argc) {
fprintf(stderr, "-p requires an argument\n");
usage_error(argv[0]);
}
n = sscanf(argv[i], "%d", &program);
if (n != 1) {
fprintf(stderr,
"-p requires an numeric argument\n");
usage_error(argv[0]);
}
continue;
}
if (!strcmp(argv[i], "-v")) {
if (++i >= argc) {
fprintf(stderr, "-v requires an argument\n");
usage_error(argv[0]);
}
n = sscanf(argv[i], "%d", &version);
if (n != 1) {
fprintf(stderr,
"-v requires an numeric argument\n");
usage_error(argv[0]);
}
continue;
}
}
if (!server) {
fprintf(stderr, "server not given\n");
usage_error(argv[0]);
}
hp = gethostbyname(server);
if (hp == NULL) {
fprintf(stderr, "server %s unknown\n", server);
usage_error(argv[0]);
}
memset(&server_sin, 0x00, sizeof(server_sin));
server_sin.sin_family = AF_INET;
memcpy(&server_sin.sin_addr, hp->h_addr, sizeof(hp->h_addr));
if (!file_name) {
fprintf(stderr, "file name not given\n");
usage_error(argv[0]);
}
gethostname(host_name, 100);
if ((hp = gethostbyname(host_name)) != NULL)
host_address = (long)*((int *)hp->h_addr_list[0]);
buffer.address = host_address;
buffer.request_id = getpid();
fp = fopen(file_name, "r");
if (!fp) {
fprintf(stderr, "Can not open %s\n", file_name);
usage_error(argv[0]);
}
if (stat(file_name, &stat_buffer))
fprintf(stderr, "stat() failed for %s, errno %d\n", file_name,
errno);
buffer.data_length = stat_buffer.st_size;
if (buffer.data_length > 2187) {
fprintf(stderr, "file too large (2187 max)\n");
usage_error(argv[0]);
}
buffer.data = malloc(buffer.data_length);
for (i = 0, p = buffer.data; i < buffer.data_length; i++, p++)
*p = getc(fp);
fclose(fp);
rc = callrpc(server, program, version, 1, (xdrproc_t)xdr_send_data,
(char *)&buffer, (xdrproc_t)xdr_receive_data,
(char *)&return_buffer);
do_compare(rc, "callrpc", &buffer, return_buffer->data);
server_sin.sin_port = 0;
sock = RPC_ANYSOCK;
timeout.tv_usec = 0;
timeout.tv_sec = 10;
clnt = clntudp_create(&server_sin, program, version, timeout, &sock);
if (clnt == NULL) {
fprintf(stderr, "clntudp_create failed\n");
exit(1);
}
timeout.tv_usec = 0;
timeout.tv_sec = 30;
rc = (int)clnt_call(clnt, 1, (xdrproc_t)xdr_send_data,
(char *)&buffer, (xdrproc_t)xdr_receive_data,
(char *)&return_buffer, timeout);
clnt_destroy(clnt);
do_compare(rc, "udp transport", &buffer, return_buffer->data);
server_sin.sin_port = 0;
sock = RPC_ANYSOCK;
clnt = clnttcp_create(&server_sin, program, version, &sock, 0, 0);
if (clnt == NULL) {
fprintf(stderr, "clntudp_create failed\n");
exit(1);
}
timeout.tv_usec = 0;
timeout.tv_sec = 30;
rc = (int)clnt_call(clnt, 1, (xdrproc_t)xdr_send_data,
(char *)&buffer, (xdrproc_t)xdr_receive_data,
(char *)&return_buffer, timeout);
clnt_destroy(clnt);
do_compare(rc, "tcp transport", &buffer, return_buffer->data);
exit(0);
}
void do_compare(int rpc_rc, char *msg, struct data *buffer, char *ret_data)
{
int rc;
if (rpc_rc) {
printf("RPC call with %s returned %d: ", msg, rpc_rc);
clnt_perrno(rpc_rc);
printf("\n");
exit(1);
}
rc = memcmp(buffer->data, ret_data, buffer->data_length);
if (rc) {
printf("Data compare for %s returned %d\n", msg, rc);
exit(1);
}
}
void usage_error(char *program_name)
{
fprintf(stderr,
"Usage: %s -s server -f file [-p program-number] [-v version]\n",
program_name);
exit(2);
}