Next: 6.4.3 Semaphores Up: msgtool: An interactive message Previous: Examples

#### The Source

The following is the source code for the `msgtool` facility. It should compile clean on any recent (decent) kernel revision that supports System V IPC. Be sure to enable System V IPC in your kernel when doing a rebuild!

On a side note, this utility will create a message queue if it does not exist, no matter what type of action is requested.

> NOTE: Since this tool uses the ftok() function to generate IPC key values, you may encounter directory conflicts. If you change directories at any point in your script, it probably won't work. Another solution would be to hardcode a more complete path into msgtool, such as ``/tmp/msgtool'', or possibly even allow the path to be passed on the command line, along with the operational arguments.

    /*****************************************************************************
      Excerpt from "Linux Programmer's Guide - Chapter 6"
      (C)opyright 1994-1995, Scott Burkett
      *****************************************************************************
      MODULE: msgtool.c
      *****************************************************************************
      A command line tool for tinkering with SysV style Message Queues
      *****************************************************************************/

     #include <stdio.h>
     #include <stdlib.h>
     #include <ctype.h>
     #include <sys/types.h>
     #include <sys/ipc.h>
     #include <sys/msg.h>

     #define MAX_SEND_SIZE 80

     struct mymsgbuf {
             long mtype;
             char mtext[MAX_SEND_SIZE];
     };

     void send_message(int qid, struct mymsgbuf *qbuf, long type, char *text);
     void read_message(int qid, struct mymsgbuf *qbuf, long type);
     void remove_queue(int qid);
     void change_queue_mode(int qid, char *mode);
     void usage(void);

     int main(int argc, char *argv[])
     {
             key_t key;
             int   msgqueue_id;
             struct mymsgbuf qbuf;

             if(argc == 1)
                     usage();

             /* Create unique key via call to ftok() */
             key = ftok(".", 'm');

             /* Open the queue - create if necessary */
             if((msgqueue_id = msgget(key, IPC_CREAT|0660)) == -1) {
                     perror("msgget");
                     exit(1);
             }

             switch(tolower(argv[1][0]))
             {
                     case 's': send_message(msgqueue_id, (struct mymsgbuf *)&qbuf,
                                            atol(argv[2]), argv[3]);
                               break;
                     case 'r': read_message(msgqueue_id, &qbuf, atol(argv[2]));
                               break;
                     case 'd': remove_queue(msgqueue_id);
                               break;
                     case 'm': change_queue_mode(msgqueue_id, argv[2]);
                               break;

                      default: usage();

             }

             return(0);
     }

     void send_message(int qid, struct mymsgbuf *qbuf, long type, char *text)
     {
             /* Send a message to the queue */
             printf("Sending a message ...\n");
             qbuf->mtype = type;
             strcpy(qbuf->mtext, text);

             if((msgsnd(qid, (struct msgbuf *)qbuf,
                     strlen(qbuf->mtext)+1, 0)) ==-1)
             {
                     perror("msgsnd");
                     exit(1);
             }
     }

     void read_message(int qid, struct mymsgbuf *qbuf, long type)
     {
             /* Read a message from the queue */
             printf("Reading a message ...\n");
             qbuf->mtype = type;
             msgrcv(qid, (struct msgbuf *)qbuf, MAX_SEND_SIZE, type, 0);

             printf("Type: %ld Text: %s\n", qbuf->mtype, qbuf->mtext);
     }

     void remove_queue(int qid)
     {
             /* Remove the queue */
             msgctl(qid, IPC_RMID, 0);
     }

     void change_queue_mode(int qid, char *mode)
     {
             struct msqid_ds myqueue_ds;

             /* Get current info */
             msgctl(qid, IPC_STAT, &myqueue_ds);

             /* Convert and load the mode */
             sscanf(mode, "%ho", &myqueue_ds.msg_perm.mode);

             /* Update the mode */
             msgctl(qid, IPC_SET, &myqueue_ds);
     }

     void usage(void)
     {
             fprintf(stderr, "msgtool - A utility for tinkering with msg queues\n");
             fprintf(stderr, "\nUSAGE: msgtool (s)end <type> <messagetext>\n");
             fprintf(stderr, "               (r)ecv <type>\n");
             fprintf(stderr, "               (d)elete\n");
             fprintf(stderr, "               (m)ode <octal mode>\n");
             exit(1);
     }