LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   message queues - please some checkup from the pros (https://www.linuxquestions.org/questions/programming-9/message-queues-please-some-checkup-from-the-pros-365126/)

kirmet 09-20-2005 02:14 AM

message queues - please some checkup from the pros
 
hi folks i hope, if some of you master-of-the-posix guys could look throught the program and say whats the problem.
the following happened:

i had to do a message queue:
prog1:
send lines from input via msq. to the next program

prog2:
change all input to big letters
and send to prog 3

prog3:
output the lines

in addition:
with quit all proggs. quit and implement a signal handler (sigint)

if someone could help with the following i would be very grateful:

1) i did this small prog. on debian
a friend of mine tried to run it on solaris and had some problems when trying to quit the proggs (it resultet in a loop)
2) i know of course this prog. can be done better faster intelligenter stronger .... :D im not a pro (yet) ... but if there are some mistakes that just happened by luck to not result in an error ... please tell me

ok here is the code

msq.h
Code:

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

#define key_in 1234
#define key_out 4321
#define size 1024

int msq_snd(int msq_id, char text[])
{
        int send_id;
        send_id=msgsnd(msq_id,text,strlen(text),0);
        if (send_id < 0)
        {
                printf("Fehler bei senden einer Nachricht ...\n");
                return -1;
        }
}

int msq_rcv(int msq_id,char text[])
{
        int receive_id;
        receive_id=msgrcv(msq_id,text,size,0,0);
        if(receive_id < 0)
        {
                printf("Fehler beim empfangen einer Nachricht ...\n");
                return -1;
        }
}

input.c

Code:

#include "./msq.h"
#include <signal.h>

static int input_id;

void term()
{
        printf("Strg+c...sending quit to msq\n");
        msq_snd(input_id,"quit");
        msgctl(input_id,IPC_RMID,0);
        exit(0);
}

int main()
{
        int n;
        char text[size];

        signal(SIGINT,term);

        input_id=msgget(key_in,IPC_CREAT);

        if (input_id == -1)
        {
                printf("Fehler beim Einrichten der Msq.\n");
                return -1;
        }
        while(1)
        {
                gets(text);       
                msq_snd(input_id,text);
                if (strcmp(text,"quit") == 0)
                {
                        printf("<<exiting>>\n");
                        msgctl(input_id,IPC_RMID,0);
                        return 0;
                }
        }
}

compute.c

Code:

#include "./msq.h"

int main()
{
        int n,tooutput_id,toinput_id,receive_id,send_id;
        char text[size];

        toinput_id=msgget(key_in, 0);
        if (toinput_id == -1)
        {
                printf("Fehler beim Einrichten der Msq.\n");
                return -1;
        }

        tooutput_id=msgget(key_out, IPC_CREAT);
        if (tooutput_id == -1)
        {
                printf("Fehler beim Einrichten der Msq.\n");
                return -1;
        }

        printf("Server läuft...\n");

        while(1)
        {
                msq_rcv(toinput_id,text);
                if(strcmp(text,"quit")==0)
                {
                        msq_snd(tooutput_id,text);
                        printf("<<exiting>>\n");
                        msgctl(toinput_id,IPC_RMID,0);
                        msgctl(tooutput_id,IPC_RMID,0);
                        return 0;
                }
               
                puts(text);
                for (n=0;n<strlen(text);n++)
                {
                        text[n]=toupper(text[n]);
                }
                printf("Changed to: ");
                puts(text);

                msq_snd(tooutput_id,text);
        }
        return 0;
}

output.c

Code:

#include "./msq.h"

int main()
{
        int output_id,receive_id;
        char text[size];

        output_id=msgget(key_out,0);

        if(output_id < 0)
        {
                printf("Fehler beim Einrichten der Msq.\n");
                return -1;
        }

        while(1)
        {
                msq_rcv(output_id,text);
                if(strcmp(text,"quit")==0)
                {
                        printf("<<exiting>>\n");
                        msgctl(output_id,IPC_RMID,0);
                        return 0;
                }
                puts(text);
        }
}

