4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
27 /* All Rights Reserved */
30 #pragma ident "%Z%%M% %I% %E% SMI"
35 * Examine and print certain things about
36 * message queues, semaphores and shared memory.
38 * IPC information is obtained via msgctl64, semctl64 and shmctl64.
39 * As of SunOS 5.8, the IPC identifiers are obtained from msgids(),
40 * semids(), and shmids() rather than reading them from /dev/kmem.
41 * This ensures that the information in each msgid_ds, semid_ds or
42 * shmid_ds data structure that we obtain is complete and consistent,
43 * and allows us not to be a setgid-sys isaexec process.
46 #include <sys/types.h>
48 #include <sys/ipc_impl.h>
69 "usage: ipcs [-AabciJmopqstZ] [-D mtype] [-z zone]\n"
71 static char chdr
[] = "T ID KEY MODE OWNER GROUP";
72 /* common header format */
73 static char chdr2
[] = " CREATOR CGROUP"; /* c option header format */
74 static char chdr3
[] = " PROJECT"; /* J option header format */
75 static char opts
[] = "AabciJmopqstD:z:Z"; /* getopt options */
77 static long mtype
; /* -D: user-supplied message type */
78 static zoneid_t zoneid
; /* -z: user-supplied zone id */
80 static int bflg
, /* biggest size: */
81 /* segsz on m; qbytes on q; nsems on s */
82 cflg
, /* creator's login and group names */
83 Dflg
, /* dump contents of message queues */
84 iflg
, /* ISM attaches */
85 Jflg
, /* dump project name */
86 mflg
, /* shared memory status */
87 oflg
, /* outstanding data: */
88 /* nattch on m; cbytes, qnum on q */
89 pflg
, /* process id's: lrpid, lspid on q; */
91 qflg
, /* message queue status */
92 sflg
, /* semaphore status */
93 tflg
, /* times: atime, ctime, dtime on m; */
94 /* ctime, rtime, stime on q; */
95 /* ctime, otime on s */
96 zflg
, /* show only objects from specified zone */
97 Zflg
, /* display zone name */
98 err
; /* option error count */
100 static void hp(char, char *, struct ipc_perm64
*, int);
101 static void jp(struct ipc_perm64
*);
102 static void tp(ipc_time_t
);
103 static void dumpmsgq(int);
104 static void dumpmsg(long, char *, size_t);
105 static zoneid_t
getzone(char *);
106 static void printzone(zoneid_t
);
109 main(int argc
, char *argv
[])
111 static int *ids
; /* array of IPC identifiers from *ids() */
112 static uint_t nids
; /* number of entries in ids */
114 int o
; /* option flag */
115 int id
; /* IPC identifier */
117 uint_t n
; /* table size */
118 time_t now
; /* date */
120 char *dfmt
; /* date format pointer */
121 char *endptr
; /* terminator for strtol() */
123 (void) setlocale(LC_ALL
, "");
124 (void) textdomain(TEXT_DOMAIN
);
126 (void) memset(tbuf
, 0, sizeof (tbuf
));
127 dfmt
= nl_langinfo(_DATE_FMT
);
129 zoneid
= getzoneid(); /* default zone id if -z and -Z not used */
131 /* Go through the options and set flags. */
132 while ((o
= getopt(argc
, argv
, opts
)) != EOF
) {
135 bflg
= cflg
= iflg
= oflg
= pflg
= tflg
= Jflg
= 1;
138 bflg
= cflg
= oflg
= pflg
= tflg
= 1;
147 mtype
= strtol(optarg
, &endptr
, 0);
148 if (endptr
== optarg
|| *endptr
!= '\0') {
149 (void) fprintf(stderr
,
150 gettext("ipcs: invalid message type: %s\n"),
183 zoneid
= getzone(optarg
);
193 if (err
|| (optind
< argc
)) {
194 (void) fprintf(stderr
, gettext(USAGE
));
198 if ((mflg
+ qflg
+ sflg
) == 0)
199 mflg
= qflg
= sflg
= 1;
202 (void) strftime(tbuf
, sizeof (tbuf
), dfmt
, localtime(&now
));
203 (void) printf(gettext("IPC status from <running system> as of %s\n"),
207 * Print Message Queue status report.
210 struct msqid_ds64 qds
;
213 if (msgids(ids
, nids
, &n
) != 0) {
219 ids
= realloc(ids
, (nids
= n
) * sizeof (int));
222 (void) printf("%s%s%s%s%s%s%s%s\n", chdr
,
224 oflg
? " CBYTES QNUM" : "",
225 bflg
? " QBYTES" : "",
226 pflg
? " LSPID LRPID" : "",
227 tflg
? " STIME RTIME CTIME " : "",
229 Zflg
? " ZONE" : "");
231 (void) printf(gettext("Message Queues:\n"));
233 for (i
= 0; i
< n
; i
++) {
235 if (msgctl64(id
, IPC_STAT64
, &qds
) < 0)
237 /* ignore zone if -Z was used and -z wasn't */
238 if ((zflg
|| !Zflg
) &&
239 qds
.msgx_perm
.ipcx_zoneid
!= zoneid
)
241 hp('q', "SRrw-rw-rw-", &qds
.msgx_perm
, id
);
243 (void) printf(" %6llu %5llu",
244 qds
.msgx_cbytes
, qds
.msgx_qnum
);
246 (void) printf(" %6llu", qds
.msgx_qbytes
);
248 (void) printf(" %5d %5d",
249 (int)qds
.msgx_lspid
, (int)qds
.msgx_lrpid
);
258 printzone(qds
.msgx_perm
.ipcx_zoneid
);
266 * Print Shared Memory status report.
269 struct shmid_ds64 mds
;
272 if (shmids(ids
, nids
, &n
) != 0) {
278 ids
= realloc(ids
, (nids
= n
) * sizeof (int));
281 if (!qflg
|| oflg
|| bflg
|| pflg
|| tflg
|| iflg
)
282 (void) printf("%s%s%s%s%s%s%s%s%s\n", chdr
,
284 oflg
? " NATTCH" : "",
285 bflg
? " SEGSZ" : "",
286 pflg
? " CPID LPID" : "",
287 tflg
? " ATIME DTIME CTIME " : "",
288 iflg
? " ISMATTCH" : "",
290 Zflg
? " ZONE" : "");
292 (void) printf(gettext("Shared Memory:\n"));
294 for (i
= 0; i
< n
; i
++) {
296 if (shmctl64(id
, IPC_STAT64
, &mds
) < 0)
298 /* ignore zone if -Z was used and -z wasn't */
299 if ((zflg
|| !Zflg
) &&
300 mds
.shmx_perm
.ipcx_zoneid
!= zoneid
)
302 hp('m', "--rw-rw-rw-", &mds
.shmx_perm
, id
);
304 (void) printf(" %6llu", mds
.shmx_nattch
);
306 (void) printf(" %10llu", mds
.shmx_segsz
);
308 (void) printf(" %5d %5d",
309 (int)mds
.shmx_cpid
, (int)mds
.shmx_lpid
);
316 (void) printf(" %8llu", mds
.shmx_cnattch
);
320 printzone(mds
.shmx_perm
.ipcx_zoneid
);
326 * Print Semaphore facility status.
329 struct semid_ds64 sds
;
332 struct semid_ds64
*buf
;
338 if (semids(ids
, nids
, &n
) != 0) {
344 ids
= realloc(ids
, (nids
= n
) * sizeof (int));
347 if (bflg
|| tflg
|| (!qflg
&& !mflg
))
348 (void) printf("%s%s%s%s%s%s\n", chdr
,
350 bflg
? " NSEMS" : "",
351 tflg
? " OTIME CTIME " : "",
353 Zflg
? " ZONE" : "");
355 (void) printf(gettext("Semaphores:\n"));
357 for (i
= 0; i
< n
; i
++) {
359 if (semctl64(id
, 0, IPC_STAT64
, semarg
) < 0)
361 /* ignore zone if -Z was used and -z wasn't */
362 if ((zflg
|| !Zflg
) &&
363 sds
.semx_perm
.ipcx_zoneid
!= zoneid
)
365 hp('s', "--ra-ra-ra-", &sds
.semx_perm
, id
);
367 (void) printf(" %5u", sds
.semx_nsems
);
375 printzone(sds
.semx_perm
.ipcx_zoneid
);
384 * hp - common header print
387 hp(char type
, char *modesp
, struct ipc_perm64
*permp
, int slot
)
389 int i
; /* loop control */
390 struct group
*g
; /* ptr to group group entry */
391 struct passwd
*u
; /* ptr to user passwd entry */
394 (void) snprintf(keyfield
, sizeof (keyfield
), " 0x%x", permp
->ipcx_key
);
395 (void) printf("%c %10d %-13s", type
, slot
, keyfield
);
397 for (i
= 02000; i
; modesp
++, i
>>= 1)
398 (void) printf("%c", (permp
->ipcx_mode
& i
) ? *modesp
: '-');
399 if ((u
= getpwuid(permp
->ipcx_uid
)) == NULL
)
400 (void) printf("%9d", (int)permp
->ipcx_uid
);
402 (void) printf("%9.8s", u
->pw_name
);
403 if ((g
= getgrgid(permp
->ipcx_gid
)) == NULL
)
404 (void) printf("%9d", (int)permp
->ipcx_gid
);
406 (void) printf("%9.8s", g
->gr_name
);
409 if ((u
= getpwuid(permp
->ipcx_cuid
)) == NULL
)
410 (void) printf("%9d", (int)permp
->ipcx_cuid
);
412 (void) printf("%9.8s", u
->pw_name
);
413 if ((g
= getgrgid(permp
->ipcx_cgid
)) == NULL
)
414 (void) printf("%9d", (int)permp
->ipcx_cgid
);
416 (void) printf("%9.8s", g
->gr_name
);
421 * jp - project header print
424 jp(struct ipc_perm64
*permp
)
427 char buf
[PROJECT_BUFSZ
];
429 if ((getprojbyid(permp
->ipcx_projid
, &proj
, buf
,
430 PROJECT_BUFSZ
)) == NULL
)
431 (void) printf("%16ld", permp
->ipcx_projid
);
433 (void) printf("%16.15s", proj
.pj_name
);
437 * tp - time entry printer
442 struct tm
*t
; /* ptr to converted time */
443 time_t gmt
= (time_t)gmt64
;
445 if (gmt
&& gmt64
<= UINT_MAX
) {
447 (void) printf(" %2d:%2.2d:%2.2d",
448 t
->tm_hour
, t
->tm_min
, t
->tm_sec
);
450 (void) printf("%9s", gettext(" no-entry"));
454 /* Round up to a sizeof (size_t) boundary */
455 #define SZROUND(x) (((x) + sizeof (size_t) - 1) & ~(sizeof (size_t) - 1))
458 * dumpmsgq - dump all messages on a message queue
463 static struct msgsnap_head
*buf
= NULL
;
464 static size_t bufsize
;
466 struct msgsnap_mhead
*mhead
;
469 /* allocate the minimum required buffer size on first time through */
471 buf
= malloc(bufsize
= sizeof (struct msgsnap_head
));
474 * Fetch all messages specified by mtype from
475 * the queue while leaving the queue intact.
478 if (msgsnap(msqid
, buf
, bufsize
, mtype
) != 0) {
480 * Don't complain; either the user does not have
481 * read permission on msqid or msqid was deleted.
485 if (bufsize
>= buf
->msgsnap_size
) {
486 /* we collected all of the messages */
489 /* The buffer is too small; allocate a bigger buffer */
490 buf
= realloc(buf
, bufsize
= buf
->msgsnap_size
);
494 * Process each message in the queue (there may be none).
495 * The first message header starts just after the buffer header.
497 mhead
= (struct msgsnap_mhead
*)(buf
+ 1);
498 for (i
= 0; i
< buf
->msgsnap_nmsg
; i
++) {
499 size_t mlen
= mhead
->msgsnap_mlen
;
501 dumpmsg(mhead
->msgsnap_mtype
, (char *)(mhead
+ 1), mlen
);
503 /* advance to next message header */
504 /* LINTED alignment */
505 mhead
= (struct msgsnap_mhead
*)
506 ((caddr_t
)(mhead
+ 1) + SZROUND(mlen
));
511 * dumpmsg - dump one message from a message queue.
514 dumpmsg(long type
, char *msg
, size_t msgsize
)
519 (void) printf(gettext(" message type %ld, size %lu\n"),
520 type
, (ulong_t
)msgsize
);
522 for (i
= 0; i
< msgsize
; i
+= 16) {
524 (void) printf(" %5ld: ", (ulong_t
)i
);
525 for (j
= 0; j
< 16; j
++) {
526 if ((k
= i
+ j
) < msgsize
)
527 (void) printf("%2.2x ", msg
[k
] & 0xff);
533 for (j
= 0; j
< 16; j
++) {
534 if ((k
= i
+ j
) >= msgsize
)
537 if (isascii(c
) && isprint(c
))
538 (void) printf("%c", c
);
546 /* convert string containing zone name or id to a numeric id */
552 if (zone_get_id(arg
, &zoneid
) != 0) {
553 (void) fprintf(stderr
,
554 gettext("ipcs: unknown zone: %s\n"), arg
);
561 printzone(zoneid_t id
)
563 char zone_name
[ZONENAME_MAX
];
565 if (getzonenamebyid(id
, zone_name
, sizeof (zone_name
)) < 0)
566 (void) printf("%9d", (int)id
);
568 (void) printf("%9.8s", zone_name
);