busybox/util-linux/ipcs.c

638 lines
17 KiB
C
Raw Normal View History

/* vi: set sw=4 ts=4: */
/*
* ipcs.c -- provides information on allocated ipc resources.
*
* 01 Sept 2004 - Rodney Radford <rradford@mindspring.com>
* Adapted for busybox from util-linux-2.12a.
*
* Licensed under GPLv2 or later, see file LICENSE in this source tree.
*/
//config:config IPCS
//config: bool "ipcs (11 kb)"
//config: default y
//config: help
//config: The ipcs utility is used to provide information on the currently
//config: allocated System V interprocess (IPC) objects in the system.
//applet:IF_IPCS(APPLET_NOEXEC(ipcs, ipcs, BB_DIR_USR_BIN, BB_SUID_DROP, ipcs))
//kbuild:lib-$(CONFIG_IPCS) += ipcs.o
/* X/OPEN tells us to use <sys/{types,ipc,sem}.h> for semctl() */
/* X/OPEN tells us to use <sys/{types,ipc,msg}.h> for msgctl() */
/* X/OPEN tells us to use <sys/{types,ipc,shm}.h> for shmctl() */
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/msg.h>
#include <sys/shm.h>
#include "libbb.h"
/*-------------------------------------------------------------------*/
/* SHM_DEST and SHM_LOCKED are defined in kernel headers,
but inside #ifdef __KERNEL__ ... #endif */
#ifndef SHM_DEST
/* shm_mode upper byte flags */
#define SHM_DEST 01000 /* segment will be destroyed on last detach */
#define SHM_LOCKED 02000 /* segment will not be swapped */
#endif
/* For older kernels the same holds for the defines below */
#ifndef MSG_STAT
#define MSG_STAT 11
#define MSG_INFO 12
#endif
#ifndef SHM_STAT
#define SHM_STAT 13
#define SHM_INFO 14
struct shm_info {
int used_ids;
unsigned long shm_tot; /* total allocated shm */
unsigned long shm_rss; /* total resident shm */
unsigned long shm_swp; /* total swapped shm */
unsigned long swap_attempts;
unsigned long swap_successes;
};
#endif
#ifndef SEM_STAT
#define SEM_STAT 18
#define SEM_INFO 19
#endif
/* Some versions of libc only define IPC_INFO when __USE_GNU is defined. */
#ifndef IPC_INFO
#define IPC_INFO 3
#endif
/*-------------------------------------------------------------------*/
/* The last arg of semctl is a union semun, but where is it defined?
X/OPEN tells us to define it ourselves, but until recently
Linux include files would also define it. */
2007-04-10 21:12:06 +05:30
#if defined(__GNU_LIBRARY__) && !defined(_SEM_SEMUN_UNDEFINED)
/* union semun is defined by including <sys/sem.h> */
#else
/* according to X/OPEN we have to define it ourselves */
union semun {
int val;
struct semid_ds *buf;
unsigned short *array;
struct seminfo *__buf;
};
#endif
/* X/OPEN (Jan 1987) does not define fields key, seq in struct ipc_perm;
libc 4/5 does not mention struct ipc_term at all, but includes
<linux/ipc.h>, which defines a struct ipc_perm with such fields.
glibc-1.09 has no support for sysv ipc.
glibc 2 uses __key, __seq */
2007-04-10 21:12:06 +05:30
#if defined(__GNU_LIBRARY__) && __GNU_LIBRARY__ > 1
#define KEY __key
#else
#define KEY key
#endif
#define LIMITS 1
#define STATUS 2
#define CREATOR 3
#define TIME 4
#define PID 5
static void print_perms(int id, struct ipc_perm *ipcp)
{
struct passwd *pw;
struct group *gr;
2006-10-27 04:51:47 +05:30
printf("%-10d %-10o", id, ipcp->mode & 0777);
2007-09-27 15:47:53 +05:30
pw = getpwuid(ipcp->cuid);
if (pw) printf(" %-10s", pw->pw_name);
else printf(" %-10d", ipcp->cuid);
gr = getgrgid(ipcp->cgid);
if (gr) printf(" %-10s", gr->gr_name);
else printf(" %-10d", ipcp->cgid);
pw = getpwuid(ipcp->uid);
if (pw) printf(" %-10s", pw->pw_name);
else printf(" %-10d", ipcp->uid);
gr = getgrgid(ipcp->gid);
if (gr) printf(" %-10s\n", gr->gr_name);
else printf(" %-10d\n", ipcp->gid);
}
static NOINLINE void do_shm(int format)
{
int maxid, shmid, id;
struct shmid_ds shmseg;
struct shm_info shm_info;
struct shminfo shminfo;
struct ipc_perm *ipcp = &shmseg.shm_perm;
struct passwd *pw;
maxid = shmctl(0, SHM_INFO, (struct shmid_ds *) (void *) &shm_info);
if (maxid < 0) {
2006-10-27 04:51:47 +05:30
printf("kernel not configured for %s\n", "shared memory");
return;
}
2006-01-25 05:38:53 +05:30
switch (format) {
case LIMITS:
2006-10-27 04:51:47 +05:30
printf("------ Shared Memory %s --------\n", "Limits");
if ((shmctl(0, IPC_INFO, (struct shmid_ds *) (void *) &shminfo)) < 0)
return;
/* glibc 2.1.3 and all earlier libc's have ints as fields
* of struct shminfo; glibc 2.1.91 has unsigned long; ach */
2006-10-27 04:51:47 +05:30
printf("max number of segments = %lu\n"
"max seg size (kbytes) = %lu\n"
"max total shared memory (pages) = %lu\n"
"min seg size (bytes) = %lu\n",
(unsigned long) shminfo.shmmni,
(unsigned long) (shminfo.shmmax >> 10),
(unsigned long) shminfo.shmall,
(unsigned long) shminfo.shmmin);
return;
case STATUS:
2006-10-27 04:51:47 +05:30
printf("------ Shared Memory %s --------\n", "Status");
printf("segments allocated %d\n"
"pages allocated %lu\n"
"pages resident %lu\n"
"pages swapped %lu\n"
"Swap performance: %lu attempts\t%lu successes\n",
shm_info.used_ids,
shm_info.shm_tot,
shm_info.shm_rss,
shm_info.shm_swp,
shm_info.swap_attempts, shm_info.swap_successes);
return;
case CREATOR:
2006-10-27 04:51:47 +05:30
printf("------ Shared Memory %s --------\n", "Segment Creators/Owners");
printf("%-10s %-10s %-10s %-10s %-10s %-10s\n",
"shmid", "perms", "cuid", "cgid", "uid", "gid");
break;
case TIME:
2006-10-27 04:51:47 +05:30
printf("------ Shared Memory %s --------\n", "Attach/Detach/Change Times");
printf("%-10s %-10s %-20s %-20s %-20s\n",
"shmid", "owner", "attached", "detached", "changed");
break;
case PID:
2006-10-27 04:51:47 +05:30
printf("------ Shared Memory %s --------\n", "Creator/Last-op");
printf("%-10s %-10s %-10s %-10s\n",
"shmid", "owner", "cpid", "lpid");
break;
default:
2006-10-27 04:51:47 +05:30
printf("------ Shared Memory %s --------\n", "Segments");
printf("%-10s %-10s %-10s %-10s %-10s %-10s %-12s\n",
"key", "shmid", "owner", "perms", "bytes", "nattch",
"status");
break;
}
for (id = 0; id <= maxid; id++) {
shmid = shmctl(id, SHM_STAT, &shmseg);
2006-01-25 05:38:53 +05:30
if (shmid < 0)
continue;
if (format == CREATOR) {
print_perms(shmid, ipcp);
continue;
}
pw = getpwuid(ipcp->uid);
switch (format) {
2006-01-25 05:38:53 +05:30
case TIME:
if (pw)
2006-10-27 04:51:47 +05:30
printf("%-10d %-10.10s", shmid, pw->pw_name);
else
2006-10-27 04:51:47 +05:30
printf("%-10d %-10d", shmid, ipcp->uid);
/* ctime uses static buffer: use separate calls */
2006-10-27 04:51:47 +05:30
printf(" %-20.16s", shmseg.shm_atime
? ctime(&shmseg.shm_atime) + 4 : "Not set");
2006-10-27 04:51:47 +05:30
printf(" %-20.16s", shmseg.shm_dtime
? ctime(&shmseg.shm_dtime) + 4 : "Not set");
2006-10-27 04:51:47 +05:30
printf(" %-20.16s\n", shmseg.shm_ctime
? ctime(&shmseg.shm_ctime) + 4 : "Not set");
break;
case PID:
if (pw)
2006-10-27 04:51:47 +05:30
printf("%-10d %-10.10s", shmid, pw->pw_name);
else
2006-10-27 04:51:47 +05:30
printf("%-10d %-10d", shmid, ipcp->uid);
printf(" %-10d %-10d\n", shmseg.shm_cpid, shmseg.shm_lpid);
break;
2006-01-25 05:38:53 +05:30
default:
2006-10-27 04:51:47 +05:30
printf("0x%08x ", ipcp->KEY);
if (pw)
2006-10-27 04:51:47 +05:30
printf("%-10d %-10.10s", shmid, pw->pw_name);
else
2006-10-27 04:51:47 +05:30
printf("%-10d %-10d", shmid, ipcp->uid);
printf(" %-10o %-10lu %-10ld %-6s %-6s\n", ipcp->mode & 0777,
/*
* earlier: int, Austin has size_t
*/
(unsigned long) shmseg.shm_segsz,
/*
* glibc-2.1.3 and earlier has unsigned short;
* Austin has shmatt_t
*/
(long) shmseg.shm_nattch,
ipcp->mode & SHM_DEST ? "dest" : " ",
ipcp->mode & SHM_LOCKED ? "locked" : " ");
break;
}
}
}
static NOINLINE void do_sem(int format)
{
int maxid, semid, id;
struct semid_ds semary;
struct seminfo seminfo;
struct ipc_perm *ipcp = &semary.sem_perm;
struct passwd *pw;
union semun arg;
arg.array = (unsigned short *) (void *) &seminfo;
maxid = semctl(0, 0, SEM_INFO, arg);
if (maxid < 0) {
2006-10-27 04:51:47 +05:30
printf("kernel not configured for %s\n", "semaphores");
return;
}
2006-01-25 05:38:53 +05:30
switch (format) {
case LIMITS:
2006-10-27 04:51:47 +05:30
printf("------ Semaphore %s --------\n", "Limits");
arg.array = (unsigned short *) (void *) &seminfo; /* damn union */
if ((semctl(0, 0, IPC_INFO, arg)) < 0)
return;
2006-10-27 04:51:47 +05:30
printf("max number of arrays = %d\n"
"max semaphores per array = %d\n"
"max semaphores system wide = %d\n"
"max ops per semop call = %d\n"
"semaphore max value = %d\n",
seminfo.semmni,
seminfo.semmsl,
seminfo.semmns, seminfo.semopm, seminfo.semvmx);
return;
case STATUS:
2006-10-27 04:51:47 +05:30
printf("------ Semaphore %s --------\n", "Status");
printf("used arrays = %d\n"
"allocated semaphores = %d\n",
seminfo.semusz, seminfo.semaem);
return;
case CREATOR:
2006-10-27 04:51:47 +05:30
printf("------ Semaphore %s --------\n", "Arrays Creators/Owners");
printf("%-10s %-10s %-10s %-10s %-10s %-10s\n",
"semid", "perms", "cuid", "cgid", "uid", "gid");
break;
case TIME:
2006-10-27 04:51:47 +05:30
printf("------ Shared Memory %s --------\n", "Operation/Change Times");
printf("%-8s %-10s %-26.24s %-26.24s\n",
"shmid", "owner", "last-op", "last-changed");
break;
case PID:
break;
default:
2006-10-27 04:51:47 +05:30
printf("------ Semaphore %s --------\n", "Arrays");
printf("%-10s %-10s %-10s %-10s %-10s\n",
"key", "semid", "owner", "perms", "nsems");
break;
}
for (id = 0; id <= maxid; id++) {
arg.buf = (struct semid_ds *) &semary;
semid = semctl(id, 0, SEM_STAT, arg);
if (semid < 0)
continue;
if (format == CREATOR) {
print_perms(semid, ipcp);
continue;
}
pw = getpwuid(ipcp->uid);
switch (format) {
2006-01-25 05:38:53 +05:30
case TIME:
if (pw)
2006-10-27 04:51:47 +05:30
printf("%-8d %-10.10s", semid, pw->pw_name);
else
2006-10-27 04:51:47 +05:30
printf("%-8d %-10d", semid, ipcp->uid);
/* ctime uses static buffer: use separate calls */
2006-10-27 04:51:47 +05:30
printf(" %-26.24s", semary.sem_otime
? ctime(&semary.sem_otime) : "Not set");
2006-10-27 04:51:47 +05:30
printf(" %-26.24s\n", semary.sem_ctime
? ctime(&semary.sem_ctime) : "Not set");
break;
case PID:
break;
2006-01-25 05:38:53 +05:30
default:
2006-10-27 04:51:47 +05:30
printf("0x%08x ", ipcp->KEY);
if (pw)
2006-10-27 04:51:47 +05:30
printf("%-10d %-10.9s", semid, pw->pw_name);
else
2006-10-27 04:51:47 +05:30
printf("%-10d %-9d", semid, ipcp->uid);
printf(" %-10o %-10ld\n", ipcp->mode & 0777,
/*
* glibc-2.1.3 and earlier has unsigned short;
* glibc-2.1.91 has variation between
* unsigned short and unsigned long
* Austin prescribes unsigned short.
*/
(long) semary.sem_nsems);
break;
}
}
}
static NOINLINE void do_msg(int format)
{
int maxid, msqid, id;
struct msqid_ds msgque;
struct msginfo msginfo;
struct ipc_perm *ipcp = &msgque.msg_perm;
struct passwd *pw;
maxid = msgctl(0, MSG_INFO, (struct msqid_ds *) (void *) &msginfo);
if (maxid < 0) {
2006-10-27 04:51:47 +05:30
printf("kernel not configured for %s\n", "message queues");
return;
}
2006-01-25 05:38:53 +05:30
switch (format) {
case LIMITS:
if ((msgctl(0, IPC_INFO, (struct msqid_ds *) (void *) &msginfo)) < 0)
return;
2006-10-27 04:51:47 +05:30
printf("------ Message%s --------\n", "s: Limits");
printf("max queues system wide = %d\n"
"max size of message (bytes) = %d\n"
"default max size of queue (bytes) = %d\n",
msginfo.msgmni, msginfo.msgmax, msginfo.msgmnb);
return;
case STATUS:
2006-10-27 04:51:47 +05:30
printf("------ Message%s --------\n", "s: Status");
printf("allocated queues = %d\n"
"used headers = %d\n"
"used space = %d bytes\n",
msginfo.msgpool, msginfo.msgmap, msginfo.msgtql);
return;
case CREATOR:
2006-10-27 04:51:47 +05:30
printf("------ Message%s --------\n", " Queues: Creators/Owners");
printf("%-10s %-10s %-10s %-10s %-10s %-10s\n",
"msqid", "perms", "cuid", "cgid", "uid", "gid");
break;
case TIME:
2006-10-27 04:51:47 +05:30
printf("------ Message%s --------\n", " Queues Send/Recv/Change Times");
printf("%-8s %-10s %-20s %-20s %-20s\n",
"msqid", "owner", "send", "recv", "change");
break;
case PID:
2006-10-27 04:51:47 +05:30
printf("------ Message%s --------\n", " Queues PIDs");
printf("%-10s %-10s %-10s %-10s\n",
"msqid", "owner", "lspid", "lrpid");
break;
default:
2006-10-27 04:51:47 +05:30
printf("------ Message%s --------\n", " Queues");
printf("%-10s %-10s %-10s %-10s %-12s %-12s\n",
"key", "msqid", "owner", "perms", "used-bytes", "messages");
break;
}
for (id = 0; id <= maxid; id++) {
msqid = msgctl(id, MSG_STAT, &msgque);
if (msqid < 0)
continue;
if (format == CREATOR) {
print_perms(msqid, ipcp);
continue;
}
pw = getpwuid(ipcp->uid);
switch (format) {
case TIME:
if (pw)
2006-10-27 04:51:47 +05:30
printf("%-8d %-10.10s", msqid, pw->pw_name);
else
2006-10-27 04:51:47 +05:30
printf("%-8d %-10d", msqid, ipcp->uid);
printf(" %-20.16s", msgque.msg_stime
? ctime(&msgque.msg_stime) + 4 : "Not set");
2006-10-27 04:51:47 +05:30
printf(" %-20.16s", msgque.msg_rtime
? ctime(&msgque.msg_rtime) + 4 : "Not set");
2006-10-27 04:51:47 +05:30
printf(" %-20.16s\n", msgque.msg_ctime
? ctime(&msgque.msg_ctime) + 4 : "Not set");
break;
case PID:
if (pw)
2006-10-27 04:51:47 +05:30
printf("%-8d %-10.10s", msqid, pw->pw_name);
else
2006-10-27 04:51:47 +05:30
printf("%-8d %-10d", msqid, ipcp->uid);
printf(" %5d %5d\n", msgque.msg_lspid, msgque.msg_lrpid);
break;
default:
2006-10-27 04:51:47 +05:30
printf("0x%08x ", ipcp->KEY);
if (pw)
2006-10-27 04:51:47 +05:30
printf("%-10d %-10.10s", msqid, pw->pw_name);
else
2006-10-27 04:51:47 +05:30
printf("%-10d %-10d", msqid, ipcp->uid);
printf(" %-10o %-12ld %-12ld\n", ipcp->mode & 0777,
/*
* glibc-2.1.3 and earlier has unsigned short;
* glibc-2.1.91 has variation between
* unsigned short, unsigned long
* Austin has msgqnum_t
*/
(long) msgque.msg_cbytes, (long) msgque.msg_qnum);
break;
}
}
}
static void print_shm(int shmid)
{
struct shmid_ds shmds;
struct ipc_perm *ipcp = &shmds.shm_perm;
if (shmctl(shmid, IPC_STAT, &shmds) == -1) {
libbb: reduce the overhead of single parameter bb_error_msg() calls Back in 2007, commit 0c97c9d43707 ("'simple' error message functions by Loic Grenie") introduced bb_simple_perror_msg() to allow for a lower overhead call to bb_perror_msg() when only a string was being printed with no parameters. This saves space for some CPU architectures because it avoids the overhead of a call to a variadic function. However there has never been a simple version of bb_error_msg(), and since 2007 many new calls to bb_perror_msg() have been added that only take a single parameter and so could have been using bb_simple_perror_message(). This changeset introduces 'simple' versions of bb_info_msg(), bb_error_msg(), bb_error_msg_and_die(), bb_herror_msg() and bb_herror_msg_and_die(), and replaces all calls that only take a single parameter, or use something like ("%s", arg), with calls to the corresponding 'simple' version. Since it is likely that single parameter calls to the variadic functions may be accidentally reintroduced in the future a new debugging config option WARN_SIMPLE_MSG has been introduced. This uses some macro magic which will cause any such calls to generate a warning, but this is turned off by default to avoid use of the unpleasant macros in normal circumstances. This is a large changeset due to the number of calls that have been replaced. The only files that contain changes other than simple substitution of function calls are libbb.h, libbb/herror_msg.c, libbb/verror_msg.c and libbb/xfuncs_printf.c. In miscutils/devfsd.c, networking/udhcp/common.h and util-linux/mdev.c additonal macros have been added for logging so that single parameter and multiple parameter logging variants exist. The amount of space saved varies considerably by architecture, and was found to be as follows (for 'defconfig' using GCC 7.4): Arm: -92 bytes MIPS: -52 bytes PPC: -1836 bytes x86_64: -938 bytes Note that for the MIPS architecture only an exception had to be made disabling the 'simple' calls for 'udhcp' (in networking/udhcp/common.h) because it made these files larger on MIPS. Signed-off-by: James Byrne <james.byrne@origamienergy.com> Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2019-07-02 15:05:03 +05:30
bb_simple_perror_msg("shmctl");
return;
}
2006-10-27 04:51:47 +05:30
printf("\nShared memory Segment shmid=%d\n"
"uid=%d\tgid=%d\tcuid=%d\tcgid=%d\n"
"mode=%#o\taccess_perms=%#o\n"
"bytes=%ld\tlpid=%d\tcpid=%d\tnattch=%ld\n",
shmid,
ipcp->uid, ipcp->gid, ipcp->cuid, ipcp->cgid,
ipcp->mode, ipcp->mode & 0777,
(long) shmds.shm_segsz, shmds.shm_lpid, shmds.shm_cpid,
(long) shmds.shm_nattch);
2006-10-27 04:51:47 +05:30
printf("att_time=%-26.24s\n",
shmds.shm_atime ? ctime(&shmds.shm_atime) : "Not set");
2006-10-27 04:51:47 +05:30
printf("det_time=%-26.24s\n",
shmds.shm_dtime ? ctime(&shmds.shm_dtime) : "Not set");
2006-10-27 04:51:47 +05:30
printf("change_time=%-26.24s\n\n", ctime(&shmds.shm_ctime));
}
static void print_msg(int msqid)
{
struct msqid_ds buf;
struct ipc_perm *ipcp = &buf.msg_perm;
if (msgctl(msqid, IPC_STAT, &buf) == -1) {
libbb: reduce the overhead of single parameter bb_error_msg() calls Back in 2007, commit 0c97c9d43707 ("'simple' error message functions by Loic Grenie") introduced bb_simple_perror_msg() to allow for a lower overhead call to bb_perror_msg() when only a string was being printed with no parameters. This saves space for some CPU architectures because it avoids the overhead of a call to a variadic function. However there has never been a simple version of bb_error_msg(), and since 2007 many new calls to bb_perror_msg() have been added that only take a single parameter and so could have been using bb_simple_perror_message(). This changeset introduces 'simple' versions of bb_info_msg(), bb_error_msg(), bb_error_msg_and_die(), bb_herror_msg() and bb_herror_msg_and_die(), and replaces all calls that only take a single parameter, or use something like ("%s", arg), with calls to the corresponding 'simple' version. Since it is likely that single parameter calls to the variadic functions may be accidentally reintroduced in the future a new debugging config option WARN_SIMPLE_MSG has been introduced. This uses some macro magic which will cause any such calls to generate a warning, but this is turned off by default to avoid use of the unpleasant macros in normal circumstances. This is a large changeset due to the number of calls that have been replaced. The only files that contain changes other than simple substitution of function calls are libbb.h, libbb/herror_msg.c, libbb/verror_msg.c and libbb/xfuncs_printf.c. In miscutils/devfsd.c, networking/udhcp/common.h and util-linux/mdev.c additonal macros have been added for logging so that single parameter and multiple parameter logging variants exist. The amount of space saved varies considerably by architecture, and was found to be as follows (for 'defconfig' using GCC 7.4): Arm: -92 bytes MIPS: -52 bytes PPC: -1836 bytes x86_64: -938 bytes Note that for the MIPS architecture only an exception had to be made disabling the 'simple' calls for 'udhcp' (in networking/udhcp/common.h) because it made these files larger on MIPS. Signed-off-by: James Byrne <james.byrne@origamienergy.com> Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2019-07-02 15:05:03 +05:30
bb_simple_perror_msg("msgctl");
return;
}
2006-10-27 04:51:47 +05:30
printf("\nMessage Queue msqid=%d\n"
"uid=%d\tgid=%d\tcuid=%d\tcgid=%d\tmode=%#o\n"
"cbytes=%ld\tqbytes=%ld\tqnum=%ld\tlspid=%d\tlrpid=%d\n",
msqid, ipcp->uid, ipcp->gid, ipcp->cuid, ipcp->cgid, ipcp->mode,
/*
* glibc-2.1.3 and earlier has unsigned short;
* glibc-2.1.91 has variation between
* unsigned short, unsigned long
* Austin has msgqnum_t (for msg_qbytes)
*/
(long) buf.msg_cbytes, (long) buf.msg_qbytes,
(long) buf.msg_qnum, buf.msg_lspid, buf.msg_lrpid);
2006-10-27 04:51:47 +05:30
printf("send_time=%-26.24s\n",
buf.msg_stime ? ctime(&buf.msg_stime) : "Not set");
2006-10-27 04:51:47 +05:30
printf("rcv_time=%-26.24s\n",
buf.msg_rtime ? ctime(&buf.msg_rtime) : "Not set");
2006-10-27 04:51:47 +05:30
printf("change_time=%-26.24s\n\n",
buf.msg_ctime ? ctime(&buf.msg_ctime) : "Not set");
}
static void print_sem(int semid)
{
struct semid_ds semds;
struct ipc_perm *ipcp = &semds.sem_perm;
union semun arg;
unsigned int i;
arg.buf = &semds;
if (semctl(semid, 0, IPC_STAT, arg)) {
libbb: reduce the overhead of single parameter bb_error_msg() calls Back in 2007, commit 0c97c9d43707 ("'simple' error message functions by Loic Grenie") introduced bb_simple_perror_msg() to allow for a lower overhead call to bb_perror_msg() when only a string was being printed with no parameters. This saves space for some CPU architectures because it avoids the overhead of a call to a variadic function. However there has never been a simple version of bb_error_msg(), and since 2007 many new calls to bb_perror_msg() have been added that only take a single parameter and so could have been using bb_simple_perror_message(). This changeset introduces 'simple' versions of bb_info_msg(), bb_error_msg(), bb_error_msg_and_die(), bb_herror_msg() and bb_herror_msg_and_die(), and replaces all calls that only take a single parameter, or use something like ("%s", arg), with calls to the corresponding 'simple' version. Since it is likely that single parameter calls to the variadic functions may be accidentally reintroduced in the future a new debugging config option WARN_SIMPLE_MSG has been introduced. This uses some macro magic which will cause any such calls to generate a warning, but this is turned off by default to avoid use of the unpleasant macros in normal circumstances. This is a large changeset due to the number of calls that have been replaced. The only files that contain changes other than simple substitution of function calls are libbb.h, libbb/herror_msg.c, libbb/verror_msg.c and libbb/xfuncs_printf.c. In miscutils/devfsd.c, networking/udhcp/common.h and util-linux/mdev.c additonal macros have been added for logging so that single parameter and multiple parameter logging variants exist. The amount of space saved varies considerably by architecture, and was found to be as follows (for 'defconfig' using GCC 7.4): Arm: -92 bytes MIPS: -52 bytes PPC: -1836 bytes x86_64: -938 bytes Note that for the MIPS architecture only an exception had to be made disabling the 'simple' calls for 'udhcp' (in networking/udhcp/common.h) because it made these files larger on MIPS. Signed-off-by: James Byrne <james.byrne@origamienergy.com> Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2019-07-02 15:05:03 +05:30
bb_simple_perror_msg("semctl");
return;
}
2006-10-27 04:51:47 +05:30
printf("\nSemaphore Array semid=%d\n"
"uid=%d\t gid=%d\t cuid=%d\t cgid=%d\n"
"mode=%#o, access_perms=%#o\n"
"nsems = %ld\n"
"otime = %-26.24s\n",
semid,
ipcp->uid, ipcp->gid, ipcp->cuid, ipcp->cgid,
ipcp->mode, ipcp->mode & 0777,
(long) semds.sem_nsems,
semds.sem_otime ? ctime(&semds.sem_otime) : "Not set");
2006-10-27 04:51:47 +05:30
printf("ctime = %-26.24s\n"
"%-10s %-10s %-10s %-10s %-10s\n",
ctime(&semds.sem_ctime),
"semnum", "value", "ncount", "zcount", "pid");
arg.val = 0;
for (i = 0; i < semds.sem_nsems; i++) {
int val, ncnt, zcnt, pid;
val = semctl(semid, i, GETVAL, arg);
ncnt = semctl(semid, i, GETNCNT, arg);
zcnt = semctl(semid, i, GETZCNT, arg);
pid = semctl(semid, i, GETPID, arg);
if (val < 0 || ncnt < 0 || zcnt < 0 || pid < 0) {
libbb: reduce the overhead of single parameter bb_error_msg() calls Back in 2007, commit 0c97c9d43707 ("'simple' error message functions by Loic Grenie") introduced bb_simple_perror_msg() to allow for a lower overhead call to bb_perror_msg() when only a string was being printed with no parameters. This saves space for some CPU architectures because it avoids the overhead of a call to a variadic function. However there has never been a simple version of bb_error_msg(), and since 2007 many new calls to bb_perror_msg() have been added that only take a single parameter and so could have been using bb_simple_perror_message(). This changeset introduces 'simple' versions of bb_info_msg(), bb_error_msg(), bb_error_msg_and_die(), bb_herror_msg() and bb_herror_msg_and_die(), and replaces all calls that only take a single parameter, or use something like ("%s", arg), with calls to the corresponding 'simple' version. Since it is likely that single parameter calls to the variadic functions may be accidentally reintroduced in the future a new debugging config option WARN_SIMPLE_MSG has been introduced. This uses some macro magic which will cause any such calls to generate a warning, but this is turned off by default to avoid use of the unpleasant macros in normal circumstances. This is a large changeset due to the number of calls that have been replaced. The only files that contain changes other than simple substitution of function calls are libbb.h, libbb/herror_msg.c, libbb/verror_msg.c and libbb/xfuncs_printf.c. In miscutils/devfsd.c, networking/udhcp/common.h and util-linux/mdev.c additonal macros have been added for logging so that single parameter and multiple parameter logging variants exist. The amount of space saved varies considerably by architecture, and was found to be as follows (for 'defconfig' using GCC 7.4): Arm: -92 bytes MIPS: -52 bytes PPC: -1836 bytes x86_64: -938 bytes Note that for the MIPS architecture only an exception had to be made disabling the 'simple' calls for 'udhcp' (in networking/udhcp/common.h) because it made these files larger on MIPS. Signed-off-by: James Byrne <james.byrne@origamienergy.com> Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2019-07-02 15:05:03 +05:30
bb_simple_perror_msg_and_die("semctl");
}
printf("%-10u %-10d %-10d %-10d %-10d\n", i, val, ncnt, zcnt, pid);
}
bb_putchar('\n');
}
//usage:#define ipcs_trivial_usage
//usage: "[[-smq] -i SHMID] | [[-asmq] [-tcplu]]"
//usage:#define ipcs_full_usage "\n\n"
//usage: " -i ID Show specific resource"
//usage: "\nResource specification:"
//usage: "\n -m Shared memory segments"
//usage: "\n -q Message queues"
//usage: "\n -s Semaphore arrays"
//usage: "\n -a All (default)"
//usage: "\nOutput format:"
//usage: "\n -t Time"
//usage: "\n -c Creator"
//usage: "\n -p Pid"
//usage: "\n -l Limits"
//usage: "\n -u Summary"
int ipcs_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
2008-07-05 14:48:54 +05:30
int ipcs_main(int argc UNUSED_PARAM, char **argv)
{
int format = 0;
unsigned opt;
char *opt_i;
opt = getopt32(argv, "i:aqsmtcplu", &opt_i);
#define flag_msg (1<<2)
#define flag_sem (1<<3)
#define flag_shm (1<<4)
if (opt & (1<<5)) format = TIME; // -t
if (opt & (1<<6)) format = CREATOR; // -c
if (opt & (1<<7)) format = PID; // -p
if (opt & (1<<8)) format = LIMITS; // -l
if (opt & (1<<9)) format = STATUS; // -u
if (opt & (1<<0)) { // -i
int id;
id = xatoi(opt_i);
if (opt & flag_shm) {
print_shm(id);
fflush_stdout_and_exit_SUCCESS();
}
if (opt & flag_sem) {
print_sem(id);
fflush_stdout_and_exit_SUCCESS();
}
if (opt & flag_msg) {
print_msg(id);
fflush_stdout_and_exit_SUCCESS();
}
bb_show_usage();
}
if ((opt & (1<<1)) // -a
|| !(opt & (flag_msg | flag_sem | flag_shm)) // none of -q,-s,-m == all
) {
opt |= flag_msg | flag_sem | flag_shm;
}
bb_putchar('\n');
if (opt & flag_msg) {
do_msg(format);
bb_putchar('\n');
}
if (opt & flag_shm) {
do_shm(format);
bb_putchar('\n');
}
if (opt & flag_sem) {
do_sem(format);
bb_putchar('\n');
}
fflush_stdout_and_exit_SUCCESS();
}