i have an exam in a few days and just dont want to miss some obvious mistakes

[edit]
oh btw. i am from austria ... so the error messages are written in german but i hope thats not a problem
[/edit]

Thinking 09-20-2005 04:49 AM

hiho kermit

german:
griaß di *g*

also ich hab mal deinen code ausprobiert
hier was mir aufgefallen ist (ich weiß nicht ob es bei dir das gleiche problem ist!)
mir sind 2 dinge aufgefallen
1. bei input.c krieg ich einen compile warning
da du gets(); stat fgets(); verwendest

erklärung:
gets(); schaut nicht auf die puffer größe (bei dir variable text) und somit könnts zu einem puffer überlauf kommen
deshalb ist diese funktion unsicher!
lösung:
ganz oben füge hinzu
#include <stdio.h>
gets(text); ersetzen durch fgets(text,size,stdin);

2. bei mir hat gar nix funktioniert, weil die berichtigung für die message queue falsch war
PS: fall du irgendwo einen fehler hast (also die funktion liefert einen fehlercode) dann verwende
perror("ERROR");
die funktion perror gibt dir den fehlertext aus, des letzten fehlers

dadurch hab ich gekriegt:
ERROR: Permission denied

lösung:
in jedem code file außer msq.h
ändere die msgget funktion!

bei der msgget musst du noch die berechtigung angeben mit der die message queue geöffnet werden soll:
z.B. bei input.c --> input_id=msgget(key_in,IPC_CREAT|0666); // 0666 ist quasi standard berechtigung (-rw-rw-rw-)
output.c --> output_id=msgget(key_out,0|0666);
compute.c --> toinput_id=msgget(key_in, 0|0666);

das waren bei mir die probleme

hoffe du schaffst die prüfung
good luck ;-)

english:
the problems i've found:
1. gets(); is used in input.c
gets is unsafe because it can cause a buffer overflow because it

from the man page:
Never use gets(). Because it is impossible to tell withÂ_
out knowing the data in advance how many characters gets()
will read, and because gets() will continue to store charÂ_
acters past the end of the buffer, it is extremely dangerÂ_
ous to use. It has been used to break computer security.
Use fgets() instead.

so i changed input.c
1: #include <stdio.h>
2: fgets(text,size,stdin);

2.
the priviledge for the message queue isn't set
using perror("ERROR");
i got
ERROR: Permission denied

so i changed every msgget(); to
msgget(key,flag|0666);
where key is the key variable used in the code and flag the flags set (0 or IPC_CREAT)

now it works great

good luck for your exam

kirmet 09-20-2005 05:00 AM

thx a lot thinking for the answer (for the german as well as for the english version) :D

first i used scanf but i couldnt solve the format problem. i guess it would have been a small syntax change but well ... works fine now.
thx even more to show me the permission error ... thats something my theacher likes to look at :D

ok im back to work :study:

working on threads and semaphores now and im sure im coming back for some questions :D

Thinking 09-20-2005 05:04 AM

you're welcome

kirmet 09-20-2005 08:40 AM

huhu i am back:D

i need some more help or verification for the following code please
ok this task was about threads and semaphores ... a better topic to do some mistakes i guess

the task just was to have

1file:
to read from stdin and write it in a message queue. then open a thread and let it read from the message queue and write the content in a file. in addition i had to do a semaphore for the second prog.

2file:
to read from the file (if the semaphore isnt set) and delete the file afterwards.

write_file (nice name or? :D)

Code:

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

#include <sys/stat.h>
#include <fcntl.h>

#include <stdio.h>

#include <pthread.h>

#include <sys/sem.h>
#include <unistd.h>
#include <stdlib.h>

#define key_sem 5555L
#define key_msq 1111
#define size 1024

static int sem_id;
static struct sembuf semaphore;

