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