Remote Procedure Call

callrpc Example (rusers)

#include <stdio.h>
#include <rpc/rpc.h>
#include <rpcsvc/rusers.h>

int main(int argc, char **argv)
{
  long nusers;
  enum clnt_stat stat;

  if (argc<=1)
  {
    printf("Usage:  %s hostname\n", argv[0]);
    exit(1);
  }

  stat=callrpc(argv[1], RUSERSPROG, RUSERSVERS_3, RUSERSPROC_NUM,
               (xdrproc_t)xdr_void, NULL,
               (xdrproc_t)xdr_u_long, (char*)&nusers);
  if(stat != RPC_SUCCESS)
  {
    clnt_perrno(stat);
    printf("\n");
    exit(1);
  }
  printf("There are %d users on %s\n", nusers, argv[1]);
}

Source code: rusers.c.

Example application: Remote Killer

RPCGEN specification

program RKILL_PRG {
  version RKILL_VERSION_1 {
    int rkill(int pid) = 1;
  } = 1;
} = 0x21000001;

Source code: rkill.x.

The remote procedure code: rkill_server.c

The server call the system function kill(2) in order to send a signal SIGKILL (see also signal(7)). The result of the function execution is returned as a result of the remote function.

/*
 * This is sample code generated by rpcgen.
 * These are only templates and you can use them
 * as a guideline for developing your own functions.
 */

#include "rkill.h"

int *
rkill_1_svc(int pid,  struct svc_req *rqstp)
{
  static int  result;

  printf("Killing process %d\n", pid);
  result = kill(pid, 9);

  return &result;
}

The client side: rkill_client.c

/*
 * This is sample code generated by rpcgen.
 * These are only templates and you can use them
 * as a guideline for developing your own functions.
 */

#include "rkill.h"


void
rkill_prg_1(char *host, int pid)
{
  CLIENT *clnt;
  int  *result_1;

#ifndef 

  clnt = clnt_create (host, RKILL_PRG, RKILL_VERSION_1, "udp");
  if (clnt == NULL) {
    clnt_pcreateerror (host);
    exit (1);
  }
#endif  /* DEBUG */

  result_1 = rkill_1(pid, clnt);
  if (result_1 == (int *) NULL) {
    clnt_perror (clnt, "call failed");
  }
#ifndef 

  clnt_destroy (clnt);
#endif   /* DEBUG */
}


int
main (int argc, char *argv[])
{
  char *host;
  int pid;

  if (argc < 3) {
    printf ("usage: %s server_host pid\n", argv[0]);
    exit (1);
  }
  host = argv[1];
  pid = atoi(argv[2]);

  rkill_prg_1 (host, pid);
  exit (0);
}

Asynchronous calls

Add to *_client.c:

struct timeval timeout = { 0, 0 };
...
clnt = clnt_create(...);
...
clnt_control(clnt, CLSET_TIMEOUT, (char*)&timeout);

XDR Filters

#include <stdio.h>
#include <rpc/xdr.h>

int main() {
  XDR xdrh;
  FILE *fp;
  long val1 = 123;
  float val2 = 3.14;

  fp = fopen("/tmp/plik", "w");
  xdrstdio_create(&xdrh, fp, XDR_ENCODE);
  xdr_long(&xdrh, &val1);
  xdr_float(&xdrh, &val2);
  fclose(fp);
}

Source code: xdr.c.

Documentation