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