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_04 |
21 | ==================================================================== |
22 | |
23 | Description: Create a message queue to send messages between two |
24 | processes. |
25 | |
26 | Algorithm: o Generate a key value given the project name and id |
27 | |
28 | o Get a unique message queue id |
29 | |
30 | o Print out message queue id |
31 | |
32 | System calls: The following system calls are made |
33 | |
34 | o msgget () - gets a message queue identifier |
35 | |
36 | Usage: message_queue_test_04 [-v] [-l logfile ] |
37 | |
38 | To compile: cc -o message_queue_test_04 message_queue_test_04.c |
39 | |
40 | Last update: Ver. 1.2, 2/26/94 14:03:55 |
41 | |
42 | Change Activity |
43 | |
44 | Version Date Name Reason |
45 | 0.1 111993 DJK Initial version for AIX 4.1 |
46 | 1.2 022694 DJK Moved to Prod directory |
47 | |
48 +---------------------------------------------------------------------*/
49
50 #include <errno.h>
51 #include <fcntl.h>
52 #include <stdio.h>
53 #include <string.h>
54 #include <unistd.h>
55 #include <sys/ipc.h>
56 #ifdef _LINUX_
57 // defines struct msgbuf
58 #define __USE_GNU
59 #endif
60 #include <sys/msg.h>
61 #include <sys/types.h>
62 #include <stdlib.h>
63
64 /*
65 * Defines
66 *
67 * MAX_MSGS: maximum number of messages per queue (8192)
68 */
69 #define DEFAULT_PROJECT_NAME "/tmp/message_queue_test"
70 #define DEFAULT_PROJECT_ID 20
71 #define MAX_MSGS 8192
72 #define USAGE "\nUsage: %s [-v] [-l logfile ]\n\n"
73
74 /*
75 * Function prototypes
76 *
77 * parse_args (): Parse command line arguments
78 * sys_error (): System error message function
79 * error (): Error message function
80 */
81 static void parse_args(int, char **);
82 static void sys_error(const char *, int);
83 static void error(const char *, int);
84
85 /*
86 * Global variables
87 *
88 * log_filename: Name of log file
89 */
90 int verbose = 0;
91 int logit = 0;
92 FILE *logfile;
93 char *log_filename = NULL;
94
95 /*---------------------------------------------------------------------+
96 | main |
97 | ==================================================================== |
98 | |
99 | Function: Main program (see prolog for more details) |
100 | |
101 | Returns: (0) Successful completion |
102 | (-1) Error occurred |
103 | |
104 +---------------------------------------------------------------------*/
main(int argc,char ** argv)105 int main(int argc, char **argv)
106 {
107 struct msqid_ds info; /* Message queue info */
108 struct msgbuf buf; /* Message queue buffer */
109 int mode = 0777; /* Default mode bits */
110 int msqid; /* Message queue identifier */
111 size_t max_bytes; /* Num bytes sent to message queue */
112 size_t msg_size; /* Num bytes sent to message queue */
113 unsigned long bytes_sent; /* Num bytes sent to message queue */
114
115 /*
116 * Parse command line options
117 */
118 parse_args(argc, argv);
119 if (logit) {
120 if ((logfile = fopen(log_filename, "w")) == NULL)
121 sys_error("msgget failed", __LINE__);
122 }
123
124 /*
125 * Print out program header
126 */
127 printf("%s: IPC Message Queue TestSuite program\n\n", *argv);
128 if (logit)
129 fprintf(logfile, "%s: IPC Message Queue TestSuite program\n\n",
130 *argv);
131
132 /*
133 * Obtain a unique message queue identifier using msgget()
134 */
135 if ((msqid = msgget(IPC_PRIVATE, IPC_CREAT | mode)) < 0)
136 sys_error("msgget failed", __LINE__);
137
138 if (verbose)
139 printf("\tCreated message queue: %d\n\n", msqid);
140 if (logit)
141 fprintf(logfile, "\tCreated message queue: %d\n\n", msqid);
142
143 /*
144 * Determine message queue limits
145 *
146 * Determine the maximum number of bytes that the message
147 * queue will hold. Then determine the message size
148 * (Max num of bytes per queue / maximum num of messages per queue)
149 */
150 if (msgctl(msqid, IPC_STAT, &info) < 0)
151 sys_error("msgctl (IPC_STAT) failed", __LINE__);
152
153 max_bytes = info.msg_qbytes;
154
155 /*
156 * this has been changed because of defect 227707 related to floating point
157 * problem, but here is not the right place to test floating point...
158 * msg_size = (size_t) (0.5 + ((float) max_bytes / MAX_MSGS));
159 */
160 msg_size = (size_t) ((max_bytes + MAX_MSGS - 1) / MAX_MSGS);
161
162 if (verbose) {
163 printf("\tMax num of bytes per queue: %ld\n", (long)max_bytes);
164 printf("\tMax messages per queue: %d\n", MAX_MSGS);
165 printf("\tCorresponding message size: %ld\n\n",
166 (long)msg_size);
167 }
168 if (logit) {
169 fprintf(logfile, "\tMax num of bytes per queue: %ld\n",
170 (long)max_bytes);
171 fprintf(logfile, "\tMax messages per queue: %d\n",
172 MAX_MSGS);
173 fprintf(logfile, "\tCorresponding message size: %ld\n\n",
174 (long)msg_size);
175 }
176
177 /*
178 * Fill up the message queue
179 *
180 * Send bytes to the message queue until it fills up
181 */
182 // buf = (struct msgbuf *) calloc (msg_size + sizeof(struct msgbuf), sizeof (char));
183
184 buf.mtype = 1L;
185
186 bytes_sent = 0;
187 while (bytes_sent < max_bytes - msg_size) {
188 if (msgsnd(msqid, &buf, msg_size, 0) < 0)
189 sys_error("msgsnd failed", __LINE__);
190 bytes_sent += msg_size;
191 //usleep(5000);
192 if (verbose) {
193 printf("\r\tBytes sent: %ld", (long)bytes_sent);
194 fflush(stdout);
195 }
196 }
197 if (verbose)
198 puts("\n");
199 if (logit)
200 fprintf(logfile, "\tBytes sent: %ld\n", (long)bytes_sent);
201 //free (buf);
202
203 /*
204 * Remove the message queue
205 */
206 if (msgctl(msqid, IPC_RMID, 0) < 0)
207 sys_error("msgctl (IPC_RMID) failed", __LINE__);
208 if (verbose)
209 printf("\n\tRemoved message queue: %d\n", msqid);
210 if (logit)
211 fprintf(logfile, "\n\tRemoved message queue: %d\n", msqid);
212
213 /* Program completed successfully -- exit */
214 printf("\nsuccessful!\n");
215 if (logit) {
216 fprintf(logfile, "\nsuccessful!\n");
217 fclose(logfile);
218 }
219
220 return (0);
221 }
222
223 /*---------------------------------------------------------------------+
224 | parse_args () |
225 | ==================================================================== |
226 | |
227 | Function: Parse the command line arguments & initialize global |
228 | variables. |
229 | |
230 | Updates: (command line options) |
231 | |
232 | [-v] verbose |
233 | |
234 | [-l] logfile: log file name |
235 | |
236 +---------------------------------------------------------------------*/
parse_args(int argc,char ** argv)237 static void parse_args(int argc, char **argv)
238 {
239 int opt;
240 int errflag = 0;
241 char *program_name = *argv;
242 extern char *optarg; /* Command line option */
243
244 /*
245 * Parse command line options.
246 */
247 while ((opt = getopt(argc, argv, "vl:")) != EOF) {
248 switch (opt) {
249 case 'v': /* verbose */
250 verbose++;
251 break;
252 case 'l': /* log file */
253 logit++;
254 log_filename = optarg;
255 break;
256 default:
257 errflag++;
258 break;
259 }
260 }
261 if (errflag) {
262 fprintf(stderr, USAGE, program_name);
263 exit(2);
264 }
265 }
266
267 /*---------------------------------------------------------------------+
268 | sys_error () |
269 | ==================================================================== |
270 | |
271 | Function: Creates system error message and calls error () |
272 | |
273 +---------------------------------------------------------------------*/
sys_error(const char * msg,int line)274 static void sys_error(const char *msg, int line)
275 {
276 char syserr_msg[256];
277
278 sprintf(syserr_msg, "%s: %s\n", msg, strerror(errno));
279 error(syserr_msg, line);
280 }
281
282 /*---------------------------------------------------------------------+
283 | error () |
284 | ==================================================================== |
285 | |
286 | Function: Prints out message and exits... |
287 | |
288 +---------------------------------------------------------------------*/
error(const char * msg,int line)289 static void error(const char *msg, int line)
290 {
291 fprintf(stderr, "ERROR [line: %d] %s\n", line, msg);
292 if (logit)
293 fprintf(logfile, "ERROR [line: %d] %s\n", line, msg);
294 exit(-1);
295 }
296