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