next up previous contents
Next: Semafory Up: msgtool: Interaktywny manipulator kolejką Previous: Przykłady   Contents

Źródło

msgtool

Następujący kod źródłowy to msgtool. Powinien skompilować się bez problemu na nowszych ( przyzwoitych ) wersjach jądra, które wspierają System V IPC. Pamiętaj o włączeniu IPC Systemu V podczas rekompilacji jądra!

Program utowrzy kolejkę wiadomości jeżeli jeszcze nie istnieje, bez względu na rodzaj żądanego działania.

UWAGA: Ponieważ narzędzie to używa funkcji ftok() do wygenerowania klucza IPC możesz zaobserwować konflikty katalogów. Jeżeli gdziekolwiek w swoim skrypcie zmienisz katalog prawdopodobnie program nie zadziała. Rozwiązaniem mogłoby być zakodowanie ścieżki wewnątrz programu ( np.: "/tmp/msgtool" ), lub przekazywanie ścieżki jako parametru wywołania.


  /*****************************************************************************
   Zaczerpnięto z "Linux Programmer's Guide - Rozdział 6"
   (C)opyright 1994-1995, Scott Burkett
   ***************************************************************************** 
   MODUŁ: msgtool.c
   *****************************************************************************
   Narzędzie linii poleceń do majstrowania z kolejkami wiadomości stylu SysV
   *****************************************************************************/
  
  #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();
  
          /* utwórz unikalny klucz poprzez wywołanie ftok() */
          key = ftok(".", 'm');
  
          /* otwórz kolejkę - utwórz jeżeli trzeba */
          if((msgqueue_id = msgget(key, IPC_CREAT|0660)) == -1) {
                  perror("msgget");
                  exit(1);
          }
          
          switch(tolower(argv[1][0]))
          {
                  case 'w': send_message(msgqueue_id, (struct mymsgbuf *)&qbuf,
                                         atol(argv[2]), argv[3]); 
                            break;
                  case 'o': read_message(msgqueue_id, &qbuf, atol(argv[2])); 
                            break;
                  case 'u': remove_queue(msgqueue_id); 
                            break;        
                  case 't': change_queue_mode(msgqueue_id, argv[2]); 
                            break;
  
                   default: usage();
  
          }
          
          return(0);
  }
  
  void send_message(int qid, struct mymsgbuf *qbuf, long type, char *text)
  {
          /* wyślij wiadomość do kolejki */
          printf("Wysyłanie wiadomości ...\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)
  {
          /* odczytaj wiadomość z kolejki */
          printf("Odczytywanie wiadomości ...\n");
          qbuf->mtype = type;
          msgrcv(qid, (struct msgbuf *)qbuf, MAX_SEND_SIZE, type, 0);
          
          printf("Typ: %ld Tekst: %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;
  
          /* pobierz informacje */
          msgctl(qid, IPC_STAT, &myqueue_ds);
  
          /* konwertuj i załaduj tryb */
          sscanf(mode, "%ho", &myqueue_ds.msg_perm.mode);
  
          /* uaktualnij tryb */
          msgctl(qid, IPC_SET, &myqueue_ds);
  }
  
  void usage(void)
  {
          fprintf(stderr, "msgtool - Narzędzie do majstrowania przy kolejkach msg\n");
          fprintf(stderr, "\nUŻYCIE: msgtool (w)yślij <typ> <tekst>\n");
          fprintf(stderr, "                (o)dbierz <typ>\n");
          fprintf(stderr, "                (u)suń\n");
          fprintf(stderr, "                (t)ryb <ósemkowy tryb>\n");
          exit(1);
  }
  



Paweł Niewiadomski
2000-10-17