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