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