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 */
getipckey(void)50 key_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 */
rm_queue(int queue_id)84 void 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 */
init_buf(MSGBUF * m_buf,int type,int size)100 void 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 */
rm_sema(int sem_id)124 void 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 */
getuserid(char * user)142 int getuserid(char *user)
143 {
144 struct passwd *ent;
145
146 /* get the uid value for the user */
147 if ((ent = getpwnam(user)) == NULL) {
148 tst_brkm(TBROK, cleanup, "Couldn't get password entry for %s",
149 user);
150 }
151
152 return (ent->pw_uid);
153 }
154
155 /*
156 * rm_shm() - removes a shared memory segment.
157 */
rm_shm(int shm_id)158 void rm_shm(int shm_id)
159 {
160 if (shm_id == -1) { /* no segment to remove */
161 return;
162 }
163
164 /*
165 * check for # of attaches ?
166 */
167
168 if (shmctl(shm_id, IPC_RMID, NULL) == -1) {
169 tst_resm(TINFO, "WARNING: shared memory deletion failed.");
170 tst_resm(TINFO, "This could lead to IPC resource problems.");
171 tst_resm(TINFO, "id = %d", shm_id);
172 }
173 }
174
175 #define BUFSIZE 512
176
177 /*
178 * Get the number of message queues already in use
179 */
get_used_msgqueues(void)180 int get_used_msgqueues(void)
181 {
182 FILE *f;
183 int used_queues;
184 char buff[BUFSIZE];
185
186 f = popen("ipcs -q", "r");
187 if (!f) {
188 tst_brkm(TBROK | TERRNO, NULL, "pipe failed");
189 }
190 /* FIXME: Start at -4 because ipcs prints four lines of header */
191 for (used_queues = -4; fgets(buff, BUFSIZE, f); used_queues++) ;
192 pclose(f);
193 if (used_queues < 0) {
194 tst_brkm(TBROK, NULL, "Could not read output of 'ipcs' to "
195 "calculate used message queues");
196 }
197 return used_queues;
198 }
199
200 /*
201 * Get the max number of message queues allowed on system
202 */
get_max_msgqueues(void)203 int get_max_msgqueues(void)
204 {
205 FILE *f;
206 char buff[BUFSIZE];
207
208 /* Get the max number of message queues allowed on system */
209 f = fopen("/proc/sys/kernel/msgmni", "r");
210 if (!f) {
211 tst_resm(TBROK, "Could not open /proc/sys/kernel/msgmni");
212 return -1;
213 }
214 if (!fgets(buff, BUFSIZE, f)) {
215 fclose(f);
216 tst_resm(TBROK, "Could not read /proc/sys/kernel/msgmni");
217 return -1;
218 }
219 fclose(f);
220 return atoi(buff);
221 }
222