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