1 /* $NetBSD: ipcs.c,v 1.37 2006/11/25 21:40:06 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[4]; 474 size_t len; 475 int i, valid; 476 477 mib[0] = CTL_KERN; 478 mib[1] = KERN_SYSVIPC; 479 mib[2] = KERN_SYSVIPC_MSG; 480 len = sizeof(valid); 481 if (sysctl(mib, 3, &valid, &len, NULL, 0) < 0) { 482 warn("sysctl(KERN_SYSVIPC_MSG)"); 483 return; 484 } 485 if (!valid) { 486 unconfmsg(); 487 return; 488 } 489 490 mib[0] = CTL_KERN; 491 mib[1] = KERN_SYSVIPC; 492 mib[2] = KERN_SYSVIPC_INFO; 493 mib[3] = KERN_SYSVIPC_MSG_INFO; 494 495 if (!(display & MSGINFO)) { 496 /* totals only */ 497 len = sizeof(struct msginfo); 498 } else { 499 if (sysctl(mib, 4, NULL, &len, NULL, 0) < 0) { 500 warn("sysctl(KERN_SYSVIPC_MSG_INFO)"); 501 return; 502 } 503 } 504 505 if ((buf = malloc(len)) == NULL) 506 err(1, "malloc"); 507 msgsi = (struct msg_sysctl_info *)buf; 508 if (sysctl(mib, 4, msgsi, &len, NULL, 0) < 0) { 509 warn("sysctl(KERN_SYSVIPC_MSG_INFO)"); 510 goto done; 511 } 512 513 if (display & MSGTOTAL) 514 show_msgtotal(&msgsi->msginfo); 515 516 if (display & MSGINFO) { 517 show_msginfo_hdr(); 518 for (i = 0; i < msgsi->msginfo.msgmni; i++) { 519 struct msgid_ds_sysctl *msqptr = &msgsi->msgids[i]; 520 if (msqptr->msg_qbytes != 0) 521 show_msginfo(msqptr->msg_stime, 522 msqptr->msg_rtime, 523 msqptr->msg_ctime, 524 IXSEQ_TO_IPCID(i, msqptr->msg_perm), 525 msqptr->msg_perm._key, 526 msqptr->msg_perm.mode, 527 msqptr->msg_perm.uid, 528 msqptr->msg_perm.gid, 529 msqptr->msg_perm.cuid, 530 msqptr->msg_perm.cgid, 531 msqptr->_msg_cbytes, 532 msqptr->msg_qnum, 533 msqptr->msg_qbytes, 534 msqptr->msg_lspid, 535 msqptr->msg_lrpid); 536 } 537 (void)printf("\n"); 538 } 539 done: 540 free(buf); 541 } 542 543 static void 544 shm_sysctl(void) 545 { 546 struct shm_sysctl_info *shmsi; 547 void *buf; 548 int mib[4]; 549 size_t len; 550 int i /*, valid */; 551 long valid; 552 553 mib[0] = CTL_KERN; 554 mib[1] = KERN_SYSVIPC; 555 mib[2] = KERN_SYSVIPC_SHM; 556 len = sizeof(valid); 557 if (sysctl(mib, 3, &valid, &len, NULL, 0) < 0) { 558 warn("sysctl(KERN_SYSVIPC_SHM)"); 559 return; 560 } 561 if (!valid) { 562 unconfshm(); 563 return; 564 } 565 566 mib[0] = CTL_KERN; 567 mib[1] = KERN_SYSVIPC; 568 mib[2] = KERN_SYSVIPC_INFO; 569 mib[3] = KERN_SYSVIPC_SHM_INFO; 570 571 if (!(display & SHMINFO)) { 572 /* totals only */ 573 len = sizeof(struct shminfo); 574 } else { 575 if (sysctl(mib, 4, NULL, &len, NULL, 0) < 0) { 576 warn("sysctl(KERN_SYSVIPC_SHM_INFO)"); 577 return; 578 } 579 } 580 581 if ((buf = malloc(len)) == NULL) 582 err(1, "malloc"); 583 shmsi = (struct shm_sysctl_info *)buf; 584 if (sysctl(mib, 4, shmsi, &len, NULL, 0) < 0) { 585 warn("sysctl(KERN_SYSVIPC_SHM_INFO)"); 586 goto done; 587 } 588 589 if (display & SHMTOTAL) 590 show_shmtotal(&shmsi->shminfo); 591 592 if (display & SHMINFO) { 593 show_shminfo_hdr(); 594 for (i = 0; i < shmsi->shminfo.shmmni; i++) { 595 struct shmid_ds_sysctl *shmptr = &shmsi->shmids[i]; 596 if (shmptr->shm_perm.mode & 0x0800) 597 show_shminfo(shmptr->shm_atime, 598 shmptr->shm_dtime, 599 shmptr->shm_ctime, 600 IXSEQ_TO_IPCID(i, shmptr->shm_perm), 601 shmptr->shm_perm._key, 602 shmptr->shm_perm.mode, 603 shmptr->shm_perm.uid, 604 shmptr->shm_perm.gid, 605 shmptr->shm_perm.cuid, 606 shmptr->shm_perm.cgid, 607 shmptr->shm_nattch, 608 shmptr->shm_segsz, 609 shmptr->shm_cpid, 610 shmptr->shm_lpid); 611 } 612 (void)printf("\n"); 613 } 614 done: 615 free(buf); 616 } 617 618 static void 619 sem_sysctl(void) 620 { 621 struct sem_sysctl_info *semsi; 622 void *buf; 623 int mib[4]; 624 size_t len; 625 int i, valid; 626 627 mib[0] = CTL_KERN; 628 mib[1] = KERN_SYSVIPC; 629 mib[2] = KERN_SYSVIPC_SEM; 630 len = sizeof(valid); 631 if (sysctl(mib, 3, &valid, &len, NULL, 0) < 0) { 632 warn("sysctl(KERN_SYSVIPC_SEM)"); 633 return; 634 } 635 if (!valid) { 636 unconfsem(); 637 return; 638 } 639 640 mib[0] = CTL_KERN; 641 mib[1] = KERN_SYSVIPC; 642 mib[2] = KERN_SYSVIPC_INFO; 643 mib[3] = KERN_SYSVIPC_SEM_INFO; 644 645 if (!(display & SEMINFO)) { 646 /* totals only */ 647 len = sizeof(struct seminfo); 648 } else { 649 if (sysctl(mib, 4, NULL, &len, NULL, 0) < 0) { 650 warn("sysctl(KERN_SYSVIPC_SEM_INFO)"); 651 return; 652 } 653 } 654 655 if ((buf = malloc(len)) == NULL) 656 err(1, "malloc"); 657 semsi = (struct sem_sysctl_info *)buf; 658 if (sysctl(mib, 4, semsi, &len, NULL, 0) < 0) { 659 warn("sysctl(KERN_SYSVIPC_SEM_INFO)"); 660 goto done; 661 } 662 663 if (display & SEMTOTAL) 664 show_semtotal(&semsi->seminfo); 665 666 if (display & SEMINFO) { 667 show_seminfo_hdr(); 668 for (i = 0; i < semsi->seminfo.semmni; i++) { 669 struct semid_ds_sysctl *semaptr = &semsi->semids[i]; 670 if ((semaptr->sem_perm.mode & SEM_ALLOC) != 0) 671 show_seminfo(semaptr->sem_otime, 672 semaptr->sem_ctime, 673 IXSEQ_TO_IPCID(i, semaptr->sem_perm), 674 semaptr->sem_perm._key, 675 semaptr->sem_perm.mode, 676 semaptr->sem_perm.uid, 677 semaptr->sem_perm.gid, 678 semaptr->sem_perm.cuid, 679 semaptr->sem_perm.cgid, 680 semaptr->sem_nsems); 681 } 682 (void)printf("\n"); 683 } 684 done: 685 free(buf); 686 } 687 688 static struct nlist symbols[] = { 689 { .n_name = "_sema" }, 690 #define X_SEMA 0 691 { .n_name = "_seminfo" }, 692 #define X_SEMINFO 1 693 { .n_name = "_semu" }, 694 #define X_SEMU 2 695 { .n_name = "_msginfo" }, 696 #define X_MSGINFO 3 697 { .n_name = "_msqids" }, 698 #define X_MSQIDS 4 699 { .n_name = "_shminfo" }, 700 #define X_SHMINFO 5 701 { .n_name = "_shmsegs" }, 702 #define X_SHMSEGS 6 703 { .n_name = NULL } 704 }; 705 706 static void 707 ipcs_kvm(void) 708 { 709 struct msginfo msginfo; 710 struct msqid_ds *msqids; 711 struct seminfo seminfo; 712 struct semid_ds *sema; 713 struct shminfo shminfo; 714 struct shmid_ds *shmsegs; 715 kvm_t *kd; 716 char errbuf[_POSIX2_LINE_MAX]; 717 int i; 718 719 if ((kd = kvm_openfiles(namelist, core, NULL, O_RDONLY, 720 errbuf)) == NULL) 721 errx(1, "can't open kvm: %s", errbuf); 722 723 724 switch (kvm_nlist(kd, symbols)) { 725 case 0: 726 break; 727 case -1: 728 errx(1, "%s: unable to read symbol table.", 729 namelist == NULL ? _PATH_UNIX : namelist); 730 /* NOTREACHED */ 731 default: 732 #ifdef notdef /* they'll be told more civilly later */ 733 warnx("nlist failed"); 734 for (i = 0; symbols[i].n_name != NULL; i++) 735 if (symbols[i].n_value == 0) 736 warnx("symbol %s not found", 737 symbols[i].n_name); 738 #endif 739 break; 740 } 741 742 if ((display & (MSGINFO | MSGTOTAL)) && 743 (kvm_read(kd, symbols[X_MSGINFO].n_value, 744 &msginfo, sizeof(msginfo)) == sizeof(msginfo))) { 745 746 if (display & MSGTOTAL) 747 show_msgtotal(&msginfo); 748 749 if (display & MSGINFO) { 750 struct msqid_ds *xmsqids; 751 752 if (kvm_read(kd, symbols[X_MSQIDS].n_value, 753 &msqids, sizeof(msqids)) != sizeof(msqids)) 754 errx(1, "kvm_read (%s): %s", 755 symbols[X_MSQIDS].n_name, kvm_geterr(kd)); 756 757 xmsqids = malloc(sizeof(struct msqid_ds) * 758 msginfo.msgmni); 759 760 if (kvm_read(kd, (u_long)msqids, xmsqids, 761 sizeof(struct msqid_ds) * msginfo.msgmni) != 762 sizeof(struct msqid_ds) * msginfo.msgmni) 763 errx(1, "kvm_read (msqids): %s", 764 kvm_geterr(kd)); 765 766 show_msginfo_hdr(); 767 for (i = 0; i < msginfo.msgmni; i++) { 768 struct msqid_ds *msqptr = &xmsqids[i]; 769 if (msqptr->msg_qbytes != 0) 770 show_msginfo(msqptr->msg_stime, 771 msqptr->msg_rtime, 772 msqptr->msg_ctime, 773 IXSEQ_TO_IPCID(i, msqptr->msg_perm), 774 (u_int64_t)msqptr->msg_perm._key, 775 msqptr->msg_perm.mode, 776 msqptr->msg_perm.uid, 777 msqptr->msg_perm.gid, 778 msqptr->msg_perm.cuid, 779 msqptr->msg_perm.cgid, 780 (u_int64_t)msqptr->_msg_cbytes, 781 (u_int64_t)msqptr->msg_qnum, 782 (u_int64_t)msqptr->msg_qbytes, 783 msqptr->msg_lspid, 784 msqptr->msg_lrpid); 785 } 786 (void)printf("\n"); 787 free(xmsqids); 788 } 789 } else 790 if (display & (MSGINFO | MSGTOTAL)) 791 unconfmsg(); 792 if ((display & (SHMINFO | SHMTOTAL)) && 793 (kvm_read(kd, symbols[X_SHMINFO].n_value, &shminfo, 794 sizeof(shminfo)) == sizeof(shminfo))) { 795 796 if (display & SHMTOTAL) 797 show_shmtotal(&shminfo); 798 799 if (display & SHMINFO) { 800 struct shmid_ds *xshmids; 801 802 if (kvm_read(kd, symbols[X_SHMSEGS].n_value, &shmsegs, 803 sizeof(shmsegs)) != sizeof(shmsegs)) 804 errx(1, "kvm_read (%s): %s", 805 symbols[X_SHMSEGS].n_name, kvm_geterr(kd)); 806 807 xshmids = malloc(sizeof(struct shmid_ds) * 808 shminfo.shmmni); 809 810 if (kvm_read(kd, (u_long)shmsegs, xshmids, 811 sizeof(struct shmid_ds) * shminfo.shmmni) != 812 sizeof(struct shmid_ds) * shminfo.shmmni) 813 errx(1, "kvm_read (shmsegs): %s", 814 kvm_geterr(kd)); 815 816 show_shminfo_hdr(); 817 for (i = 0; i < shminfo.shmmni; i++) { 818 struct shmid_ds *shmptr = &xshmids[i]; 819 if (shmptr->shm_perm.mode & 0x0800) 820 show_shminfo(shmptr->shm_atime, 821 shmptr->shm_dtime, 822 shmptr->shm_ctime, 823 IXSEQ_TO_IPCID(i, shmptr->shm_perm), 824 (u_int64_t)shmptr->shm_perm._key, 825 shmptr->shm_perm.mode, 826 shmptr->shm_perm.uid, 827 shmptr->shm_perm.gid, 828 shmptr->shm_perm.cuid, 829 shmptr->shm_perm.cgid, 830 shmptr->shm_nattch, 831 (u_int64_t)shmptr->shm_segsz, 832 shmptr->shm_cpid, 833 shmptr->shm_lpid); 834 } 835 (void)printf("\n"); 836 free(xshmids); 837 } 838 } else 839 if (display & (SHMINFO | SHMTOTAL)) 840 unconfshm(); 841 if ((display & (SEMINFO | SEMTOTAL)) && 842 (kvm_read(kd, symbols[X_SEMINFO].n_value, &seminfo, 843 sizeof(seminfo)) == sizeof(seminfo))) { 844 struct semid_ds *xsema; 845 846 if (display & SEMTOTAL) 847 show_semtotal(&seminfo); 848 849 if (display & SEMINFO) { 850 if (kvm_read(kd, symbols[X_SEMA].n_value, &sema, 851 sizeof(sema)) != sizeof(sema)) 852 errx(1, "kvm_read (%s): %s", 853 symbols[X_SEMA].n_name, kvm_geterr(kd)); 854 855 xsema = malloc(sizeof(struct semid_ds) * 856 seminfo.semmni); 857 858 if (kvm_read(kd, (u_long)sema, xsema, 859 sizeof(struct semid_ds) * seminfo.semmni) != 860 sizeof(struct semid_ds) * seminfo.semmni) 861 errx(1, "kvm_read (sema): %s", 862 kvm_geterr(kd)); 863 864 show_seminfo_hdr(); 865 for (i = 0; i < seminfo.semmni; i++) { 866 struct semid_ds *semaptr = &xsema[i]; 867 if ((semaptr->sem_perm.mode & SEM_ALLOC) != 0) 868 show_seminfo(semaptr->sem_otime, 869 semaptr->sem_ctime, 870 IXSEQ_TO_IPCID(i, semaptr->sem_perm), 871 (u_int64_t)semaptr->sem_perm._key, 872 semaptr->sem_perm.mode, 873 semaptr->sem_perm.uid, 874 semaptr->sem_perm.gid, 875 semaptr->sem_perm.cuid, 876 semaptr->sem_perm.cgid, 877 semaptr->sem_nsems); 878 } 879 880 (void)printf("\n"); 881 free(xsema); 882 } 883 } else 884 if (display & (SEMINFO | SEMTOTAL)) 885 unconfsem(); 886 (void)kvm_close(kd); 887 } 888 889 static void 890 usage(void) 891 { 892 893 (void)fprintf(stderr, 894 "Usage: %s [-abcmopqstMQST] [-C corefile] [-N namelist]\n", 895 getprogname()); 896 exit(1); 897 } 898