libipc.c revision 7aa9dbd60fa99f7115a5642767d6b9115a70dfaa
1/*
2 *
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19
20/*
21 * NAME
22 *	libmsg.c
23 *
24 * DESCRIPTION
25 *	common routines for the IPC system call tests.
26 *
27 *	The library contains the following routines:
28 *
29 *	getipckey()
30 *	rm_queue()
31 *	init_buf()
32 *	rm_sema()
33 *	check_root()
34 *	getuserid()
35 *	rm_shm()
36 */
37
38#define LIBIPC
39#include "ipcmsg.h"
40#include "ipcsem.h"
41
42#include <pwd.h>
43#include <sys/timeb.h>
44#include <sys/ipc.h>
45#include <sys/shm.h>
46
47/*
48 * getipckey() - generates and returns a message key used by the "get"
49 *		 calls to create an IPC resource.
50 */
51key_t getipckey()
52{
53	const char a = 'a';
54	int ascii_a = (int)a;
55	char *curdir = NULL;
56	size_t size = 0;
57	key_t ipc_key;
58	int proj_id;
59	static int count = 0;
60
61	if (NULL == (curdir = getcwd(curdir, size))) {
62		tst_brkm(TBROK, cleanup, "Can't get current directory "
63			 "in getipckey()");
64	}
65
66	/*
67	 * Get a Sys V IPC key
68	 *
69	 * ftok() requires a character as a second argument.  This is
70	 * refered to as a "project identifier" in the man page.
71	 */
72	proj_id = count % 26 + ascii_a;
73	count++;
74
75	if ((ipc_key = ftok(curdir, proj_id)) == -1) {
76		tst_brkm(TBROK, cleanup, "Can't get msgkey from ftok()");
77	}
78
79	return (ipc_key);
80}
81
82/*
83 * rm_queue() - removes a message queue.
84 */
85void rm_queue(int queue_id)
86{
87	if (queue_id == -1) {	/* no queue to remove */
88		return;
89	}
90
91	if (msgctl(queue_id, IPC_RMID, NULL) == -1) {
92		tst_resm(TINFO, "WARNING: message queue deletion failed.");
93		tst_resm(TINFO, "This could lead to IPC resource problems.");
94		tst_resm(TINFO, "id = %d", queue_id);
95	}
96}
97
98/*
99 * init_buf() - initialize the message buffer with some text and a type.
100 */
101void init_buf(MSGBUF * m_buf, int type, int size)
102{
103	int i;
104	int ascii_a = (int)'a';	/* the ascii value for 'a' */
105
106	/* this fills the message with a repeating alphabet string */
107	for (i = 0; i < size; i++) {
108		m_buf->mtext[i] = ascii_a + (i % 26);
109	}
110
111	/* terminate the message */
112	m_buf->mtext[i] = '\0';
113
114	/* if the type isn't valid, set it to 1 */
115	if (type < 1) {
116		m_buf->mtype = 1;
117	} else {
118		m_buf->mtype = type;
119	}
120}
121
122/*
123 * rm_sema() - removes a semaphore.
124 */
125void rm_sema(int sem_id)
126{
127	union semun arr;
128
129	if (sem_id == -1) {	/* no semaphore to remove */
130		return;
131	}
132
133	if (semctl(sem_id, 0, IPC_RMID, arr) == -1) {
134		tst_resm(TINFO, "WARNING: semaphore deletion failed.");
135		tst_resm(TINFO, "This could lead to IPC resource problems.");
136		tst_resm(TINFO, "id = %d", sem_id);
137	}
138}
139
140/*
141 * check_root() - make sure the process ID is root
142 */
143void check_root()
144{
145	if (geteuid() != 0) {
146		tst_brkm(TBROK, cleanup, "test must be run as root");
147	}
148}
149
150/*
151 * getuserid() - return the integer value for the "user" id
152 */
153int getuserid(char *user)
154{
155	struct passwd *ent;
156
157	/* allocate some space for the passwd struct */
158	if ((ent = (struct passwd *)malloc(sizeof(struct passwd))) == NULL) {
159		tst_brkm(TBROK, cleanup, "couldn't allocate space for passwd"
160			 " structure");
161	}
162
163	/* get the uid value for the user */
164	if ((ent = getpwnam(user)) == NULL) {
165		tst_brkm(TBROK, cleanup, "Couldn't get password entry for %s",
166			 user);
167	}
168
169	return (ent->pw_uid);
170}
171
172/*
173 * rm_shm() - removes a shared memory segment.
174 */
175void rm_shm(int shm_id)
176{
177	if (shm_id == -1) {	/* no segment to remove */
178		return;
179	}
180
181	/*
182	 * check for # of attaches ?
183	 */
184
185	if (shmctl(shm_id, IPC_RMID, NULL) == -1) {
186		tst_resm(TINFO, "WARNING: shared memory deletion failed.");
187		tst_resm(TINFO, "This could lead to IPC resource problems.");
188		tst_resm(TINFO, "id = %d", shm_id);
189	}
190}
191
192#define BUFSIZE 512
193
194/*
195 * Get the number of message queues already in use
196 */
197int get_used_msgqueues()
198{
199	FILE *f;
200	int used_queues;
201	char buff[BUFSIZE];
202
203	f = popen("ipcs -q", "r");
204	if (!f) {
205		tst_resm(TBROK, "Could not run 'ipcs' to calculate used "
206			 "message queues");
207		tst_exit();
208	}
209	/* FIXME: Start at -4 because ipcs prints four lines of header */
210	for (used_queues = -4; fgets(buff, BUFSIZE, f); used_queues++) ;
211	pclose(f);
212	if (used_queues < 0) {
213		tst_resm(TBROK, "Could not read output of 'ipcs' to "
214			 "calculate used message queues");
215		tst_exit();
216	}
217	return used_queues;
218}
219
220/*
221 * Get the max number of message queues allowed on system
222 */
223int get_max_msgqueues()
224{
225	FILE *f;
226	char buff[BUFSIZE];
227
228	/* Get the max number of message queues allowed on system */
229	f = fopen("/proc/sys/kernel/msgmni", "r");
230	if (!f) {
231		tst_resm(TBROK, "Could not open /proc/sys/kernel/msgmni");
232		return -1;
233	}
234	if (!fgets(buff, BUFSIZE, f)) {
235		fclose(f);
236		tst_resm(TBROK, "Could not read /proc/sys/kernel/msgmni");
237		return -1;
238	}
239	fclose(f);
240	return atoi(buff);
241}
242