/*## copyright DIGIT-LABS Jun 2012 uk                    *://digit-labs.org/ #*/
/*## rpc.espd                                                                #*/

/*   this code asks espd for a file and it complies, useless now              */
/*   (mimicked for posterity)                                                 */

#include <sys/types.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <netinet/in.h>
#include <rpc/rpc.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>

#define ESPD_PROG     391029
#define ESPD_VERS     1
#define ESPD_PROC     3

typedef struct{int bytes;int foff;int fnamelen;char *fname;}req_t;
typedef struct{int flag;int err;int bytes1;int bytes2;int fnamelen;char *fname;char *data;}res_t;

void hexdump(char *p,int tl,int l){
  int i,j;
  for(i=0;i<tl;i+=l){
    for(j=i;j<(i+l>tl?tl:i+l);j++)printf("%02x ",p[j]);
    if(i+l>tl)for(j=0;j<l-(tl-i);j++)printf("   ");
    printf(": ");
    for(j=i;j<(i+l>tl?tl:i+l);j++)
      if(p[j]<32)printf(".");
      else printf("%c",p[j]);
    printf("\n");
  }
}

bool_t xdr_req(XDR *xdrs,req_t *objp){
  if(!xdr_int(xdrs,&objp->bytes)) return(FALSE);
  if(!xdr_int(xdrs,&objp->foff)) return(FALSE);
  if(!xdr_int(xdrs,&objp->fnamelen)) return(FALSE);
  if(!xdr_bytes(xdrs,&objp->fname,(unsigned*)&objp->fnamelen,~0)) return(FALSE);
  fprintf(stdout,"* %s\n** bytes: %d, foff: %d, fnamelen: %d\n** fname: %s\n",
          __FUNCTION__,objp->bytes,objp->foff,objp->fnamelen,objp->fname);
  return(TRUE);
}

bool_t xdr_res(XDR *xdrs,res_t *objp){
  if(!xdr_int(xdrs,&objp->flag)) return(FALSE);
  if(!xdr_int(xdrs,&objp->err)) return(FALSE);
  if(!xdr_int(xdrs,&objp->bytes1)) return(FALSE);
  if(!xdr_int(xdrs,&objp->bytes2)) return(FALSE);
  if(!xdr_int(xdrs,&objp->fnamelen)) return(FALSE);
  if(!xdr_bytes(xdrs,&objp->fname,(unsigned*)&objp->fnamelen,~0)) return(FALSE);
  if(!xdr_bytes(xdrs,&objp->data,(unsigned*)&objp->bytes1,objp->bytes1)) return(FALSE);
  fprintf(stdout,"* %s\n** err: %d, bytes1: %d, fname: %s\n** data:\n",
          __FUNCTION__,objp->err,objp->bytes1,objp->fname);
  hexdump(objp->data,objp->bytes1,16);
  return(TRUE);
}

int main(int argc,char **argv){
  char c,*h,*file=NULL;
  int i,fd,port=0;
  CLIENT *cl;enum clnt_stat stat;
  struct hostent *hp;
  struct sockaddr_in adr;
  struct timeval tm={10,0};
  req_t req;
  res_t res;

  printf("copyright DIGIT-LABS Jun 2012 uk  /digit-labs.org/\n");
  printf("rpc.espd for irix 6.5.?\n\n");

  if(argc<3){
    printf("usage: %s address file [-p port] [-f output file]\n",argv[0]);
    exit(-1);
  }
  while((c=getopt(argc-2,&argv[2],"p:f:"))!=-1){
    switch(c){
      case 'p':port=atoi(optarg);break;
      case 'f':file=optarg;
    }
  }

  if(file&&(fd=open(file,O_CREAT|O_WRONLY,S_IRUSR|S_IWUSR))==-1){
    perror("error");exit(-1);
  }
  adr.sin_family=AF_INET;
  adr.sin_port=htons(port);
  if((adr.sin_addr.s_addr=inet_addr(argv[1]))==-1){
    if((hp=gethostbyname(argv[1]))==NULL){
      errno=EADDRNOTAVAIL;perror("error");exit(-1);
    }
    memcpy(&adr.sin_addr.s_addr,hp->h_addr,4);
  }else{
    if((hp=gethostbyaddr((char*)&adr.sin_addr.s_addr,4,AF_INET))==NULL){
      errno=EADDRNOTAVAIL;perror("error");exit(-1);
    }
  }
  if((h=(char*)strchr(hp->h_name,'.'))!=NULL) *(h+1)=0;
  else strcat(hp->h_name,".");

  i=RPC_ANYSOCK;
  if(!(cl=clnttcp_create(&adr,ESPD_PROG,ESPD_VERS,&i,0,0))){
    clnt_pcreateerror("error");exit(-1);
  }

  cl->cl_auth=authunix_create(hp->h_name,0,0,0,NULL);
  memset(&res,0,sizeof res);

  req.bytes=req.foff=0;req.fname=argv[2];req.fnamelen=strlen(argv[2])+1;
  stat=clnt_call(cl,ESPD_PROC,(xdrproc_t)xdr_req,(void*)&req,(xdrproc_t)xdr_res,(void*)&res,tm);
  if(stat!=RPC_SUCCESS) {clnt_perror(cl,"error");exit(-1);}
  if(file){write(fd,res.data,res.bytes1);close(fd);}
  auth_destroy(cl->cl_auth);clnt_destroy(cl);
  printf("%s\n",(!res.err)?"ok":"failed");

  return(EXIT_SUCCESS);
}
