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