home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Collection - Online Library - January 1996 / CKITOS2196.ISO / diskette / gg244090.dsk / unc.dsk / CHAPTER.09 / MANAGER.C < prev    next >
C/C++ Source or Header  |  1993-10-28  |  15KB  |  357 lines

  1. /***************************************************************************/
  2. /*                                                                         */
  3. /* Name:        manager.c                                                  */
  4. /*                                                                         */
  5. /* Description: Implements the handling procedures for the mbox data       */
  6. /*              structure in the MessageBox sample application             */
  7. /*                                                                         */
  8. /***************************************************************************/
  9.  
  10. # include <string.h>
  11. # include <stdio.h>
  12.  
  13. # include "mbox.h"
  14. # include "common.h"
  15.  
  16. # define MAX_USERS                      100
  17. # define MBOX_IMPORT_FAILED             -14
  18. # define MBOX_EXPORT_FAILED             -15
  19. # define EOF_READ                       0
  20. # define STR_READ                       1
  21.  
  22. /* prototypes for routines imported from the security module */
  23. char *get_principal ( handle_t );
  24. int is_authorized ( handle_t );
  25.  
  26. /* entry is the structure for a single message in the message queue */
  27. struct entry {
  28.         char            *msg;
  29.         char            *sdr;
  30.         struct entry    *nxt;
  31. };
  32.  
  33. typedef struct entry    entry_t;
  34.  
  35. /* mbox is the structure for a message box for a principal */
  36. struct mbox {
  37.         char            *principal;
  38.         struct entry    *first;
  39. };
  40.  
  41. typedef struct mbox     mbox_t;
  42.  
  43. /* allocate empty message boxes for MAX_USERS */
  44. mbox_t          mbox[MAX_USERS] = { NULL, NULL };
  45.  
  46.  
  47. /***************************************************************************/
  48. /*                                                                         */
  49. /* Name:        function get_mbox()                                        */
  50. /*                                                                         */
  51. /* Description: get_mbox returns a pointer to the message box of principal */
  52. /*              or a NULL if there is no message box for this principal.   */
  53. /*                                                                         */
  54. /***************************************************************************/
  55. mbox_t *get_mbox(  char *principal )
  56. {
  57.         mbox_t          *mb = mbox;
  58.  
  59.         while ( mb -> principal ) {
  60.                 if ( strcmp (principal, mb -> principal) == 0 )
  61.                         return mb;
  62.                 mb++;
  63.         }
  64.         return NULL;
  65. }
  66.  
  67. /***************************************************************************/
  68. /*                                                                         */
  69. /* Name:        function new_message()                                     */
  70. /*                                                                         */
  71. /* Description: new_msg inserts a new entry structure a the end of the     */
  72. /*              message queue and returns a pointer on it.                 */
  73. /*                                                                         */
  74. /***************************************************************************/
  75. entry_t *new_msg( mbox_t *mbox )
  76. {
  77.         entry_t         *last;
  78.         entry_t         *new = (entry_t *) malloc( sizeof(entry_t) );
  79.  
  80.         new -> msg = NULL;
  81.         new -> sdr = NULL;
  82.         new -> nxt = NULL;
  83.  
  84.         if ( mbox -> first ) {
  85.                 last = mbox -> first;
  86.                 while ( last -> nxt )
  87.                         last = last -> nxt;
  88.                 last -> nxt = new;
  89.         } else
  90.                 mbox -> first = new;
  91.  
  92.         return new;
  93. }
  94.  
  95. /****************************************************************************/
  96. /*                                                                          */
  97. /* Name:        function mbox_new()                                         */
  98. /*                                                                          */
  99. /* Description: mbox_new is advertised by the server to RPC clients.        */
  100. /*              It creates a new message box entry for the given principal. */
  101. /*              The ACLs on /.:/Servers/MessageBox must grant you control   */
  102. /*              rights to use this command from a client application.       */
  103. /*              mbox_new checks against existing principals for free        */
  104. /*              message box entries.                                        */
  105. /*                                                                          */
  106. /****************************************************************************/
  107. idl_long_int mbox_new ( handle_t bh,  unsigned char *principal )
  108. {
  109.         mbox_t          *mb = mbox;
  110.  
  111.         /* check authorization */
  112.         if ( ! is_authorized(bh) )
  113.                 return ( MBOX_NOT_AUTHORIZED );
  114.  
  115.         /* look up the principal name among the existing enries */
  116.         while ( mb -> principal ) {
  117.                 if ( strcmp (principal, mb -> principal) == 0 )
  118.                         return( MBOX_PRINCIPAL_EXIST );
  119.                 mb++;
  120.         }
  121.  
  122.         /* check if there is a next free entry */
  123.         if ( mb - mbox > MAX_USERS - 2 )
  124.                 return ( MBOX_ALL_USED );
  125.  
  126.         /* assign principal name */
  127.         mb -> principal = strdup( principal );
  128.         printf("Creating new Message Box for Principal %s.\n",principal);
  129.  
  130.         /* initialize next entry */
  131.         mb++;
  132.         mb -> principal = NULL;
  133.         mb -> first     = NULL;
  134.  
  135.         return ( MBOX_OK );
  136. }
  137.  
  138. /***************************************************************************/
  139. /*                                                                         */
  140. /* Name:        function mbox_append()                                     */
  141. /*                                                                         */
  142. /* Description: mbox_append is advertised by the server to RPC clients.    */
  143. /*              It appends a new message to the existing message box of    */
  144. /*              the given principal.                                       */
  145. /*              Every authenticated user can call mbox_append. It tries    */
  146. /*              to get the principal name from the RPC runtime.            */
  147. /*                                                                         */
  148. /***************************************************************************/
  149. idl_long_int    mbox_append (
  150.         handle_t        bh,
  151.         unsigned char  *principal,
  152.         unsigned char  *message
  153. )
  154. {
  155.         mbox_t          *mb;
  156.         entry_t         *new;
  157.  
  158.         /* look up the mbox entry of the principal */
  159.         if ( ! (mb = get_mbox( principal )) )
  160.                 return ( MBOX_PRINCIPAL_NOT_EXIST );
  161.  
  162.         /* append the new message entry to the message list */
  163.         new = new_msg( mb );
  164.  
  165.         /* assign the message and the sender principal to the */
  166.         /* message enntry                                     */
  167.         new -> msg = strdup( message );
  168.         new -> sdr = get_principal( bh );
  169.         printf("Message from %s for %s.\n",new->sdr,principal);
  170.  
  171.         return ( MBOX_OK );
  172. }
  173.  
  174. /***************************************************************************/
  175. /*                                                                         */
  176. /* Name:        function mbox_next()                                       */
  177. /*                                                                         */
  178. /* Description: mbox_next is advertised by the server to RPC clients.      */
  179. /*              It returns in the message parameter the oldest unread      */
  180. /*              message from caller's mbox structure.                      */
  181. /*              mbox_next uses the get_principal call from the security    */
  182. /*              module to select users message box.                        */
  183. /*              The returned message is dicarded from the message queue.   */
  184. /*                                                                         */
  185. /***************************************************************************/
  186. idl_long_int mbox_next ( handle_t bh,unsigned char *message )
  187. {
  188.         mbox_t          *mb;
  189.         char            *principal;
  190.  
  191.         /* get caller's principal name */
  192.         if ( (principal = get_principal(bh)) == NULL )
  193.                 return ( MBOX_NOT_AUTHORIZED );
  194.  
  195.         /* get corresponding mbox */
  196.         if ( ! (mb = get_mbox( principal )) )
  197.                 return ( MBOX_PRINCIPAL_NOT_EXIST );
  198.  
  199.         /* prepare message out of entry */
  200.         if ( mb -> first ) {
  201.                 /* copy the message into message */
  202.                 strcpy( message, mb -> first -> sdr );
  203.                 strcat( message,": ");
  204.                 strcat( message, mb -> first -> msg );
  205.                 printf("%s reads message from %s.\n",principal,mb->first->sdr);
  206.                 /* discard the entry */
  207.                 mb -> first = mb -> first -> nxt;
  208.                 return ( MBOX_OK );
  209.         }
  210.  
  211.         return ( MBOX_NO_MSG );
  212. }
  213.  
  214. /***************************************************************************/
  215. /*                                                                         */
  216. /* Name:        function mbox_export()                                     */
  217. /*                                                                         */
  218. /* Description: mbox_export exports the mbox structure from memory to a    */
  219. /*              local file to save the message queue entries for the next  */
  220. /*              restart of the server.                                     */
  221. /*                                                                         */
  222. /* File format: <message box owner principal>:                             */
  223. /*              <sender principal>:<message>                               */
  224. /*              empty line                                                 */
  225. /*              ........                                                   */
  226. /*                                                                         */
  227. /***************************************************************************/
  228. int mbox_export( const char *fname )
  229. {
  230.         entry_t         *me;
  231.         FILE            *export;
  232.         mbox_t          *mb = mbox;
  233.  
  234.         /* open the file for writing */
  235.         if ( (export = fopen(fname,"w")) == NULL ) {
  236.                 fprintf(stderr,"Cannot export messages to file %s\n", fname);
  237.                 return ( MBOX_EXPORT_FAILED );
  238.         }
  239.  
  240.         /* loop through the mbox array and print out the name and messages */
  241.         printf("Exporting unread messages to file %s.\n",fname);
  242.         while ( mb -> principal ) {
  243.                 fprintf(export,"%s:\n", mb -> principal);
  244.  
  245.                 me = mb -> first;
  246.                 while ( me ) {
  247.                         fprintf(export,"%s:%s\n",me -> sdr, me -> msg);
  248.                         me = me -> nxt;
  249.                 }
  250.                 fputc('\n',export);
  251.                 mb++;
  252.         }
  253.  
  254.         fclose(export);
  255.         return ( MBOX_OK );
  256.  
  257. }
  258.  
  259. /***************************************************************************/
  260. /*                                                                         */
  261. /* Name:        function readln()                                          */
  262. /*                                                                         */
  263. /* Description: readln reads a line into buffer from file 'stream' until   */
  264. /*              it reads a newline character '\n' or the end-of-file       */
  265. /*              mark EOF. The newline character is replaced by '\0'.       */
  266. /*              readln discards carriage returns '\r' == 0xd.              */
  267. /*                                                                         */
  268. /* Return Values:                                                          */
  269. /*              STR_READ = 1 if a line is read.                            */
  270. /*              EOF_READ = 0 if EOF is encountered.                        */
  271. /*                                                                         */
  272. /* NOTE:        The last line is returned together with EOF_READ.          */
  273. /*                                                                         */
  274. /***************************************************************************/
  275. int readln (FILE *stream, char *buffer)
  276. {
  277.         int     i;
  278.         char    *c = buffer;
  279.  
  280.         while ( 1 ) {
  281.                 switch ( i = fgetc(stream) ) {
  282.                 case EOF:
  283.                         *c = '\0';
  284.                         return EOF_READ;
  285.                 case '\n':
  286.                         *c = '\0';
  287.                         return STR_READ;
  288.                 case '\r':
  289.                         continue;
  290.                 default:
  291.                         *c++ = i;
  292.                         if ( c - buffer > MAX_CHAR )
  293.                                 return STR_READ;
  294.  
  295.                         continue;
  296.                 }
  297.         }
  298. }
  299.  
  300. /***************************************************************************/
  301. /*                                                                         */
  302. /* Name:        function mbox_import()                                     */
  303. /*                                                                         */
  304. /* Description: mbox_import imports the mbox structure from the file fname */
  305. /*              written by mbox_export.                                    */
  306. /*                                                                         */
  307. /***************************************************************************/
  308. int mbox_import ( const char *fname )
  309. {
  310.         FILE            *import;
  311.         char            buffer[MAX_CHAR];
  312.         char            *m;
  313.         entry_t         *me;
  314.         mbox_t          *mb = mbox;
  315.  
  316.         /* open local file fname for reading */
  317.         if ( (import = fopen(fname,"r")) == NULL ) {
  318.                 fprintf(stderr, "Cannot import messages from file %s\n",fname);
  319.                 return( MBOX_IMPORT_FAILED );
  320.         }
  321.  
  322.         printf("Importing old messages from file %s.\n",fname);
  323.  
  324.         /* while file is not empty read lines */
  325.         /* NOTE: The last line is ignored because it is always */
  326.         /* empty by definition of the file format.             */
  327.         while ( readln(import, buffer) ) {
  328.                 if ( *buffer == '\0' ) {
  329.                         /* line read is empty -> new principal */
  330.  
  331.                         if ( ++mb - mbox > MAX_USERS - 2 )
  332.                                 return ( MBOX_ALL_USED );
  333.  
  334.                         mb -> principal = NULL;
  335.                         mb -> first     = NULL;
  336.                         continue;
  337.                 }
  338.  
  339.                 /* split line after ':' */
  340.                 if ( m = strchr(buffer,':') )
  341.                         *m++ = '\0';
  342.  
  343.                 /* if principal is not set a new message box is read */
  344.                 if ( mb -> principal ) {
  345.                         /* append message to message list */
  346.                         me = new_msg( mb );
  347.                         me -> sdr = strdup(buffer);
  348.                         me -> msg = strdup(m);
  349.                 } else
  350.                         /* set principal to assign new message box */
  351.                         mb -> principal = strdup(buffer);
  352.         }
  353.  
  354.         fclose( import );
  355.         return( MBOX_OK );
  356. }
  357.