LinuxQuestions.org
Share your knowledge at the LQ Wiki.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 09-20-2005, 02:14 AM   #1
kirmet
Member
 
Registered: Sep 2005
Location: austria
Distribution: fedora,backtrack
Posts: 31

Rep: Reputation: 15
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 .... 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]

Last edited by kirmet; 09-20-2005 at 02:21 AM.
 
Old 09-20-2005, 04:49 AM   #2
Thinking
Member
 
Registered: Oct 2003
Posts: 249

Rep: Reputation: 30
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
 
Old 09-20-2005, 05:00 AM   #3
kirmet
Member
 
Registered: Sep 2005
Location: austria
Distribution: fedora,backtrack
Posts: 31

Original Poster
Rep: Reputation: 15
thx a lot thinking for the answer (for the german as well as for the english version)

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

ok im back to work

working on threads and semaphores now and im sure im coming back for some questions
 
Old 09-20-2005, 05:04 AM   #4
Thinking
Member
 
Registered: Oct 2003
Posts: 249

Rep: Reputation: 30
you're welcome
 
Old 09-20-2005, 08:40 AM   #5
kirmet
Member
 
Registered: Sep 2005
Location: austria
Distribution: fedora,backtrack
Posts: 31

Original Poster
Rep: Reputation: 15
huhu i am back

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? )

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 ) could take a quick look at it to point to me to some mistakes.

thanks
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
POSIX message queues(Solaris) to SYS V message queues(Linux) devershetty Programming 1 01-22-2007 10:15 AM
Posix Message queues? gdipierro Programming 20 07-26-2005 04:59 PM
Message Queues rag_mg Programming 1 05-08-2005 08:00 AM
POSIX message queues... infamous41md Programming 6 05-25-2004 02:53 PM
Message Queues BoldKiller Programming 1 05-28-2003 05:40 PM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 09:59 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration