Chapter Contents

Previous

Next
msgctl

msgctl



Control a Message Queue

Portability:


SYNOPSIS
DESCRIPTION
RETURN VALUE
USAGE NOTES
EXAMPLE 1
EXAMPLE 2
RELATED FUNCTIONS


SYNOPSIS

#include <sys/msg.h>
int msgctl(int id, int cmd,
           struct msgid_ds *buf);


DESCRIPTION

The msgctl function is used to perform one of several control operations on an UNIX System Services message queue.

Note:   See the msgget function description in section msgget for general information about message queues.   [cautionend]

The id argument to msgctl specifies a message queue id. This argument is an id, such as the id returned by msgget , not a message queue key, which might be passed as an argument to msgget .

The cmd argument should be specified as a symbolic constant specifying the particular operation to be performed by msgctl . The constant values are described below.

Several of the msgctl operations allow you to obtain or access the message queue id data structure, which is mapped by the struct msqid_ds type defined in sys/msg.h . This data structure is defined as follows:

struct msqid_ds {
   /* permission information */
   struct ipc_perm msg_perm;

   /* messages presently on the queue */
   unsigned msg_qnum;

   /* max bytes of queued info */
   unsigned msg_qbytes;

   /* process id of last sender */
   pid_t msg_lspid;

   /* process id of last receiver */
   pid_t msg_lrpid;

   /* time of last msgsnd call */
   time_t msg_stime;

   /* time of last msg(x)rcv call */
   time_t msg_rtime;

   /* time of last change by msgget/msgctl */
   time_t msg_ctime;
};

The ipc_perm structure, which contains security information about the owner and the creator of the message queue, is defined as follows:

struct ipc_perm {
   /* owner's effective user ID */
   uid_t uid;

   /* owner's effective group ID */
   gid_t gid;

   /* creator's effective user ID */
   uid_t cuid;

   /* creator's effective group ID */
   gid_t cgid;

   /* read/write permission bits */
   mode_t mode;
};

For msgctl operations which access or modify the message queue data structure, the buf argument addresses a struct msqid_ds , used as described below. For other operations, the buf argument is ignored.

The cmd values accepted by msgctl and their meanings are as follows:


RETURN VALUE

msgctl returns 0 if successful, or -1 if unsuccessful.


USAGE NOTES

The msgctl function can only be used with MVS 5.2.2 or a later release.


EXAMPLE 1

This example is compiled using sascc370 -Krent -o . This program uses the functions msgget() , msgsnd() , msgrcv() , and msgctl() to establish an IPC Server using Message Queues.

/*-------------------------+
| POSIX/UNIX header files  |
+-------------------------*/
#include <sys/types.h>

#include <unistd.h>

#include <fcntl.h>

#include <sys/ipc.h>

#include <sys/msg.h>

/*-------------------------+
| ISO/ANSI header files    |
+-------------------------*/
#include <stdlib.h>

#include <stdio.h>

#include <string.h>

#include <errno.h>

/*---------------------------+
| Constants                  |
+---------------------------*/
/* maximum message size           */
#define MAX_MSGSIZE          256    

/* message key, set by server     */
#define MSG_KEY      (key_t)1097    

/* Server's message type          */
#define SERVER_MSG_TYPE (long)10    

/* Client's message type          */
#define CLIENT_MSG_TYPE (long)20    

/* give everyone read/write        */
/* permission to messages          */
#define MSG_PERM  (S_IRUSR|S_IWUSR
|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)

/*----------------------------------+
| Types                             |
+-----------------------------------*/
/* Declare the message structure.   */
typedef struct Message              
{
    /* positive message type        */
    long    type;                   
    /* message data                 */
    char    text[MAX_MSGSIZE];      
}Message;

