ipcs: read shared memory values from /proc

[kzak@redhat.com: - move to ipcutils.{c,h},
                  - fix datatypes to be arch independent]

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
Signed-off-by: Karel Zak <kzak@redhat.com>
This commit is contained in:
Sami Kerola 2012-10-14 16:01:05 +01:00 committed by Karel Zak
parent e5995acda2
commit 058e81540f
3 changed files with 205 additions and 39 deletions

View file

@ -25,14 +25,14 @@
#include "ipcutils.h"
#define LIMITS 1
#define STATUS 2
#define CREATOR 3
#define TIME 4
#define PID 5
void do_shm (char format);
static void do_shm (char format);
void do_sem (char format);
void do_msg (char format);
void print_shm (int id);
@ -190,14 +190,13 @@ static void print_perms (int id, struct ipc_perm *ipcp)
printf(" %-10u\n", ipcp->gid);
}
void do_shm (char format)
static void do_shm (char format)
{
int maxid, shmid, id;
struct shmid_ds shmseg;
int maxid;
struct shm_info shm_info;
struct ipc_perm *ipcp = &shmseg.shm_perm;
struct passwd *pw;
struct ipc_limits lim;
struct shm_data *shmds, *shmdsp;
maxid = shmctl (0, SHM_INFO, (struct shmid_ds *) (void *) &shm_info);
if (maxid < 0) {
@ -269,60 +268,56 @@ void do_shm (char format)
break;
}
for (id = 0; id <= maxid; id++) {
shmid = shmctl (id, SHM_STAT, &shmseg);
if (shmid < 0)
continue;
if (ipc_shm_get_info(maxid, -1, &shmds) < 1)
return;
shmdsp = shmds;
for (shmdsp = shmds; shmdsp->next != NULL; shmdsp = shmdsp->next) {
if (format == CREATOR) {
print_perms (shmid, ipcp);
ipc_print_perms(stdout, &shmdsp->shm_perm);
continue;
}
pw = getpwuid(ipcp->uid);
pw = getpwuid(shmdsp->shm_perm.uid);
switch (format) {
case TIME:
if (pw)
printf ("%-10d %-10.10s", shmid, pw->pw_name);
printf ("%-10d %-10.10s", shmdsp->shm_perm.id, pw->pw_name);
else
printf ("%-10d %-10u", shmid, ipcp->uid);
printf ("%-10d %-10u", shmdsp->shm_perm.id, shmdsp->shm_perm.uid);
/* ctime uses static buffer: use separate calls */
printf(" %-20.16s", shmseg.shm_atime
? ctime(&shmseg.shm_atime) + 4 : _("Not set"));
printf(" %-20.16s", shmseg.shm_dtime
? ctime(&shmseg.shm_dtime) + 4 : _("Not set"));
printf(" %-20.16s\n", shmseg.shm_ctime
? ctime(&shmseg.shm_ctime) + 4 : _("Not set"));
printf(" %-20.16s", shmdsp->shm_atim
? ctime(&shmdsp->shm_atim) + 4 : _("Not set"));
printf(" %-20.16s", shmdsp->shm_dtim
? ctime(&shmdsp->shm_dtim) + 4 : _("Not set"));
printf(" %-20.16s\n", shmdsp->shm_ctim
? ctime(&shmdsp->shm_ctim) + 4 : _("Not set"));
break;
case PID:
if (pw)
printf ("%-10d %-10.10s", shmid, pw->pw_name);
printf ("%-10d %-10.10s", shmdsp->shm_perm.id, pw->pw_name);
else
printf ("%-10d %-10u", shmid, ipcp->uid);
printf (" %-10d %-10d\n",
shmseg.shm_cpid, shmseg.shm_lpid);
printf ("%-10d %-10u", shmdsp->shm_perm.id, shmdsp->shm_perm.uid);
printf (" %-10u %-10u\n",
shmdsp->shm_cprid, shmdsp->shm_lprid);
break;
default:
printf("0x%08x ",ipcp->KEY );
printf("0x%08x ", shmdsp->shm_perm.key);
if (pw)
printf ("%-10d %-10.10s", shmid, pw->pw_name);
printf ("%-10d %-10.10s", shmdsp->shm_perm.id, pw->pw_name);
else
printf ("%-10d %-10u", shmid, ipcp->uid);
printf ("%-10d %-10u", shmdsp->shm_perm.id, shmdsp->shm_perm.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") : " ");
shmdsp->shm_perm.mode & 0777,
shmdsp->shm_segsz,
shmdsp->shm_nattch,
shmdsp->shm_perm.mode & SHM_DEST ? _("dest") : " ",
shmdsp->shm_perm.mode & SHM_LOCKED ? _("locked") : " ");
break;
}
}
ipc_shm_free_info(shmds);
return;
}

View file

@ -1,5 +1,8 @@
#include <inttypes.h>
#include "c.h"
#include "xalloc.h"
#include "path.h"
#include "pathnames.h"
#include "ipcutils.h"
@ -87,3 +90,138 @@ int ipc_shm_get_limits(struct ipc_limits *lim)
return 0;
}
int ipc_shm_get_info(int maxid, int id, struct shm_data **shmds)
{
FILE *f;
int i;
struct shm_data *p;
p = *shmds = xmalloc(sizeof(struct shm_data));
p->next = NULL;
f = path_fopen("r", 0, _PATH_PROC_SYSV_SHM);
if (!f)
goto fallback;
while (fgetc(f) != '\n'); /* skip header */
for (i = 0; !feof(f); i++) {
if (fscanf(f,
"%d %d %o %"SCNu64 " %u %u "
"%"SCNu64 " %u %u %u %u %"SCNu64 " %"SCNu64 " %"SCNu64
" %"SCNu64 " %"SCNu64 "\n",
&p->shm_perm.key,
&p->shm_perm.id,
&p->shm_perm.mode,
&p->shm_segsz,
&p->shm_cprid,
&p->shm_lprid,
&p->shm_nattch,
&p->shm_perm.uid,
&p->shm_perm.gid,
&p->shm_perm.cuid,
&p->shm_perm.cgid,
&p->shm_atim,
&p->shm_dtim,
&p->shm_ctim,
&p->shm_rss,
&p->shm_swp) != 16)
continue;
if (id < 0) {
p->next = xmalloc(sizeof(struct shm_data));
p = p->next;
p->next = NULL;
}
}
if (i == 0)
free(*shmds);
fclose(f);
return i;
/* Fallback; /proc or /sys file(s) missing. */
fallback:
i = id < 0 ? 0 : id;
while (i <= maxid) {
int shmid;
struct shmid_ds shmseg;
struct ipc_perm *ipcp = &shmseg.shm_perm;
shmid = shmctl(i, SHM_STAT, &shmseg);
if (shmid < 0) {
if (-1 < id) {
free(*shmds);
return 0;
}
i++;
continue;
}
p->shm_perm.key = ipcp->KEY;
p->shm_perm.id = shmid;
p->shm_perm.mode = ipcp->mode;
p->shm_segsz = shmseg.shm_segsz;
p->shm_cprid = shmseg.shm_cpid;
p->shm_lprid = shmseg.shm_lpid;
p->shm_nattch = shmseg.shm_nattch;
p->shm_perm.uid = ipcp->uid;
p->shm_perm.gid = ipcp->gid;
p->shm_perm.cuid = ipcp->cuid;
p->shm_perm.cgid = ipcp->cuid;
p->shm_atim = shmseg.shm_atime;
p->shm_dtim = shmseg.shm_dtime;
p->shm_ctim = shmseg.shm_ctime;
p->shm_rss = 0xdead;
p->shm_swp = 0xdead;
if (id < 0) {
p->next = xmalloc(sizeof(struct shm_data));
p = p->next;
p->next = NULL;
i++;
} else
return 1;
}
return i;
}
void ipc_shm_free_info(struct shm_data *shmds)
{
while (shmds) {
struct shm_data *next = shmds->next;
free(shmds);
shmds = next;
}
}
void ipc_print_perms(FILE *f, struct ipc_stat *is)
{
struct passwd *pw;
struct group *gr;
fprintf(f, "%-10d %-10o", is->id, is->mode & 0777);
if ((pw = getpwuid(is->cuid)))
fprintf(f, " %-10s", pw->pw_name);
else
fprintf(f, " %-10u", is->cuid);
if ((gr = getgrgid(is->cgid)))
fprintf(f, " %-10s", gr->gr_name);
else
fprintf(f, " %-10u", is->cgid);
if ((pw = getpwuid(is->uid)))
fprintf(f, " %-10s", pw->pw_name);
else
fprintf(f, " %-10u", is->uid);
if ((gr = getgrgid(is->gid)))
fprintf(f, " %-10s\n", gr->gr_name);
else
fprintf(f, " %-10u\n", is->gid);
}

View file

@ -99,4 +99,37 @@ extern int ipc_msg_get_limits(struct ipc_limits *lim);
extern int ipc_sem_get_limits(struct ipc_limits *lim);
extern int ipc_shm_get_limits(struct ipc_limits *lim);
struct ipc_stat {
int id;
key_t key;
uid_t uid; /* current uid */
gid_t gid; /* current gid */
uid_t cuid; /* creator uid */
gid_t cgid; /* creator gid */
unsigned int mode;
};
extern void ipc_print_perms(FILE *f, struct ipc_stat *is);
/* See 'struct shmid_kernel' in kernel sources
*/
struct shm_data {
struct ipc_stat shm_perm;
uint64_t shm_nattch;
uint64_t shm_segsz;
time_t shm_atim;
time_t shm_dtim;
time_t shm_ctim;
pid_t shm_cprid;
pid_t shm_lprid;
uint64_t shm_rss;
uint64_t shm_swp;
struct shm_data *next;
};
extern int ipc_shm_get_info(int maxid, int id, struct shm_data **shmds);
extern void ipc_shm_free_info(struct shm_data *shmds);
#endif /* UTIL_LINUX_IPCUTILS_H */