Home | History | Annotate | Download | only in lib
      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