libipc.c revision 6eaecb2f051cee4b1a36e6092b408e8f378e3406
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/* 49 * getipckey() - generates and returns a message key used by the "get" 50 * calls to create an IPC resource. 51 */ 52int 53getipckey() 54{ 55 const char a = 'a'; 56 int ascii_a = (int)a; 57 char *curdir = NULL; 58 size_t size = 0; 59 key_t ipc_key; 60 struct timeb time_info; 61 62 if (NULL == (curdir = getcwd(curdir, size))) { 63 tst_brkm(TBROK, cleanup, "Can't get current directory " 64 "in getipckey()"); 65 } 66 67 /* 68 * Get a Sys V IPC key 69 * 70 * ftok() requires a character as a second argument. This is 71 * refered to as a "project identifier" in the man page. In 72 * order to maximize the chance of getting a unique key, the 73 * project identifier is a "random character" produced by 74 * generating a random number between 0 and 25 and then adding 75 * that to the ascii value of 'a'. The "seed" for the random 76 * number is the millisecond value that is set in the timeb 77 * structure after calling ftime(). 78 */ 79 (void)ftime(&time_info); 80 srandom((unsigned int)time_info.millitm); 81 82 if ((ipc_key = ftok(curdir, ascii_a + random()%26)) == -1) { 83 tst_brkm(TBROK, cleanup, "Can't get msgkey from ftok()"); 84 } 85 86 return(ipc_key); 87} 88 89/* 90 * rm_queue() - removes a message queue. 91 */ 92void 93rm_queue(int queue_id) 94{ 95 if (queue_id == -1) { /* no queue to remove */ 96 return; 97 } 98 99 if (msgctl(queue_id, IPC_RMID, NULL) == -1) { 100 tst_resm(TINFO, "WARNING: message queue deletion failed."); 101 tst_resm(TINFO, "This could lead to IPC resource problems."); 102 tst_resm(TINFO, "id = %d", queue_id); 103 } 104} 105 106/* 107 * init_buf() - initialize the message buffer with some text and a type. 108 */ 109void 110init_buf(MSGBUF *m_buf, int type, int size) 111{ 112 int i; 113 int ascii_a = (int)'a'; /* the ascii value for 'a' */ 114 115 /* this fills the message with a repeating alphabet string */ 116 for (i=0; i<size; i++) { 117 m_buf->mtext[i] = ascii_a + (i % 26); 118 } 119 120 /* terminate the message */ 121 m_buf->mtext[i] = (char)NULL; 122 123 /* if the type isn't valid, set it to 1 */ 124 if (type < 1) { 125 m_buf->mtype = 1; 126 } else { 127 m_buf->mtype = type; 128 } 129} 130 131/* 132 * rm_sema() - removes a semaphore. 133 */ 134void 135rm_sema(int sem_id) 136{ 137 union semun arr; 138 139 if (sem_id == -1) { /* no semaphore to remove */ 140 return; 141 } 142 143 if (semctl(sem_id, 0, IPC_RMID, arr) == -1) { 144 tst_resm(TINFO, "WARNING: semaphore deletion failed."); 145 tst_resm(TINFO, "This could lead to IPC resource problems."); 146 tst_resm(TINFO, "id = %d", sem_id); 147 } 148} 149 150/* 151 * check_root() - make sure the process ID is root 152 */ 153void 154check_root() 155{ 156 if (geteuid() != 0) { 157 tst_brkm(TBROK, cleanup, "test must be run as root"); 158 } 159} 160 161/* 162 * getuserid() - return the integer value for the "user" id 163 */ 164int 165getuserid(char *user) 166{ 167 struct passwd *ent; 168 169 /* allocate some space for the passwd struct */ 170 if ((ent = (struct passwd *)malloc(sizeof(struct passwd))) == NULL) { 171 tst_brkm(TBROK, cleanup, "couldn't allocate space for passwd" 172 " structure"); 173 } 174 175 /* get the uid value for the user */ 176 if ((ent = getpwnam(user)) == NULL) { 177 tst_brkm(TBROK, cleanup, "Couldn't get password entry for %s", 178 user); 179 } 180 181 return(ent->pw_uid); 182} 183 184/* 185 * rm_shm() - removes a shared memory segment. 186 */ 187void 188rm_shm(int shm_id) 189{ 190 if (shm_id == -1) { /* no segment to remove */ 191 return; 192 } 193 194 /* 195 * check for # of attaches ? 196 */ 197 198 if (shmctl(shm_id, IPC_RMID, NULL) == -1) { 199 tst_resm(TINFO, "WARNING: shared memory deletion failed."); 200 tst_resm(TINFO, "This could lead to IPC resource problems."); 201 tst_resm(TINFO, "id = %d\n", shm_id); 202 } 203} 204