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