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