Controlling a Message Queue

The initial examination of the message queue will concern control functions such as message queue creation, modification, and destruction. Message sending and receiving is covered later.

Creating Message Queues

The last chapter provided a sneak peek at the message queue creation process. The function synopsis is repeated here for your convenience:

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>

int msgget(key_t key, int flags);

The argument key must have the value IPC_PRIVATE or a valid IPC key value.

The flags argument must contain the permission bits for the new queue and IPC_CREAT if the queue is being created. The flag IPC_EXCL can be added to cause msgget(3) to return an error if the message queue already exists. Otherwise, IPC_CREAT attempts to create the queue but will use the existing one that matches key, if it already exists.

The function returns the IPC ID of the message queue when it is successful, which is a zero or positive value. The value -1 is returned when an error occurs, and the variable errno contains the error code.

Accessing a Message Queue

To locate an existing message queue, do not specify the IPC_CREAT flag. An error is returned in this case if the queue does not already exist. You may specify zero for the flags argument when a queue is not being created, since the permission bits are ignored.

Destroying a Message Queue

To perform control operations on a message queue, including its destruction, you must invoke the msgctl(3) function:

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>

int msgctl(int msqid, int cmd, struct msqid_ds *buf);

The first argument, msqid, is the message queue IPC ID. The argument cmd is a command constant, and the last argument, buf, is a pointer to a structure.

The function msgctl(3) returns 0 when it is successful. When -1 is returned, errno holds the error code.

The operation commands accepted by this function include

IPC_RMID Destroy the message queue.
IPC_STAT Query the message queue for information.
IPC_SET Change certain message queue attributes.

The command IPC_RMID is the one that you are interested in for queue destruction. The argument buf is not used for this command, and is permitted to be a null pointer. The following example shows how a queue can be destroyed:

int z;

z = msgctl(msqid,IPC_RMID,0);
if ( z == -1 )
    perror("msgctl(3)")

Obtaining Message Queue Information

The stat(2) call is available to obtain information about files. The msgctl(3) command IPC_STAT performs a similar function for message queues. In this case, the third argument must point to a struct msqid_ds to receive the results. The structure definition is shown in the synopsis:

struct msqid_ds {
    struct ipc_perm msg_perm;  /* msg queue permission bits */
    struct msg *msg_first;     /* first message in the queue */
    struct msg *msg_last;      /* last message in the queue */
    u_long  msg_cbytes;        /* number of bytes in use on the queue */
    u_long  msg_qnum;          /* number of msgs in the queue */
    u_long  msg_qbytes;        /* max # of bytes on the queue */
    pid_t   msg_lspid;         /* pid of last msgsnd() */
    pid_t   msg_lrpid;         /* pid of last msgrcv() */
    time_t  msg_stime;         /* time of last msgsnd() */
    time_t  msg_rtime;         /* time of last msgrcv() */
    time_t  msg_ctime;         /* time of last msgctl() */
};

There are a number of informational members in this structure, including the number of messages in the queue (msg_qnum) and time stamps.

Structure member msg_perm is important for controlling access to your message queue. Its structure is described in the following synopsis:

struct ipc_perm {
    ushort  cuid;              /* creator user id */
    ushort  cgid;              /* creator group id */
    ushort  uid;               /* user id */
    ushort  gid;               /* group id */
    ushort  mode;              /* r/w permission */
    ushort  seq;               /* sequence # (to generate unique msg/sem/shm id) */
    key_t   key;               /* user specified msg/sem/shm key */
};

The members cuid and cgid are the user and group IDs of the creator of the queue. The members uid and gid are the current owner user and group ID values for the message queue. The member mode specifies the permission bits for this queue.

The only members that can be altered after a queue has been created are the members uid, gid, mode, and the msqid_ds member msg_qbytes. You must be the creator of the message queue, have an effective user ID that matches the current uid value, or be superuser to be permitted to make changes.

The following example shows how the IPC_STAT command is used:

int z;
struct msqid_ds stbuf;

z = msgctl(msqid,IPC_STAT,&stbuf);
if ( z == -1 )
    perror("msgctl(3)");

Altering a Message Queue

You may occasionally need to change the ownership of your message queue, or otherwise modify the permission on it. The msgctl(3) command IPC_SET enables you to do this.

The following example queries the current message queue to fill in the structure stbuf. Then it looks up the uid_t value for the login postgres. Finally, the owner user ID is changed in stbuf, and msgctl(3) is called with IPC_SET to establish the new owner of this message queue:

int z;
struct msqid_ds stbuf;
struct passwd *pw;
// Obtain status info :
z = msgctl(msqid,IPC_STAT,&stbuf);
if ( z == -1 )
    abort();

// lookup postgres uid_t value :
pw = getpwnam("postgres");
if ( !pw )
    abort();

// Change owner to postgres
stbuf.msg_perm.uid = (ushort)pw->pw_uid;

z = msgctl(msqid,IPC_SET,&stbuf);
if ( z == -1 )
    perror("msgctl(IPC_SET)");

Note that although the owner of the message queue is changed here, the creator user and group ID values do not change.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.117.158.47