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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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