1 /* 2 * Copyright (c) 1994 SigmaSoft, Th. Lockert <tholo@sigmasoft.com> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. The name of the author may not be used to endorse or promote products 14 * derived from this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, 17 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 18 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 19 * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 20 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28 #include <sys/cdefs.h> 29 __FBSDID("$FreeBSD$"); 30 31 #include <sys/types.h> 32 #include <sys/param.h> 33 #include <sys/time.h> 34 #include <sys/proc.h> 35 #include <sys/sysctl.h> 36 #define _KERNEL 37 #include <sys/ipc.h> 38 #include <sys/sem.h> 39 #include <sys/shm.h> 40 #include <sys/msg.h> 41 #undef _KERNEL 42 43 #include <assert.h> 44 #include <err.h> 45 #include <fcntl.h> 46 #include <grp.h> 47 #include <kvm.h> 48 #include <limits.h> 49 #include <nlist.h> 50 #include <paths.h> 51 #include <pwd.h> 52 #include <stddef.h> 53 #include <stdio.h> 54 #include <stdlib.h> 55 #include <string.h> 56 #include <unistd.h> 57 58 /* SysCtlGatherStruct structure. */ 59 struct scgs_vector { 60 const char *sysctl; 61 off_t offset; 62 size_t size; 63 }; 64 65 int use_sysctl = 1; 66 struct semid_kernel *sema; 67 struct seminfo seminfo; 68 struct msginfo msginfo; 69 struct msqid_kernel *msqids; 70 struct shminfo shminfo; 71 struct shmid_kernel *shmsegs; 72 73 char *fmt_perm(u_short); 74 void cvt_time(time_t, char *); 75 void sysctlgatherstruct(void *addr, size_t size, struct scgs_vector *vec); 76 void kget(int idx, void *addr, size_t size); 77 void usage(void); 78 uid_t user2uid(char *username); 79 void print_kmsqtotal(struct msginfo msginfo); 80 void print_kmsqheader(int option); 81 void print_kmsqptr(int i, int option, struct msqid_kernel *kmsqptr); 82 void print_kshmtotal(struct shminfo shminfo); 83 void print_kshmheader(int option); 84 void print_kshmptr(int i, int option, struct shmid_kernel *kshmptr); 85 void print_ksemtotal(struct seminfo seminfo); 86 void print_ksemheader(int option); 87 void print_ksemptr(int i, int option, struct semid_kernel *ksemaptr); 88 89 static struct nlist symbols[] = { 90 {"sema"}, 91 #define X_SEMA 0 92 {"seminfo"}, 93 #define X_SEMINFO 1 94 {"msginfo"}, 95 #define X_MSGINFO 2 96 {"msqids"}, 97 #define X_MSQIDS 3 98 {"shminfo"}, 99 #define X_SHMINFO 4 100 {"shmsegs"}, 101 #define X_SHMSEGS 5 102 {NULL} 103 }; 104 105 #define SHMINFO_XVEC X(shmmax, sizeof(u_long)) \ 106 X(shmmin, sizeof(u_long)) \ 107 X(shmmni, sizeof(u_long)) \ 108 X(shmseg, sizeof(u_long)) \ 109 X(shmall, sizeof(u_long)) 110 111 #define SEMINFO_XVEC X(semmap, sizeof(int)) \ 112 X(semmni, sizeof(int)) \ 113 X(semmns, sizeof(int)) \ 114 X(semmnu, sizeof(int)) \ 115 X(semmsl, sizeof(int)) \ 116 X(semopm, sizeof(int)) \ 117 X(semume, sizeof(int)) \ 118 X(semusz, sizeof(int)) \ 119 X(semvmx, sizeof(int)) \ 120 X(semaem, sizeof(int)) 121 122 #define MSGINFO_XVEC X(msgmax, sizeof(int)) \ 123 X(msgmni, sizeof(int)) \ 124 X(msgmnb, sizeof(int)) \ 125 X(msgtql, sizeof(int)) \ 126 X(msgssz, sizeof(int)) \ 127 X(msgseg, sizeof(int)) 128 129 #define X(a, b) { "kern.ipc." #a, offsetof(TYPEC, a), (b) }, 130 #define TYPEC struct shminfo 131 struct scgs_vector shminfo_scgsv[] = { SHMINFO_XVEC { NULL } }; 132 #undef TYPEC 133 #define TYPEC struct seminfo 134 struct scgs_vector seminfo_scgsv[] = { SEMINFO_XVEC { NULL } }; 135 #undef TYPEC 136 #define TYPEC struct msginfo 137 struct scgs_vector msginfo_scgsv[] = { MSGINFO_XVEC { NULL } }; 138 #undef TYPEC 139 #undef X 140 141 static kvm_t *kd; 142 143 char * 144 fmt_perm(u_short mode) 145 { 146 static char buffer[100]; 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 void 164 cvt_time(time_t t, char *buf) 165 { 166 struct tm *tm; 167 168 if (t == 0) { 169 strcpy(buf, "no-entry"); 170 } else { 171 tm = localtime(&t); 172 sprintf(buf, "%2d:%02d:%02d", 173 tm->tm_hour, tm->tm_min, tm->tm_sec); 174 } 175 } 176 #define SHMINFO 1 177 #define SHMTOTAL 2 178 #define MSGINFO 4 179 #define MSGTOTAL 8 180 #define SEMINFO 16 181 #define SEMTOTAL 32 182 183 #define BIGGEST 1 184 #define CREATOR 2 185 #define OUTSTANDING 4 186 #define PID 8 187 #define TIME 16 188 189 int 190 main(int argc, char *argv[]) 191 { 192 int display = SHMINFO | MSGINFO | SEMINFO; 193 int option = 0; 194 char *core = NULL, *user = NULL, *namelist = NULL; 195 char kvmoferr[_POSIX2_LINE_MAX]; /* Error buf for kvm_openfiles. */ 196 int i; 197 uid_t uid = 0; 198 199 while ((i = getopt(argc, argv, "MmQqSsabC:cN:optTu:y")) != -1) 200 switch (i) { 201 case 'T': 202 display = SHMTOTAL | MSGTOTAL | SEMTOTAL; 203 break; 204 case 'a': 205 option |= BIGGEST | CREATOR | OUTSTANDING | PID | TIME; 206 break; 207 case 'b': 208 option |= BIGGEST; 209 break; 210 case 'C': 211 core = optarg; 212 break; 213 case 'c': 214 option |= CREATOR; 215 break; 216 case 'M': 217 display = SHMTOTAL; 218 break; 219 case 'm': 220 display = SHMINFO; 221 break; 222 case 'N': 223 namelist = optarg; 224 break; 225 case 'o': 226 option |= OUTSTANDING; 227 break; 228 case 'p': 229 option |= PID; 230 break; 231 case 'Q': 232 display = MSGTOTAL; 233 break; 234 case 'q': 235 display = MSGINFO; 236 break; 237 case 'S': 238 display = SEMTOTAL; 239 break; 240 case 's': 241 display = SEMINFO; 242 break; 243 case 't': 244 option |= TIME; 245 break; 246 case 'u': 247 user = optarg; 248 uid = user2uid(user); 249 break; 250 case 'y': 251 use_sysctl = 0; 252 break; 253 default: 254 usage(); 255 } 256 257 /* 258 * If paths to the exec file or core file were specified, we 259 * aren't operating on the running kernel, so we can't use 260 * sysctl. 261 */ 262 if (namelist != NULL || core != NULL) 263 use_sysctl = 0; 264 265 if (!use_sysctl) { 266 kd = kvm_openfiles(namelist, core, NULL, O_RDONLY, kvmoferr); 267 if (kd == NULL) 268 errx(1, "kvm_openfiles: %s", kvmoferr); 269 switch (kvm_nlist(kd, symbols)) { 270 case 0: 271 break; 272 case -1: 273 errx(1, "unable to read kernel symbol table"); 274 default: 275 break; 276 } 277 } 278 279 kget(X_MSGINFO, &msginfo, sizeof(msginfo)); 280 if ((display & (MSGINFO | MSGTOTAL))) { 281 if (display & MSGTOTAL) 282 print_kmsqtotal(msginfo); 283 284 if (display & MSGINFO) { 285 struct msqid_kernel *kxmsqids; 286 size_t kxmsqids_len; 287 288 kxmsqids_len = 289 sizeof(struct msqid_kernel) * msginfo.msgmni; 290 kxmsqids = malloc(kxmsqids_len); 291 kget(X_MSQIDS, kxmsqids, kxmsqids_len); 292 293 print_kmsqheader(option); 294 295 for (i = 0; i < msginfo.msgmni; i += 1) { 296 if (kxmsqids[i].u.msg_qbytes != 0) { 297 if (user && 298 uid != kxmsqids[i].u.msg_perm.uid) 299 continue; 300 301 print_kmsqptr(i, option, &kxmsqids[i]); 302 } 303 304 } 305 306 printf("\n"); 307 } 308 } else 309 if (display & (MSGINFO | MSGTOTAL)) { 310 fprintf(stderr, 311 "SVID messages facility " 312 "not configured in the system\n"); 313 } 314 315 kget(X_SHMINFO, &shminfo, sizeof(shminfo)); 316 if ((display & (SHMINFO | SHMTOTAL))) { 317 318 if (display & SHMTOTAL) 319 print_kshmtotal(shminfo); 320 321 if (display & SHMINFO) { 322 struct shmid_kernel *kxshmids; 323 size_t kxshmids_len; 324 325 kxshmids_len = 326 sizeof(struct shmid_kernel) * shminfo.shmmni; 327 kxshmids = malloc(kxshmids_len); 328 kget(X_SHMSEGS, kxshmids, kxshmids_len); 329 330 print_kshmheader(option); 331 332 for (i = 0; i < shminfo.shmmni; i += 1) { 333 if (kxshmids[i].u.shm_perm.mode & 0x0800) { 334 if (user && 335 uid != kxshmids[i].u.shm_perm.uid) 336 continue; 337 338 print_kshmptr(i, option, &kxshmids[i]); 339 } 340 } 341 printf("\n"); 342 } 343 } else 344 if (display & (SHMINFO | SHMTOTAL)) { 345 fprintf(stderr, 346 "SVID shared memory facility " 347 "not configured in the system\n"); 348 } 349 350 kget(X_SEMINFO, &seminfo, sizeof(seminfo)); 351 if ((display & (SEMINFO | SEMTOTAL))) { 352 struct semid_kernel *kxsema; 353 size_t kxsema_len; 354 355 if (display & SEMTOTAL) 356 print_ksemtotal(seminfo); 357 358 if (display & SEMINFO) { 359 kxsema_len = 360 sizeof(struct semid_kernel) * seminfo.semmni; 361 kxsema = malloc(kxsema_len); 362 kget(X_SEMA, kxsema, kxsema_len); 363 364 print_ksemheader(option); 365 366 for (i = 0; i < seminfo.semmni; i += 1) { 367 if ((kxsema[i].u.sem_perm.mode & SEM_ALLOC) != 0) { 368 if (user && 369 uid != kxsema[i].u.sem_perm.uid) 370 continue; 371 372 print_ksemptr(i, option, &kxsema[i]); 373 374 } 375 } 376 377 printf("\n"); 378 } 379 } else 380 if (display & (SEMINFO | SEMTOTAL)) { 381 fprintf(stderr, 382 "SVID semaphores facility " 383 "not configured in the system\n"); 384 } 385 386 if (!use_sysctl) 387 kvm_close(kd); 388 389 exit(0); 390 } 391 392 void 393 print_kmsqtotal(struct msginfo msginfo) 394 { 395 396 printf("msginfo:\n"); 397 printf("\tmsgmax: %12d\t(max characters in a message)\n", 398 msginfo.msgmax); 399 printf("\tmsgmni: %12d\t(# of message queues)\n", 400 msginfo.msgmni); 401 printf("\tmsgmnb: %12d\t(max characters in a message queue)\n", 402 msginfo.msgmnb); 403 printf("\tmsgtql: %12d\t(max # of messages in system)\n", 404 msginfo.msgtql); 405 printf("\tmsgssz: %12d\t(size of a message segment)\n", 406 msginfo.msgssz); 407 printf("\tmsgseg: %12d\t(# of message segments in system)\n\n", 408 msginfo.msgseg); 409 } 410 411 void print_kmsqheader(int option) { 412 413 printf("Message Queues:\n"); 414 printf("T %12s %12s %-11s %-8s %-8s", 415 "ID", "KEY", "MODE", "OWNER", "GROUP"); 416 if (option & CREATOR) 417 printf(" %-8s %-8s", "CREATOR", "CGROUP"); 418 if (option & OUTSTANDING) 419 printf(" %20s %20s", "CBYTES", "QNUM"); 420 if (option & BIGGEST) 421 printf(" %20s", "QBYTES"); 422 if (option & PID) 423 printf(" %12s %12s", "LSPID", "LRPID"); 424 if (option & TIME) 425 printf(" %-8s %-8s %-8s", "STIME", "RTIME", "CTIME"); 426 printf("\n"); 427 } 428 429 void 430 print_kmsqptr(int i, int option, struct msqid_kernel *kmsqptr) 431 { 432 char stime_buf[100], rtime_buf[100], ctime_buf[100]; 433 434 cvt_time(kmsqptr->u.msg_stime, stime_buf); 435 cvt_time(kmsqptr->u.msg_rtime, rtime_buf); 436 cvt_time(kmsqptr->u.msg_ctime, ctime_buf); 437 438 printf("q %12d %12d %s %8s %8s", 439 IXSEQ_TO_IPCID(i, kmsqptr->u.msg_perm), 440 (int)kmsqptr->u.msg_perm.key, 441 fmt_perm(kmsqptr->u.msg_perm.mode), 442 user_from_uid(kmsqptr->u.msg_perm.uid, 0), 443 group_from_gid(kmsqptr->u.msg_perm.gid, 0)); 444 445 if (option & CREATOR) 446 printf(" %8s %8s", 447 user_from_uid(kmsqptr->u.msg_perm.cuid, 0), 448 group_from_gid(kmsqptr->u.msg_perm.cgid, 0)); 449 450 if (option & OUTSTANDING) 451 printf(" %12lu %12lu", 452 kmsqptr->u.msg_cbytes, 453 kmsqptr->u.msg_qnum); 454 455 if (option & BIGGEST) 456 printf(" %20lu", kmsqptr->u.msg_qbytes); 457 458 if (option & PID) 459 printf(" %12d %12d", 460 kmsqptr->u.msg_lspid, 461 kmsqptr->u.msg_lrpid); 462 463 if (option & TIME) 464 printf(" %s %s %s", 465 stime_buf, 466 rtime_buf, 467 ctime_buf); 468 469 printf("\n"); 470 } 471 472 void 473 print_kshmtotal(struct shminfo shminfo) 474 { 475 476 printf("shminfo:\n"); 477 printf("\tshmmax: %12d\t(max shared memory segment size)\n", 478 shminfo.shmmax); 479 printf("\tshmmin: %12d\t(min shared memory segment size)\n", 480 shminfo.shmmin); 481 printf("\tshmmni: %12d\t(max number of shared memory identifiers)\n", 482 shminfo.shmmni); 483 printf("\tshmseg: %12d\t(max shared memory segments per process)\n", 484 shminfo.shmseg); 485 printf("\tshmall: %12d\t(max amount of shared memory in pages)\n\n", 486 shminfo.shmall); 487 } 488 489 void 490 print_kshmheader(int option) 491 { 492 493 printf("Shared Memory:\n"); 494 printf("T %12s %12s %-11s %-8s %-8s", 495 "ID", "KEY", "MODE", "OWNER", "GROUP"); 496 if (option & CREATOR) 497 printf(" %-8s %-8s", "CREATOR", "CGROUP"); 498 if (option & OUTSTANDING) 499 printf(" %12s", "NATTCH"); 500 if (option & BIGGEST) 501 printf(" %12s", "SEGSZ"); 502 if (option & PID) 503 printf(" %12s %12s", "CPID", "LPID"); 504 if (option & TIME) 505 printf(" %-8s %-8s %-8s", "ATIME", "DTIME", "CTIME"); 506 printf("\n"); 507 } 508 509 void 510 print_kshmptr(int i, int option, struct shmid_kernel *kshmptr) 511 { 512 char atime_buf[100], dtime_buf[100], ctime_buf[100]; 513 514 cvt_time(kshmptr->u.shm_atime, atime_buf); 515 cvt_time(kshmptr->u.shm_dtime, dtime_buf); 516 cvt_time(kshmptr->u.shm_ctime, ctime_buf); 517 518 printf("m %12d %12d %s %8s %8s", 519 IXSEQ_TO_IPCID(i, kshmptr->u.shm_perm), 520 (int)kshmptr->u.shm_perm.key, 521 fmt_perm(kshmptr->u.shm_perm.mode), 522 user_from_uid(kshmptr->u.shm_perm.uid, 0), 523 group_from_gid(kshmptr->u.shm_perm.gid, 0)); 524 525 if (option & CREATOR) 526 printf(" %8s %8s", 527 user_from_uid(kshmptr->u.shm_perm.cuid, 0), 528 group_from_gid(kshmptr->u.shm_perm.cgid, 0)); 529 530 if (option & OUTSTANDING) 531 printf(" %12d", 532 kshmptr->u.shm_nattch); 533 534 if (option & BIGGEST) 535 printf(" %12d", 536 kshmptr->u.shm_segsz); 537 538 if (option & PID) 539 printf(" %12d %12d", 540 kshmptr->u.shm_cpid, 541 kshmptr->u.shm_lpid); 542 543 if (option & TIME) 544 printf(" %s %s %s", 545 atime_buf, 546 dtime_buf, 547 ctime_buf); 548 549 printf("\n"); 550 } 551 552 void 553 print_ksemtotal(struct seminfo seminfo) 554 { 555 556 printf("seminfo:\n"); 557 printf("\tsemmap: %12d\t(# of entries in semaphore map)\n", 558 seminfo.semmap); 559 printf("\tsemmni: %12d\t(# of semaphore identifiers)\n", 560 seminfo.semmni); 561 printf("\tsemmns: %12d\t(# of semaphores in system)\n", 562 seminfo.semmns); 563 printf("\tsemmnu: %12d\t(# of undo structures in system)\n", 564 seminfo.semmnu); 565 printf("\tsemmsl: %12d\t(max # of semaphores per id)\n", 566 seminfo.semmsl); 567 printf("\tsemopm: %12d\t(max # of operations per semop call)\n", 568 seminfo.semopm); 569 printf("\tsemume: %12d\t(max # of undo entries per process)\n", 570 seminfo.semume); 571 printf("\tsemusz: %12d\t(size in bytes of undo structure)\n", 572 seminfo.semusz); 573 printf("\tsemvmx: %12d\t(semaphore maximum value)\n", 574 seminfo.semvmx); 575 printf("\tsemaem: %12d\t(adjust on exit max value)\n\n", 576 seminfo.semaem); 577 } 578 579 void 580 print_ksemheader(int option) { 581 582 printf("Semaphores:\n"); 583 printf("T %12s %12s %-11s %-8s %-8s", 584 "ID", "KEY", "MODE", "OWNER", "GROUP"); 585 if (option & CREATOR) 586 printf(" %-8s %-8s", "CREATOR", "CGROUP"); 587 if (option & BIGGEST) 588 printf(" %12s", "NSEMS"); 589 if (option & TIME) 590 printf(" %-8s %-8s", "OTIME", "CTIME"); 591 printf("\n"); 592 } 593 594 void 595 print_ksemptr(int i, int option, struct semid_kernel *ksemaptr) 596 { 597 char ctime_buf[100], otime_buf[100]; 598 599 cvt_time(ksemaptr->u.sem_otime, otime_buf); 600 cvt_time(ksemaptr->u.sem_ctime, ctime_buf); 601 602 printf("s %12d %12d %s %8s %8s", 603 IXSEQ_TO_IPCID(i, ksemaptr->u.sem_perm), 604 (int)ksemaptr->u.sem_perm.key, 605 fmt_perm(ksemaptr->u.sem_perm.mode), 606 user_from_uid(ksemaptr->u.sem_perm.uid, 0), 607 group_from_gid(ksemaptr->u.sem_perm.gid, 0)); 608 609 if (option & CREATOR) 610 printf(" %8s %8s", 611 user_from_uid(ksemaptr->u.sem_perm.cuid, 0), 612 group_from_gid(ksemaptr->u.sem_perm.cgid, 0)); 613 614 if (option & BIGGEST) 615 printf(" %12d", 616 ksemaptr->u.sem_nsems); 617 618 if (option & TIME) 619 printf(" %s %s", 620 otime_buf, 621 ctime_buf); 622 623 printf("\n"); 624 } 625 626 void 627 sysctlgatherstruct(void *addr, size_t size, struct scgs_vector *vecarr) 628 { 629 struct scgs_vector *xp; 630 size_t tsiz; 631 int rv; 632 633 for (xp = vecarr; xp->sysctl != NULL; xp++) { 634 assert(xp->offset <= size); 635 tsiz = xp->size; 636 rv = sysctlbyname(xp->sysctl, (char *)addr + xp->offset, 637 &tsiz, NULL, 0); 638 if (rv == -1) 639 err(1, "sysctlbyname: %s", xp->sysctl); 640 if (tsiz != xp->size) 641 errx(1, "%s size mismatch (expected %d, got %d)", 642 xp->sysctl, xp->size, tsiz); 643 } 644 } 645 646 void 647 kget(int idx, void *addr, size_t size) 648 { 649 char *symn; /* symbol name */ 650 size_t tsiz; 651 int rv; 652 unsigned long kaddr; 653 const char *sym2sysctl[] = { /* symbol to sysctl name table */ 654 "kern.ipc.sema", 655 "kern.ipc.seminfo", 656 "kern.ipc.msginfo", 657 "kern.ipc.msqids", 658 "kern.ipc.shminfo", 659 "kern.ipc.shmsegs" }; 660 661 assert((unsigned)idx <= sizeof(sym2sysctl) / sizeof(*sym2sysctl)); 662 if (!use_sysctl) { 663 symn = symbols[idx].n_name; 664 if (*symn == '_') 665 symn++; 666 if (symbols[idx].n_type == 0 || symbols[idx].n_value == 0) 667 errx(1, "symbol %s undefined", symn); 668 /* 669 * For some symbols, the value we retrieve is 670 * actually a pointer; since we want the actual value, 671 * we have to manually dereference it. 672 */ 673 switch (idx) { 674 case X_MSQIDS: 675 tsiz = sizeof(msqids); 676 rv = kvm_read(kd, symbols[idx].n_value, 677 &msqids, tsiz); 678 kaddr = (u_long)msqids; 679 break; 680 case X_SHMSEGS: 681 tsiz = sizeof(shmsegs); 682 rv = kvm_read(kd, symbols[idx].n_value, 683 &shmsegs, tsiz); 684 kaddr = (u_long)shmsegs; 685 break; 686 case X_SEMA: 687 tsiz = sizeof(sema); 688 rv = kvm_read(kd, symbols[idx].n_value, 689 &sema, tsiz); 690 kaddr = (u_long)sema; 691 break; 692 default: 693 rv = tsiz = 0; 694 kaddr = symbols[idx].n_value; 695 break; 696 } 697 if ((unsigned)rv != tsiz) 698 errx(1, "%s: %s", symn, kvm_geterr(kd)); 699 if ((unsigned)kvm_read(kd, kaddr, addr, size) != size) 700 errx(1, "%s: %s", symn, kvm_geterr(kd)); 701 } else { 702 switch (idx) { 703 case X_SHMINFO: 704 sysctlgatherstruct(addr, size, shminfo_scgsv); 705 break; 706 case X_SEMINFO: 707 sysctlgatherstruct(addr, size, seminfo_scgsv); 708 break; 709 case X_MSGINFO: 710 sysctlgatherstruct(addr, size, msginfo_scgsv); 711 break; 712 default: 713 tsiz = size; 714 rv = sysctlbyname(sym2sysctl[idx], addr, &tsiz, 715 NULL, 0); 716 if (rv == -1) 717 err(1, "sysctlbyname: %s", sym2sysctl[idx]); 718 if (tsiz != size) 719 errx(1, "%s size mismatch " 720 "(expected %d, got %d)", 721 sym2sysctl[idx], size, tsiz); 722 break; 723 } 724 } 725 } 726 727 uid_t 728 user2uid(char *username) 729 { 730 struct passwd *pwd; 731 uid_t uid; 732 char *r; 733 734 uid = strtoul(username, &r, 0); 735 if (!*r && r != username) 736 return (uid); 737 if ((pwd = getpwnam(username)) == NULL) 738 errx(1, "getpwnam failed: No such user"); 739 endpwent(); 740 return (pwd->pw_uid); 741 } 742 743 void 744 usage(void) 745 { 746 747 fprintf(stderr, 748 "usage: " 749 "ipcs [-abcmopqstyMQST] [-C corefile] [-N namelist] [-u user]\n"); 750 exit(1); 751 } 752