Home | History | Annotate | Line # | Download | only in ipcs
ipcs.c revision 1.40.2.1
      1 /*	$NetBSD: ipcs.c,v 1.40.2.1 2008/05/18 12:36:06 yamt 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/inttypes.h>
     61 #include <sys/ipc.h>
     62 #include <sys/sem.h>
     63 #include <sys/shm.h>
     64 #include <sys/msg.h>
     65 
     66 #include <err.h>
     67 #include <fcntl.h>
     68 #include <grp.h>
     69 #include <kvm.h>
     70 #include <limits.h>
     71 #include <nlist.h>
     72 #include <paths.h>
     73 #include <pwd.h>
     74 #include <stdio.h>
     75 #include <stdlib.h>
     76 #include <string.h>
     77 #include <time.h>
     78 #include <unistd.h>
     79 
     80 #define	SHMINFO		1
     81 #define	SHMTOTAL	2
     82 #define	MSGINFO		4
     83 #define	MSGTOTAL	8
     84 #define	SEMINFO		16
     85 #define	SEMTOTAL	32
     86 
     87 #define BIGGEST		1
     88 #define CREATOR		2
     89 #define OUTSTANDING	4
     90 #define PID		8
     91 #define TIME		16
     92 
     93 static char	*core = NULL, *namelist = NULL;
     94 static int	display = 0;
     95 static int	option = 0;
     96 
     97 static void	cvt_time(time_t, char *, size_t);
     98 static char    *fmt_perm(u_short);
     99 static void	ipcs_kvm(void);
    100 static void	msg_sysctl(void);
    101 static void	sem_sysctl(void);
    102 static void	shm_sysctl(void);
    103 static void	show_msginfo(time_t, time_t, time_t, int, u_int64_t, mode_t,
    104     uid_t, gid_t, uid_t, gid_t, u_int64_t, u_int64_t, u_int64_t, pid_t, pid_t);
    105 static void	show_msginfo_hdr(void);
    106 static void	show_msgtotal(struct msginfo *);
    107 static void	show_seminfo_hdr(void);
    108 static void	show_seminfo(time_t, time_t, int, u_int64_t, mode_t, uid_t,
    109     gid_t, uid_t, gid_t, int16_t);
    110 static void	show_semtotal(struct seminfo *);
    111 static void	show_shminfo(time_t, time_t, time_t, int, u_int64_t, mode_t,
    112     uid_t, gid_t, uid_t, gid_t, u_int32_t, u_int64_t, pid_t, pid_t);
    113 static void	show_shminfo_hdr(void);
    114 static void	show_shmtotal(struct shminfo *);
    115 static void	usage(void) __dead;
    116 static void	unconfsem(void);
    117 static void	unconfmsg(void);
    118 static void	unconfshm(void);
    119 
    120 static void
    121 unconfsem(void)
    122 {
    123 	warnx("SVID semaphores facility not configured in the system");
    124 }
    125 
    126 static void
    127 unconfmsg(void)
    128 {
    129 	warnx("SVID messages facility not configured in the system");
    130 }
    131 
    132 static void
    133 unconfshm(void)
    134 {
    135 	warnx("SVID shared memory facility not configured in the system");
    136 }
    137 
    138 static char *
    139 fmt_perm(u_short mode)
    140 {
    141 	static char buffer[12];
    142 
    143 	buffer[0] = '-';
    144 	buffer[1] = '-';
    145 	buffer[2] = ((mode & 0400) ? 'r' : '-');
    146 	buffer[3] = ((mode & 0200) ? 'w' : '-');
    147 	buffer[4] = ((mode & 0100) ? 'a' : '-');
    148 	buffer[5] = ((mode & 0040) ? 'r' : '-');
    149 	buffer[6] = ((mode & 0020) ? 'w' : '-');
    150 	buffer[7] = ((mode & 0010) ? 'a' : '-');
    151 	buffer[8] = ((mode & 0004) ? 'r' : '-');
    152 	buffer[9] = ((mode & 0002) ? 'w' : '-');
    153 	buffer[10] = ((mode & 0001) ? 'a' : '-');
    154 	buffer[11] = '\0';
    155 	return (&buffer[0]);
    156 }
    157 
    158 static void
    159 cvt_time(time_t t, char *buf, size_t buflen)
    160 {
    161 	struct tm *tm;
    162 
    163 	if (t == 0)
    164 		(void)strlcpy(buf, "no-entry", buflen);
    165 	else {
    166 		tm = localtime(&t);
    167 		(void)snprintf(buf, buflen, "%2d:%02d:%02d",
    168 			tm->tm_hour, tm->tm_min, tm->tm_sec);
    169 	}
    170 }
    171 int
    172 main(int argc, char *argv[])
    173 {
    174 	int i;
    175 	time_t now;
    176 
    177 	while ((i = getopt(argc, argv, "MmQqSsabC:cN:optT")) != -1)
    178 		switch (i) {
    179 		case 'M':
    180 			display |= SHMTOTAL;
    181 			break;
    182 		case 'm':
    183 			display |= SHMINFO;
    184 			break;
    185 		case 'Q':
    186 			display |= MSGTOTAL;
    187 			break;
    188 		case 'q':
    189 			display |= MSGINFO;
    190 			break;
    191 		case 'S':
    192 			display |= SEMTOTAL;
    193 			break;
    194 		case 's':
    195 			display |= SEMINFO;
    196 			break;
    197 		case 'T':
    198 			display |= SHMTOTAL | MSGTOTAL | SEMTOTAL;
    199 			break;
    200 		case 'a':
    201 			option |= BIGGEST | CREATOR | OUTSTANDING | PID | TIME;
    202 			break;
    203 		case 'b':
    204 			option |= BIGGEST;
    205 			break;
    206 		case 'C':
    207 			core = optarg;
    208 			break;
    209 		case 'c':
    210 			option |= CREATOR;
    211 			break;
    212 		case 'N':
    213 			namelist = optarg;
    214 			break;
    215 		case 'o':
    216 			option |= OUTSTANDING;
    217 			break;
    218 		case 'p':
    219 			option |= PID;
    220 			break;
    221 		case 't':
    222 			option |= TIME;
    223 			break;
    224 		default:
    225 			usage();
    226 		}
    227 
    228 	if (argc - optind > 0)
    229 		usage();
    230 
    231 	(void)time(&now);
    232 	(void)printf("IPC status from %s as of %s\n",
    233 	    /* and extra \n from ctime(3) */
    234 	    core == NULL ? "<running system>" : core, ctime(&now));
    235 
    236         if (display == 0)
    237 		display = SHMINFO | MSGINFO | SEMINFO;
    238 
    239 	if (core == NULL) {
    240 		if (display & (MSGINFO | MSGTOTAL))
    241 			msg_sysctl();
    242 		if (display & (SHMINFO | SHMTOTAL))
    243 			shm_sysctl();
    244 		if (display & (SEMINFO | SEMTOTAL))
    245 			sem_sysctl();
    246 	} else
    247 		ipcs_kvm();
    248 	return 0;
    249 }
    250 
    251 static void
    252 show_msgtotal(struct msginfo *msginfo)
    253 {
    254 	(void)printf("msginfo:\n");
    255 	(void)printf("\tmsgmax: %6d\t(max characters in a message)\n",
    256 	    msginfo->msgmax);
    257 	(void)printf("\tmsgmni: %6d\t(# of message queues)\n",
    258 	    msginfo->msgmni);
    259 	(void)printf("\tmsgmnb: %6d\t(max characters in a message queue)\n",
    260 	    msginfo->msgmnb);
    261 	(void)printf("\tmsgtql: %6d\t(max # of messages in system)\n",
    262 	    msginfo->msgtql);
    263 	(void)printf("\tmsgssz: %6d\t(size of a message segment)\n",
    264 	    msginfo->msgssz);
    265 	(void)printf("\tmsgseg: %6d\t(# of message segments in system)\n\n",
    266 	    msginfo->msgseg);
    267 }
    268 
    269 static void
    270 show_shmtotal(struct shminfo *shminfo)
    271 {
    272 	(void)printf("shminfo:\n");
    273 	(void)printf("\tshmmax: %" PRIu64 "\t(max shared memory segment size)\n",
    274 	    shminfo->shmmax);
    275 	(void)printf("\tshmmin: %7d\t(min shared memory segment size)\n",
    276 	    shminfo->shmmin);
    277 	(void)printf("\tshmmni: %7d\t(max number of shared memory identifiers)\n",
    278 	    shminfo->shmmni);
    279 	(void)printf("\tshmseg: %7d\t(max shared memory segments per process)\n",
    280 	    shminfo->shmseg);
    281 	(void)printf("\tshmall: %7d\t(max amount of shared memory in pages)\n\n",
    282 	    shminfo->shmall);
    283 }
    284 
    285 static void
    286 show_semtotal(struct seminfo *seminfo)
    287 {
    288 	(void)printf("seminfo:\n");
    289 	(void)printf("\tsemmap: %6d\t(# of entries in semaphore map)\n",
    290 	    seminfo->semmap);
    291 	(void)printf("\tsemmni: %6d\t(# of semaphore identifiers)\n",
    292 	    seminfo->semmni);
    293 	(void)printf("\tsemmns: %6d\t(# of semaphores in system)\n",
    294 	    seminfo->semmns);
    295 	(void)printf("\tsemmnu: %6d\t(# of undo structures in system)\n",
    296 	    seminfo->semmnu);
    297 	(void)printf("\tsemmsl: %6d\t(max # of semaphores per id)\n",
    298 	    seminfo->semmsl);
    299 	(void)printf("\tsemopm: %6d\t(max # of operations per semop call)\n",
    300 	    seminfo->semopm);
    301 	(void)printf("\tsemume: %6d\t(max # of undo entries per process)\n",
    302 	    seminfo->semume);
    303 	(void)printf("\tsemusz: %6d\t(size in bytes of undo structure)\n",
    304 	    seminfo->semusz);
    305 	(void)printf("\tsemvmx: %6d\t(semaphore maximum value)\n",
    306 	    seminfo->semvmx);
    307 	(void)printf("\tsemaem: %6d\t(adjust on exit max value)\n\n",
    308 	    seminfo->semaem);
    309 }
    310 
    311 static void
    312 show_msginfo_hdr(void)
    313 {
    314 	(void)printf("Message Queues:\n");
    315 	(void)printf("T        ID     KEY        MODE       OWNER    GROUP");
    316 	if (option & CREATOR)
    317 		(void)printf("  CREATOR   CGROUP");
    318 	if (option & OUTSTANDING)
    319 		(void)printf(" CBYTES  QNUM");
    320 	if (option & BIGGEST)
    321 		(void)printf(" QBYTES");
    322 	if (option & PID)
    323 		(void)printf(" LSPID LRPID");
    324 	if (option & TIME)
    325 		(void)printf("    STIME    RTIME    CTIME");
    326 	(void)printf("\n");
    327 }
    328 
    329 static void
    330 show_msginfo(time_t s_time, time_t r_time, time_t c_time, int ipcid,
    331     u_int64_t key,
    332     mode_t mode, uid_t uid, gid_t gid, uid_t cuid, gid_t cgid,
    333     u_int64_t cbytes, u_int64_t qnum, u_int64_t qbytes, pid_t lspid,
    334     pid_t lrpid)
    335 {
    336 	char s_time_buf[100], r_time_buf[100], c_time_buf[100];
    337 
    338 	if (option & TIME) {
    339 		cvt_time(s_time, s_time_buf, sizeof(s_time_buf));
    340 		cvt_time(r_time, r_time_buf, sizeof(r_time_buf));
    341 		cvt_time(c_time, c_time_buf, sizeof(c_time_buf));
    342 	}
    343 
    344 	(void)printf("q %9d %10lld %s %8s %8s", ipcid, (long long)key, fmt_perm(mode),
    345 	    user_from_uid(uid, 0), group_from_gid(gid, 0));
    346 
    347 	if (option & CREATOR)
    348 		(void)printf(" %8s %8s", user_from_uid(cuid, 0),
    349 		    group_from_gid(cgid, 0));
    350 
    351 	if (option & OUTSTANDING)
    352 		(void)printf(" %6lld %5lld", (long long)cbytes, (long long)qnum);
    353 
    354 	if (option & BIGGEST)
    355 		(void)printf(" %6lld", (long long)qbytes);
    356 
    357 	if (option & PID)
    358 		(void)printf(" %5d %5d", lspid, lrpid);
    359 
    360 	if (option & TIME)
    361 		(void)printf(" %s %s %s", s_time_buf, r_time_buf, c_time_buf);
    362 
    363 	(void)printf("\n");
    364 }
    365 
    366 static void
    367 show_shminfo_hdr(void)
    368 {
    369 	(void)printf("Shared Memory:\n");
    370 	(void)printf("T        ID     KEY        MODE       OWNER    GROUP");
    371 	if (option & CREATOR)
    372 		(void)printf("  CREATOR   CGROUP");
    373 	if (option & OUTSTANDING)
    374 		(void)printf(" NATTCH");
    375 	if (option & BIGGEST)
    376 		(void)printf("   SEGSZ");
    377 	if (option & PID)
    378 		(void)printf("  CPID  LPID");
    379 	if (option & TIME)
    380 		(void)printf("    ATIME    DTIME    CTIME");
    381 	(void)printf("\n");
    382 }
    383 
    384 static void
    385 show_shminfo(time_t atime, time_t dtime, time_t c_time, int ipcid, u_int64_t key,
    386     mode_t mode, uid_t uid, gid_t gid, uid_t cuid, gid_t cgid,
    387     u_int32_t nattch, u_int64_t segsz, pid_t cpid, pid_t lpid)
    388 {
    389 	char atime_buf[100], dtime_buf[100], c_time_buf[100];
    390 
    391 	if (option & TIME) {
    392 		cvt_time(atime, atime_buf, sizeof(atime_buf));
    393 		cvt_time(dtime, dtime_buf, sizeof(dtime_buf));
    394 		cvt_time(c_time, c_time_buf, sizeof(c_time_buf));
    395 	}
    396 
    397 	(void)printf("m %9d %10lld %s %8s %8s", ipcid, (long long)key, fmt_perm(mode),
    398 	    user_from_uid(uid, 0), group_from_gid(gid, 0));
    399 
    400 	if (option & CREATOR)
    401 		(void)printf(" %8s %8s", user_from_uid(cuid, 0),
    402 		    group_from_gid(cgid, 0));
    403 
    404 	if (option & OUTSTANDING)
    405 		(void)printf(" %6d", nattch);
    406 
    407 	if (option & BIGGEST)
    408 		(void)printf(" %7llu", (long long)segsz);
    409 
    410 	if (option & PID)
    411 		(void)printf(" %5d %5d", cpid, lpid);
    412 
    413 	if (option & TIME)
    414 		(void)printf(" %s %s %s",
    415 		    atime_buf,
    416 		    dtime_buf,
    417 		    c_time_buf);
    418 
    419 	(void)printf("\n");
    420 }
    421 
    422 static void
    423 show_seminfo_hdr(void)
    424 {
    425 	(void)printf("Semaphores:\n");
    426 	(void)printf("T        ID     KEY        MODE       OWNER    GROUP");
    427 	if (option & CREATOR)
    428 		(void)printf("  CREATOR   CGROUP");
    429 	if (option & BIGGEST)
    430 		(void)printf(" NSEMS");
    431 	if (option & TIME)
    432 		(void)printf("    OTIME    CTIME");
    433 	(void)printf("\n");
    434 }
    435 
    436 static void
    437 show_seminfo(time_t otime, time_t c_time, int ipcid, u_int64_t key, mode_t mode,
    438     uid_t uid, gid_t gid, uid_t cuid, gid_t cgid, int16_t nsems)
    439 {
    440 	char c_time_buf[100], otime_buf[100];
    441 
    442 	if (option & TIME) {
    443 		cvt_time(otime, otime_buf, sizeof(otime_buf));
    444 		cvt_time(c_time, c_time_buf, sizeof(c_time_buf));
    445 	}
    446 
    447 	(void)printf("s %9d %10lld %s %8s %8s", ipcid, (long long)key, fmt_perm(mode),
    448 	    user_from_uid(uid, 0), group_from_gid(gid, 0));
    449 
    450 	if (option & CREATOR)
    451 		(void)printf(" %8s %8s", user_from_uid(cuid, 0),
    452 		    group_from_gid(cgid, 0));
    453 
    454 	if (option & BIGGEST)
    455 		(void)printf(" %5d", nsems);
    456 
    457 	if (option & TIME)
    458 		(void)printf(" %s %s", otime_buf, c_time_buf);
    459 
    460 	(void)printf("\n");
    461 }
    462 
    463 static void
    464 msg_sysctl(void)
    465 {
    466 	struct msg_sysctl_info *msgsi;
    467 	void *buf;
    468 	int mib[4];
    469 	size_t len;
    470 	int i, valid;
    471 
    472 	mib[0] = CTL_KERN;
    473 	mib[1] = KERN_SYSVIPC;
    474 	mib[2] = KERN_SYSVIPC_MSG;
    475 	len = sizeof(valid);
    476 	if (sysctl(mib, 3, &valid, &len, NULL, 0) < 0) {
    477 		warn("sysctl(KERN_SYSVIPC_MSG)");
    478 		return;
    479 	}
    480 	if (!valid) {
    481 		unconfmsg();
    482 		return;
    483 	}
    484 
    485 	mib[0] = CTL_KERN;
    486 	mib[1] = KERN_SYSVIPC;
    487 	mib[2] = KERN_SYSVIPC_INFO;
    488 	mib[3] = KERN_SYSVIPC_MSG_INFO;
    489 
    490 	if (!(display & MSGINFO)) {
    491 		/* totals only */
    492 		len = sizeof(struct msginfo);
    493 	} else {
    494 		if (sysctl(mib, 4, NULL, &len, NULL, 0) < 0) {
    495 			warn("sysctl(KERN_SYSVIPC_MSG_INFO)");
    496 			return;
    497 		}
    498 	}
    499 
    500 	if ((buf = malloc(len)) == NULL)
    501 		err(1, "malloc");
    502 	msgsi = (struct msg_sysctl_info *)buf;
    503 	if (sysctl(mib, 4, msgsi, &len, NULL, 0) < 0) {
    504 		warn("sysctl(KERN_SYSVIPC_MSG_INFO)");
    505 		goto done;
    506 	}
    507 
    508 	if (display & MSGTOTAL)
    509 		show_msgtotal(&msgsi->msginfo);
    510 
    511 	if (display & MSGINFO) {
    512 		show_msginfo_hdr();
    513 		for (i = 0; i < msgsi->msginfo.msgmni; i++) {
    514 			struct msgid_ds_sysctl *msqptr = &msgsi->msgids[i];
    515 			if (msqptr->msg_qbytes != 0)
    516 				show_msginfo(msqptr->msg_stime,
    517 				    msqptr->msg_rtime,
    518 				    msqptr->msg_ctime,
    519 				    IXSEQ_TO_IPCID(i, msqptr->msg_perm),
    520 				    msqptr->msg_perm._key,
    521 				    msqptr->msg_perm.mode,
    522 				    msqptr->msg_perm.uid,
    523 				    msqptr->msg_perm.gid,
    524 				    msqptr->msg_perm.cuid,
    525 				    msqptr->msg_perm.cgid,
    526 				    msqptr->_msg_cbytes,
    527 				    msqptr->msg_qnum,
    528 				    msqptr->msg_qbytes,
    529 				    msqptr->msg_lspid,
    530 				    msqptr->msg_lrpid);
    531 		}
    532 		(void)printf("\n");
    533 	}
    534 done:
    535 	free(buf);
    536 }
    537 
    538 static void
    539 shm_sysctl(void)
    540 {
    541 	struct shm_sysctl_info *shmsi;
    542 	void *buf;
    543 	int mib[4];
    544 	size_t len;
    545 	int i /*, valid */;
    546 	long valid;
    547 
    548 	mib[0] = CTL_KERN;
    549 	mib[1] = KERN_SYSVIPC;
    550 	mib[2] = KERN_SYSVIPC_SHM;
    551 	len = sizeof(valid);
    552 	if (sysctl(mib, 3, &valid, &len, NULL, 0) < 0) {
    553 		warn("sysctl(KERN_SYSVIPC_SHM)");
    554 		return;
    555 	}
    556 	if (!valid) {
    557 		unconfshm();
    558 		return;
    559 	}
    560 
    561 	mib[0] = CTL_KERN;
    562 	mib[1] = KERN_SYSVIPC;
    563 	mib[2] = KERN_SYSVIPC_INFO;
    564 	mib[3] = KERN_SYSVIPC_SHM_INFO;
    565 
    566 	if (!(display & SHMINFO)) {
    567 		/* totals only */
    568 		len = sizeof(struct shminfo);
    569 	} else {
    570 		if (sysctl(mib, 4, NULL, &len, NULL, 0) < 0) {
    571 			warn("sysctl(KERN_SYSVIPC_SHM_INFO)");
    572 			return;
    573 		}
    574 	}
    575 
    576 	if ((buf = malloc(len)) == NULL)
    577 		err(1, "malloc");
    578 	shmsi = (struct shm_sysctl_info *)buf;
    579 	if (sysctl(mib, 4, shmsi, &len, NULL, 0) < 0) {
    580 		warn("sysctl(KERN_SYSVIPC_SHM_INFO)");
    581 		goto done;
    582 	}
    583 
    584 	if (display & SHMTOTAL)
    585 		show_shmtotal(&shmsi->shminfo);
    586 
    587 	if (display & SHMINFO) {
    588 		show_shminfo_hdr();
    589 		for (i = 0; i < shmsi->shminfo.shmmni; i++) {
    590 			struct shmid_ds_sysctl *shmptr = &shmsi->shmids[i];
    591 			if (shmptr->shm_perm.mode & 0x0800)
    592 				show_shminfo(shmptr->shm_atime,
    593 				    shmptr->shm_dtime,
    594 				    shmptr->shm_ctime,
    595 				    IXSEQ_TO_IPCID(i, shmptr->shm_perm),
    596 				    shmptr->shm_perm._key,
    597 				    shmptr->shm_perm.mode,
    598 				    shmptr->shm_perm.uid,
    599 				    shmptr->shm_perm.gid,
    600 				    shmptr->shm_perm.cuid,
    601 				    shmptr->shm_perm.cgid,
    602 				    shmptr->shm_nattch,
    603 				    shmptr->shm_segsz,
    604 				    shmptr->shm_cpid,
    605 				    shmptr->shm_lpid);
    606 		}
    607 		(void)printf("\n");
    608 	}
    609 done:
    610 	free(buf);
    611 }
    612 
    613 static void
    614 sem_sysctl(void)
    615 {
    616 	struct sem_sysctl_info *semsi;
    617 	void *buf;
    618 	int mib[4];
    619 	size_t len;
    620 	int i, valid;
    621 
    622 	mib[0] = CTL_KERN;
    623 	mib[1] = KERN_SYSVIPC;
    624 	mib[2] = KERN_SYSVIPC_SEM;
    625 	len = sizeof(valid);
    626 	if (sysctl(mib, 3, &valid, &len, NULL, 0) < 0) {
    627 		warn("sysctl(KERN_SYSVIPC_SEM)");
    628 		return;
    629 	}
    630 	if (!valid) {
    631 		unconfsem();
    632 		return;
    633 	}
    634 
    635 	mib[0] = CTL_KERN;
    636 	mib[1] = KERN_SYSVIPC;
    637 	mib[2] = KERN_SYSVIPC_INFO;
    638 	mib[3] = KERN_SYSVIPC_SEM_INFO;
    639 
    640 	if (!(display & SEMINFO)) {
    641 		/* totals only */
    642 		len = sizeof(struct seminfo);
    643 	} else {
    644 		if (sysctl(mib, 4, NULL, &len, NULL, 0) < 0) {
    645 			warn("sysctl(KERN_SYSVIPC_SEM_INFO)");
    646 			return;
    647 		}
    648 	}
    649 
    650 	if ((buf = malloc(len)) == NULL)
    651 		err(1, "malloc");
    652 	semsi = (struct sem_sysctl_info *)buf;
    653 	if (sysctl(mib, 4, semsi, &len, NULL, 0) < 0) {
    654 		warn("sysctl(KERN_SYSVIPC_SEM_INFO)");
    655 		goto done;
    656 	}
    657 
    658 	if (display & SEMTOTAL)
    659 		show_semtotal(&semsi->seminfo);
    660 
    661 	if (display & SEMINFO) {
    662 		show_seminfo_hdr();
    663 		for (i = 0; i < semsi->seminfo.semmni; i++) {
    664 			struct semid_ds_sysctl *semaptr = &semsi->semids[i];
    665 			if ((semaptr->sem_perm.mode & SEM_ALLOC) != 0)
    666 				show_seminfo(semaptr->sem_otime,
    667 				    semaptr->sem_ctime,
    668 				    IXSEQ_TO_IPCID(i, semaptr->sem_perm),
    669 				    semaptr->sem_perm._key,
    670 				    semaptr->sem_perm.mode,
    671 				    semaptr->sem_perm.uid,
    672 				    semaptr->sem_perm.gid,
    673 				    semaptr->sem_perm.cuid,
    674 				    semaptr->sem_perm.cgid,
    675 				    semaptr->sem_nsems);
    676 		}
    677 		(void)printf("\n");
    678 	}
    679 done:
    680 	free(buf);
    681 }
    682 
    683 static struct nlist symbols[] = {
    684 	{ .n_name = "_sema" },
    685 #define X_SEMA		0
    686 	{ .n_name = "_seminfo" },
    687 #define X_SEMINFO	1
    688 	{ .n_name = "_semu" },
    689 #define X_SEMU		2
    690 	{ .n_name = "_msginfo" },
    691 #define X_MSGINFO	3
    692 	{ .n_name = "_msqids" },
    693 #define X_MSQIDS	4
    694 	{ .n_name = "_shminfo" },
    695 #define X_SHMINFO	5
    696 	{ .n_name = "_shmsegs" },
    697 #define X_SHMSEGS	6
    698 	{ .n_name = NULL }
    699 };
    700 
    701 static void
    702 ipcs_kvm(void)
    703 {
    704 	struct msginfo msginfo;
    705 	struct msqid_ds *msqids;
    706 	struct seminfo seminfo;
    707 	struct semid_ds *sema;
    708 	struct shminfo shminfo;
    709 	struct shmid_ds *shmsegs;
    710 	kvm_t *kd;
    711 	char errbuf[_POSIX2_LINE_MAX];
    712 	int i;
    713 
    714 	if ((kd = kvm_openfiles(namelist, core, NULL, O_RDONLY,
    715 	    errbuf)) == NULL)
    716 		errx(1, "can't open kvm: %s", errbuf);
    717 
    718 
    719 	switch (kvm_nlist(kd, symbols)) {
    720 	case 0:
    721 		break;
    722 	case -1:
    723 		errx(1, "%s: unable to read symbol table.",
    724 		    namelist == NULL ? _PATH_UNIX : namelist);
    725 		/* NOTREACHED */
    726 	default:
    727 #ifdef notdef		/* they'll be told more civilly later */
    728 		warnx("nlist failed");
    729 		for (i = 0; symbols[i].n_name != NULL; i++)
    730 			if (symbols[i].n_value == 0)
    731 				warnx("symbol %s not found",
    732 				    symbols[i].n_name);
    733 #endif
    734 		break;
    735 	}
    736 
    737 	if ((display & (MSGINFO | MSGTOTAL)) &&
    738 	    (kvm_read(kd, symbols[X_MSGINFO].n_value,
    739 	     &msginfo, sizeof(msginfo)) == sizeof(msginfo))) {
    740 
    741 		if (display & MSGTOTAL)
    742 			show_msgtotal(&msginfo);
    743 
    744 		if (display & MSGINFO) {
    745 			struct msqid_ds *xmsqids;
    746 
    747 			if (kvm_read(kd, symbols[X_MSQIDS].n_value,
    748 			    &msqids, sizeof(msqids)) != sizeof(msqids))
    749 				errx(1, "kvm_read (%s): %s",
    750 				    symbols[X_MSQIDS].n_name, kvm_geterr(kd));
    751 
    752 			xmsqids = malloc(sizeof(struct msqid_ds) *
    753 			    msginfo.msgmni);
    754 
    755 			if (kvm_read(kd, (u_long)msqids, xmsqids,
    756 			    sizeof(struct msqid_ds) * msginfo.msgmni) !=
    757 			    sizeof(struct msqid_ds) * msginfo.msgmni)
    758 				errx(1, "kvm_read (msqids): %s",
    759 				    kvm_geterr(kd));
    760 
    761 			show_msginfo_hdr();
    762 			for (i = 0; i < msginfo.msgmni; i++) {
    763 				struct msqid_ds *msqptr = &xmsqids[i];
    764 				if (msqptr->msg_qbytes != 0)
    765 					show_msginfo(msqptr->msg_stime,
    766 					    msqptr->msg_rtime,
    767 					    msqptr->msg_ctime,
    768 					    IXSEQ_TO_IPCID(i, msqptr->msg_perm),
    769 					    (u_int64_t)msqptr->msg_perm._key,
    770 					    msqptr->msg_perm.mode,
    771 					    msqptr->msg_perm.uid,
    772 					    msqptr->msg_perm.gid,
    773 					    msqptr->msg_perm.cuid,
    774 					    msqptr->msg_perm.cgid,
    775 					    (u_int64_t)msqptr->_msg_cbytes,
    776 					    (u_int64_t)msqptr->msg_qnum,
    777 					    (u_int64_t)msqptr->msg_qbytes,
    778 					    msqptr->msg_lspid,
    779 					    msqptr->msg_lrpid);
    780 			}
    781 			(void)printf("\n");
    782 			free(xmsqids);
    783 		}
    784 	} else
    785 		if (display & (MSGINFO | MSGTOTAL))
    786 			unconfmsg();
    787 	if ((display & (SHMINFO | SHMTOTAL)) &&
    788 	    (kvm_read(kd, symbols[X_SHMINFO].n_value, &shminfo,
    789 	     sizeof(shminfo)) == sizeof(shminfo))) {
    790 
    791 		if (display & SHMTOTAL)
    792 			show_shmtotal(&shminfo);
    793 
    794 		if (display & SHMINFO) {
    795 			struct shmid_ds *xshmids;
    796 
    797 			if (kvm_read(kd, symbols[X_SHMSEGS].n_value, &shmsegs,
    798 			    sizeof(shmsegs)) != sizeof(shmsegs))
    799 				errx(1, "kvm_read (%s): %s",
    800 				    symbols[X_SHMSEGS].n_name, kvm_geterr(kd));
    801 
    802 			xshmids = malloc(sizeof(struct shmid_ds) *
    803 			    shminfo.shmmni);
    804 
    805 			if (kvm_read(kd, (u_long)shmsegs, xshmids,
    806 			    sizeof(struct shmid_ds) * shminfo.shmmni) !=
    807 			    sizeof(struct shmid_ds) * shminfo.shmmni)
    808 				errx(1, "kvm_read (shmsegs): %s",
    809 				    kvm_geterr(kd));
    810 
    811 			show_shminfo_hdr();
    812 			for (i = 0; i < shminfo.shmmni; i++) {
    813 				struct shmid_ds *shmptr = &xshmids[i];
    814 				if (shmptr->shm_perm.mode & 0x0800)
    815 					show_shminfo(shmptr->shm_atime,
    816 					    shmptr->shm_dtime,
    817 					    shmptr->shm_ctime,
    818 					    IXSEQ_TO_IPCID(i, shmptr->shm_perm),
    819 					    (u_int64_t)shmptr->shm_perm._key,
    820 					    shmptr->shm_perm.mode,
    821 					    shmptr->shm_perm.uid,
    822 					    shmptr->shm_perm.gid,
    823 					    shmptr->shm_perm.cuid,
    824 					    shmptr->shm_perm.cgid,
    825 					    shmptr->shm_nattch,
    826 					    (u_int64_t)shmptr->shm_segsz,
    827 					    shmptr->shm_cpid,
    828 					    shmptr->shm_lpid);
    829 			}
    830 			(void)printf("\n");
    831 			free(xshmids);
    832 		}
    833 	} else
    834 		if (display & (SHMINFO | SHMTOTAL))
    835 			unconfshm();
    836 	if ((display & (SEMINFO | SEMTOTAL)) &&
    837 	    (kvm_read(kd, symbols[X_SEMINFO].n_value, &seminfo,
    838 	     sizeof(seminfo)) == sizeof(seminfo))) {
    839 		struct semid_ds *xsema;
    840 
    841 		if (display & SEMTOTAL)
    842 			show_semtotal(&seminfo);
    843 
    844 		if (display & SEMINFO) {
    845 			if (kvm_read(kd, symbols[X_SEMA].n_value, &sema,
    846 			    sizeof(sema)) != sizeof(sema))
    847 				errx(1, "kvm_read (%s): %s",
    848 				    symbols[X_SEMA].n_name, kvm_geterr(kd));
    849 
    850 			xsema = malloc(sizeof(struct semid_ds) *
    851 			    seminfo.semmni);
    852 
    853 			if (kvm_read(kd, (u_long)sema, xsema,
    854 			    sizeof(struct semid_ds) * seminfo.semmni) !=
    855 			    sizeof(struct semid_ds) * seminfo.semmni)
    856 				errx(1, "kvm_read (sema): %s",
    857 				    kvm_geterr(kd));
    858 
    859 			show_seminfo_hdr();
    860 			for (i = 0; i < seminfo.semmni; i++) {
    861 				struct semid_ds *semaptr = &xsema[i];
    862 				if ((semaptr->sem_perm.mode & SEM_ALLOC) != 0)
    863 					show_seminfo(semaptr->sem_otime,
    864 					    semaptr->sem_ctime,
    865 					    IXSEQ_TO_IPCID(i, semaptr->sem_perm),
    866 					    (u_int64_t)semaptr->sem_perm._key,
    867 					    semaptr->sem_perm.mode,
    868 					    semaptr->sem_perm.uid,
    869 					    semaptr->sem_perm.gid,
    870 					    semaptr->sem_perm.cuid,
    871 					    semaptr->sem_perm.cgid,
    872 					    semaptr->sem_nsems);
    873 			}
    874 
    875 			(void)printf("\n");
    876 			free(xsema);
    877 		}
    878 	} else
    879 		if (display & (SEMINFO | SEMTOTAL))
    880 			unconfsem();
    881 	(void)kvm_close(kd);
    882 }
    883 
    884 static void
    885 usage(void)
    886 {
    887 
    888 	(void)fprintf(stderr,
    889 	    "Usage: %s [-abcmopqstMQST] [-C corefile] [-N namelist]\n",
    890 	    getprogname());
    891 	exit(1);
    892 }
    893