static int init_semaphore(void)
{
        sem_id = semget(key_sem,1,IPC_CREAT | 0666);
        if(sem_id < 0)
        {
                perror("Fehler bei semget()");
                return -1;
        }
        if (semctl(sem_id,0,SETVAL,(int) 1) < 0)
        {
                perror("Fehler bei semctl()");
                return -1;
        }

        return 1;
}

static int op_semaphore(int stat)
{
        semaphore.sem_op = stat;
        semaphore.sem_flg = SEM_UNDO;
        if (semop (sem_id,&semaphore,1) < 0)
        {
                perror("Fehler bei semop()");
                return -1;
        }
        return 1;
}

static void function(void *file) 
{
        int msq_id,rcv_id,fd_file;
        char text[size];


        msq_id=msgget(key_msq,0|0666);
        if(msq_id < 0)
        {
                perror("Fehler bei msgget()");
                pthread_exit(NULL);
        }

        rcv_id=msgrcv(msq_id,text,size,0,0);
        if (rcv_id < 0)
        {
                perror("Fehler bei msgrcv()");
                pthread_exit(NULL);
        }

        op_semaphore(-1);

        fd_file=open((char *) file,O_RDWR | O_EXCL | O_CREAT, 0666);
        if (fd_file < 0)
        {
                perror("Fehler bei open()");
                pthread_exit(NULL);
        }

        if (write(fd_file,text,strlen(text)) != strlen(text))
        {
                perror("Fehler bei write()");
                pthread_exit(NULL);
        }

        op_semaphore(1);
        pthread_exit(NULL);
}

int main(int argc, char *argv[])
{
        int msq_id,send_id;
        int ress;
        char text[size];
        pthread_t th;

        if (argc < 2)
        {
                printf("syntax %s <filename>\n",argv[0]);
                return -1;
        }

        ress = init_semaphore();
        if (ress < 0)
        {
                printf("Fehler bei init_semaphore()\n");
                return -1;
        }

        if (pthread_create(&th,NULL,&function,argv[1]) < 0)
        {
                perror("Fehler bei pthread_create()");
                return -1;
        }

        msq_id=msgget(key_msq,IPC_CREAT|0666);
        if(msq_id < 0)
        {
                perror("Fehler bei msgget()");
                return -1;
        }

        fgets(text,size,stdin);

        send_id=msgsnd(msq_id,text,strlen(text),0);
        if(send_id < 0)
        {
                perror("Fehler bei msgsnd()");
                return -1;
        }

        pthread_join(th,NULL);
        return 0;
}

read_file

Code:

#include <sys/types.h>
#include <sys/sem.h>

#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>

#define key_sem 5555L
#define size 1024

static int sem_id;
static struct sembuf semaphore;

static int init_semaphore(void)
{
        sem_id = semget(key_sem,1,0 | 0666);
        if(sem_id < 0)
        {
                perror("Fehler bei semget()");
                return -1;
        }
        return 1;
}

static int op_semaphore(int stat)
{
        semaphore.sem_op = stat;
        semaphore.sem_flg = SEM_UNDO;
        if (semop (sem_id,&semaphore,1) < 0)
        {
                perror("Fehler bei semop()");
                return -1;
        }
        return 1;
}

int main(int argc, char *argv[])
{
        int fd_file;
        char text[size];

        init_semaphore();
        op_semaphore(-1);

        fd_file=open(argv[1],O_RDONLY,0666);
        if (fd_file < 0)
        {
                perror("Fehler bei open()");
                return -1;
        }

        if (read(fd_file,text,size) < 0)
        {
                perror("Fehler bei read()");
                return -1;
        }
       
        remove (argv[1]);
        op_semaphore(1);
        semctl(sem_id,0,IPC_RMID,0);
        puts(text);

        return 0;
}


i hope someone (thinking perhaps :D ) could take a quick look at it to point to me to some mistakes.

thanks


All times are GMT -5. The time now is 12:33 AM.