home *** CD-ROM | disk | FTP | other *** search
/ Mega CD-ROM 1 / megacd_rom_1.zip / megacd_rom_1 / DESQVIEW / API_EXAM.ZIP / SERVER.C < prev    next >
Text File  |  1988-04-28  |  10KB  |  331 lines

  1. /****************************************************************
  2. *
  3. *  Name:          SERVER
  4. *
  5. *  Function:      This program provides a very simple file 
  6. *                 management service.  It maintains a database 
  7. *                 consisting of arbitrary length text strings and 
  8. *                 allows the database to be queried for all 
  9. *                 records containing a specified substring.  
  10. *                 Queries are sent by mail from REQUEST windows.  
  11. *                 The results are returned to the REQUESTers 
  12. *                 mailbox. 
  13. *
  14. *  Shows how to:  1. use named mailboxes to detect multiple 
  15. *                    instances of the same program.
  16. *                 2. use named mailboxes to control access to 
  17. *                    public utilities.          
  18. *                 3. send and receive mail.
  19. *                 4. use a timer object to display a running clock.
  20. *                 5. optimize a program by performing the equivalent
  21. *                    of multiple C library calls in one encoded stream.
  22. *
  23. ****************************************************************/
  24.  
  25. #include <stdio.h>
  26. #include <malloc.h>
  27. #include <memory.h>
  28. #include <string.h>
  29. #include "dvapi.h"
  30.  
  31. /* minimum required API version */
  32. #define required 0x201
  33.  
  34. /* public name of file server mailbox */
  35. char mbname[] = "Example File Server";
  36. int lmbname = sizeof(mbname);
  37.  
  38. /* status values for messages to server */
  39. #define LOGON           1
  40. #define LOGOFF          2
  41. #define ADDREC          3
  42. #define QUERY           4
  43.  
  44. /* status values for messages from server */
  45. #define LOGGED_ON       1
  46. #define LOGGED_OFF      2
  47. #define READY           3
  48. #define FOUND           4
  49.  
  50. /* object handles */
  51. ulong win,kbd,mal,tim,obj,sender,hisbox;
  52.  
  53. /* variables used when reading mail */
  54. char *mptr;
  55. int  mlng,status;
  56.  
  57. /* other variables */
  58. int  version,k;
  59. int nusers = 0;
  60. unsigned int nqueries = 0;
  61.  
  62. /* format of database records */
  63. struct record {
  64.   struct record *link;
  65.   int  lng;
  66.   char data[1];
  67.   };
  68.  
  69. /* database queue pointers */
  70. struct record *head = NULL;
  71. struct record *tail = NULL;
  72. struct record *newrec = NULL;
  73.  
  74. /* contents of server window */
  75. char menu1[] = "\
  76.   FILE SERVER                Users = 0    Queries = 0      \n\
  77. ───────────────────────────────────────────────────────────\n\
  78.  This program provides a VERY simple data management       \n\
  79.  service.  You access the service by running one or more   \n\
  80.  REQUEST windows.  These windows can add records to the    \n\
  81.  data base in the form of arbitrary text strings.  They    \n\
  82.  can then query the data base by asking for all records    \n\
  83.  containing a specified string.";
  84.  
  85.  
  86. /* field table for server window */
  87. char ftab1[] = {ftab(4,FTH_NODATA,0,0,9,2),
  88.                      0,1,0,13,FTE_OUTPUT,0,0,0,
  89.                      0,17,0,24,FTE_OUTPUT,0,0,0,
  90.                      0,37,0,38,FTE_OUTPUT,0,0,0,
  91.                      0,52,0,57,FTE_OUTPUT,0,0,0,
  92.                      };
  93.  
  94. /* initial "canned" database contents */
  95. #define ncanned 3
  96. char *canned[ncanned] = {
  97.   "a stitch in time saves nine.",
  98.   "time, time, time, see what's become of me.",
  99.   "time is money."
  100.   };
  101.  
  102.  
  103. /**********************************************************************
  104. *  main  -  check for DESQview present and enable required extensions.
  105. ***********************************************************************/
  106.  
  107. main () {
  108.   /* initialize C interfaces and get API version number */
  109.   version = api_init();
  110.  
  111.   /* if DESQview is not running or version is too low, display a message */ 
  112.   if (version < required) {
  113.     printf ("This program requires DESQview version %d.02%d or later.\n",
  114.              required/256,required%256);
  115.     }
  116.  
  117.   /* tell DESQview what extensions to enable and start application */
  118.   else {
  119.     api_level (required);
  120.     program_body();
  121.     }
  122.  
  123.   /* disable C interfaces and return from program */
  124.   api_exit();
  125.   }
  126.  
  127.  
  128. /*********************************************************************
  129. /*  program_body  -  initialize and loop waiting for input events.
  130. /*********************************************************************/
  131.  
  132. program_body () {
  133.   /* get default handles and create a timer object */
  134.   win = win_me();
  135.   kbd = key_me();
  136.   mal = mal_me();  
  137.   tim = tim_new();
  138.  
  139.   /* add canned records to database */
  140.   build_data_base();
  141.  
  142.   /* set logical attributes and clear window */
  143.   win_stream (win,"\x1B\x00\x04\x00\xDA\xE2\x01\xE3");
  144.       /*  the stream above is equivalent to:
  145.       win_logattr (win,1);
  146.       win_attr (win,1);
  147.       win_erase (win);
  148.       */
  149.  
  150.   /* write the contents and field table to the window */
  151.   win_swrite (win,menu1);
  152.   win_stream (win,ftab1);
  153.  
  154.   /* highlight field 1, reposition and display window */
  155.   win_stream (win,
  156.     "\x1B\x00\x0D\x00\xF2\x01\x09\xC4\x00\x00\xC3\x08\x3B\xC2\x01\x0A\xE4");
  157.       /* the stream above is equivalent to:
  158.       fld_attr (win,1,9);
  159.       win_origin (win,0,0);
  160.       win_resize (win,8,59);
  161.       win_move (win,1,10);
  162.       win_redraw (win);
  163.       */  
  164.  
  165.   /* close the task's keyboard object to inhibit keyboard input */
  166.   key_close (kbd);
  167.  
  168.   /* open the objectq and start clock timer */
  169.   obq_open();
  170.   tim_addto (tim,1L);
  171.  
  172.   /* assign global name.  Abort if a file server is already running */
  173.   api_beginc();
  174.   if (mal_find(mbname,lmbname) != 0) return;
  175.   mal_name (mal,mbname,lmbname);
  176.   api_endc();
  177.  
  178.   /* loop until the window is closed */
  179.   while (1) {
  180.  
  181.     /* wait for an object to produce input and process it */
  182.     obj = obq_read();
  183.     if (obj == tim) process_timer_event();
  184.     else
  185.     if (obj == mal) process_mail_event();
  186.     };
  187.   }
  188.  
  189.  
  190. /*********************************************************************
  191. /*  build_data_base  -  put canned records containing "time" into database.
  192. /*********************************************************************/
  193.  
  194. build_data_base () {
  195.   int i;
  196.   for (i=0; i<ncanned; i++) {
  197.     mptr = canned[i];
  198.     mlng = strlen(canned[i]);
  199.     add_record();
  200.     }
  201.   }
  202.  
  203.  
  204. /*********************************************************************
  205. /*  process_timer_event  -  update the time in field 2.
  206. /*********************************************************************/
  207.  
  208. process_timer_event () {
  209.   int hr,mn,sc;
  210.   long ltime;
  211.  
  212.   /* find out what time the timer expired and restart timer for 1 second */ 
  213.   ltime = tim_read (tim);
  214.   tim_addto (tim,100L);
  215.  
  216.   /* compute the hour, minute, and second */
  217.   hr = (int)(ltime / 360000);
  218.   mn = (int)((ltime / 6000) % 60);
  219.   sc = (int)((ltime / 100) % 60);
  220.  
  221.   /* write the time to field 2 */
  222.   fld_cursor (win,2);
  223.   win_printf (win,"%02d:%02d:%02d",hr,mn,sc);
  224.   }
  225.  
  226.  
  227. /*********************************************************************
  228. /*  process_mail_event  -  read mail and dispatch by status value.
  229. /*********************************************************************/
  230.  
  231. process_mail_event () {
  232.   /* read a message and its status from the mailbox */
  233.   status = mal_read (mal,&mptr,&mlng);
  234.  
  235.   /* determine which task sent the message and get its mailbox */
  236.   sender = mal_addr (mal);
  237.   hisbox = mal_of (sender);
  238.  
  239.   /* dispatch based on the message status */
  240.   switch (status) {
  241.  
  242.     /* increment user count and send ACK */
  243.     case LOGON:  set_users (nusers+1);
  244.                  mal_addto (hisbox,NULL,0,LOGGED_ON);
  245.                  break;
  246.  
  247.     /* decrement user count and send ACK */
  248.     case LOGOFF: set_users (nusers-1);
  249.                  mal_addto (hisbox,NULL,0,LOGGED_OFF);
  250.                  break;
  251.  
  252.     /* add new record to the database */
  253.     case ADDREC: add_record();
  254.                  mal_addto (hisbox,NULL,0,READY);
  255.                  break;
  256.  
  257.     /* find specified records in the database */
  258.     case QUERY:  find_records();
  259.                  fld_cursor (win,4);
  260.                  win_printf (win,"%-6u",++nqueries);
  261.                  mal_addto (hisbox,NULL,0,READY);
  262.                  break;
  263.     default: win_disperor (win," Invalid message received ",26,1,26,1,0); 
  264.     }
  265.   }
  266.  
  267.  
  268. /*********************************************************************
  269. /*  set_users  -  update user count and (dis)allow CLOSE as needed.
  270. /*********************************************************************/
  271.  
  272. set_users (newval) int newval; {
  273.   /* display new user count */
  274.   fld_cursor (win,3);
  275.   win_printf (win,"%-2d",nusers=newval);
  276.  
  277.   /* disallow closing of server if there are active users */
  278.   if (nusers == 0)
  279.     win_allow (win,ALW_CLOSE);
  280.   else
  281.     win_disallow (win,ALW_CLOSE);
  282.   }
  283.  
  284.  
  285. /*********************************************************************
  286. /*  add_record  -  add a record to the database.
  287. /*********************************************************************/
  288.  
  289. add_record () {
  290.   /* allocate room for new record - ignore if no room left */
  291.   newrec = (struct record *)malloc(mlng+sizeof(struct record));
  292.   if (newrec == NULL) return;
  293.  
  294.   /* copy message into new record and link into database */
  295.   memcpy (newrec->data,mptr,mlng);  
  296.   newrec->lng  = mlng;
  297.   newrec->link = NULL;
  298.   tail->link = newrec;
  299.   tail = newrec;
  300.   if (head == NULL) head = newrec;
  301.   }
  302.  
  303.  
  304. /*********************************************************************
  305. /*  find_records  -  send all records containing search string to the caller.
  306. /*********************************************************************/
  307.  
  308. find_records () {
  309.   struct record *rec;
  310.  
  311.   /* walk through database until a NULL link is found */ 
  312.   rec = head;
  313.   while (rec != NULL) {
  314.  
  315.     /* if the record contains the search string, send it to caller */
  316.     if (strstr(rec->data,mptr) != NULL) 
  317.       mal_addto (hisbox,rec->data,rec->lng,FOUND);
  318.  
  319.     /* walk to next record */
  320.     rec = rec->link;
  321.     }
  322.   }
  323.   
  324.         
  325.  
  326.  
  327.  
  328.  
  329.  
  330.  
  331.