• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *   Copyright (C) Bull S.A. 1996
3  *   Copyright (c) International Business Machines  Corp., 2001
4  *
5  *   This program is free software;  you can redistribute it and/or modify
6  *   it under the terms of the GNU General Public License as published by
7  *   the Free Software Foundation; either version 2 of the License, or
8  *   (at your option) any later version.
9  *
10  *   This program is distributed in the hope that it will be useful,
11  *   but WITHOUT ANY WARRANTY;  without even the implied warranty of
12  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
13  *   the GNU General Public License for more details.
14  *
15  *   You should have received a copy of the GNU General Public License
16  *   along with this program;  if not, write to the Free Software
17  *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18  */
19 /*---------------------------------------------------------------------+
20 |                       message_queue_test_01                          |
21 | ==================================================================== |
22 |                                                                      |
23 | Description:  Create a message queue to send messages between two    |
24 |               processes.                                             |
25 |                                                                      |
26 | Algorithm:    o  Parent                                              |
27 |                  - Create a pipe                                     |
28 |                  - Spawn a child process                             |
29 |                  - Create unique message queue identifier and send   |
30 |                    it to child process via pipe                      |
31 |                                                                      |
32 |               o  Child                                               |
33 |                  - Wait for message queue identifier from parent     |
34 |                  - Send data to parent via message queue and exit    |
35 |                                                                      |
36 |               o  Parent                                              |
37 |                  - Receive message from child process                |
38 |                  - Remove message queue                              |
39 |                  - Wait for child process to exit                    |
40 |                                                                      |
41 | System calls: The following system calls are made                    |
42 |                                                                      |
43 |               msgget() - Gets a message queue identifier             |
44 |               msgrcv() - Reads a message from a queue                |
45 |               msgctl() - Provides message control operations         |
46 |                                                                      |
47 | Usage:        message_queue_test_01                                  |
48 |                                                                      |
49 | To compile:   cc -o message_queue_test_01 message_queue_test_01.     |
50 |                                                                      |
51 | Last update:   Ver. 1.2, 2/26/94 14:03:30                           |
52 |                                                                      |
53 | Change Activity                                                      |
54 |                                                                      |
55 |   Version  Date    Name  Reason                                      |
56 |    0.1     050689  CTU   Initial version                             |
57 |    1.2     111993  DJK   Modify for AIX version 4.1                  |
58 |    1.3     022693  DJK   Move to Prod directory                      |
59 |                                                                      |
60 +---------------------------------------------------------------------*/
61 
62 #include <errno.h>
63 #include <signal.h>
64 #include <stdio.h>
65 #include <unistd.h>
66 #include <sys/ipc.h>
67 #ifdef _LINUX_
68 // defines struct msgbuf
69 #define __USE_GNU
70 #endif
71 #include <sys/msg.h>
72 #include <sys/types.h>
73 #include <string.h>
74 #include <stdlib.h>
75 /*
76  * Defines
77  *
78  * BUF_SIZE: size of message buffer...
79  */
80 
81 #define key_tt int
82 #define	FIRST_MSG	0
83 #define BUF_SIZE        256
84 
85 #define SAFE_FREE(p) { if (p) { free(p); (p)=NULL; } }
86 
87 /*
88  * Function prototypes
89  *
90  * sys_error (): System error message function
91  * error (): Error message function
92  */
93 static void sys_error(const char *, int);
94 static void error(const char *, int);
95 static void child(int[]);
96 enum { READ, WRITE };
97 
98 /*---------------------------------------------------------------------+
99 |                               main                                   |
100 | ==================================================================== |
101 |                                                                      |
102 | Function:  Main program  (see prolog for more details)               |
103 |                                                                      |
104 | Returns:   (0)  Successful completion                                |
105 |            (-1) Error occurred                                       |
106 |                                                                      |
107 +---------------------------------------------------------------------*/
main(int argc,char ** argv)108 int main(int argc, char **argv)
109 {
110 	key_tt msqid;		/* message queue id */
111 	struct msgbuf *buf;
112 	pid_t pid;
113 	int mode = 0666;
114 	int fd[2];
115 
116 	/*
117 	 * Print out program header
118 	 */
119 	printf("%s: IPC Message Queue TestSuite program\n", *argv);
120 	fflush(stdout);
121 	pipe(fd);
122 
123 	if ((pid = fork()) == 0) {
124 		child(fd);
125 		exit(0);
126 	} else if (pid < (pid_t) 0)
127 		sys_error("fork failed", __LINE__);
128 
129 	/*
130 	 * Create a NEW unique message queue identifier.
131 	 */
132 	if ((msqid = msgget(IPC_PRIVATE, mode | IPC_CREAT | IPC_EXCL)) < 0)
133 		sys_error("msgget failed", __LINE__);
134 	printf("\n\tCreate message queue, id: 0x%8.8x\n", msqid);
135 	fflush(stdout);
136 
137 	/*
138 	 * Send the newly created message queue identifier to the child
139 	 * process via pipes.  Close pipes after sending identifier.
140 	 */
141 	close(fd[READ]);
142 	if (write(fd[WRITE], &msqid, sizeof(key_tt)) < 0)
143 		sys_error("write failed", __LINE__);
144 	close(fd[WRITE]);
145 
146 	/*
147 	 * Read the data from the message queue
148 	 */
149 	buf =
150 	    (struct msgbuf *)calloc((size_t) (sizeof(struct msgbuf) + BUF_SIZE),
151 				    sizeof(char));
152 	if (!buf)
153 		sys_error("calloc failed", __LINE__);
154 
155 	if (msgrcv(msqid, (void *)buf, (size_t) BUF_SIZE, FIRST_MSG, 0) < 0) {
156 		SAFE_FREE(buf);
157 		sys_error("msgsnd failed", __LINE__);
158 	}
159 	printf("\n\tParent: received message: %s\n", buf->mtext);
160 	fflush(stdout);
161 	SAFE_FREE(buf);
162 
163 	/*
164 	 * Remove the message queue from the system
165 	 */
166 	printf("\n\tRemove the message queue\n");
167 	fflush(stdout);
168 	if (msgctl(msqid, IPC_RMID, 0) < 0)
169 		sys_error("msgctl (IPC_RMID) failed", __LINE__);
170 
171 	printf("\nsuccessful!\n");
172 	fflush(stdout);
173 	return (0);
174 }
175 
176 /*---------------------------------------------------------------------+
177 |                               child                                  |
178 | ==================================================================== |
179 |                                                                      |
180 | Function:  ...                                                       |
181 |                                                                      |
182 +---------------------------------------------------------------------*/
child(int fd[])183 static void child(int fd[])
184 {
185 	key_tt msqid;		/* message queue id */
186 	size_t nbytes;
187 	struct msgbuf *buf;
188 
189 	/*
190 	 * Read the message queue identifier from the parent through
191 	 * the pipe.  Close pipe after reading identifier.
192 	 */
193 	close(fd[WRITE]);
194 	if (read(fd[READ], &msqid, sizeof(key_tt)) < 0)
195 		sys_error("read failed", __LINE__);
196 	close(fd[READ]);
197 	printf("\n\tChild:  received message queue id: %d\n", msqid);
198 	fflush(stdout);
199 
200 	/*
201 	 * Put data on the message queue
202 	 */
203 	buf =
204 	    (struct msgbuf *)calloc((size_t) (sizeof(struct msgbuf) + BUF_SIZE),
205 				    sizeof(char));
206 	if (!buf)
207 		sys_error("calloc failed", __LINE__);
208 
209 	buf->mtype = 1;
210 	sprintf(buf->mtext, "\"message queue transmission test....\"");
211 	nbytes = strlen(buf->mtext) + 1;
212 
213 	printf("\n\tChild:  sending message:  %s\n", buf->mtext);
214 	fflush(stdout);
215 	if (msgsnd(msqid, buf, nbytes, 0) < 0) {
216 		SAFE_FREE(buf);
217 		sys_error("msgsnd failed", __LINE__);
218 	}
219 	SAFE_FREE(buf);
220 }
221 
222 /*---------------------------------------------------------------------+
223 |                             sys_error ()                             |
224 | ==================================================================== |
225 |                                                                      |
226 | Function:  Creates system error message and calls error ()           |
227 |                                                                      |
228 +---------------------------------------------------------------------*/
sys_error(const char * msg,int line)229 static void sys_error(const char *msg, int line)
230 {
231 	char syserr_msg[256];
232 
233 	sprintf(syserr_msg, "%s: %s\n", msg, strerror(errno));
234 	error(syserr_msg, line);
235 }
236 
237 /*---------------------------------------------------------------------+
238 |                               error ()                               |
239 | ==================================================================== |
240 |                                                                      |
241 | Function:  Prints out message and exits...                           |
242 |                                                                      |
243 +---------------------------------------------------------------------*/
error(const char * msg,int line)244 static void error(const char *msg, int line)
245 {
246 	fprintf(stderr, "ERROR [line: %d] %s\n", line, msg);
247 	exit(-1);
248 }
249