• 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_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