home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 164.lha / IPC / DemoSources / MinClient.c < prev    next >
C/C++ Source or Header  |  1988-04-28  |  11KB  |  307 lines

  1. /************************************************************
  2.  *                                                          *
  3.  *        Minimal Print server Client Demo for IPC          *
  4.  *                                                          *
  5.  *                Pete Goodeve 88:7:25                      *
  6.  *                                                          *
  7.  *  [This module has only been compiled under Lattice;      *
  8.  *   it will need some modification for Manx/Aztec]         *
  9.  *                                                          *
  10.  *                                                          *
  11.  *  This is a simple test module for the "Print Format"     *
  12.  *  server.  When you type the return key, it generates     *
  13.  *  a message with a set of items in various formats,       *
  14.  *  and sends it to the print server. (For test purposes    *
  15.  *  the items are fixed.)  If you simply type a return,     *
  16.  *  the formatted string generated from the message is      *
  17.  *  displayed in the print server's own window; if you      *
  18.  *  type an 'F' before the return, a file handle to this    *
  19.  *  Client program's console window is passed in the        *
  20.  *  message and the string will be output to this instead;  *
  21.  *  if you type an 'M' before the return, the string will   *
  22.  *  be passed back in the reply message and again shown     *
  23.  *  in the Client's console window.                         *
  24.  *                                                          *
  25.  *  Typing 'Q' will send a 'QUIT' message to the server     *
  26.  *  instead of a print request.  To exit the client         *
  27.  *  program type an 'end-of-file' (cntrl-'\'); the          *
  28.  *  print server is currently programmed to exit also       *
  29.  *  when there are no running clients left.                 *
  30.  *                                                          *
  31.  *  It is a simple "synchronous" client: when it sends a    *
  32.  *  message it waits for the reply before continuing        *
  33.  *  (unlike others that may continue with other activities  *
  34.  *  while the server is processing a message).  The main    *
  35.  *  loop is simple:                                         *
  36.  *                                                          *
  37.  *          Wait for keyboard command                       *
  38.  *          Send message                                    *
  39.  *          Wait for reply                                  *
  40.  *          Display string from reply if supplied           *
  41.  *          Loop to wait for keyboard again.                *
  42.  *                                                          *
  43.  *                                                          *
  44.  ************************************************************/
  45.  
  46. #include "IPC.h"
  47. #include "exec/memory.h"
  48.  
  49. #define LINESZ 120
  50. #define SHOWREAL 1
  51.  
  52. /*
  53.  *  Define the ID codes recognized by the print format server
  54.  *
  55.  *  (MAKE_ID is defined in IPC.h)
  56.  */
  57.  
  58. /* Message IDs: */
  59. #define CNVA  MAKE_ID('C','N','V','A')
  60.     /* CoNVert to Ascii */
  61. #define QUIT  MAKE_ID('Q','U','I','T')
  62.  
  63. /* Item IDs: */
  64. #define RETS  MAKE_ID('R','E','T','S')
  65.     /* RETurn String */
  66.  
  67. #define FILH  MAKE_ID('F','I','L','H')
  68.     /* FILe Handle */
  69.  
  70.  
  71. #define PATS  MAKE_ID('P','A','T','S')
  72.     /* PATtern String */
  73.  
  74. #define PAT1  MAKE_ID('P','A','T','1')
  75.     /* PATtern -- 1 item */
  76.  
  77. #define LINE  MAKE_ID('L','I','N','E')
  78.     /* indicates a complete line of text -- omitting newline */
  79.  
  80. #define TEXT  MAKE_ID('T','E','X','T')
  81.     /* Text block -- may include newlines */
  82.  
  83. #define STRG  MAKE_ID('S','T','R','G')
  84.     /* general non-specific ASCII STRinG */
  85.  
  86.     /* The above three categories are treated identically by Pserver
  87.        -- they may have distinct meanings to other servers */
  88.  
  89. #define CHAR  MAKE_ID('C','H','A','R')
  90.     /* A single character in L.S byte of ii_Ptr */
  91.  
  92. #define INTG  MAKE_ID('I','N','T','G')
  93.     /* A 32-bit INTeGer in ii_Ptr */
  94.  
  95. #define REAL  MAKE_ID('R','E','A','L')
  96.     /* A 32-bit floating point value in ii_Ptr (care in conversion!) */
  97.  
  98.  
  99. /*******************
  100. rather than the above if you prefer, with Lattice 4.0 you can simply
  101. use 4-character constants as in the following (compile with the -cm option):
  102.  
  103. #define CNVA 'CNVA'
  104. #define QUIT 'QUIT'
  105.  
  106. #define RETS 'RETS'
  107. #define FILH 'FILH'
  108.  
  109. #define PATS 'PATS'
  110. #define PAT1 'PAT1'
  111. #define LINE 'LINE'
  112. #define TEXT 'TEXT'
  113. #define STRG 'STRG'
  114. #define CHAR 'CHAR'
  115. #define INTG 'INTG'
  116. #define REAL 'REAL'
  117. *********************/
  118.  
  119.  
  120. struct IPCPort *port=NULL; /* will point to server port */
  121. struct MsgPort *rport=NULL; /* where we get our replies */
  122. struct IPCMessage *imsg=NULL; /* this one message is used repeatedly */
  123.  
  124. struct MsgPort * CreatePort(char *, int);
  125. ULONG Output();
  126.  
  127. void Cleanup();
  128. void outputstr(char *);
  129.  
  130.  
  131. /***************************
  132.  *
  133.  *  Main program entry point:
  134.  *
  135.  *  -- Note that to save overhead we use '_main'; you should also compile
  136.  *  (under Lattice) using the -v switch, to suppress stack checking and
  137.  *  the associated baggage.
  138.  *
  139.  *  We avoid using any C level I/O also -- just AmigaDOS calls, so we
  140.  *  dont need <stdio.h>.
  141.  */
  142.  
  143. void _main()
  144. {
  145.     struct IPCItem *item, *item0; /* pointers to access message items */
  146.  
  147.     int count=0; /* dummy value used to stuff into message */
  148.     float realcount=0.0; /* -- ditto */
  149.  
  150.     char tbuf[22]; /* keyboard input dumped in here */
  151.  
  152.  
  153.     /* First we set up our ports: */
  154.  
  155.     port = GetIPCPort("Print_Format");
  156.     if (!port) _exit(20);
  157.  
  158.     rport = CreatePort(NULL,0);
  159.     if (!rport) {Cleanup(); _exit(21);}
  160.  
  161.     /* ... then make a message block */
  162.     imsg = CreateIPCMsg(20,0,rport); /* large enough for playing with... */
  163.     if (!imsg) {Cleanup(); _exit(22);}
  164.  
  165.     item0 = &imsg->ipc_Items[0]; /* a convenient permanent reference */
  166.  
  167.  
  168.     /* The main program loop:
  169.      * -- continues until told to quit by end-of-file (ctrl-\)
  170.      */
  171.     while (1) {
  172.         item = item0; /* reset item pointer */
  173.         imsg->ipc_Id = CNVA; /* only message ID needed (except QUIT) */
  174.             /*
  175.              * Initially we assume that the first item will be a slot
  176.              * in which the server will return the formatted string.
  177.              * This will be overwritten if another option is chosen
  178.              */
  179.         item->ii_Id = RETS;
  180.         item->ii_Ptr = NULL; /* The server will provide the data block */
  181.         item->ii_Size = 0;
  182.         item->ii_Flags = imsg->ipc_Flags = 0;
  183.  
  184.         /* get keyboard input (terminated by return): */
  185.         /* E-O-F returns a length of zero, causing break from loop */
  186.         if (Read(Input(), tbuf, 21) <= 0) break;
  187.  
  188.         /*
  189.          * decode first character of input to decide action
  190.          *  (sorry about the crudity... but it suffices)
  191.          */
  192.         switch(*tbuf) {
  193.         case 'Q':   /* Send a QUIT message */
  194.         case 'q':
  195.         case '.':   imsg->ipc_Id = QUIT; /* all items are ignored */
  196.                     break;
  197.  
  198.         case 'm':   /* Request string in reply Message */
  199.         case 'M':
  200.         case '?':   item++; /* leave default RETS in place */
  201.                     item->ii_Id = STRG; /* Add in a string item to
  202.                                            distinguish displayed line */
  203.                     item->ii_Ptr = (void *)("Returned: ");
  204.                     item++;
  205.                     break;
  206.  
  207.         case 'F':   /* Pass File handle to this console */
  208.         case 'f':
  209.         case '^':   item->ii_Id = FILH; /* overwrites RETS */
  210.                     item++->ii_Ptr = (void *)Output(); /* the file handle */
  211.                     break;
  212.  
  213.         default:    /* anything else just overwrites RETS with output
  214.                        items, so string appears on Pserver window */
  215.                     break;
  216.         }
  217.  
  218.         /*
  219.          * The rest of the setup code simply stuffs a few values of
  220.          * different types into successive items -- rearrange to your
  221.          * own satisfaction...
  222.          * NOTE that we haven't bothered to put the strings into public
  223.          * memory, contrary to the suggestions of the IPC standard
  224.          *  [For shame, Peter!] but this is really only a restriction
  225.          * that needs to be observed for general messages that may have
  226.          * a destination outside the ken of the sender (or for a future
  227.          * machine that has process-private memory).  This isn't relevant
  228.          * to such a simple test program, so we've simplified things.
  229.          * At the same time, the ii_Size field for the string items is
  230.          * set to ZERO, indicating that the "data block" is Read-Only
  231.          * as far as the server is concerned.
  232.          */
  233.         item->ii_Id = STRG; /* A short string to start out with */
  234.         item->ii_Ptr = (void *)("Test line...");
  235.         item++;
  236.         item->ii_Id = PAT1; /* then a format specifier for a value */
  237.         item->ii_Ptr = (void *)(" #%3d");
  238.         item++;
  239.         item->ii_Id = INTG; /* the integer value to be formatted */
  240.         item->ii_Ptr = (void *)(count++); /* (just a sequential count...) */
  241.         item++;
  242.         item->ii_Id = STRG; /* another string... */
  243.         item->ii_Ptr = (void *)("... value=");
  244.         item++;
  245.         item->ii_Id = REAL; /* A float value in default format */
  246.             /* note the messy conversion to get it into the ii_Ptr field */
  247.         *(float *) &item->ii_Ptr = (realcount += 1.234);
  248.         item++;
  249.         item->ii_Id = CHAR; /* and a newline character to end the section */
  250.         item->ii_Ptr = (void *)('\n');
  251.         item++;
  252.         item->ii_Id = PATS; /* Multi item format specifier */
  253.         item->ii_Ptr = (void *)("formatted line #%2d %s\n");
  254.         item++;
  255.         item->ii_Id = INTG;
  256.         item->ii_Ptr = (void *)(count++);
  257.         item++;
  258.         item->ii_Id = STRG;
  259.         item->ii_Ptr = (void *)((count & 3) ? "..." : "tick...");
  260.         /* no more items allowed after PATS is satisfied */
  261.  
  262.         /* set actual ItemCount into message: */
  263.         imsg->ipc_ItemCount = item - item0 + 1;
  264.  
  265.         /* Send the message (if possible) */
  266.         if (!PutIPCMsg(port, imsg)) {
  267.                 outputstr("No server!\n");
  268.                 continue; /* don't wait for a reply that won't come! */
  269.         }
  270.         /* Wait at the reply port: */
  271.         WaitPort(rport);
  272.         GetMsg(rport);  /* we assume we know what's there! */
  273.         if (imsg->ipc_Flags & IPC_NOTKNOWN)
  274.             outputstr("Server barfed\n");
  275.         /*
  276.          * If we asked for a return string, display it in our
  277.          * window, then dispose of the block of memory passed to us
  278.          * by the server:
  279.          */
  280.         if (item0->ii_Id == RETS) {
  281.             Write(Output(), item0->ii_Ptr, strlen(item0->ii_Ptr));
  282.             /* note that we DON'T use the ii_Size value above!
  283.                There is no guarantee that it is exactly the size of
  284.                the string. */
  285.             FreeMem(item0->ii_Ptr, item0->ii_Size);
  286.         }
  287.     }
  288.     /*** end of main loop ***/
  289.  
  290.     Cleanup();
  291. }
  292.  
  293.  
  294. void Cleanup()
  295. {
  296.     if (port) DropIPCPort(port);
  297.     if (rport) DeletePort(rport);
  298.     if (imsg) DeleteIPCMsg(imsg);
  299. }
  300.  
  301.  
  302. void outputstr(str) char *str;
  303. {
  304.     Write(Output(), str, strlen(str));
  305. }
  306.  
  307.