home *** CD-ROM | disk | FTP | other *** search
/ Resource Library: Multimedia / Resource Library: Multimedia.iso / maestro / source / ntwrkprt / receiver.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-06-15  |  21.1 KB  |  620 lines

  1. /*
  2.  * Copyright (c) 1990, 1991 Stanford University
  3.  *
  4.  * Permission to use, copy, modify, and distribute this software and 
  5.  * its documentation for any purpose is hereby granted without fee, provided
  6.  * that (i) the above copyright notices and this permission notice appear in
  7.  * all copies of the software and related documentation, and (ii) the name
  8.  * Stanford may not be used in any advertising or publicity relating to
  9.  * the software without the specific, prior written permission of
  10.  * Stanford.
  11.  * 
  12.  * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
  13.  * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
  14.  * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
  15.  *
  16.  * IN NO EVENT SHALL STANFORD BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
  17.  * INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES
  18.  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT
  19.  * ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY,
  20.  * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  21.  * SOFTWARE.
  22.  */
  23.  
  24. /* $Header: /Source/Media/drapeau/NetworkProtocol/RCS/Receiver.c,v 1.39 92/09/13 22:43:20 drapeau Exp $ */
  25. /* $Log:    Receiver.c,v $
  26.  * Revision 1.39  92/09/13  22:43:20  drapeau
  27.  * Fixed minor error in the reporting of an error creating a socket on a
  28.  * particular port.  The error message mistakenly reported that the requested
  29.  * port number was the defined constant "PortMgrPortNumber", instead of the
  30.  * variable "tempPortNumber" as requested.
  31.  * 
  32.  * Revision 1.38  92/05/29  12:40:36  drapeau
  33.  * Changed the name of the "Selection" structure to "MAESelection",
  34.  * to avoid name conflicts with other software packages and toolkits
  35.  * that might also define a "Selection" structure.
  36.  * 
  37.  * Revision 1.37  91/11/25  12:59:10  drapeau
  38.  * Two major changes:
  39.  * 1) Cosmetic changes to default Receiver methods.  They no longer print
  40.  *    a message saying that the particular method has not been implemented.
  41.  * 2) Plugged a memory leak in DestroyReceiver().  The Port information
  42.  *    associated with the Receiver was not being de-allocated.
  43.  * 
  44.  * Revision 1.36  91/09/26  23:22:34  drapeau
  45.  * Modified CreateSocketOnPort() so that it takes a pointer to an integer.
  46.  * This is so that it can return the actual port number used for the new
  47.  * socket.
  48.  * Also, commented CreateSocketOnPort().
  49.  * 
  50.  * Revision 1.35  91/09/18  12:53:05  drapeau
  51.  * - Minor changes to some error messages; they now report as "MAEstro Protocol" in keeping with the
  52.  *   project name.
  53.  * - The name of the RPC protocol was changed from "LinkProtocol" to "MAEstro"; several changes in
  54.  *   the RPC service code were made as a result.
  55.  * - Took out extraneous code in ReceiverGetSelection(), since the default Selection structure is
  56.  *   initialized at the beginning of the function.
  57.  * - Modified the ReceiverGetPortFromName() method so that it returns a PortArray* instead of a Port*,
  58.  *   in keeping with the new protocol specification for this message.
  59.  * 
  60.  * Revision 1.34  91/09/03  16:56:51  drapeau
  61.  * Made minor cosmetic changes to enhance code readability.
  62.  * Also, changed the definition of ReceiverGetPortFromName() so that
  63.  * it returns a Port* instead of a void*.
  64.  * 
  65.  * Revision 1.33  91/06/19  14:05:39  drapeau
  66.  * Added support for five new messages:
  67.  *  - PauseSelection
  68.  *  - ResumeSelection
  69.  *  - HideApplication
  70.  *  - ShowApplication
  71.  *  - GetAppIcon
  72.  * Also, replaced the "PerformPartialSelection" message with
  73.  * "HaltSelection" message.
  74.  * 
  75.  * Specifically, changes occurred in the DispatchTable structure and
  76.  * BuildDispatchTable() function, the addition of new Receiver messages, and
  77.  * modification of the default ReceiverGetSelection() message to return a
  78.  * valid Selection structure with new offset and label fields filled in.
  79.  * 
  80.  * Also, minor cosmetic changes (reformatting) of the code.
  81.  * 
  82.  * Revision 1.32  91/06/17  18:17:20  drapeau
  83.  * Added copyright notice.
  84.  * 
  85.  * Revision 1.31  1991/02/28  07:17:07  drapeau
  86.  * No code changes; this version uses a new version numbering scheme and a new
  87.  * version of RCS.
  88.  *
  89.  * Revision 1.3  1991/02/27  03:39:23  drapeau
  90.  * Changed a comment in "CreateSocketOnPort()" to accurately describe the address
  91.  * to which is to be bound.
  92.  *
  93.  * Revision 1.2  90/11/30  13:58:49  drapeau
  94.  * Modified NewReceiver() -- now, receiver structure is filled in all the time,
  95.  * regardless of whether the Port Manager Sender is valid.  This is important
  96.  * for the PortManager application which does not create a Sender to register
  97.  * itself (the PortManager is the authority handling registration, so it
  98.  * should not register itself), because even though it does not have a valid
  99.  * Sender, the Port Manager still has a Receiver and so its information
  100.  * needs to be filled in.
  101.  * 
  102.  * Revision 1.1  90/10/24  18:24:10  drapeau
  103.  * Initial revision
  104.  *  */
  105.  
  106. static char ReceiverRcsid[] = "$Header: /Source/Media/drapeau/NetworkProtocol/RCS/Receiver.c,v 1.39 92/09/13 22:43:20 drapeau Exp $";
  107.  
  108. #include <stdio.h>
  109. #include <string.h>
  110. #include <Receiver.h>
  111. #include <sys/types.h>
  112. #include <sys/socket.h>
  113.  
  114. static DispatchTable    ReceiverDispatchTable = 
  115. {
  116.   ReceiverOpenDocument,
  117.   ReceiverGetCurrentDocName,
  118.   ReceiverGetSelection,
  119.   ReceiverSetSelection,
  120.   ReceiverPerformSelection,
  121.   ReceiverConnectWithPortMgr,
  122.   ReceiverGetOpenApps,
  123.   ReceiverGetPortFromName,
  124.   ReceiverDispatchMessage,
  125.   ReceiverDisconnectFromPortMgr,
  126.   ReceiverPing,
  127.   ReceiverHaltSelection,
  128.   ReceiverPauseSelection,
  129.   ReceiverResumeSelection,
  130.   ReceiverHideApplication,
  131.   ReceiverShowApplication,
  132.   ReceiverGetAppIcon
  133. };
  134.  
  135. void BuildDispatchTable(DispatchTable* table)
  136. {
  137.   if (table == NULL)
  138.     return;
  139.   if (table->openDocumentPtr)
  140.     ReceiverDispatchTable.openDocumentPtr = table->openDocumentPtr;
  141.   if (table->getCurrentDocNamePtr)
  142.     ReceiverDispatchTable.getCurrentDocNamePtr = table->getCurrentDocNamePtr;
  143.   if (table->getSelectionPtr)
  144.     ReceiverDispatchTable.getSelectionPtr = table->getSelectionPtr;
  145.   if (table->setSelectionPtr)
  146.     ReceiverDispatchTable.setSelectionPtr = table->setSelectionPtr;
  147.   if (table->performSelectionPtr)
  148.     ReceiverDispatchTable.performSelectionPtr = table->performSelectionPtr;
  149.   if (table->connectWithPortMgrPtr)
  150.     ReceiverDispatchTable.connectWithPortMgrPtr = table->connectWithPortMgrPtr;
  151.   if (table->getOpenAppsPtr)
  152.     ReceiverDispatchTable.getOpenAppsPtr = table->getOpenAppsPtr;
  153.   if (table->getPortFromNamePtr)
  154.     ReceiverDispatchTable.getPortFromNamePtr = table->getPortFromNamePtr;
  155.   if (table->dispatchMessagePtr)
  156.     ReceiverDispatchTable.dispatchMessagePtr = table->dispatchMessagePtr;
  157.   if (table->disconnectFromPortMgrPtr)
  158.     ReceiverDispatchTable.disconnectFromPortMgrPtr = table->disconnectFromPortMgrPtr;
  159.   if (table->pingPtr)
  160.     ReceiverDispatchTable.pingPtr = table->pingPtr;
  161.   if (table->haltSelectionPtr)
  162.     ReceiverDispatchTable.haltSelectionPtr = table->haltSelectionPtr;
  163.   if (table->pauseSelectionPtr)
  164.     ReceiverDispatchTable.pauseSelectionPtr = table->pauseSelectionPtr;
  165.   if (table->resumeSelectionPtr)
  166.     ReceiverDispatchTable.resumeSelectionPtr = table->resumeSelectionPtr;
  167.   if (table->hideApplicationPtr)
  168.     ReceiverDispatchTable.hideApplicationPtr = table->hideApplicationPtr;
  169.   if (table->showApplicationPtr)
  170.     ReceiverDispatchTable.showApplicationPtr = table->showApplicationPtr;
  171.   if (table->getAppIconPtr)
  172.     ReceiverDispatchTable.getAppIconPtr = table->getAppIconPtr;
  173.   return;
  174. }                                    /* end function BuildDispatchTable */
  175.  
  176.  
  177.  
  178. /******************************************************************
  179.   *    CreateSocketOnPort
  180.   *
  181.   *    This function attempts to create a socket, bind an address
  182.   *    to that socket, and return that bound socket to the caller.
  183.   *    The function takes as argument a pointer to an integer.
  184.   *    The integer pointed to should contain the port number
  185.   *    being requested (this function allows the caller to
  186.   *    request a specific port number).  If the port number
  187.   *    passed in as argument is set to the defined constant
  188.   *    "AnyPort", this function will let the kernel pick a port
  189.   *    number.
  190.   *    The function returns the socket descriptor, and will also
  191.   *    replace the portNumber passed in as argument with the
  192.   *    port number to which the socket is bound.
  193.   *    If the function fails, a zero (0) will be returned, and
  194.   *    the port number passed in as argument will be set to 0.
  195.   */
  196.  
  197. int    CreateSocketOnPort(int*  portNumber)
  198. {
  199.   int            newSocket;
  200.   struct sockaddr_in    address;
  201.   int            addressLength = sizeof(struct sockaddr_in);
  202.   int            result;
  203.   
  204.   if ((newSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)  /* Try to create a new socket */
  205.     {
  206.       perror("MAEstro Protocol: Unable to create a socket.");
  207.       *portNumber = 0;
  208.       return(0);
  209.     }
  210.   bzero((char *)&address, sizeof (address));                /* Clear out the address to which to bind the socket */
  211.   address.sin_family = AF_INET;
  212.   address.sin_port = *portNumber;
  213.   result = bind(newSocket, (struct sockaddr *)&address,            /* Attempt to make the socket use the port number passed in */
  214.         addressLength);
  215.   if (result == -1)
  216.     {
  217.       perror("MAEstro Protocol: Unable to reserve the port the PortManager requests.");
  218.       *portNumber = 0;
  219.       return(0);
  220.     }
  221.   *portNumber = ntohs(address.sin_port);
  222.   return(newSocket);
  223. }                                    /* end function CreateSocketOnPort */
  224.  
  225.  
  226. Receiver* NewReceiver(Sender* portMgrSender, char* appName, int    receivingPort)
  227. {
  228.   Receiver*    receiver;
  229.   int        transportSocket;
  230.   int        tempPortNumber = 0;
  231.   
  232.   tempPortNumber = receivingPort;
  233.   receiver = (Receiver*)malloc(sizeof(Receiver));
  234.   receiver->receiveSocket = 0;                        /* Initialize member variables  */
  235.   receiver->transport =  (SVCXPRT*) NULL;
  236.   receiver->createErrorCode = 0;
  237.   receiver->receivePort.portNumber = 0;
  238.   receiver->receivePort.appName = NULL;
  239.   receiver->receivePort.hostName = NULL;
  240.   pmap_unset(MAEstro, FirstTestVersion);                /* Unregister this protocol with the portmapper*/
  241.   transportSocket = CreateSocketOnPort(&tempPortNumber);        /* Attempt to create a socket bound to the receivingPort */
  242.   if (transportSocket == 0)                        /* Did the socket creation succeed? */
  243.     {                                    /* No, print an error message and return a NULL Receiver */
  244.       fprintf(stderr,"Unable to create a new Receiver on %d.\n",
  245.           tempPortNumber);
  246.       return((Receiver*)NULL);
  247.     }
  248.   receiver->transport = svctcp_create(transportSocket,0,0);        /*  Attempt to create port on which to listen for messages*/
  249.   if (receiver->transport == NULL)                    /*  Did the attempt fail?*/
  250.     {
  251.       (void)fprintf(stderr, "cannot create tcp service.\n");        /* Yes, report the error and return an error code*/
  252.       receiver->createErrorCode =1;
  253.     }
  254.   if (!svc_register(receiver->transport, MAEstro,            /* Attempt to associate this version of the Link...*/
  255.             FirstTestVersion,                    /* ...protocol with the DispatchMessage method*/
  256.             ReceiverDispatchMessage, 0))
  257.     {
  258.       (void)fprintf(stderr,                        /* Failure -- report the error and return an error code*/
  259.             "unable to register (MAEstro, FirstTestVersion, tcp).\n");
  260.       receiver->createErrorCode =1;
  261.     }
  262.   receiver->receivePort.appName = strdup(appName);            /* Fill in the name of this application*/
  263.   receiver->receivePort.portNumber =                    /* Fill Port structure with info from RPC service creation*/
  264.     receiver->transport->xp_port;
  265.   receiver->receivePort.hostName = strdup("localhost");
  266.   receiver->receiveSocket = receiver->transport->xp_sock;
  267.   if (SenderPortNumber(portMgrSender) != 0)                /* If the Port Manager Sender is valid, then ...*/
  268.     {                                    /* ...register with the Port Manager.*/
  269.       SenderConnectWithPortMgr(portMgrSender, &(receiver->receivePort));
  270.     }
  271.   return(receiver);
  272. }                                    /* end function NewReceiver */
  273.  
  274.  
  275.  
  276. void DestroyReceiver(Sender* portMgrSender, Receiver* receiver)
  277. {
  278.   int    result = 0;
  279.   
  280.   if (portMgrSender)                            /* Was the Sender passed in valid? */
  281.   {
  282.     result = SenderDisconnectFromPortMgr(portMgrSender,            /* Yes, tell the Port Manager "I'm outtahere" */
  283.                      &(receiver->receivePort));
  284.     if (result != 0)
  285.       perror("MAEstro Protocol: Could not successfully disconnect from the Port Manager.");
  286.   }
  287.   svc_destroy(receiver->transport);                    /* Destroy the RPC service data structures */
  288.   if (receiver->receivePort.appName != (char*)NULL)            /* Free space taken by Port fields.  Cannot use... */
  289.     free(receiver->receivePort.appName);                /* ...DestroyPort() here, since receiver->receivePort is... */
  290.   if (receiver->receivePort.hostName != (char*)NULL)            /* allocated at compile time (i.e., not by malloc()) */
  291.     free(receiver->receivePort.hostName);
  292.   free(receiver);                            /* Free space taken by the receiver */
  293.   return;
  294. }                                    /* end function DestroyReceiver */
  295.  
  296.  
  297.  
  298. /*******************************************************************
  299.  *    This function checks for new incoming RPC requests
  300.  *    and dispatches them.  It is meant to be used by application
  301.  *    programmers who do not have a toolkit that does automatic
  302.  *    RPC dispatching (Sun's XView toolkit does RPC dispatching
  303.  *    automatically).  If the programmer's toolkit does not support
  304.  *    RPC dispatching, the programmer should tell the toolkit to call
  305.  *    this function every so often (perhaps every second or so).
  306.  */
  307.  
  308. void ReceiverListenForMessages()
  309. {
  310.   fd_set        rpcSockets;                    /* Variable holding list of RPC sockets to listen... */
  311.                                     /* ...on.  Used as an argument to select() to determine... */
  312.                                     /* ...whether there are requests on any RPC socket ... */
  313.                                     /* ...waiting to be processed. */
  314.   int            descriptorTableSize = 0;
  315.   int            numSockets = 0;                    /* Return value from select, tells how many files had... */
  316.                                     /* ...input ready to be processed. */
  317.   struct timeval    waitTime;                    /* Used to tell select() how long to wait until it returns */
  318.   
  319.   descriptorTableSize = getdtablesize();                /* Get size of descriptor table for later use by select() */
  320.   waitTime.tv_sec = 1;                            /* Set up a timeval to wait for 1.0 seconds */
  321.   waitTime.tv_usec = 0;
  322.   rpcSockets = svc_fdset;                        /* Get the list of RPC sockets accepting requests */
  323.   numSockets = select(descriptorTableSize,                /* Check for input on RPC sockets */
  324.               &rpcSockets, (int*)0,(int*)0,            /* Only concerned with incoming stuff (see select() man page)*/
  325.               &waitTime);                    /* Tell select how long to wait (1 second, in this case) */
  326.   switch (numSockets)                            /* Based on how many sockets had input, determine what to do */
  327.     {
  328.     case -1:                                /* An error occurred */
  329.     break;                                /* For now, don't do anything */
  330.     
  331.     case 0:                                /* There was no input to process */
  332.     break;
  333.     
  334.     default:                                /* There was input to process */
  335.     svc_getreqset(&rpcSockets);                        /* Handle the incoming RPC requests */
  336.     break;
  337.     }                                    /* end switch */
  338.   return;
  339.   }                                    /* end function ReceiverListenForMessages */
  340.  
  341.  
  342.  
  343.  
  344. int ReceiverGetReceiverSocket(Receiver* receiver)
  345. {
  346.   return(receiver->receiveSocket);
  347. }                                    /* end function ReceiverGetReceiverSocket */
  348.  
  349.  
  350.  
  351. void ReceiverOpenDocument(char** docName)
  352. {
  353.   return;
  354. }
  355.  
  356.  
  357.  
  358. char** ReceiverGetCurrentDocName(void* unusedArg)
  359. {
  360.   static char*    returnVal = "NoDocument";
  361.   
  362.   return(&returnVal);
  363. }
  364.  
  365.  
  366.  
  367. MAESelection* ReceiverGetSelection(void* unusedArg)
  368. {
  369.   static MAESelection    returnVal = {0,0,0,0,"No Label"};
  370.  
  371.   return(&returnVal);
  372. }
  373.  
  374.  
  375. void ReceiverSetSelection(MAESelection* selection)
  376. {
  377.   return;
  378. }
  379.  
  380.  
  381. void ReceiverPerformSelection(void* unusedArg)
  382. {
  383.   return;
  384. }
  385.  
  386.  
  387.  
  388. void ReceiverConnectWithPortMgr(Port* app)
  389. {
  390.   return;
  391. }
  392.  
  393.  
  394.  
  395. PortArray* ReceiverGetOpenApps(void* unusedArg)
  396. {
  397.   static PortArray    returnVal;
  398.   
  399.   returnVal.portArray = (Port*) NULL;
  400.   returnVal.numberOfPorts = 0;
  401.   return(&returnVal);
  402. }
  403.  
  404.  
  405. PortArray* ReceiverGetPortFromName(Port* appPort)
  406. {
  407.   static PortArray    dummyPortArray;
  408.   
  409.   dummyPortArray.portArray = (Port*) NULL;
  410.   dummyPortArray.numberOfPorts = 0;
  411.   return(&dummyPortArray);
  412. }
  413.  
  414.  
  415. void ReceiverDisconnectFromPortMgr(Port* appPort)
  416. {
  417.   appPort->portNumber = 0;                        /* Fill in a dummy value*/
  418.   return;
  419. }
  420.  
  421.  
  422. void ReceiverPing(void* unusedArg)
  423. {
  424.   return;
  425. }
  426.  
  427.  
  428. void ReceiverHaltSelection(void* unusedArg)
  429. {
  430.   return;
  431. }
  432.  
  433.  
  434. void ReceiverPauseSelection(void* unusedArg)
  435. {
  436.   return;
  437. }
  438.  
  439.  
  440.  
  441. void ReceiverResumeSelection(void* unusedArg)
  442. {
  443.   return;
  444. }
  445.  
  446.  
  447.  
  448. void ReceiverHideApplication(void* unusedArg)
  449. {
  450.   return;
  451. }
  452.  
  453.  
  454.  
  455. void ReceiverShowApplication(void* unusedArg)
  456. {
  457.   return;
  458. }
  459.  
  460.  
  461.  
  462. IconData*    ReceiverGetAppIcon(void* unusedArg)
  463. {
  464.   static IconData    returnVal;
  465.   
  466.   returnVal.dataLength = 0;
  467.   returnVal.iconData = (char*) NULL;
  468.   return(&returnVal);
  469. }
  470.  
  471.  
  472. void ReceiverDispatchMessage(struct svc_req* requestPtr, SVCXPRT* transport)
  473. {
  474.   union
  475.     {
  476.       char*        opendocument_1_arg;
  477.       MAESelection    setselection_1_arg;
  478.       Port        connectwithportmgr_1_arg;
  479.       Port        getportfromname_1_arg;
  480.       Port        disconnectfromportmgr_1_arg;
  481.     } argument;
  482.   char*        result;
  483.   char*        (*local)();
  484.   bool_t    (*xdr_argument)();
  485.   bool_t    (*xdr_result)();
  486.   bool_t    replyResult;
  487.  
  488.   switch (requestPtr->rq_proc)                        /* Determine what procedure is being requested*/
  489.   {
  490.    case NULLPROC:
  491.     (void)svc_sendreply(transport, xdr_void, (char *)NULL);
  492.     return;
  493.     
  494.    case OpenDocumentProc:
  495.     xdr_argument = xdr_wrapstring;
  496.     xdr_result = xdr_void;
  497.     local = (char *(*)()) ReceiverDispatchTable.openDocumentPtr;
  498.     break;
  499.     
  500.    case GetCurrentDocNameProc:
  501.     xdr_argument = xdr_void;
  502.     xdr_result = xdr_wrapstring;
  503.     local = (char *(*)()) ReceiverDispatchTable.getCurrentDocNamePtr;
  504.     break;
  505.     
  506.    case GetSelectionProc:
  507.     xdr_argument = xdr_void;
  508.     xdr_result = xdr_MAESelection;
  509.     local = (char *(*)()) ReceiverDispatchTable.getSelectionPtr;
  510.     break;
  511.     
  512.    case SetSelectionProc:
  513.     xdr_argument = xdr_MAESelection;
  514.     xdr_result = xdr_void;
  515.     local = (char *(*)()) ReceiverDispatchTable.setSelectionPtr;
  516.     break;
  517.     
  518.    case PerformSelectionProc:
  519.     xdr_argument = xdr_void;
  520.     xdr_result = xdr_void;
  521.     local = (char *(*)()) ReceiverDispatchTable.performSelectionPtr;
  522.     break;
  523.     
  524.    case ConnectWithPortMgrProc:
  525.     xdr_argument = xdr_Port;
  526.     xdr_result = xdr_void;
  527.     local = (char *(*)()) ReceiverDispatchTable.connectWithPortMgrPtr;
  528.     break;
  529.     
  530.    case GetOpenAppsProc:
  531.     xdr_argument = xdr_void;
  532.     xdr_result = xdr_PortArray;
  533.     local = (char *(*)()) ReceiverDispatchTable.getOpenAppsPtr;
  534.     break;
  535.     
  536.    case GetPortFromNameProc:
  537.     xdr_argument = xdr_Port;
  538.     xdr_result = xdr_PortArray;
  539.     local = (char *(*)()) ReceiverDispatchTable.getPortFromNamePtr;
  540.     break;
  541.     
  542.    case DisconnectFromPortMgrProc:
  543.     xdr_argument = xdr_Port;
  544.     xdr_result = xdr_void;
  545.     local = (char *(*)()) ReceiverDispatchTable.disconnectFromPortMgrPtr;
  546.     break;
  547.     
  548.    case PingProc:
  549.     xdr_argument = xdr_void;
  550.     xdr_result = xdr_void;
  551.     local = (char *(*)()) ReceiverDispatchTable.pingPtr;
  552.     break;
  553.     
  554.    case HaltSelectionProc:
  555.     xdr_argument = xdr_void;
  556.     xdr_result = xdr_void;
  557.     local = (char *(*)()) ReceiverDispatchTable.haltSelectionPtr;
  558.     break;
  559.     
  560.    case PauseSelectionProc:
  561.     xdr_argument = xdr_void;
  562.     xdr_result = xdr_void;
  563.     local = (char *(*)()) ReceiverDispatchTable.pauseSelectionPtr;
  564.     break;
  565.     
  566.    case ResumeSelectionProc:
  567.     xdr_argument = xdr_void;
  568.     xdr_result = xdr_void;
  569.     local = (char *(*)()) ReceiverDispatchTable.resumeSelectionPtr;
  570.     break;
  571.     
  572.    case HideApplicationProc:
  573.     xdr_argument = xdr_void;
  574.     xdr_result = xdr_void;
  575.     local = (char *(*)()) ReceiverDispatchTable.hideApplicationPtr;
  576.     break;
  577.     
  578.    case ShowApplicationProc:
  579.     xdr_argument = xdr_void;
  580.     xdr_result = xdr_void;
  581.     local = (char *(*)()) ReceiverDispatchTable.showApplicationPtr;
  582.     break;
  583.     
  584.    case GetAppIconProc:
  585.     xdr_argument = xdr_void;
  586.     xdr_result = xdr_IconData;
  587.     local = (char *(*)()) ReceiverDispatchTable.getAppIconPtr;
  588.     break;
  589.     
  590.    default:
  591.     svcerr_noproc(transport);
  592.     return;
  593.   }                                    /* end switch (requestPtr->rq_proc)*/
  594.   bzero((void *)&argument, sizeof(argument));
  595.   if (!svc_getargs(transport, xdr_argument, (char*)&argument))
  596.     {
  597.       svcerr_decode(transport);                        /* Determine if there were errors retrieving the argument*/
  598.       return;
  599.     }
  600.   result = (*local)(&argument, requestPtr);                /* Call the function requested*/
  601.   if (result != NULL ||                            /* Determine whether there's a reply to send; if a result... */
  602.       xdr_result == xdr_void)                        /* ...was returned, or if the called function returns... */
  603.     replyResult = svc_sendreply(transport, xdr_result, result);        /* ...void, then try to reply to the remote procedure caller */
  604.   else                                    /* If this stmt is reached, then result must've been NULL... */
  605.     {                                    /* ...and xdr_result was supposed to return data, not... */
  606.     if (result == NULL)                            /* ...just NULL.  This shouldn't happen, and is an error. */
  607.       printf("Message was received but there was an error performing the message.\n");
  608.     return;
  609.     }
  610.   if (replyResult == FALSE)                        /* Was the reply done, and Did it succeed? */
  611.     {
  612.     svcerr_systemerr(transport);                    /* No, report an error */
  613.     printf("There was an error performing a received message.\n");
  614.     }
  615.   if (!svc_freeargs(transport, xdr_argument, (char*)&argument))        /* Free space taken by the function argument*/
  616.     {
  617.     (void)fprintf(stderr, "unable to free arguments\n");
  618.     }
  619. }                                    /* end ReceiverDispatchMessage*/
  620.