libipc.c revision 6eaecb2f051cee4b1a36e6092b408e8f378e3406
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/*
49 * getipckey() - generates and returns a message key used by the "get"
50 *		 calls to create an IPC resource.
51 */
52int
53getipckey()
54{
55	const char a = 'a';
56	int ascii_a = (int)a;
57	char *curdir = NULL;
58	size_t size = 0;
59	key_t ipc_key;
60	struct timeb time_info;
61
62	if (NULL == (curdir = getcwd(curdir, size))) {
63		tst_brkm(TBROK, cleanup, "Can't get current directory "
64			 "in getipckey()");
65	}
66
67	/*
68	 * Get a Sys V IPC key
69	 *
70	 * ftok() requires a character as a second argument.  This is
71	 * refered to as a "project identifier" in the man page.  In
72	 * order to maximize the chance of getting a unique key, the
73	 * project identifier is a "random character" produced by
74	 * generating a random number between 0 and 25 and then adding
75	 * that to the ascii value of 'a'.  The "seed" for the random
76	 * number is the millisecond value that is set in the timeb
77	 * structure after calling ftime().
78	 */
79	(void)ftime(&time_info);
80	srandom((unsigned int)time_info.millitm);
81
82	if ((ipc_key = ftok(curdir, ascii_a + random()%26)) == -1) {
83		tst_brkm(TBROK, cleanup, "Can't get msgkey from ftok()");
84	}
85
86	return(ipc_key);
87}
88
89/*
90 * rm_queue() - removes a message queue.
91 */
92void
93rm_queue(int queue_id)
94{
95	if (queue_id == -1) {		/* no queue to remove */
96		return;
97	}
98
99	if (msgctl(queue_id, IPC_RMID, NULL) == -1) {
100		tst_resm(TINFO, "WARNING: message queue deletion failed.");
101		tst_resm(TINFO, "This could lead to IPC resource problems.");
102		tst_resm(TINFO, "id = %d", queue_id);
103	}
104}
105
106/*
107 * init_buf() - initialize the message buffer with some text and a type.
108 */
109void
110init_buf(MSGBUF *m_buf, int type, int size)
111{
112	int i;
113	int ascii_a = (int)'a';		/* the ascii value for 'a' */
114
115	/* this fills the message with a repeating alphabet string */
116	for (i=0; i<size; i++) {
117		m_buf->mtext[i] = ascii_a + (i % 26);
118	}
119
120	/* terminate the message */
121	m_buf->mtext[i] = (char)NULL;
122
123	/* if the type isn't valid, set it to 1 */
124	if (type < 1) {
125		m_buf->mtype = 1;
126	} else {
127		m_buf->mtype = type;
128	}
129}
130
131/*
132 * rm_sema() - removes a semaphore.
133 */
134void
135rm_sema(int sem_id)
136{
137	union semun arr;
138
139	if (sem_id == -1) {		/* no semaphore to remove */
140		return;
141	}
142
143	if (semctl(sem_id, 0, IPC_RMID, arr) == -1) {
144		tst_resm(TINFO, "WARNING: semaphore deletion failed.");
145		tst_resm(TINFO, "This could lead to IPC resource problems.");
146		tst_resm(TINFO, "id = %d", sem_id);
147	}
148}
149
150/*
151 * check_root() - make sure the process ID is root
152 */
153void
154check_root()
155{
156	if (geteuid() != 0) {
157		tst_brkm(TBROK, cleanup, "test must be run as root");
158	}
159}
160
161/*
162 * getuserid() - return the integer value for the "user" id
163 */
164int
165getuserid(char *user)
166{
167	struct passwd *ent;
168
169	/* allocate some space for the passwd struct */
170	if ((ent = (struct passwd *)malloc(sizeof(struct passwd))) == NULL) {
171	     tst_brkm(TBROK, cleanup, "couldn't allocate space for passwd"
172		      " structure");
173        }
174
175	/* get the uid value for the user */
176	if ((ent = getpwnam(user)) == NULL) {
177		tst_brkm(TBROK, cleanup, "Couldn't get password entry for %s",
178			 user);
179	}
180
181	return(ent->pw_uid);
182}
183
184/*
185 * rm_shm() - removes a shared memory segment.
186 */
187void
188rm_shm(int shm_id)
189{
190	if (shm_id == -1) {		/* no segment to remove */
191		return;
192	}
193
194	/*
195	 * check for # of attaches ?
196	 */
197
198	if (shmctl(shm_id, IPC_RMID, NULL) == -1) {
199		tst_resm(TINFO, "WARNING: shared memory deletion failed.");
200		tst_resm(TINFO, "This could lead to IPC resource problems.");
201		tst_resm(TINFO, "id = %d\n", shm_id);
202	}
203}
204