Home | History | Annotate | Line # | Download | only in ipcs
      1 /*	$NetBSD: ipcs.c,v 1.44 2021/03/18 19:34:05 cheusov Exp $	*/
      2 
      3 /*-
      4  * Copyright (c) 2000 The NetBSD Foundation, Inc.
      5  * All rights reserved.
      6  *
      7  * This code is derived from software contributed to The NetBSD Foundation
      8  * by Simon Burge.
      9  *
     10  * Redistribution and use in source and binary forms, with or without
     11  * modification, are permitted provided that the following conditions
     12  * are met:
     13  * 1. Redistributions of source code must retain the above copyright
     14  *    notice, this list of conditions and the following disclaimer.
     15  * 2. Redistributions in binary form must reproduce the above copyright
     16  *    notice, this list of conditions and the following disclaimer in the
     17  *    documentation and/or other materials provided with the distribution.
     18  *
     19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     29  * POSSIBILITY OF SUCH DAMAGE.
     30  */
     31 
     32 /*
     33  * Copyright (c) 1994 SigmaSoft, Th. Lockert <tholo (at) sigmasoft.com>
     34  * All rights reserved.
     35  *
     36  * Redistribution and use in source and binary forms, with or without
     37  * modification, are permitted provided that the following conditions
     38  * are met:
     39  * 1. Redistributions of source code must retain the above copyright
     40  *    notice, this list of conditions and the following disclaimer.
     41  * 2. Redistributions in binary form must reproduce the above copyright
     42  *    notice, this list of conditions and the following disclaimer in the
     43  *    documentation and/or other materials provided with the distribution.
     44  *
     45  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
     46  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
     47  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
     48  * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     49  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     50  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
     51  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     52  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
     53  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
     54  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     55  */
     56 
     57 #include <sys/cdefs.h>
     58 #include <sys/param.h>
     59 #include <sys/sysctl.h>
     60 #include <sys/ipc.h>
     61 #include <sys/sem.h>
     62 #include <sys/shm.h>
     63 #include <sys/msg.h>
     64 
     65 #include <err.h>
     66 #include <fcntl.h>
     67 #include <grp.h>
     68 #include <limits.h>
     69 #include <paths.h>
     70 #include <pwd.h>
     71 #include <stdio.h>
     72 #include <stdlib.h>
     73 #include <string.h>
     74 #include <time.h>
     75 #include <unistd.h>
     76 
     77 #define	SHMINFO		1
     78 #define	SHMTOTAL	2
     79 #define	MSGINFO		4
     80 #define	MSGTOTAL	8
     81 #define	SEMINFO		16
     82 #define	SEMTOTAL	32
     83 
     84 #define BIGGEST		1
     85 #define CREATOR		2
     86 #define OUTSTANDING	4
     87 #define PID		8
     88 #define TIME		16
     89 
     90 static int	display = 0;
     91 static int	option = 0;
     92 
     93 static void	cvt_time(time_t, char *, size_t);
     94 static char    *fmt_perm(u_short);
     95 static void	msg_sysctl(void);
     96 static void	sem_sysctl(void);
     97 static void	shm_sysctl(void);
     98 static void	show_msginfo(time_t, time_t, time_t, int, u_int64_t, mode_t,
     99     uid_t, gid_t, uid_t, gid_t, u_int64_t, u_int64_t, u_int64_t, pid_t, pid_t);
    100 static void	show_msginfo_hdr(void);
    101 static void	show_msgtotal(struct msginfo *);
    102 static void	show_seminfo_hdr(void);
    103 static void	show_seminfo(time_t, time_t, int, u_int64_t, mode_t, uid_t,
    104     gid_t, uid_t, gid_t, int16_t);
    105 static void	show_semtotal(struct seminfo *);
    106 static void	show_shminfo(time_t, time_t, time_t, int, u_int64_t, mode_t,
    107     uid_t, gid_t, uid_t, gid_t, u_int32_t, u_int64_t, pid_t, pid_t);
    108 static void	show_shminfo_hdr(void);
    109 static void	show_shmtotal(struct shminfo *);
    110 static void	usage(void) __dead;
    111 static void	unconfsem(void);
    112 static void	unconfmsg(void);
    113 static void	unconfshm(void);
    114 
    115 static void
    116 unconfsem(void)
    117 {
    118 	warnx("SVID semaphores facility not configured in the system");
    119 }
    120 
    121 static void
    122 unconfmsg(void)
    123 {
    124 	warnx("SVID messages facility not configured in the system");
    125 }
    126 
    127 static void
    128 unconfshm(void)
    129 {
    130 	warnx("SVID shared memory facility not configured in the system");
    131 }
    132 
    133 static char *
    134 fmt_perm(u_short mode)
    135 {
    136 	static char buffer[12];
    137 
    138 	buffer[0] = '-';
    139 	buffer[1] = '-';
    140 	buffer[2] = ((mode & 0400) ? 'r' : '-');
    141 	buffer[3] = ((mode & 0200) ? 'w' : '-');
    142 	buffer[4] = ((mode & 0100) ? 'a' : '-');
    143 	buffer[5] = ((mode & 0040) ? 'r' : '-');
    144 	buffer[6] = ((mode & 0020) ? 'w' : '-');
    145 	buffer[7] = ((mode & 0010) ? 'a' : '-');
    146 	buffer[8] = ((mode & 0004) ? 'r' : '-');
    147 	buffer[9] = ((mode & 0002) ? 'w' : '-');
    148 	buffer[10] = ((mode & 0001) ? 'a' : '-');
    149 	buffer[11] = '\0';
    150 	return (&buffer[0]);
    151 }
    152 
    153 static void
    154 cvt_time(time_t t, char *buf, size_t buflen)
    155 {
    156 	struct tm *tm;
    157 
    158 	if (t == 0)
    159 		(void)strlcpy(buf, "no-entry", buflen);
    160 	else {
    161 		tm = localtime(&t);
    162 		(void)snprintf(buf, buflen, "%2d:%02d:%02d",
    163 			tm->tm_hour, tm->tm_min, tm->tm_sec);
    164 	}
    165 }
    166 int
    167 main(int argc, char *argv[])
    168 {
    169 	int i;
    170 	time_t now;
    171 
    172 	while ((i = getopt(argc, argv, "MmQqSsabcoptT")) != -1)
    173 		switch (i) {
    174 		case 'M':
    175 			display |= SHMTOTAL;
    176 			break;
    177 		case 'm':
    178 			display |= SHMINFO;
    179 			break;
    180 		case 'Q':
    181 			display |= MSGTOTAL;
    182 			break;
    183 		case 'q':
    184 			display |= MSGINFO;
    185 			break;
    186 		case 'S':
    187 			display |= SEMTOTAL;
    188 			break;
    189 		case 's':
    190 			display |= SEMINFO;
    191 			break;
    192 		case 'T':
    193 			display |= SHMTOTAL | MSGTOTAL | SEMTOTAL;
    194 			break;
    195 		case 'a':
    196 			option |= BIGGEST | CREATOR | OUTSTANDING | PID | TIME;
    197 			break;
    198 		case 'b':
    199 			option |= BIGGEST;
    200 			break;
    201 		case 'c':
    202 			option |= CREATOR;
    203 			break;
    204 		case 'o':
    205 			option |= OUTSTANDING;
    206 			break;
    207 		case 'p':
    208 			option |= PID;
    209 			break;
    210 		case 't':
    211 			option |= TIME;
    212 			break;
    213 		default:
    214 			usage();
    215 		}
    216 
    217 	if (argc - optind > 0)
    218 		usage();
    219 
    220 	(void)time(&now);
    221 	(void)printf("IPC status from <running system> as of %s\n",
    222 	    /* and extra \n from ctime(3) */
    223 	    ctime(&now));
    224 
    225         if (display == 0)
    226 		display = SHMINFO | MSGINFO | SEMINFO;
    227 
    228 	if (display & (MSGINFO | MSGTOTAL))
    229 		msg_sysctl();
    230 	if (display & (SHMINFO | SHMTOTAL))
    231 		shm_sysctl();
    232 	if (display & (SEMINFO | SEMTOTAL))
    233 		sem_sysctl();
    234 	return 0;
    235 }
    236 
    237 static void
    238 show_msgtotal(struct msginfo *msginfo)
    239 {
    240 	(void)printf("msginfo:\n");
    241 	(void)printf("\tmsgmax: %6d\t(max characters in a message)\n",
    242 	    msginfo->msgmax);
    243 	(void)printf("\tmsgmni: %6d\t(# of message queues)\n",
    244 	    msginfo->msgmni);
    245 	(void)printf("\tmsgmnb: %6d\t(max characters in a message queue)\n",
    246 	    msginfo->msgmnb);
    247 	(void)printf("\tmsgtql: %6d\t(max # of messages in system)\n",
    248 	    msginfo->msgtql);
    249 	(void)printf("\tmsgssz: %6d\t(size of a message segment)\n",
    250 	    msginfo->msgssz);
    251 	(void)printf("\tmsgseg: %6d\t(# of message segments in system)\n\n",
    252 	    msginfo->msgseg);
    253 }
    254 
    255 static void
    256 show_shmtotal(struct shminfo *shminfo)
    257 {
    258 	(void)printf("shminfo:\n");
    259 	(void)printf("\tshmmax: %" PRIu64 "\t(max shared memory segment size)\n",
    260 	    shminfo->shmmax);
    261 	(void)printf("\tshmmin: %7d\t(min shared memory segment size)\n",
    262 	    shminfo->shmmin);
    263 	(void)printf("\tshmmni: %7d\t(max number of shared memory identifiers)\n",
    264 	    shminfo->shmmni);
    265 	(void)printf("\tshmseg: %7d\t(max shared memory segments per process)\n",
    266 	    shminfo->shmseg);
    267 	(void)printf("\tshmall: %7d\t(max amount of shared memory in pages)\n\n",
    268 	    shminfo->shmall);
    269 }
    270 
    271 static void
    272 show_semtotal(struct seminfo *seminfo)
    273 {
    274 	(void)printf("seminfo:\n");
    275 	(void)printf("\tsemmap: %6d\t(# of entries in semaphore map)\n",
    276 	    seminfo->semmap);
    277 	(void)printf("\tsemmni: %6d\t(# of semaphore identifiers)\n",
    278 	    seminfo->semmni);
    279 	(void)printf("\tsemmns: %6d\t(# of semaphores in system)\n",
    280 	    seminfo->semmns);
    281 	(void)printf("\tsemmnu: %6d\t(# of undo structures in system)\n",
    282 	    seminfo->semmnu);
    283 	(void)printf("\tsemmsl: %6d\t(max # of semaphores per id)\n",
    284 	    seminfo->semmsl);
    285 	(void)printf("\tsemopm: %6d\t(max # of operations per semop call)\n",
    286 	    seminfo->semopm);
    287 	(void)printf("\tsemume: %6d\t(max # of undo entries per process)\n",
    288 	    seminfo->semume);
    289 	(void)printf("\tsemusz: %6d\t(size in bytes of undo structure)\n",
    290 	    seminfo->semusz);
    291 	(void)printf("\tsemvmx: %6d\t(semaphore maximum value)\n",
    292 	    seminfo->semvmx);
    293 	(void)printf("\tsemaem: %6d\t(adjust on exit max value)\n\n",
    294 	    seminfo->semaem);
    295 }
    296 
    297 static void
    298 show_msginfo_hdr(void)
    299 {
    300 	(void)printf("Message Queues:\n");
    301 	(void)printf("T        ID     KEY        MODE       OWNER    GROUP");
    302 	if (option & CREATOR)
    303 		(void)printf("  CREATOR   CGROUP");
    304 	if (option & OUTSTANDING)
    305 		(void)printf(" CBYTES  QNUM");
    306 	if (option & BIGGEST)
    307 		(void)printf(" QBYTES");
    308 	if (option & PID)
    309 		(void)printf(" LSPID LRPID");
    310 	if (option & TIME)
    311 		(void)printf("    STIME    RTIME    CTIME");
    312 	(void)printf("\n");
    313 }
    314 
    315 static void
    316 show_msginfo(time_t s_time, time_t r_time, time_t c_time, int ipcid,
    317     u_int64_t key,
    318     mode_t mode, uid_t uid, gid_t gid, uid_t cuid, gid_t cgid,
    319     u_int64_t cbytes, u_int64_t qnum, u_int64_t qbytes, pid_t lspid,
    320     pid_t lrpid)
    321 {
    322 	char s_time_buf[100], r_time_buf[100], c_time_buf[100];
    323 
    324 	if (option & TIME) {
    325 		cvt_time(s_time, s_time_buf, sizeof(s_time_buf));
    326 		cvt_time(r_time, r_time_buf, sizeof(r_time_buf));
    327 		cvt_time(c_time, c_time_buf, sizeof(c_time_buf));
    328 	}
    329 
    330 	(void)printf("q %9d %10lld %s %8s %8s", ipcid, (long long)key, fmt_perm(mode),
    331 	    user_from_uid(uid, 0), group_from_gid(gid, 0));
    332 
    333 	if (option & CREATOR)
    334 		(void)printf(" %8s %8s", user_from_uid(cuid, 0),
    335 		    group_from_gid(cgid, 0));
    336 
    337 	if (option & OUTSTANDING)
    338 		(void)printf(" %6lld %5lld", (long long)cbytes, (long long)qnum);
    339 
    340 	if (option & BIGGEST)
    341 		(void)printf(" %6lld", (long long)qbytes);
    342 
    343 	if (option & PID)
    344 		(void)printf(" %5d %5d", lspid, lrpid);
    345 
    346 	if (option & TIME)
    347 		(void)printf(" %s %s %s", s_time_buf, r_time_buf, c_time_buf);
    348 
    349 	(void)printf("\n");
    350 }
    351 
    352 static void
    353 show_shminfo_hdr(void)
    354 {
    355 	(void)printf("Shared Memory:\n");
    356 	(void)printf("T        ID     KEY        MODE       OWNER    GROUP");
    357 	if (option & CREATOR)
    358 		(void)printf("  CREATOR   CGROUP");
    359 	if (option & OUTSTANDING)
    360 		(void)printf(" NATTCH");
    361 	if (option & BIGGEST)
    362 		(void)printf("   SEGSZ");
    363 	if (option & PID)
    364 		(void)printf("  CPID  LPID");
    365 	if (option & TIME)
    366 		(void)printf("    ATIME    DTIME    CTIME");
    367 	(void)printf("\n");
    368 }
    369 
    370 static void
    371 show_shminfo(time_t atime, time_t dtime, time_t c_time, int ipcid, u_int64_t key,
    372     mode_t mode, uid_t uid, gid_t gid, uid_t cuid, gid_t cgid,
    373     u_int32_t nattch, u_int64_t segsz, pid_t cpid, pid_t lpid)
    374 {
    375 	char atime_buf[100], dtime_buf[100], c_time_buf[100];
    376 
    377 	if (option & TIME) {
    378 		cvt_time(atime, atime_buf, sizeof(atime_buf));
    379 		cvt_time(dtime, dtime_buf, sizeof(dtime_buf));
    380 		cvt_time(c_time, c_time_buf, sizeof(c_time_buf));
    381 	}
    382 
    383 	(void)printf("m %9d %10lld %s %8s %8s", ipcid, (long long)key, fmt_perm(mode),
    384 	    user_from_uid(uid, 0), group_from_gid(gid, 0));
    385 
    386 	if (option & CREATOR)
    387 		(void)printf(" %8s %8s", user_from_uid(cuid, 0),
    388 		    group_from_gid(cgid, 0));
    389 
    390 	if (option & OUTSTANDING)
    391 		(void)printf(" %6d", nattch);
    392 
    393 	if (option & BIGGEST)
    394 		(void)printf(" %7llu", (long long)segsz);
    395 
    396 	if (option & PID)
    397 		(void)printf(" %5d %5d", cpid, lpid);
    398 
    399 	if (option & TIME)
    400 		(void)printf(" %s %s %s",
    401 		    atime_buf,
    402 		    dtime_buf,
    403 		    c_time_buf);
    404 
    405 	(void)printf("\n");
    406 }
    407 
    408 static void
    409 show_seminfo_hdr(void)
    410 {
    411 	(void)printf("Semaphores:\n");
    412 	(void)printf("T        ID     KEY        MODE       OWNER    GROUP");
    413 	if (option & CREATOR)
    414 		(void)printf("  CREATOR   CGROUP");
    415 	if (option & BIGGEST)
    416 		(void)printf(" NSEMS");
    417 	if (option & TIME)
    418 		(void)printf("    OTIME    CTIME");
    419 	(void)printf("\n");
    420 }
    421 
    422 static void
    423 show_seminfo(time_t otime, time_t c_time, int ipcid, u_int64_t key, mode_t mode,
    424     uid_t uid, gid_t gid, uid_t cuid, gid_t cgid, int16_t nsems)
    425 {
    426 	char c_time_buf[100], otime_buf[100];
    427 
    428 	if (option & TIME) {
    429 		cvt_time(otime, otime_buf, sizeof(otime_buf));
    430 		cvt_time(c_time, c_time_buf, sizeof(c_time_buf));
    431 	}
    432 
    433 	(void)printf("s %9d %10lld %s %8s %8s", ipcid, (long long)key, fmt_perm(mode),
    434 	    user_from_uid(uid, 0), group_from_gid(gid, 0));
    435 
    436 	if (option & CREATOR)
    437 		(void)printf(" %8s %8s", user_from_uid(cuid, 0),
    438 		    group_from_gid(cgid, 0));
    439 
    440 	if (option & BIGGEST)
    441 		(void)printf(" %5d", nsems);
    442 
    443 	if (option & TIME)
    444 		(void)printf(" %s %s", otime_buf, c_time_buf);
    445 
    446 	(void)printf("\n");
    447 }
    448 
    449 static void
    450 msg_sysctl(void)
    451 {
    452 	struct msg_sysctl_info *msgsi;
    453 	void *buf;
    454 	int mib[4];
    455 	size_t len;
    456 	int i, valid;
    457 
    458 	mib[0] = CTL_KERN;
    459 	mib[1] = KERN_SYSVIPC;
    460 	mib[2] = KERN_SYSVIPC_MSG;
    461 	len = sizeof(valid);
    462 	if (sysctl(mib, 3, &valid, &len, NULL, 0) < 0) {
    463 		warn("sysctl(KERN_SYSVIPC_MSG)");
    464 		return;
    465 	}
    466 	if (!valid) {
    467 		unconfmsg();
    468 		return;
    469 	}
    470 
    471 	mib[0] = CTL_KERN;
    472 	mib[1] = KERN_SYSVIPC;
    473 	mib[2] = KERN_SYSVIPC_INFO;
    474 	mib[3] = KERN_SYSVIPC_MSG_INFO;
    475 
    476 	if (!(display & MSGINFO)) {
    477 		/* totals only */
    478 		len = sizeof(struct msginfo);
    479 	} else {
    480 		if (sysctl(mib, 4, NULL, &len, NULL, 0) < 0) {
    481 			warn("sysctl(KERN_SYSVIPC_MSG_INFO)");
    482 			return;
    483 		}
    484 	}
    485 
    486 	if ((buf = malloc(len)) == NULL)
    487 		err(1, "malloc");
    488 	msgsi = (struct msg_sysctl_info *)buf;
    489 	if (sysctl(mib, 4, msgsi, &len, NULL, 0) < 0) {
    490 		warn("sysctl(KERN_SYSVIPC_MSG_INFO)");
    491 		goto done;
    492 	}
    493 
    494 	if (display & MSGTOTAL)
    495 		show_msgtotal(&msgsi->msginfo);
    496 
    497 	if (display & MSGINFO) {
    498 		show_msginfo_hdr();
    499 		for (i = 0; i < msgsi->msginfo.msgmni; i++) {
    500 			struct msgid_ds_sysctl *msqptr = &msgsi->msgids[i];
    501 			if (msqptr->msg_qbytes != 0)
    502 				show_msginfo(msqptr->msg_stime,
    503 				    msqptr->msg_rtime,
    504 				    msqptr->msg_ctime,
    505 				    IXSEQ_TO_IPCID(i, msqptr->msg_perm),
    506 				    msqptr->msg_perm._key,
    507 				    msqptr->msg_perm.mode,
    508 				    msqptr->msg_perm.uid,
    509 				    msqptr->msg_perm.gid,
    510 				    msqptr->msg_perm.cuid,
    511 				    msqptr->msg_perm.cgid,
    512 				    msqptr->_msg_cbytes,
    513 				    msqptr->msg_qnum,
    514 				    msqptr->msg_qbytes,
    515 				    msqptr->msg_lspid,
    516 				    msqptr->msg_lrpid);
    517 		}
    518 		(void)printf("\n");
    519 	}
    520 done:
    521 	free(buf);
    522 }
    523 
    524 static void
    525 shm_sysctl(void)
    526 {
    527 	struct shm_sysctl_info *shmsi;
    528 	void *buf;
    529 	int mib[4];
    530 	size_t len;
    531 	uint32_t i;
    532 	long valid;
    533 
    534 	mib[0] = CTL_KERN;
    535 	mib[1] = KERN_SYSVIPC;
    536 	mib[2] = KERN_SYSVIPC_SHM;
    537 	len = sizeof(valid);
    538 	if (sysctl(mib, 3, &valid, &len, NULL, 0) < 0) {
    539 		warn("sysctl(KERN_SYSVIPC_SHM)");
    540 		return;
    541 	}
    542 	if (!valid) {
    543 		unconfshm();
    544 		return;
    545 	}
    546 
    547 	mib[0] = CTL_KERN;
    548 	mib[1] = KERN_SYSVIPC;
    549 	mib[2] = KERN_SYSVIPC_INFO;
    550 	mib[3] = KERN_SYSVIPC_SHM_INFO;
    551 
    552 	if (!(display & SHMINFO)) {
    553 		/* totals only */
    554 		len = sizeof(struct shminfo);
    555 	} else {
    556 		if (sysctl(mib, 4, NULL, &len, NULL, 0) < 0) {
    557 			warn("sysctl(KERN_SYSVIPC_SHM_INFO)");
    558 			return;
    559 		}
    560 	}
    561 
    562 	if ((buf = malloc(len)) == NULL)
    563 		err(1, "malloc");
    564 	shmsi = (struct shm_sysctl_info *)buf;
    565 	if (sysctl(mib, 4, shmsi, &len, NULL, 0) < 0) {
    566 		warn("sysctl(KERN_SYSVIPC_SHM_INFO)");
    567 		goto done;
    568 	}
    569 
    570 	if (display & SHMTOTAL)
    571 		show_shmtotal(&shmsi->shminfo);
    572 
    573 	if (display & SHMINFO) {
    574 		show_shminfo_hdr();
    575 		for (i = 0; i < shmsi->shminfo.shmmni; i++) {
    576 			struct shmid_ds_sysctl *shmptr = &shmsi->shmids[i];
    577 			if (shmptr->shm_perm.mode & 0x0800)
    578 				show_shminfo(shmptr->shm_atime,
    579 				    shmptr->shm_dtime,
    580 				    shmptr->shm_ctime,
    581 				    IXSEQ_TO_IPCID(i, shmptr->shm_perm),
    582 				    shmptr->shm_perm._key,
    583 				    shmptr->shm_perm.mode,
    584 				    shmptr->shm_perm.uid,
    585 				    shmptr->shm_perm.gid,
    586 				    shmptr->shm_perm.cuid,
    587 				    shmptr->shm_perm.cgid,
    588 				    shmptr->shm_nattch,
    589 				    shmptr->shm_segsz,
    590 				    shmptr->shm_cpid,
    591 				    shmptr->shm_lpid);
    592 		}
    593 		(void)printf("\n");
    594 	}
    595 done:
    596 	free(buf);
    597 }
    598 
    599 static void
    600 sem_sysctl(void)
    601 {
    602 	struct sem_sysctl_info *semsi;
    603 	void *buf;
    604 	int mib[4];
    605 	size_t len;
    606 	int i, valid;
    607 
    608 	mib[0] = CTL_KERN;
    609 	mib[1] = KERN_SYSVIPC;
    610 	mib[2] = KERN_SYSVIPC_SEM;
    611 	len = sizeof(valid);
    612 	if (sysctl(mib, 3, &valid, &len, NULL, 0) < 0) {
    613 		warn("sysctl(KERN_SYSVIPC_SEM)");
    614 		return;
    615 	}
    616 	if (!valid) {
    617 		unconfsem();
    618 		return;
    619 	}
    620 
    621 	mib[0] = CTL_KERN;
    622 	mib[1] = KERN_SYSVIPC;
    623 	mib[2] = KERN_SYSVIPC_INFO;
    624 	mib[3] = KERN_SYSVIPC_SEM_INFO;
    625 
    626 	if (!(display & SEMINFO)) {
    627 		/* totals only */
    628 		len = sizeof(struct seminfo);
    629 	} else {
    630 		if (sysctl(mib, 4, NULL, &len, NULL, 0) < 0) {
    631 			warn("sysctl(KERN_SYSVIPC_SEM_INFO)");
    632 			return;
    633 		}
    634 	}
    635 
    636 	if ((buf = malloc(len)) == NULL)
    637 		err(1, "malloc");
    638 	semsi = (struct sem_sysctl_info *)buf;
    639 	if (sysctl(mib, 4, semsi, &len, NULL, 0) < 0) {
    640 		warn("sysctl(KERN_SYSVIPC_SEM_INFO)");
    641 		goto done;
    642 	}
    643 
    644 	if (display & SEMTOTAL)
    645 		show_semtotal(&semsi->seminfo);
    646 
    647 	if (display & SEMINFO) {
    648 		show_seminfo_hdr();
    649 		for (i = 0; i < semsi->seminfo.semmni; i++) {
    650 			struct semid_ds_sysctl *semaptr = &semsi->semids[i];
    651 			if ((semaptr->sem_perm.mode & SEM_ALLOC) != 0)
    652 				show_seminfo(semaptr->sem_otime,
    653 				    semaptr->sem_ctime,
    654 				    IXSEQ_TO_IPCID(i, semaptr->sem_perm),
    655 				    semaptr->sem_perm._key,
    656 				    semaptr->sem_perm.mode,
    657 				    semaptr->sem_perm.uid,
    658 				    semaptr->sem_perm.gid,
    659 				    semaptr->sem_perm.cuid,
    660 				    semaptr->sem_perm.cgid,
    661 				    semaptr->sem_nsems);
    662 		}
    663 		(void)printf("\n");
    664 	}
    665 done:
    666 	free(buf);
    667 }
    668 
    669 static void
    670 usage(void)
    671 {
    672 
    673 	(void)fprintf(stderr,
    674 	    "Usage: %s [-abcmopqstMQST]\n",
    675 	    getprogname());
    676 	exit(1);
    677 }
    678