/***************************************************
 *   Main program for random server
 **************************************************/
#include <stdio.h>
#include <mach.h>
#include <mach_error.h>
#include <mig_errors.h>
#include <mach/message.h>
#include <mach/notify.h>
#include <servers/envmgr.h>

extern boolean_t	random_server();

/*********************************************************
 * procedure random_run:
 *   Waits for messages to server,
 *   handles them, and replies to sender.
 *********************************************************/
void random_run ()
{
   typedef int space[1024]; /* Maximum message size */

   typedef struct DumMsg
        {
           msg_header_t 	head;
	   msg_type_t		retcodetype;
	   kern_return_t	return_code;
           space 		body;
        } DumMsg;

   kern_return_t	retcode;
   msg_return_t		msgcode;
   boolean_t 		ok;
   DumMsg 		*pInMsg, *pRepMsg;

   pInMsg = (DumMsg *)malloc(sizeof(DumMsg));
   pRepMsg = (DumMsg *)malloc(sizeof(DumMsg));

   while (TRUE)
   {
       pInMsg->head.msg_size = sizeof(DumMsg); /* bytes */
       pInMsg->head.msg_local_port = PORT_DEFAULT;

	/* wait to receive request from client */
       msgcode = msg_receive(&pInMsg->head,MSG_OPTION_NONE,0);
       if (msgcode != RCV_SUCCESS)
           printf("error %s in Receive, message will be ignored.\n",
		mach_errormsg((kern_return_t)msgcode));
       else 
       {   if (pInMsg->head.msg_type == MSG_TYPE_EMERGENCY)
           {
              if (pInMsg->head.msg_id == NOTIFY_PORT_DELETED)
		  {  /* probably the death of a client's reply */}
	      else
		printf("Unexpected emergency message received: id is %d\n",
			pInMsg->head.msg_id);
           }
          else  /* normal message */
          {   
		/* call server interface module */
	      ok = random_server((msg_header_t *)pInMsg,
				   (msg_header_t *)pRepMsg);
	      if (pRepMsg->return_code != MIG_NO_REPLY)
	      {  
		  /* sending reply message to client */
              	pRepMsg->head.msg_local_port = pInMsg->head.msg_local_port;
              	pRepMsg->head.msg_remote_port = pInMsg->head.msg_remote_port;
              	msgcode = msg_send(&pRepMsg->head,MSG_OPTION_NONE,0);
              	if ((msgcode != SEND_SUCCESS) && 
		    (msgcode != SEND_INVALID_PORT))
                               /* Probably remote process death */
                    printf("error %s at Send.\n",
				mach_errormsg((kern_return_t)msgcode));
	      }
	  } /* normal message */
       } /* of message handling */
     }  /* of main loop */

}


main()
{
   port_t	ServerPort;
   kern_return_t retcode;

	/* add notification port to default port set */
   retcode = port_unrestrict(task_self_,task_notify_);
	/* allocate a service port */
   retcode = port_allocate(task_self(), &ServerPort);
   if (retcode == KERN_SUCCESS)
   {    /* add service port to default port set */
      (void) port_unrestrict(task_self(),ServerPort);
	/* check it in so users can find it */
      retcode  = netname_check_in(NameServerPort,"RandomServerPort",
		PORT_NULL,ServerPort);
   }
   if (retcode != KERN_SUCCESS)
	printf("netname_check_in of RandomServerPort failed with code %s\n",
			mach_errormsg(retcode));
   random_run ();
   printf("(* !!!!! Random server exited - give it up !!!!! *)\n");
   exit(2);  
}
