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@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