/*----------------------------------+
| Name:      main                   |
| Returns:   exit(EXIT_SUCCESS) or  |
|            exit(EXIT_FAILURE)     |
+----------------------------------*/
int main()
{
/* message queue id                 */
    int msgQID;          

/* message flags                     */
    int msgFlags;         

/* message type                      */
    long msgType;         

/* message key                       */
    key_t msgKey;         

/* message to send                   */
    Message sendMsg;      

/* message received                  */
    Message recvMsg;      

/*------------------------------------*/
/* Create message queue.              */
/* Give everyone read/write           */
/* permissions.                       */
/*------------------------------------*/
   msgKey = MSG_KEY;
   msgFlags = IPC_CREAT | MSG_PERM;

   if ( (msgQID = msgget(msgKey, msgFlags)) < 0 )
   {
       perror("SERVER: msgget");
       exit(EXIT_FAILURE);
   }

/*---------------------------------------*/
/* Receive a message from client.        */
/*---------------------------------------*/
   msgType = CLIENT_MSG_TYPE;
   msgFlags = 0;

   if (msgrcv(msgQID, &recMsg, MAX_MSGSIZE, 
       msgType, msgFlags) < 0)
   {
       perror("SERVER: msgrcv");
       msgctl(msgQID, IPC_RMID, NULL);
       exit(EXIT_FAILURE);
   }

/*-----------------------------------------*/
/* Print message received from client.     */
/*-----------------------------------------*/
   printf("%s\n", recvMsg.text);

/*------------------------------------------*/
/* Send ACK Message to client.              */
/*------------------------------------------*/
sendMsg.type = SERVER_MSG_TYPE;
sprintf(sendMsg.text, 
        "From SERVER: Message received!");
msgFlags = 0;

   if (msgsnd(msgQID, &sendMsg, 
   strlen(sendMsg.text)+1, msgFlags) < 0)
   {
       perror("SERVER: msgsnd");
       msgctl(msgQID, IPC_RMID, NULL);
       exit(EXIT_FAILURE);
   }

/*--------------------------------------------*/
/* Go to sleep to allow time for the client   */
/* to recieve the message                     */
/* before removing the message queue.         */
/*--------------------------------------------*/
   sleep(60);

/*--------------------------------------------*/
/* Call msgctl to remove message queue.       */
/*--------------------------------------------*/
   if (msgctl(msgQID, IPC_RMID, NULL) < 0)
   {
       perror("SERVER: msgctl");
       exit(EXIT_FAILURE);
   }
 
   exit(EXIT_SUCCESS);

}  
/* end of main() */


EXAMPLE 2

This example is compiled using sascc370 -Krent -o.

This program usese the functions msgctl() , msgget() , msgsnd() , and msgxrcv to establish IPC Client using XMessage Queues. Also, it uses UNIX System Service's extended Message structure.

Note:   You cannot use the Extended Message structure to send a message, i.e., call msgsnd() with this structure. Attempting to do so will cause the program to "hang".  [cautionend]

/*--------------------------------------------+
| POSIX/UNIX header files                     |
+--------------------------------------------*/
#include <sys/types.h>

#include <unistd.h>

#include <fcntl.h>

#include <sys/ipc.h>

#include <sys/msg.h>

/*--------------------------------------------+
| ISO/ANSI header files                       |
+--------------------------------------------*/
#include <stdlib.h>

#include <stdio.h>

#include <string.h>

#include <time.h>

#include <errno.h>

/*--------------------------------------------+
| Constants                                   |
+--------------------------------------------*/
 /* maximum message size                      */
#define MAX_MSGSIZE          256   

/* message key, set by server                 */
#define MSG_KEY      (key_t)1097    

/* Server's message type                      */
#define SERVER_MSG_TYPE (long)10    

/* Client's message type                      */
#define CLIENT_MSG_TYPE (long)20    


/* give everyone read/write                   */
/* permission to messages                     */
#define MSG_PERM  
(S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)

