2 * Copyright (c) 1994 SigmaSoft, Th. Lockert <tholo@sigmasoft.com>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. The name of the author may not be used to endorse or promote products
14 * derived from this software without specific prior written permission.
16 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
17 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
18 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
19 * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 #include <sys/cdefs.h>
45 #include <sys/types.h>
46 #include <sys/ucred.h>
49 #include <sys/param.h>
50 #include <sys/sysctl.h>
53 #define KERNEL 1 /* To get new ipc_perm and __(sem|shm|msg)ds_new */
55 #include "sys/sem_internal.h"
56 #include "sys/shm_internal.h"
60 /* The following is a kludge, until the problem of multiple inclusions
61 of ipc.h is taken care of. */
62 #ifndef IXSEQ_TO_IPCID
63 #define IXSEQ_TO_IPCID(ix,perm) (((perm._seq) << 16L) | (ix & 0xffff))
67 fmt_perm(u_short mode
, char write_char
)
69 static char buffer
[100];
73 buffer
[2] = ((mode
& 0400) ?
'r' : '-');
74 buffer
[3] = ((mode
& 0200) ? write_char
: '-');
76 buffer
[5] = ((mode
& 0040) ?
'r' : '-');
77 buffer
[6] = ((mode
& 0020) ? write_char
: '-');
79 buffer
[8] = ((mode
& 0004) ?
'r' : '-');
80 buffer
[9] = ((mode
& 0002) ? write_char
: '-');
87 cvt_time(time_t t
, char *buf
)
92 strcpy(buf
, "no-entry");
95 sprintf(buf
, "%2d:%02d:%02d",
96 tm
->tm_hour
, tm
->tm_min
, tm
->tm_sec
);
108 #define OUTSTANDING 4
114 errx(EX_USAGE
, "%s","usage: ipcs [-abcmopqstMQST]\n");
117 int safe_sysctlbyname(const char *name
, void *oldp
, size_t *oldlenp
, void *newp
,
123 if (seteuid(0)) /* iterator needs root write access to sysctl */
124 err(1, "seteuid(0) failed");
126 rv
= sysctlbyname(name
, oldp
, oldlenp
, newp
, newlen
);
130 if (seteuid(getuid()))
131 err(1, "seteuid(%d) failed", getuid());
147 char datestring
[100];
150 if (seteuid(getuid())) /* run as user */
151 err(1, "seteuid(%d) failed", getuid());
153 while ((i
= getopt(argc
, argv
, "MmQqSsabcoptT")) != -1)
174 display
= SHMTOTAL
| MSGTOTAL
| SEMTOTAL
;
177 option
|= BIGGEST
| CREATOR
| OUTSTANDING
| PID
| TIME
;
186 option
|= OUTSTANDING
;
198 display
= SHMINFO
| MSGINFO
| SEMINFO
;
200 if (0 == strftime(datestring
, sizeof(datestring
), "%a %b %e %H:%M:%S %Z %Y", localtime(&now
)))
201 errx(1, "strftime failed\n");
202 printf("IPC status from <running system> as of %s\n", datestring
);
203 if ((display
& (MSGINFO
| MSGTOTAL
))) {
204 if (display
& MSGTOTAL
) {
205 struct IPCS_command ic
;
206 struct msginfo msginfo
;
207 size_t ic_size
= sizeof(ic
);
209 ic
.ipcs_magic
= IPCS_MAGIC
;
210 ic
.ipcs_op
= IPCS_MSG_CONF
;
211 ic
.ipcs_cursor
= 0; /* 0 for fw. compat. */
212 ic
.ipcs_data
= &msginfo
;
213 ic
.ipcs_datalen
= sizeof(msginfo
);
215 if (safe_sysctlbyname(IPCS_MSG_SYSCTL
, &ic
, &ic_size
, &ic
, ic_size
)) {
216 if (errno
!= EPERM
) {
218 snprintf(buffer
, 1024, "sysctlbyname(IPCS_MSG_SYSCTL, op=CONF, &ic, &%ld) datalen=%d",
219 sizeof(ic
), ic
.ipcs_datalen
);
222 perror("sysctlbyname IPCS_MSG_SYSCTL");
225 printf("msginfo:\n");
226 printf("\tmsgmax: %6d\t(max characters in a message)\n",
228 printf("\tmsgmni: %6d\t(# of message queues)\n",
230 printf("\tmsgmnb: %6d\t(max characters in a message queue)\n",
232 printf("\tmsgtql: %6d\t(max # of messages in system)\n",
234 printf("\tmsgssz: %6d\t(size of a message segment)\n",
236 printf("\tmsgseg: %6d\t(# of message segments in system)\n\n",
239 if (display
& MSGINFO
) {
240 struct IPCS_command ic
;
241 struct __msqid_ds_new ds
;
242 struct __msqid_ds_new
*msqptr
= &ds
;
243 size_t ic_size
= sizeof(ic
);
245 printf("T ID KEY MODE OWNER GROUP");
246 if (option
& CREATOR
)
247 printf(" CREATOR CGROUP");
248 if (option
& OUTSTANDING
)
249 printf(" CBYTES QNUM");
250 if (option
& BIGGEST
)
253 printf(" LSPID LRPID");
255 printf(" STIME RTIME CTIME");
256 printf("\nMessage Queues:\n");
258 ic
.ipcs_magic
= IPCS_MAGIC
;
259 ic
.ipcs_op
= IPCS_MSG_ITER
;
260 ic
.ipcs_cursor
= 0; /* start */
261 ic
.ipcs_datalen
= sizeof(*msqptr
);
262 ic
.ipcs_data
= msqptr
;
264 memset(msqptr
, 0, sizeof(*msqptr
));
266 while(!(safe_sysctlbyname(IPCS_MSG_SYSCTL
, &ic
, &ic_size
, &ic
, ic_size
))) {
267 ic
.ipcs_data
= msqptr
;
269 if (msqptr
->msg_qbytes
!= 0) {
270 char stime_buf
[100], rtime_buf
[100],
273 cvt_time(msqptr
->msg_stime
, stime_buf
);
274 cvt_time(msqptr
->msg_rtime
, rtime_buf
);
275 cvt_time(msqptr
->msg_ctime
, ctime_buf
);
277 printf("q %6d 0x%08x %s %8s %8s",
278 IXSEQ_TO_IPCID(ic
.ipcs_cursor
-1, msqptr
->msg_perm
),
279 (int)msqptr
->msg_perm
._key
,
280 fmt_perm(msqptr
->msg_perm
.mode
, 'w'),
281 user_from_uid(msqptr
->msg_perm
.uid
, 0),
282 group_from_gid(msqptr
->msg_perm
.gid
, 0));
284 if (option
& CREATOR
)
286 user_from_uid(msqptr
->msg_perm
.cuid
, 0),
287 group_from_gid(msqptr
->msg_perm
.cgid
, 0));
289 if (option
& OUTSTANDING
)
294 if (option
& BIGGEST
)
311 memset(msqptr
, 0, sizeof(*msqptr
));
315 if (errno
!= ENOENT
&& errno
!= ERANGE
) {
316 if (errno
!= EPERM
) {
317 errx(1, "sysctlbyname(IPCS_MSG_SYSCTL, op=ITER, &ic, &%ld) datalen=%d failed:%s\n",
318 sizeof(ic
), ic
.ipcs_datalen
, strerror(errno
));
320 errx(1, "sysctlbyname IPCS_MSG_SYSCTL: %s", strerror(errno
));
325 if (display
& (MSGINFO
| MSGTOTAL
)) {
326 errx(1, "%s", "SVID messages facility not configured in the system\n");
329 if ((display
& (SHMINFO
| SHMTOTAL
))) {
330 if (display
& SHMTOTAL
) {
331 struct IPCS_command ic
;
332 struct shminfo shminfo
;
333 size_t ic_size
= sizeof(ic
);
335 ic
.ipcs_magic
= IPCS_MAGIC
;
336 ic
.ipcs_op
= IPCS_SHM_CONF
;
337 ic
.ipcs_cursor
= 0; /* 0 for fw. compat. */
338 ic
.ipcs_data
= &shminfo
;
339 ic
.ipcs_datalen
= sizeof(shminfo
);
341 if (safe_sysctlbyname(IPCS_SHM_SYSCTL
, &ic
, &ic_size
, &ic
, ic_size
)) {
342 if (errno
!= EPERM
) {
343 errx(1, "sysctlbyname(IPCS_SHM_SYSCTL, op=CONF, &ic, &%ld) datalen=%d failed: %s\n",
344 sizeof(ic
), ic
.ipcs_datalen
, strerror(errno
));
346 errx(1, "sysctlbyname: %s", strerror(errno
));
348 printf("shminfo:\n");
349 printf("\tshmmax: %7lld\t(max shared memory segment size)\n",
351 printf("\tshmmin: %7lld\t(min shared memory segment size)\n",
353 printf("\tshmmni: %7lld\t(max number of shared memory identifiers)\n",
355 printf("\tshmseg: %7lld\t(max shared memory segments per process)\n",
357 printf("\tshmall: %7lld\t(max amount of shared memory in pages)\n\n",
360 if (display
& SHMINFO
) {
361 struct IPCS_command ic
;
362 struct __shmid_ds_new ds
;
363 struct __shmid_ds_new
*shmptr
= &ds
;
364 size_t ic_size
= sizeof(ic
);
366 printf("T ID KEY MODE OWNER GROUP");
367 if (option
& CREATOR
)
368 printf(" CREATOR CGROUP");
369 if (option
& OUTSTANDING
)
371 if (option
& BIGGEST
)
374 printf(" CPID LPID");
376 printf(" ATIME DTIME CTIME");
377 printf("\nShared Memory:\n");
380 ic
.ipcs_magic
= IPCS_MAGIC
;
381 ic
.ipcs_op
= IPCS_SHM_ITER
;
382 ic
.ipcs_cursor
= 0; /* start */
383 ic
.ipcs_datalen
= sizeof(*shmptr
);
384 ic
.ipcs_data
= shmptr
;
385 memset(shmptr
, 0, sizeof(shmptr
));
387 while(!(safe_sysctlbyname(IPCS_SHM_SYSCTL
, &ic
, &ic_size
, &ic
, ic_size
))) {
388 ic
.ipcs_data
= shmptr
; /* xnu workaround */
390 if (shmptr
->shm_perm
.mode
& 0x0800) {
391 char atime_buf
[100], dtime_buf
[100],
394 cvt_time(shmptr
->shm_atime
, atime_buf
);
395 cvt_time(shmptr
->shm_dtime
, dtime_buf
);
396 cvt_time(shmptr
->shm_ctime
, ctime_buf
);
398 printf("m %6d 0x%08x %s %8s %8s",
399 IXSEQ_TO_IPCID(ic
.ipcs_cursor
-1, shmptr
->shm_perm
),
400 (int)shmptr
->shm_perm
._key
,
401 fmt_perm(shmptr
->shm_perm
.mode
, 'w'),
402 user_from_uid(shmptr
->shm_perm
.uid
, 0),
403 group_from_gid(shmptr
->shm_perm
.gid
, 0));
405 if (option
& CREATOR
)
407 user_from_uid(shmptr
->shm_perm
.cuid
, 0),
408 group_from_gid(shmptr
->shm_perm
.cgid
, 0));
410 if (option
& OUTSTANDING
)
414 if (option
& BIGGEST
)
431 memset(shmptr
, 0, sizeof(*shmptr
));
435 if (errno
!= ENOENT
&& errno
!= ERANGE
) {
436 if (errno
!= EPERM
) {
437 errx(1, "sysctlbyname(IPCS_SHM_SYSCTL, op=ITER, &ic, &%ld) datalen=%d failed:%s\n",
438 sizeof(ic
), ic
.ipcs_datalen
, strerror(errno
));
440 errx(1, "sysctlbyname: %s", strerror(errno
));
447 if (display
& (SHMINFO
| SHMTOTAL
)) {
448 errx(1, "%s", "SVID shared memory facility not configured in the system\n");
451 if ((display
& (SEMINFO
| SEMTOTAL
))) {
452 if (display
& SEMTOTAL
) {
453 struct IPCS_command ic
;
454 struct seminfo seminfo
;
455 size_t ic_size
= sizeof(ic
);
457 ic
.ipcs_magic
= IPCS_MAGIC
;
458 ic
.ipcs_op
= IPCS_SEM_CONF
;
459 ic
.ipcs_cursor
= 0; /* 0 for fw. compat. */
460 ic
.ipcs_data
= &seminfo
;
461 ic
.ipcs_datalen
= sizeof(seminfo
);
463 if (safe_sysctlbyname(IPCS_SEM_SYSCTL
, &ic
, &ic_size
, &ic
, ic_size
)) {
464 if (errno
!= EPERM
) {
466 snprintf(buffer
, 1024, "sysctlbyname(IPCS_SEM_SYSCTL, op=CONF, &ic, &%ld) datalen=%d",
467 sizeof(ic
), ic
.ipcs_datalen
);
470 perror("sysctlbyname IPCS_SEM_SYSCTL/SEM_CONF");
473 printf("seminfo:\n");
474 printf("\tsemmap: %6d\t(# of entries in semaphore map)\n",
476 printf("\tsemmni: %6d\t(# of semaphore identifiers)\n",
478 printf("\tsemmns: %6d\t(# of semaphores in system)\n",
480 printf("\tsemmnu: %6d\t(# of undo structures in system)\n",
482 printf("\tsemmsl: %6d\t(max # of semaphores per id)\n",
484 printf("\tsemopm: %6d\t(max # of operations per semop call)\n",
486 printf("\tsemume: %6d\t(max # of undo entries per process)\n",
488 printf("\tsemusz: %6d\t(size in bytes of undo structure)\n",
490 printf("\tsemvmx: %6d\t(semaphore maximum value)\n",
492 printf("\tsemaem: %6d\t(adjust on exit max value)\n\n",
495 if (display
& SEMINFO
) {
496 struct IPCS_command ic
;
497 struct __semid_ds_new ds
;
498 struct __semid_ds_new
*semaptr
= &ds
;
499 size_t ic_size
= sizeof(ic
);
501 printf("T ID KEY MODE OWNER GROUP");
502 if (option
& CREATOR
)
503 printf(" CREATOR CGROUP");
504 if (option
& BIGGEST
)
507 printf(" OTIME CTIME");
508 printf("\nSemaphores:\n");
510 ic
.ipcs_magic
= IPCS_MAGIC
;
511 ic
.ipcs_op
= IPCS_SEM_ITER
;
512 ic
.ipcs_cursor
= 0; /* start */
513 ic
.ipcs_datalen
= sizeof(*semaptr
);
514 ic
.ipcs_data
= semaptr
;
516 memset(semaptr
, 0, sizeof(*semaptr
));
518 while(!(safe_sysctlbyname(IPCS_SEM_SYSCTL
, &ic
, &ic_size
, &ic
, ic_size
))) {
519 ic
.ipcs_data
= semaptr
; /* xnu workaround */
521 if ((semaptr
->sem_perm
.mode
& SEM_ALLOC
) != 0) {
522 char ctime_buf
[100], otime_buf
[100];
524 cvt_time(semaptr
->sem_otime
, otime_buf
);
525 cvt_time(semaptr
->sem_ctime
, ctime_buf
);
527 printf("s %6d 0x%08x %s %8s %8s",
528 IXSEQ_TO_IPCID(ic
.ipcs_cursor
-1, semaptr
->sem_perm
),
529 (int)semaptr
->sem_perm
._key
,
530 fmt_perm(semaptr
->sem_perm
.mode
, 'a'),
531 user_from_uid(semaptr
->sem_perm
.uid
, 0),
532 group_from_gid(semaptr
->sem_perm
.gid
, 0));
534 if (option
& CREATOR
)
536 user_from_uid(semaptr
->sem_perm
.cuid
, 0),
537 group_from_gid(semaptr
->sem_perm
.cgid
, 0));
539 if (option
& BIGGEST
)
550 memset(semaptr
, 0, sizeof(*semaptr
));
554 if (errno
!= ENOENT
&& errno
!= ERANGE
) {
555 if (errno
!= EPERM
) {
556 errx(1, "sysctlbyname(IPCS_SEM_SYSCTL/ITER, op=ITER, &ic, &%ld) datalen=%d failed: %s\n",
557 sizeof(ic
), ic
.ipcs_datalen
, strerror(errno
));
559 errx(1, "sysctlbyname: IPCS_SEM_SYSCTL %s", strerror(errno
));
564 if (display
& (SEMINFO
| SEMTOTAL
)) {
565 errx(1, "%s", "SVID semaphores facility not configured in the system\n");