
/*
 *
 *  rpproc.c -- Procedures to implement a simple (perhaps brain-asleep) RPC
 *		protocol over a TCP connection.
 *	     	This side handles the server's side of the connection.
 *
 */

/* Includes */

#include <sys/types.h>
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/stat.h>
#include <netdb.h>
#include <errno.h>
#include <pwd.h>
#include "tfile.h"
#include "rpc.h"
#include "config.h"

#ifdef INETD
#define ASSOC 1
#endif

#ifdef SUBPROC
#define ASSOC 1
#endif


#define SUCCESS 1
#define ERROR   -1
#define min(a, b) (a < b ? a : b)

/* global */
char rpc_caller[30];

extern int numprocs;
extern struct proc_table procs [1];
extern char *malloc();
extern int errno;

/* Static variables */

/* argument info */
static int procno;				/* procedure number */

/* connections & socket info */
static USPStream *us = NULL;

/*
 *
 * init_rpc () -- Initialize the RPC mechanism
 *
 */
init_rpc ()
{
#ifdef SUBPROC
     int uid;
     struct passwd *pwent;
#endif

#ifdef ASSOC
     /* safety check -- 0 better be a socket, not a pipe or file */
     {
	  if (isatty (0))
	      panic ("Must be run as a subprocess");
     }

     us = USP_associate (0);
#else    
     /* to be added */
     if (us == NULL) {
	  panic ("Can't accept connection");
     }
#endif

     strcpy (rpc_caller, "???");		/* safety drop */

#ifdef SUBPROC
     uid = getuid ();
     pwent = getpwuid(uid);
     if (pwent != 0) {
	  strcpy (rpc_caller, pwent -> pw_name);
     }
#endif
     strcat (rpc_caller, "@");
     strcat (rpc_caller, REALM);
}

/*
 *
 * recvit ()  -- Routine to accept an RPC call.
 *
 */
recvit (servname)
char *servname;					/* ignore for now */
{
     USPCardinal bt;
     int procno;


     if (USP_rcv_blk(us, &bt) != SUCCESS) {
	  if (errno = ECONNRESET) {		/* he went away, so do we */
	       USP_close_connection(us);
	       exit (0);
	  }
	  
	  panic ("Can't receive block");
     }

     procno = bt - PROC_BASE;

     if (procno == 0 || procno > numprocs) {
	  USP_close_connection(us);
	  panic ("Bad procedure");
     }

     dispatch (procno);
     return;
}

int recvint ()
{
     USPLong_integer li;

     if (USP_get_long_integer(us, &li) != SUCCESS) {
	  USP_close_connection(us);
	  panic ("No long integer");
     }

     return (li);
}

/*
 *
 * recvstr ()  -- Receive a string from an RPC call
 *
 */
char *recvstr ()
{
     USPString str;

     if (USP_get_string(us, &str) != SUCCESS) {
	  USP_close_connection(us);
	  panic ("No string");
     }

     return (str);
}

/*
 *
 * recvbool ()  -- Receive a boolean in an RPC call.
 *
 */
unsigned short recvbool()
{
     USPBoolean flag;

     if (USP_get_boolean(us, &flag) != SUCCESS) {
	  USP_close_connection(us);
	  panic ("No boolean");
     }

     return (flag);
}

/*
 *
 * recvfile() -- Receive a file in an RPC call.
 *
 */
tfile recvfile ()
{
     int tfs,j,numleft;
     tfile tf;
     char *buf,*str,*bptr;

     if (USP_get_long_integer(us, &tfs) != SUCCESS) {
	  USP_close_connection(us);
	  panic ("Can't get file");
     }

     tf = net_tfile (tfs,us);

     return (tf);
}

/*
 *
 * startreply()  -- Get ready to send reply of an RPC call.
 *
 */
startreply()
{
     USP_begin_block(us,REPLY_TYPE);

     return;
}

/*
 *
 * sendint(i)  -- Send an integer in an RPC return.
 *
 */
sendint(i)
int i;
{
     if (USP_put_long_integer(us, i) != SUCCESS) {
	  USP_close_connection(us);
	  panic ("Can't send integer");
     }
}

/*
 *
 * sendstr(i)  -- Send a string in an RPC return.
 *
 */
sendstr(str)
char *str;
{
     if (USP_put_string(us, str) != SUCCESS) {
	  USP_close_connection(us);
	  panic ("Can't send string");
     }
}

/*
 *
 * sendbool(b)  -- Send a boolean in an RPC return.
 *
 */
sendbool(b)
unsigned short b;
{
     if (USP_put_boolean(us, b) != SUCCESS) {
	  USP_close_connection(us);
	  panic ("Can't send boolean");
     }
}

/*
 *
 * sendreply () -- Make the final call.
 *
 */
sendreply()
{
     if (USP_end_block(us) != SUCCESS) {
	  USP_close_connection(us);
	  panic("Can't end block");
     }
     return;
}