/*---------------------------------------------+
| Types                                        |
+---------------------------------------------*/
/* Declare the message structure. */
typedef struct Message              
{
/* positive message type          */
    long    type;                   
/* message data                   */
    char    text[MAX_MSGSIZE];      
}Message;

/* Declare the message structure. */
typedef struct XMessage              
{
/* time msg sent                  */
    time_t  time;                   

/* effective uid of sender        */
    uid_t   uid;                    

/* effective gid of sender        */
    gid_t   gid;                    

/* process id of sender           */
    pid_t   pid;                    

/* positive message type          */
    long    type;                   

/* message data                   */
    char    text[MAX_MSGSIZE];      
}XMessage;

/*-------------------------------------------+
| Name:      main                            |
| Returns:   exit(EXIT_SUCCESS) or           |
|            exit(EXIT_FAILURE)              |
+-------------------------------------------*/
int main()
{
/* message queue id                         */
    int msgQID;           

/* message flags                            */
    int msgFlags;         

/* command to message queue, used w/ msgctl *
    int msgQcmd;          /

/* message type                             */
    long msgType;         

/* message key                              */
    key_t msgKey;         

/* message to send                          */
    Message sendMsg;      

/* message received - eXtended              */
    XMessage recvMsg;     

/*------------------------------------------*/
/* Create message queue.                    */
/* Give everyone read/write permissions.    */
/*------------------------------------------*/
   msgKey = MSG_KEY;
   msgFlags = IPC_CREAT | MSG_PERM;

 if ( (msgQID = msgget(msgKey, msgFlags)) < 0 )
   {
       perror("SERVER: msgget");
       exit(EXIT_FAILURE);
   }

/*---------------------------------------------*/
/* Receive a message from client.              */
/*---------------------------------------------*/
   msgType = CLIENT_MSG_TYPE;
   msgFlags = 0;

   if (msgxrcv(msgQID, &recMsg, MAX_MSGSIZE, 
         msgType, msgFlags) < 0)
   {
       perror("SERVER: msgrcv");
       msgctl(msgQID, IPC_RMID, NULL);
       exit(EXIT_FAILURE);
   }

/*---------------------------------------------*/
/* Print message received from client.         */
/*---------------------------------------------*/
   printf("Message: %s\n", recvMsg.text);
   printf("   Time message was sent: %s\n", 
     ctime(&recvMsg.time));
   printf("   The user id of sender: %d\n", 
     (int)recvMsg.uid);
   printf("  The group id of sender: %d\n", 
     (int)recvMsg.gid);
   printf("The process id of sender: %d\n", 
     (int)recvMsg.pid);

   /*-------------------------------------------*/
   /* Send ACK XMessage to client.              */
   /*-------------------------------------------*/
   sendMsg.type = SERVER_MSG_TYPE;
   sprintf(
    sendMsg.text, 
     "From SERVER: XMessage received!");
   msgFlags = 0;

   if (msgsnd(msgQID, &sendMsg, 
      strlen(sendMsg.text)+1, msgFlags) < 0)
   {
       perror("SERVER: msgsnd");
       msgctl(msgQID, IPC_RMID, NULL);
       exit(EXIT_FAILURE);
   }

/*----------------------------------------------*/
/* Go to sleep to allow time for the client to  */
/* recieve the message                          */
/* before removing the message queue.           */
   /*-------------------------------------------*/
   sleep(60);

/*----------------------------------------------*/
/* Call msgctl to remove message queue.         */
/*----------------------------------------------*/
   if (msgctl(msgQID, IPC_RMID, NULL) < 0)
   {
   perror("SERVER: msgctl");
   exit(EXIT_FAILURE);
   }
 
   exit(EXIT_SUCCESS);

}  /* end of main() */


RELATED FUNCTIONS

msgget , msgrcv , msgsnd , msgxrcv


Chapter Contents

Previous

Next

Top of Page

Copyright © 2001 by SAS Institute Inc., Cary, NC, USA. All rights reserved.