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