home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / games / volume2 / nchess / part03 / daemon.c < prev    next >
C/C++ Source or Header  |  1987-11-25  |  5KB  |  168 lines

  1. /*
  2.  * Copyright 1987 Tom Anderson; 20831 Frank Waters Road;
  3.  * Stanwood, WA  98282.   All rights reserved.
  4.  */
  5.  
  6. /*
  7.  * chess invitation rendezvous server
  8.  *
  9.  * there are three entry points: 
  10.  *     - request a game 
  11.  *    - reply to a request
  12.  *    - cancel a request
  13.  */
  14.  
  15. #include <stdio.h>
  16. #include <rpc/rpc.h>
  17. #include <sys/time.h>
  18. #include <strings.h>
  19.  
  20. #include "nchess.h"
  21.  
  22. char LocalHostName[256];        /* local host name string */
  23.  
  24. #define    MAXINVITES    32
  25. typedef struct {            /* registered invitations with call-back information */
  26.     GameRequest gr;            /* call-back information */
  27.     BOOL active;            /* is this slot active? */
  28.     unsigned long time;            /* time invitation was registered */
  29. } Invitation;
  30.  
  31. Invitation Invitations[MAXINVITES];
  32.  
  33. /*
  34.  * register a game invitation and print a message on the console.
  35.  */
  36. void
  37. gameRequest(gameReq)
  38.     GameRequest * gameReq;
  39. {
  40.     struct timeval tv;
  41.     struct tm * timep;
  42.     register int i, oldSlot, oldTime;
  43.     register Invitation * invp;
  44.     int avail = -1;
  45.     FILE * console;
  46.  
  47.  
  48.     (void) gettimeofday(&tv, (struct timezone *) 0);
  49.     timep = localtime((long *) &tv.tv_sec);
  50.     oldTime = tv.tv_sec;
  51.     /* find an empty invitation slot, keeping track of the oldest active one */
  52.     for (i = 0 ; i < MAXINVITES ; i++) {
  53.     invp = &Invitations[i];
  54.     if ( ! invp->active) {
  55.         avail = i;
  56.         break;
  57.     } else if (invp->time < oldTime) {
  58.         oldSlot = i;
  59.         oldTime = invp->time;
  60.     }
  61.     }
  62.     /* if no slots are empty, re-use the oldest one */
  63.     if (avail < 0) 
  64.     avail = oldSlot;
  65.     /* fill out the invitation slot */
  66.     invp = &Invitations[avail];
  67.     invp->active = TRUE;
  68.     invp->time = tv.tv_sec;
  69.     invp->gr.progNum = gameReq->progNum;
  70.     invp->gr.color = gameReq->color;
  71.     invp->gr.resumeGame = gameReq->resumeGame;
  72.     strncpy(invp->gr.hostName, gameReq->hostName, sizeof(gameReq->hostName));
  73.     strncpy(invp->gr.userName, gameReq->userName, sizeof(gameReq->userName));
  74.     /* 
  75.      * print the invitation message on the local console 
  76.      */
  77.     if ((console = fopen("/dev/console", "w")) != (FILE *) 0) {
  78.     fprintf(console, "\n\007\007\007Message from Chess Daemon@%s at %d:%02d ...\n", 
  79.         LocalHostName, timep->tm_hour, timep->tm_min);
  80.     if (gameReq->resumeGame) 
  81.         fprintf(console, "%s wants to resume a game of chess.\n", 
  82.         gameReq->userName);
  83.     else
  84.         fprintf(console, "%s wants to play a game of chess.\n", 
  85.         gameReq->userName);
  86.     fprintf(console, "reply with: nchess %s@%s\n", 
  87.         gameReq->userName, gameReq->hostName);
  88.     fflush (console);
  89.     fclose(console);
  90.     }
  91. }
  92.  
  93. /*
  94.  * attempt to respond to a game invitation 
  95.  */
  96. GameRequest *
  97. gameAcknowledge(gameAck)
  98.     GameRequest * gameAck;
  99. {
  100.     static GameRequest gr;
  101.     register int i, newestTime = 0, newestIndex = -1;
  102.     
  103.     /* 
  104.      * look for the most recently registered invitation
  105.      * if one exists, return the prog. number and the color,
  106.      *        then remove the entry.
  107.      * else return an entry with a program number of zero.
  108.      */
  109.     gr.progNum = 0;
  110.     for (i = 0 ; i < MAXINVITES && Invitations[i].active ; i++) {
  111.     if (strcmp(Invitations[i].gr.hostName, gameAck->hostName) == 0
  112.     && strcmp(Invitations[i].gr.userName, gameAck->userName) == 0
  113.     && Invitations[i].time > newestTime) {
  114.         newestIndex = i;
  115.         newestTime = Invitations[i].time;
  116.     }
  117.     }
  118.     if (newestIndex >= 0) {
  119.     gr.progNum = Invitations[newestIndex].gr.progNum;
  120.     gr.color = Invitations[newestIndex].gr.color;
  121.     gr.resumeGame = Invitations[newestIndex].gr.resumeGame;
  122.     Invitations[newestIndex].active = FALSE;
  123.     }
  124.     return(&gr);
  125. }
  126.  
  127. /*
  128.  * cancel a game invitation 
  129.  */
  130. void
  131. cancelRequest(gr)
  132.     GameRequest * gr;
  133. {
  134.     register int i;
  135.     
  136.     for (i = 0 ; i < MAXINVITES && Invitations[i].active ; i++) {
  137.     if (strcmp(Invitations[i].gr.hostName, gr->hostName) == 0
  138.     && strcmp(Invitations[i].gr.userName, gr->userName) == 0
  139.     && Invitations[i].gr.progNum == gr->progNum) {
  140.         Invitations[i].active = FALSE;
  141.         break;
  142.     }
  143.     }
  144. }
  145.  
  146. /*ARGSUSED*/
  147. main(argc, argv)
  148.     int argc;
  149.     char ** argv;
  150. {
  151.     if (gethostname(LocalHostName, sizeof(LocalHostName)) != 0) {
  152.     fprintf(stderr, "%s: can't determine the local host name\n", argv[0]);
  153.     exit(1);
  154.     }
  155.     pmap_unset(SERVERPROGNUM, VERSNUM);
  156.     /* register the entry points */
  157.     registerrpc(SERVERPROGNUM, VERSNUM, REQPROCNUM, 
  158.     gameRequest, XdrGameReq, xdr_void);
  159.     registerrpc(SERVERPROGNUM, VERSNUM, ACKPROCNUM, 
  160.     gameAcknowledge, XdrGameReq, XdrGameReq);
  161.     registerrpc(SERVERPROGNUM, VERSNUM, CANCELPROCNUM, 
  162.     cancelRequest, XdrGameReq, xdr_void);
  163.     svc_run();
  164.     fprintf(stderr, "%s: exiting - svc_run returned\n", argv[0]);
  165.     exit(1);
  166. }
  167.  
  168.