1 #if !defined( WNT ) && !defined(__hpux)
18 #ifdef HAVE_SYS_TYPES_H
19 # include <sys/types.h>
27 int create_sharedmemory (int **,char *,int);
28 int open_sharedmemory (int **,char *,int);
29 int remove_sharedmemory (int * ,char * );
32 /* This is a multi-server & multi-client asynchronous mailbox management */
35 /* The UNIX mail box is based on shared memory
38 / The messages are send via shared memory .
39 / AST like functions (VMS) are simulated with a signal handler using SIGUSR1.
41 / To manage multiple mail boxes , an internal use shared memory is used
42 / to communicate index among table of mail box informations .
45 / Primitives to manage mail boxes :
46 / osd_crmbox Create a mail box
47 / osd_opmbox Open a mail box
48 / osd_clmbox Close a mail box
49 / osd_wrmbox Write into a mail box
51 / user function needed to receive messages :
52 / user_function (int *box_id, char *box_name, char *message_address, int message_length)
56 / In following explanations, "special shared memory" designates an internal
57 / data area implemented with shared memory used to send index of mail box
58 / informations table for the signal handler.
62 / To create a mail box - Find a free entry in mail box infos table
63 / - If first mail box, create special shared memory
64 / - Create a shared memory for messages
65 / - Put PID of creator into shared memory
66 / - Install signal handler for SIGUSR1
69 / To open a mailbox - Find a free entry in mail box infos table
70 / - Attach shared memory to process
71 / - Get PID of creator from shared memory
75 / To close a mail box - Remove shared memory
76 / - Free entry in mail box infos table
77 / - If last mail box, remove special shared memory
80 / To write in a mail box - Write message into shared memory using
81 / following protocol :
84 / - Send signal SIGUSR1 to server process
87 / To receive message - Get mail box identification from special shared
89 / - Get message with protocol
90 / - Get all informations for user function
91 / - Call user function
92 / - Arm again the signal handler
97 #define MAX_BOX 256 /* Maximum number of mail boxes */
99 /* Protocol to communicate PID of server to clients */
101 #define BEGIN_PROTOCOL 0xAABB
102 #define END_PROTOCOL 0xCCDD
104 #define SIZEOFNAME 64 /* length of mailbox name */
107 /* Mail boxes informations table */
111 int channel; /* Id of shared memory (IPC) */
112 int size; /* Size of data area */
113 int (* user_func) (); /* User function */
114 char name[SIZEOFNAME]; /* Name of mail box VMS only */
115 int *address; /* Address of data area */
117 } id_table[MAX_BOX +1]; /* Allows up to MAX_BOX mail boxes */
118 /* char *address; */ /* Address of data area */
120 static int first_mail_box = 1; /* Flag to initialize mail boxes */
121 static int pid; /* Pid of server or client */
122 static int nb_mail = 0;
123 static int max_mail = MAX_BOX;
125 /* For special shared memory only */
127 /*static char *shared_infos;*/ /* Address of shared memory */
128 static int *shared_infos; /* Address of shared memory */
129 static int shared_shmid; /* Id (IPC) of shared memory */
135 int code1; /* Beginning of protocol */
136 int pid; /* PID of server */
137 int code2; /* End of protocol */
149 /*====== Private : ======================================================
151 find an entry in the mail_box identification table
153 -----------------------------------------------------------------------*/
160 /* If first use, initialize id_table */
162 if (first_mail_box) {
163 memset(id_table,0,sizeof(id_table));
166 /* Allocate special shared memory named "XptY" why not ?! */
168 if (! create_sharedmemory(&shared_infos, "XptY", sizeof( id_table ) ))
171 shared_shmid = open_sharedmemory (&shared_infos, "XptY", sizeof (id_table) );
172 if (shared_shmid == 0) max_mail = 1;
178 while ( id_table[i].address != NULL && i < MAX_BOX)
181 if (i == MAX_BOX-1) return -1; /* Too many mail boxes opened */
188 /*========= Private : ===================================================
190 Remove special shared memory (internal use) when no more mail boxes
192 -----------------------------------------------------------------------*/
197 remove_sharedmemory (&shared_shmid,"Xpty");
205 /*========= Private : ===================================================
207 Set specific error for Mail boxes
208 This allow more detailed error decoding
210 -----------------------------------------------------------------------*/
215 errno = number + 256; /* Set specific error for Mail boxes */
221 /*====== Private : ======================================================
223 Put PID of handler process into shared memory
224 using a special protocol AABB pid CCDD
226 ----------------------------------------------------------------------*/
232 protocol.code1 = BEGIN_PROTOCOL;
233 protocol.pid = getpid();
234 protocol.code2 = END_PROTOCOL;
235 memcpy (id_table[boxid].address, &protocol, sizeof(protocol));
241 memcpy(&protocol, id_table[boxid].address, sizeof(protocol));
242 if (protocol.code1 != BEGIN_PROTOCOL) return(-1);
243 if (protocol.pid <= 2) return(-2);
244 if (protocol.code2 != END_PROTOCOL) return(-3);
254 /*====== Private : ======================================================
258 This simulate a VMS AST function :
259 Asynchronous function
261 ----------------------------------------------------------------------*/
272 memcpy (boxname, shared_infos, SIZEOFNAME); /* Get name of mailbox */
274 for (boxid=1; boxid <= MAX_BOX; boxid++)
275 if (strcmp(boxname,id_table[boxid].name) == 0) break;
277 if (boxid > MAX_BOX) return ; /* ****** What could we do ? ***** */
279 address = id_table[boxid].address;
281 address += sizeof(protocol); /* Pass the protocol JPT */
283 memcpy(&length, address, sizeof(int)); /* Restore length of message */
285 address += sizeof(int); /* Adjust pointer to the message */
287 /* Call user function */
289 /* Don't forget to give again PID
290 of handler process in case of multi-clients */
293 /* call user-function */
295 (*id_table[boxid].user_func) (&boxid,
296 id_table[boxid].name,
303 signal (SIGUSR1, handler);
306 /* don't forget to give again PID of handler process in case of multi-clients
314 /*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
316 / P U B L I C functions
318 /@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/
322 /*====================== Create a mail box =========================
325 mail box identification if succeeded
327 ================================================================*/
330 create_mailbox(char *box_name, int box_size,
331 int (* async_func) (int *box_id, char *box_name,
332 char *message_address, int message_length) )
339 /* Test function security */
341 if (async_func == NULL) {
343 return (0); /* Verifies function exists */
351 if (box_name == NULL) {
356 index = alloc_entry(); /* Find an entry for id_table */
363 if (max_mail == 1 && index > 0) { /* If only one mail box authorized */
368 /* Create shared memory for the process */
370 shmid = create_sharedmemory ( &id_table[index].address, box_name, box_size);
371 if (shmid == 0) return (0);
374 put_pid (index); /* Put pid of server into shared memory */
376 id_table[index].channel = shmid; /* Keep id of shared memory */
377 id_table[index].size = box_size; /* Keep size of mail box */
378 strncpy(id_table[index].name,box_name,SIZEOFNAME); /* Keep name of mail box */
379 id_table[index].user_func = async_func; /* Keep user function */
382 /* Install asynchronous function : AST function */
384 signal (SIGUSR1, handler);
392 /*====================== Open a mail box =======================
395 mail box identification if succeeded
397 ================================================================*/
400 open_mailbox(char * box_name, int box_size)
403 int index; /* Index for mail box informations access */
405 /* Test function security */
412 if (box_name == NULL) {
417 index = alloc_entry(); /* Find an entry for id_table */
420 if (nb_mail == 0) keep_clean();
424 id_table[index].size = box_size; /* Keep size of mail box */
425 strncpy(id_table[index].name,box_name,SIZEOFNAME); /* Keep name of mail box */
427 /* Attach shared memory to the process */
429 status = open_sharedmemory ( (int **)&id_table[index].address, box_name,
434 if (get_pid (index) < 0){ /* Get pid from shared memory */
440 id_table[index].channel = status;
446 id_table[index].address = NULL; /* ensure pointer is empty */
456 /*====================== Close a mail box =======================*/
459 remove_mailbox(int *boxid, char *box_name)
466 if (box_name == NULL) {
472 /* (*boxid)--; JPT */
476 /* If last mail box removed, remove special shared memory */
478 if (nb_mail == 0) keep_clean();
480 remove_sharedmemory (&id_table[*boxid].channel, box_name ); /* Close shared memory */
481 id_table[*boxid].address = NULL;
488 /*====================== Write into a mail box =======================*/
491 write_mailbox(int *boxid, char *box_name, char *message, int length)
494 /* char * address;*/ /* Used for protocol : length message */
495 int * address; /* Used for protocol : length message */
496 int interm_length; /* Used to copy length into shared memory */
503 if (message == NULL) {
508 /* (*boxid)--; JPT */
510 address = id_table[*boxid].address;
512 address += sizeof(protocol); /* After the protocol JPT */
514 interm_length = length; /* Use an intermediate variable for memcpy transfert */
516 memcpy(address, &interm_length, sizeof(int)); /* Put length of message */
517 address += sizeof(int); /* Adjust address for message */
519 memcpy(address, message, length+1); /* Put message */
521 memcpy(shared_infos, id_table[*boxid].name, SIZEOFNAME ); /* Give index in table infos */
523 status = kill (pid, SIGUSR1); /* Send signal to server */
525 if (status == 0) return (1);