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);
}