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