home *** CD-ROM | disk | FTP | other *** search
- /****************************************************************
- *
- * Name: SERVER
- *
- * Function: This program provides a very simple file
- * management service. It maintains a database
- * consisting of arbitrary length text strings and
- * allows the database to be queried for all
- * records containing a specified substring.
- * Queries are sent by mail from REQUEST windows.
- * The results are returned to the REQUESTers
- * mailbox.
- *
- * Shows how to: 1. use named mailboxes to detect multiple
- * instances of the same program.
- * 2. use named mailboxes to control access to
- * public utilities.
- * 3. send and receive mail.
- * 4. use a timer object to display a running clock.
- * 5. optimize a program by performing the equivalent
- * of multiple C library calls in one encoded stream.
- *
- ****************************************************************/
-
- #include <stdio.h>
- #include <malloc.h>
- #include <memory.h>
- #include <string.h>
- #include "dvapi.h"
-
- /* minimum required API version */
- #define required 0x201
-
- /* public name of file server mailbox */
- char mbname[] = "Example File Server";
- int lmbname = sizeof(mbname);
-
- /* status values for messages to server */
- #define LOGON 1
- #define LOGOFF 2
- #define ADDREC 3
- #define QUERY 4
-
- /* status values for messages from server */
- #define LOGGED_ON 1
- #define LOGGED_OFF 2
- #define READY 3
- #define FOUND 4
-
- /* object handles */
- ulong win,kbd,mal,tim,obj,sender,hisbox;
-
- /* variables used when reading mail */
- char *mptr;
- int mlng,status;
-
- /* other variables */
- int version,k;
- int nusers = 0;
- unsigned int nqueries = 0;
-
- /* format of database records */
- struct record {
- struct record *link;
- int lng;
- char data[1];
- };
-
- /* database queue pointers */
- struct record *head = NULL;
- struct record *tail = NULL;
- struct record *newrec = NULL;
-
- /* contents of server window */
- char menu1[] = "\
- FILE SERVER Users = 0 Queries = 0 \n\
- ───────────────────────────────────────────────────────────\n\
- This program provides a VERY simple data management \n\
- service. You access the service by running one or more \n\
- REQUEST windows. These windows can add records to the \n\
- data base in the form of arbitrary text strings. They \n\
- can then query the data base by asking for all records \n\
- containing a specified string.";
-
-
- /* field table for server window */
- char ftab1[] = {ftab(4,FTH_NODATA,0,0,9,2),
- 0,1,0,13,FTE_OUTPUT,0,0,0,
- 0,17,0,24,FTE_OUTPUT,0,0,0,
- 0,37,0,38,FTE_OUTPUT,0,0,0,
- 0,52,0,57,FTE_OUTPUT,0,0,0,
- };
-
- /* initial "canned" database contents */
- #define ncanned 3
- char *canned[ncanned] = {
- "a stitch in time saves nine.",
- "time, time, time, see what's become of me.",
- "time is money."
- };
-
-
- /**********************************************************************
- * main - check for DESQview present and enable required extensions.
- ***********************************************************************/
-
- main () {
- /* initialize C interfaces and get API version number */
- version = api_init();
-
- /* if DESQview is not running or version is too low, display a message */
- if (version < required) {
- printf ("This program requires DESQview version %d.02%d or later.\n",
- required/256,required%256);
- }
-
- /* tell DESQview what extensions to enable and start application */
- else {
- api_level (required);
- program_body();
- }
-
- /* disable C interfaces and return from program */
- api_exit();
- }
-
-
- /*********************************************************************
- /* program_body - initialize and loop waiting for input events.
- /*********************************************************************/
-
- program_body () {
- /* get default handles and create a timer object */
- win = win_me();
- kbd = key_me();
- mal = mal_me();
- tim = tim_new();
-
- /* add canned records to database */
- build_data_base();
-
- /* set logical attributes and clear window */
- win_stream (win,"\x1B\x00\x04\x00\xDA\xE2\x01\xE3");
- /* the stream above is equivalent to:
- win_logattr (win,1);
- win_attr (win,1);
- win_erase (win);
- */
-
- /* write the contents and field table to the window */
- win_swrite (win,menu1);
- win_stream (win,ftab1);
-
- /* highlight field 1, reposition and display window */
- win_stream (win,
- "\x1B\x00\x0D\x00\xF2\x01\x09\xC4\x00\x00\xC3\x08\x3B\xC2\x01\x0A\xE4");
- /* the stream above is equivalent to:
- fld_attr (win,1,9);
- win_origin (win,0,0);
- win_resize (win,8,59);
- win_move (win,1,10);
- win_redraw (win);
- */
-
- /* close the task's keyboard object to inhibit keyboard input */
- key_close (kbd);
-
- /* open the objectq and start clock timer */
- obq_open();
- tim_addto (tim,1L);
-
- /* assign global name. Abort if a file server is already running */
- api_beginc();
- if (mal_find(mbname,lmbname) != 0) return;
- mal_name (mal,mbname,lmbname);
- api_endc();
-
- /* loop until the window is closed */
- while (1) {
-
- /* wait for an object to produce input and process it */
- obj = obq_read();
- if (obj == tim) process_timer_event();
- else
- if (obj == mal) process_mail_event();
- };
- }
-
-
- /*********************************************************************
- /* build_data_base - put canned records containing "time" into database.
- /*********************************************************************/
-
- build_data_base () {
- int i;
- for (i=0; i<ncanned; i++) {
- mptr = canned[i];
- mlng = strlen(canned[i]);
- add_record();
- }
- }
-
-
- /*********************************************************************
- /* process_timer_event - update the time in field 2.
- /*********************************************************************/
-
- process_timer_event () {
- int hr,mn,sc;
- long ltime;
-
- /* find out what time the timer expired and restart timer for 1 second */
- ltime = tim_read (tim);
- tim_addto (tim,100L);
-
- /* compute the hour, minute, and second */
- hr = (int)(ltime / 360000);
- mn = (int)((ltime / 6000) % 60);
- sc = (int)((ltime / 100) % 60);
-
- /* write the time to field 2 */
- fld_cursor (win,2);
- win_printf (win,"%02d:%02d:%02d",hr,mn,sc);
- }
-
-
- /*********************************************************************
- /* process_mail_event - read mail and dispatch by status value.
- /*********************************************************************/
-
- process_mail_event () {
- /* read a message and its status from the mailbox */
- status = mal_read (mal,&mptr,&mlng);
-
- /* determine which task sent the message and get its mailbox */
- sender = mal_addr (mal);
- hisbox = mal_of (sender);
-
- /* dispatch based on the message status */
- switch (status) {
-
- /* increment user count and send ACK */
- case LOGON: set_users (nusers+1);
- mal_addto (hisbox,NULL,0,LOGGED_ON);
- break;
-
- /* decrement user count and send ACK */
- case LOGOFF: set_users (nusers-1);
- mal_addto (hisbox,NULL,0,LOGGED_OFF);
- break;
-
- /* add new record to the database */
- case ADDREC: add_record();
- mal_addto (hisbox,NULL,0,READY);
- break;
-
- /* find specified records in the database */
- case QUERY: find_records();
- fld_cursor (win,4);
- win_printf (win,"%-6u",++nqueries);
- mal_addto (hisbox,NULL,0,READY);
- break;
- default: win_disperor (win," Invalid message received ",26,1,26,1,0);
- }
- }
-
-
- /*********************************************************************
- /* set_users - update user count and (dis)allow CLOSE as needed.
- /*********************************************************************/
-
- set_users (newval) int newval; {
- /* display new user count */
- fld_cursor (win,3);
- win_printf (win,"%-2d",nusers=newval);
-
- /* disallow closing of server if there are active users */
- if (nusers == 0)
- win_allow (win,ALW_CLOSE);
- else
- win_disallow (win,ALW_CLOSE);
- }
-
-
- /*********************************************************************
- /* add_record - add a record to the database.
- /*********************************************************************/
-
- add_record () {
- /* allocate room for new record - ignore if no room left */
- newrec = (struct record *)malloc(mlng+sizeof(struct record));
- if (newrec == NULL) return;
-
- /* copy message into new record and link into database */
- memcpy (newrec->data,mptr,mlng);
- newrec->lng = mlng;
- newrec->link = NULL;
- tail->link = newrec;
- tail = newrec;
- if (head == NULL) head = newrec;
- }
-
-
- /*********************************************************************
- /* find_records - send all records containing search string to the caller.
- /*********************************************************************/
-
- find_records () {
- struct record *rec;
-
- /* walk through database until a NULL link is found */
- rec = head;
- while (rec != NULL) {
-
- /* if the record contains the search string, send it to caller */
- if (strstr(rec->data,mptr) != NULL)
- mal_addto (hisbox,rec->data,rec->lng,FOUND);
-
- /* walk to next record */
- rec = rec->link;
- }
- }
-
-
-
-
-
-
-
-