ipcs.c revision 90878
12731Sdfr/* 22738Sdfr * Copyright (c) 1994 SigmaSoft, Th. Lockert <tholo@sigmasoft.com> 32738Sdfr * All rights reserved. 42738Sdfr * 52738Sdfr * Redistribution and use in source and binary forms, with or without 62738Sdfr * modification, are permitted provided that the following conditions 72738Sdfr * are met: 82738Sdfr * 1. Redistributions of source code must retain the above copyright 92738Sdfr * notice, this list of conditions and the following disclaimer. 102738Sdfr * 2. Redistributions in binary form must reproduce the above copyright 112738Sdfr * notice, this list of conditions and the following disclaimer in the 122738Sdfr * documentation and/or other materials provided with the distribution. 132738Sdfr * 3. The name of the author may not be used to endorse or promote products 142738Sdfr * derived from this software without specific prior written permission. 152738Sdfr * 162738Sdfr * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, 172738Sdfr * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 182738Sdfr * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 192738Sdfr * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 202738Sdfr * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 212738Sdfr * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 222738Sdfr * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 232738Sdfr * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 242738Sdfr * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 252738Sdfr * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 262731Sdfr */ 272731Sdfr 2827421Scharnier#ifndef lint 2927421Scharnierstatic const char rcsid[] = 3050477Speter "$FreeBSD: head/usr.bin/ipcs/ipcs.c 90878 2002-02-19 00:05:59Z imp $"; 3127421Scharnier#endif /* not lint */ 3227421Scharnier 3377551Sdd#include <assert.h> 3427421Scharnier#include <err.h> 3527421Scharnier#include <fcntl.h> 3690878Simp#include <grp.h> 3727421Scharnier#include <kvm.h> 3827421Scharnier#include <nlist.h> 3977551Sdd#include <limits.h> 4027421Scharnier#include <paths.h> 4190878Simp#include <pwd.h> 4277551Sdd#include <stddef.h> 432731Sdfr#include <stdio.h> 442731Sdfr#include <stdlib.h> 4578718Sdd#include <string.h> 462731Sdfr#include <unistd.h> 472731Sdfr 482731Sdfr#include <sys/types.h> 492731Sdfr#include <sys/param.h> 502738Sdfr#include <sys/time.h> 512731Sdfr#include <sys/proc.h> 5277551Sdd#include <sys/sysctl.h> 5355206Speter#define _KERNEL 542731Sdfr#include <sys/ipc.h> 552731Sdfr#include <sys/sem.h> 562731Sdfr#include <sys/shm.h> 572731Sdfr#include <sys/msg.h> 582731Sdfr 5977551Sdd/* SysCtlGatherStruct structure. */ 6077551Sddstruct scgs_vector { 6177551Sdd const char *sysctl; 6277551Sdd off_t offset; 6377551Sdd size_t size; 6477551Sdd}; 6577551Sdd 6677551Sddint use_sysctl = 1; 679499Sbdestruct semid_ds *sema; 682890Sdgstruct seminfo seminfo; 692890Sdgstruct msginfo msginfo; 709499Sbdestruct msqid_ds *msqids; 719499Sbdestruct shminfo shminfo; 729499Sbdestruct shmid_ds *shmsegs; 732890Sdg 7477551Sddvoid sysctlgatherstruct __P((void *addr, size_t size, 7577551Sdd struct scgs_vector *vec)); 7677551Sddvoid kget __P((int idx, void *addr, size_t size)); 772738Sdfrvoid usage __P((void)); 782731Sdfr 792738Sdfrstatic struct nlist symbols[] = { 8077551Sdd {"sema"}, 812738Sdfr#define X_SEMA 0 8277551Sdd {"seminfo"}, 832738Sdfr#define X_SEMINFO 1 8477551Sdd {"msginfo"}, 8577551Sdd#define X_MSGINFO 2 8677551Sdd {"msqids"}, 8777551Sdd#define X_MSQIDS 3 8877551Sdd {"shminfo"}, 8977551Sdd#define X_SHMINFO 4 9077551Sdd {"shmsegs"}, 9177551Sdd#define X_SHMSEGS 5 922738Sdfr {NULL} 932738Sdfr}; 942731Sdfr 9577551Sdd#define SHMINFO_XVEC \ 9677551SddX(shmmax, sizeof(int)) \ 9777551SddX(shmmin, sizeof(int)) \ 9877551SddX(shmmni, sizeof(int)) \ 9977551SddX(shmseg, sizeof(int)) \ 10077551SddX(shmall, sizeof(int)) 10177551Sdd 10277551Sdd#define SEMINFO_XVEC \ 10377551SddX(semmap, sizeof(int)) \ 10477551SddX(semmni, sizeof(int)) \ 10577551SddX(semmns, sizeof(int)) \ 10677551SddX(semmnu, sizeof(int)) \ 10777551SddX(semmsl, sizeof(int)) \ 10877551SddX(semopm, sizeof(int)) \ 10977551SddX(semume, sizeof(int)) \ 11077551SddX(semusz, sizeof(int)) \ 11177551SddX(semvmx, sizeof(int)) \ 11277551SddX(semaem, sizeof(int)) 11377551Sdd 11477551Sdd#define MSGINFO_XVEC \ 11577551SddX(msgmax, sizeof(int)) \ 11677551SddX(msgmni, sizeof(int)) \ 11777551SddX(msgmnb, sizeof(int)) \ 11877551SddX(msgtql, sizeof(int)) \ 11977551SddX(msgssz, sizeof(int)) \ 12077551SddX(msgseg, sizeof(int)) 12177551Sdd 12277551Sdd#define X(a, b) { "kern.ipc." #a, offsetof(TYPEC, a), (b) }, 12377551Sdd#define TYPEC struct shminfo 12477551Sddstruct scgs_vector shminfo_scgsv[] = { SHMINFO_XVEC { NULL } }; 12577551Sdd#undef TYPEC 12677551Sdd#define TYPEC struct seminfo 12777551Sddstruct scgs_vector seminfo_scgsv[] = { SEMINFO_XVEC { NULL } }; 12877551Sdd#undef TYPEC 12977551Sdd#define TYPEC struct msginfo 13077551Sddstruct scgs_vector msginfo_scgsv[] = { MSGINFO_XVEC { NULL } }; 13177551Sdd#undef TYPEC 13277551Sdd#undef X 13377551Sdd 1342738Sdfrstatic kvm_t *kd; 1352738Sdfr 1362738Sdfrchar * 1372738Sdfrfmt_perm(mode) 1382738Sdfr u_short mode; 1392731Sdfr{ 1402738Sdfr static char buffer[100]; 1412731Sdfr 1422738Sdfr buffer[0] = '-'; 1432738Sdfr buffer[1] = '-'; 1442738Sdfr buffer[2] = ((mode & 0400) ? 'r' : '-'); 1452738Sdfr buffer[3] = ((mode & 0200) ? 'w' : '-'); 1462738Sdfr buffer[4] = ((mode & 0100) ? 'a' : '-'); 1472738Sdfr buffer[5] = ((mode & 0040) ? 'r' : '-'); 1482738Sdfr buffer[6] = ((mode & 0020) ? 'w' : '-'); 1492738Sdfr buffer[7] = ((mode & 0010) ? 'a' : '-'); 1502738Sdfr buffer[8] = ((mode & 0004) ? 'r' : '-'); 1512738Sdfr buffer[9] = ((mode & 0002) ? 'w' : '-'); 1522738Sdfr buffer[10] = ((mode & 0001) ? 'a' : '-'); 1532738Sdfr buffer[11] = '\0'; 1542738Sdfr return (&buffer[0]); 1552731Sdfr} 1562731Sdfr 1572731Sdfrvoid 1582738Sdfrcvt_time(t, buf) 1592738Sdfr time_t t; 1602738Sdfr char *buf; 1612731Sdfr{ 1622738Sdfr struct tm *tm; 1632731Sdfr 1642738Sdfr if (t == 0) { 1652738Sdfr strcpy(buf, "no-entry"); 1662738Sdfr } else { 1672738Sdfr tm = localtime(&t); 1682738Sdfr sprintf(buf, "%2d:%02d:%02d", 1692738Sdfr tm->tm_hour, tm->tm_min, tm->tm_sec); 1702731Sdfr } 1712731Sdfr} 1722738Sdfr#define SHMINFO 1 1732738Sdfr#define SHMTOTAL 2 1742738Sdfr#define MSGINFO 4 1752738Sdfr#define MSGTOTAL 8 1762738Sdfr#define SEMINFO 16 1772738Sdfr#define SEMTOTAL 32 1782731Sdfr 1792738Sdfr#define BIGGEST 1 1802738Sdfr#define CREATOR 2 1812738Sdfr#define OUTSTANDING 4 1822738Sdfr#define PID 8 1832738Sdfr#define TIME 16 1842731Sdfr 1852738Sdfrint 1862738Sdfrmain(argc, argv) 1872738Sdfr int argc; 1882738Sdfr char *argv[]; 1892731Sdfr{ 1902738Sdfr int display = SHMINFO | MSGINFO | SEMINFO; 1912738Sdfr int option = 0; 1922738Sdfr char *core = NULL, *namelist = NULL; 19377551Sdd char kvmoferr[_POSIX2_LINE_MAX]; /* Error buf for kvm_openfiles. */ 1942738Sdfr int i; 1952731Sdfr 19677551Sdd while ((i = getopt(argc, argv, "MmQqSsabC:cN:optTy")) != -1) 1972738Sdfr switch (i) { 1982738Sdfr case 'M': 1992738Sdfr display = SHMTOTAL; 2002738Sdfr break; 2012738Sdfr case 'm': 2022738Sdfr display = SHMINFO; 2032738Sdfr break; 2042738Sdfr case 'Q': 2052738Sdfr display = MSGTOTAL; 2062738Sdfr break; 2072738Sdfr case 'q': 2082738Sdfr display = MSGINFO; 2092738Sdfr break; 2102738Sdfr case 'S': 2112738Sdfr display = SEMTOTAL; 2122738Sdfr break; 2132738Sdfr case 's': 2142738Sdfr display = SEMINFO; 2152738Sdfr break; 2162738Sdfr case 'T': 2172738Sdfr display = SHMTOTAL | MSGTOTAL | SEMTOTAL; 2182738Sdfr break; 2192738Sdfr case 'a': 2202738Sdfr option |= BIGGEST | CREATOR | OUTSTANDING | PID | TIME; 2212738Sdfr break; 2222738Sdfr case 'b': 2232738Sdfr option |= BIGGEST; 2242738Sdfr break; 2252738Sdfr case 'C': 2262738Sdfr core = optarg; 2272738Sdfr break; 2282738Sdfr case 'c': 2292738Sdfr option |= CREATOR; 2302738Sdfr break; 2312738Sdfr case 'N': 2322738Sdfr namelist = optarg; 2332738Sdfr break; 2342738Sdfr case 'o': 2352738Sdfr option |= OUTSTANDING; 2362738Sdfr break; 2372738Sdfr case 'p': 2382738Sdfr option |= PID; 2392738Sdfr break; 2402738Sdfr case 't': 2412738Sdfr option |= TIME; 2422738Sdfr break; 24377551Sdd case 'y': 24477551Sdd use_sysctl = 0; 24577551Sdd break; 2462738Sdfr default: 2472738Sdfr usage(); 2482738Sdfr } 24915990Spst 25015990Spst /* 25177551Sdd * If paths to the exec file or core file were specified, we 25277551Sdd * aren't operating on the running kernel, so we can't use 25377551Sdd * sysctl. 25415990Spst */ 25515990Spst if (namelist != NULL || core != NULL) 25677551Sdd use_sysctl = 0; 25715990Spst 25877551Sdd if (!use_sysctl) { 25977551Sdd kd = kvm_openfiles(namelist, core, NULL, O_RDONLY, kvmoferr); 26077551Sdd if (kd == NULL) 26177551Sdd errx(1, "kvm_openfiles: %s", kvmoferr); 26277551Sdd switch (kvm_nlist(kd, symbols)) { 26377551Sdd case 0: 26477551Sdd break; 26577551Sdd case -1: 26677551Sdd errx(1, "unable to read kernel symbol table"); 26777551Sdd default: 2682738Sdfr#ifdef notdef /* they'll be told more civilly later */ 26977551Sdd warnx("nlist failed"); 27077551Sdd for (i = 0; symbols[i].n_name != NULL; i++) 27177551Sdd if (symbols[i].n_value == 0) 27277551Sdd warnx("symbol %s not found", 27377551Sdd symbols[i].n_name); 27477551Sdd break; 2752738Sdfr#endif 27677551Sdd } 2772731Sdfr } 2782731Sdfr 27977551Sdd kget(X_MSGINFO, &msginfo, sizeof(msginfo)); 28077551Sdd if ((display & (MSGINFO | MSGTOTAL))) { 2812738Sdfr if (display & MSGTOTAL) { 2822738Sdfr printf("msginfo:\n"); 2832738Sdfr printf("\tmsgmax: %6d\t(max characters in a message)\n", 2842738Sdfr msginfo.msgmax); 2852738Sdfr printf("\tmsgmni: %6d\t(# of message queues)\n", 2862738Sdfr msginfo.msgmni); 2872738Sdfr printf("\tmsgmnb: %6d\t(max characters in a message queue)\n", 2882738Sdfr msginfo.msgmnb); 2892738Sdfr printf("\tmsgtql: %6d\t(max # of messages in system)\n", 2902738Sdfr msginfo.msgtql); 2912738Sdfr printf("\tmsgssz: %6d\t(size of a message segment)\n", 2922738Sdfr msginfo.msgssz); 2932738Sdfr printf("\tmsgseg: %6d\t(# of message segments in system)\n\n", 2942738Sdfr msginfo.msgseg); 2952738Sdfr } 2962738Sdfr if (display & MSGINFO) { 2972738Sdfr struct msqid_ds *xmsqids; 29877551Sdd size_t xmsqids_len; 2992731Sdfr 3002731Sdfr 30177551Sdd xmsqids_len = sizeof(struct msqid_ds) * msginfo.msgmni; 30277551Sdd xmsqids = malloc(xmsqids_len); 30377551Sdd kget(X_MSQIDS, xmsqids, xmsqids_len); 30477551Sdd 3052738Sdfr printf("Message Queues:\n"); 3062738Sdfr printf("T ID KEY MODE OWNER GROUP"); 3072738Sdfr if (option & CREATOR) 3082738Sdfr printf(" CREATOR CGROUP"); 3092738Sdfr if (option & OUTSTANDING) 3102738Sdfr printf(" CBYTES QNUM"); 3112738Sdfr if (option & BIGGEST) 3122738Sdfr printf(" QBYTES"); 3132738Sdfr if (option & PID) 3142738Sdfr printf(" LSPID LRPID"); 3152738Sdfr if (option & TIME) 3162738Sdfr printf(" STIME RTIME CTIME"); 3172738Sdfr printf("\n"); 3182738Sdfr for (i = 0; i < msginfo.msgmni; i += 1) { 3192738Sdfr if (xmsqids[i].msg_qbytes != 0) { 3202738Sdfr char stime_buf[100], rtime_buf[100], 3212738Sdfr ctime_buf[100]; 3222738Sdfr struct msqid_ds *msqptr = &xmsqids[i]; 3232731Sdfr 3242738Sdfr cvt_time(msqptr->msg_stime, stime_buf); 3252738Sdfr cvt_time(msqptr->msg_rtime, rtime_buf); 3262738Sdfr cvt_time(msqptr->msg_ctime, ctime_buf); 3272731Sdfr 3282738Sdfr printf("q %6d %10d %s %8s %8s", 3292738Sdfr IXSEQ_TO_IPCID(i, msqptr->msg_perm), 3302738Sdfr msqptr->msg_perm.key, 3312738Sdfr fmt_perm(msqptr->msg_perm.mode), 3322738Sdfr user_from_uid(msqptr->msg_perm.uid, 0), 3332738Sdfr group_from_gid(msqptr->msg_perm.gid, 0)); 3342731Sdfr 3352738Sdfr if (option & CREATOR) 3362738Sdfr printf(" %8s %8s", 3372738Sdfr user_from_uid(msqptr->msg_perm.cuid, 0), 3382738Sdfr group_from_gid(msqptr->msg_perm.cgid, 0)); 3392731Sdfr 3402738Sdfr if (option & OUTSTANDING) 3412738Sdfr printf(" %6d %6d", 3422738Sdfr msqptr->msg_cbytes, 3432738Sdfr msqptr->msg_qnum); 3442731Sdfr 3452738Sdfr if (option & BIGGEST) 3462738Sdfr printf(" %6d", 3472738Sdfr msqptr->msg_qbytes); 3482731Sdfr 3492738Sdfr if (option & PID) 3502738Sdfr printf(" %6d %6d", 3512738Sdfr msqptr->msg_lspid, 3522738Sdfr msqptr->msg_lrpid); 3532731Sdfr 3542738Sdfr if (option & TIME) 3552738Sdfr printf("%s %s %s", 3562738Sdfr stime_buf, 3572738Sdfr rtime_buf, 3582738Sdfr ctime_buf); 3592731Sdfr 3602738Sdfr printf("\n"); 3612738Sdfr } 3622738Sdfr } 3632738Sdfr printf("\n"); 3642738Sdfr } 3652738Sdfr } else 3662738Sdfr if (display & (MSGINFO | MSGTOTAL)) { 3672738Sdfr fprintf(stderr, 3682738Sdfr "SVID messages facility not configured in the system\n"); 3692738Sdfr } 37077551Sdd 37177551Sdd kget(X_SHMINFO, &shminfo, sizeof(shminfo)); 37277551Sdd if ((display & (SHMINFO | SHMTOTAL))) { 3732738Sdfr if (display & SHMTOTAL) { 3742738Sdfr printf("shminfo:\n"); 3752738Sdfr printf("\tshmmax: %7d\t(max shared memory segment size)\n", 3762738Sdfr shminfo.shmmax); 3772738Sdfr printf("\tshmmin: %7d\t(min shared memory segment size)\n", 3782738Sdfr shminfo.shmmin); 3792738Sdfr printf("\tshmmni: %7d\t(max number of shared memory identifiers)\n", 3802738Sdfr shminfo.shmmni); 3812738Sdfr printf("\tshmseg: %7d\t(max shared memory segments per process)\n", 3822738Sdfr shminfo.shmseg); 3832738Sdfr printf("\tshmall: %7d\t(max amount of shared memory in pages)\n\n", 3842738Sdfr shminfo.shmall); 3852738Sdfr } 3862738Sdfr if (display & SHMINFO) { 3872738Sdfr struct shmid_ds *xshmids; 38877551Sdd size_t xshmids_len; 3892731Sdfr 39077551Sdd xshmids_len = sizeof(struct shmid_ds) * shminfo.shmmni; 39177551Sdd xshmids = malloc(xshmids_len); 39277551Sdd kget(X_SHMSEGS, xshmids, xshmids_len); 3932731Sdfr 3942738Sdfr printf("Shared Memory:\n"); 3952738Sdfr printf("T ID KEY MODE OWNER GROUP"); 3962738Sdfr if (option & CREATOR) 3972738Sdfr printf(" CREATOR CGROUP"); 3982738Sdfr if (option & OUTSTANDING) 3992738Sdfr printf(" NATTCH"); 4002738Sdfr if (option & BIGGEST) 4012738Sdfr printf(" SEGSZ"); 4022738Sdfr if (option & PID) 4032738Sdfr printf(" CPID LPID"); 4042738Sdfr if (option & TIME) 4052738Sdfr printf(" ATIME DTIME CTIME"); 4062738Sdfr printf("\n"); 4072738Sdfr for (i = 0; i < shminfo.shmmni; i += 1) { 4082738Sdfr if (xshmids[i].shm_perm.mode & 0x0800) { 4092738Sdfr char atime_buf[100], dtime_buf[100], 4102738Sdfr ctime_buf[100]; 4112738Sdfr struct shmid_ds *shmptr = &xshmids[i]; 4122731Sdfr 4132738Sdfr cvt_time(shmptr->shm_atime, atime_buf); 4142738Sdfr cvt_time(shmptr->shm_dtime, dtime_buf); 4152738Sdfr cvt_time(shmptr->shm_ctime, ctime_buf); 4162731Sdfr 4172738Sdfr printf("m %6d %10d %s %8s %8s", 4182738Sdfr IXSEQ_TO_IPCID(i, shmptr->shm_perm), 4192738Sdfr shmptr->shm_perm.key, 4202738Sdfr fmt_perm(shmptr->shm_perm.mode), 4212738Sdfr user_from_uid(shmptr->shm_perm.uid, 0), 4222738Sdfr group_from_gid(shmptr->shm_perm.gid, 0)); 4232731Sdfr 4242738Sdfr if (option & CREATOR) 4252738Sdfr printf(" %8s %8s", 4262738Sdfr user_from_uid(shmptr->shm_perm.cuid, 0), 4272738Sdfr group_from_gid(shmptr->shm_perm.cgid, 0)); 4282731Sdfr 4292738Sdfr if (option & OUTSTANDING) 4302738Sdfr printf(" %6d", 4312738Sdfr shmptr->shm_nattch); 4322731Sdfr 4332738Sdfr if (option & BIGGEST) 4342738Sdfr printf(" %6d", 4352738Sdfr shmptr->shm_segsz); 4362731Sdfr 4372738Sdfr if (option & PID) 4382738Sdfr printf(" %6d %6d", 4392738Sdfr shmptr->shm_cpid, 4402738Sdfr shmptr->shm_lpid); 4412731Sdfr 4422738Sdfr if (option & TIME) 4432738Sdfr printf("%s %s %s", 4442738Sdfr atime_buf, 4452738Sdfr dtime_buf, 4462738Sdfr ctime_buf); 4472731Sdfr 4482738Sdfr printf("\n"); 4492738Sdfr } 4502738Sdfr } 4512738Sdfr printf("\n"); 4522738Sdfr } 4532738Sdfr } else 4542738Sdfr if (display & (SHMINFO | SHMTOTAL)) { 4552738Sdfr fprintf(stderr, 4562738Sdfr "SVID shared memory facility not configured in the system\n"); 4572738Sdfr } 45877551Sdd 45977551Sdd kget(X_SEMINFO, &seminfo, sizeof(seminfo)); 46077551Sdd if ((display & (SEMINFO | SEMTOTAL))) { 4612738Sdfr struct semid_ds *xsema; 46277551Sdd size_t xsema_len; 4632731Sdfr 4642738Sdfr if (display & SEMTOTAL) { 4652738Sdfr printf("seminfo:\n"); 4662738Sdfr printf("\tsemmap: %6d\t(# of entries in semaphore map)\n", 4672738Sdfr seminfo.semmap); 4682738Sdfr printf("\tsemmni: %6d\t(# of semaphore identifiers)\n", 4692738Sdfr seminfo.semmni); 4702738Sdfr printf("\tsemmns: %6d\t(# of semaphores in system)\n", 4712738Sdfr seminfo.semmns); 4722738Sdfr printf("\tsemmnu: %6d\t(# of undo structures in system)\n", 4732738Sdfr seminfo.semmnu); 4742738Sdfr printf("\tsemmsl: %6d\t(max # of semaphores per id)\n", 4752738Sdfr seminfo.semmsl); 4762738Sdfr printf("\tsemopm: %6d\t(max # of operations per semop call)\n", 4772738Sdfr seminfo.semopm); 4782738Sdfr printf("\tsemume: %6d\t(max # of undo entries per process)\n", 4792738Sdfr seminfo.semume); 4802738Sdfr printf("\tsemusz: %6d\t(size in bytes of undo structure)\n", 4812738Sdfr seminfo.semusz); 4822738Sdfr printf("\tsemvmx: %6d\t(semaphore maximum value)\n", 4832738Sdfr seminfo.semvmx); 4842738Sdfr printf("\tsemaem: %6d\t(adjust on exit max value)\n\n", 4852738Sdfr seminfo.semaem); 4862731Sdfr } 4872738Sdfr if (display & SEMINFO) { 48877551Sdd xsema_len = sizeof(struct semid_ds) * seminfo.semmni; 48977551Sdd xsema = malloc(xsema_len); 49077551Sdd kget(X_SEMA, xsema, xsema_len); 4912731Sdfr 4922738Sdfr printf("Semaphores:\n"); 4932738Sdfr printf("T ID KEY MODE OWNER GROUP"); 4942738Sdfr if (option & CREATOR) 4952738Sdfr printf(" CREATOR CGROUP"); 4962738Sdfr if (option & BIGGEST) 4972738Sdfr printf(" NSEMS"); 4982738Sdfr if (option & TIME) 4992738Sdfr printf(" OTIME CTIME"); 5002738Sdfr printf("\n"); 5012738Sdfr for (i = 0; i < seminfo.semmni; i += 1) { 5022738Sdfr if ((xsema[i].sem_perm.mode & SEM_ALLOC) != 0) { 5032738Sdfr char ctime_buf[100], otime_buf[100]; 5042738Sdfr struct semid_ds *semaptr = &xsema[i]; 5052731Sdfr 5062738Sdfr cvt_time(semaptr->sem_otime, otime_buf); 5072738Sdfr cvt_time(semaptr->sem_ctime, ctime_buf); 5082731Sdfr 5092738Sdfr printf("s %6d %10d %s %8s %8s", 5102738Sdfr IXSEQ_TO_IPCID(i, semaptr->sem_perm), 5112738Sdfr semaptr->sem_perm.key, 5122738Sdfr fmt_perm(semaptr->sem_perm.mode), 5132738Sdfr user_from_uid(semaptr->sem_perm.uid, 0), 5142738Sdfr group_from_gid(semaptr->sem_perm.gid, 0)); 5152731Sdfr 5162738Sdfr if (option & CREATOR) 5172738Sdfr printf(" %8s %8s", 5182738Sdfr user_from_uid(semaptr->sem_perm.cuid, 0), 5192738Sdfr group_from_gid(semaptr->sem_perm.cgid, 0)); 5202731Sdfr 5212738Sdfr if (option & BIGGEST) 5222738Sdfr printf(" %6d", 5232738Sdfr semaptr->sem_nsems); 5242731Sdfr 5252738Sdfr if (option & TIME) 5262738Sdfr printf("%s %s", 5272738Sdfr otime_buf, 5282738Sdfr ctime_buf); 5292731Sdfr 5302738Sdfr printf("\n"); 5312738Sdfr } 5322738Sdfr } 5332731Sdfr 5342738Sdfr printf("\n"); 5352738Sdfr } 5362738Sdfr } else 5372738Sdfr if (display & (SEMINFO | SEMTOTAL)) { 5382738Sdfr fprintf(stderr, "SVID semaphores facility not configured in the system\n"); 5392738Sdfr } 54077551Sdd if (!use_sysctl) 54177551Sdd kvm_close(kd); 5422731Sdfr 5432738Sdfr exit(0); 5442738Sdfr} 5452731Sdfr 5462738Sdfrvoid 54777551Sddsysctlgatherstruct(addr, size, vecarr) 54877551Sdd void *addr; 54977551Sdd size_t size; 55077551Sdd struct scgs_vector *vecarr; 55177551Sdd{ 55277551Sdd struct scgs_vector *xp; 55377551Sdd size_t tsiz; 55477551Sdd int rv; 55577551Sdd 55677551Sdd for (xp = vecarr; xp->sysctl != NULL; xp++) { 55777551Sdd assert(xp->offset <= size); 55877551Sdd tsiz = xp->size; 55977551Sdd rv = sysctlbyname(xp->sysctl, (char *)addr + xp->offset, 56077551Sdd &tsiz, NULL, 0); 56177551Sdd if (rv == -1) 56277551Sdd errx(1, "sysctlbyname: %s", xp->sysctl); 56377551Sdd if (tsiz != xp->size) 56477551Sdd errx(1, "%s size mismatch (expected %d, got %d)", 56577551Sdd xp->sysctl, xp->size, tsiz); 56677551Sdd } 56777551Sdd} 56877551Sdd 56977551Sddvoid 57077551Sddkget(idx, addr, size) 57177551Sdd int idx; 57277551Sdd void *addr; 57377551Sdd size_t size; 57477551Sdd{ 57577551Sdd char *symn; /* symbol name */ 57677551Sdd size_t tsiz; 57777551Sdd int rv; 57877551Sdd unsigned long kaddr; 57977551Sdd const char *sym2sysctl[] = { /* symbol to sysctl name table */ 58077551Sdd "kern.ipc.sema", 58177551Sdd "kern.ipc.seminfo", 58277551Sdd "kern.ipc.msginfo", 58377551Sdd "kern.ipc.msqids", 58477551Sdd "kern.ipc.shminfo", 58577551Sdd "kern.ipc.shmsegs" }; 58677551Sdd 58777551Sdd assert((unsigned)idx <= sizeof(sym2sysctl) / sizeof(*sym2sysctl)); 58877551Sdd if (!use_sysctl) { 58977551Sdd symn = symbols[idx].n_name; 59077551Sdd if (*symn == '_') 59177551Sdd symn++; 59277551Sdd if (symbols[idx].n_type == 0 || symbols[idx].n_value == 0) 59377551Sdd errx(1, "symbol %s undefined", symn); 59477551Sdd /* 59577551Sdd * For some symbols, the value we retreieve is 59677551Sdd * actually a pointer; since we want the actual value, 59777551Sdd * we have to manually dereference it. 59877551Sdd */ 59977551Sdd switch (idx) { 60077551Sdd case X_MSQIDS: 60177551Sdd tsiz = sizeof(msqids); 60277551Sdd rv = kvm_read(kd, symbols[idx].n_value, 60377551Sdd &msqids, tsiz); 60477551Sdd kaddr = (u_long)msqids; 60577551Sdd break; 60677551Sdd case X_SHMSEGS: 60777551Sdd tsiz = sizeof(shmsegs); 60877551Sdd rv = kvm_read(kd, symbols[idx].n_value, 60977551Sdd &shmsegs, tsiz); 61077551Sdd kaddr = (u_long)shmsegs; 61177551Sdd break; 61277551Sdd case X_SEMA: 61377551Sdd tsiz = sizeof(sema); 61477551Sdd rv = kvm_read(kd, symbols[idx].n_value, 61577551Sdd &sema, tsiz); 61677551Sdd kaddr = (u_long)sema; 61777551Sdd break; 61877551Sdd default: 61977551Sdd rv = tsiz = 0; 62077551Sdd kaddr = symbols[idx].n_value; 62177551Sdd break; 62277551Sdd } 62377551Sdd if ((unsigned)rv != tsiz) 62477551Sdd errx(1, "%s: %s", symn, kvm_geterr(kd)); 62577551Sdd if ((unsigned)kvm_read(kd, kaddr, addr, size) != size) 62677551Sdd errx(1, "%s: %s", symn, kvm_geterr(kd)); 62777551Sdd } else { 62877551Sdd switch (idx) { 62977551Sdd case X_SHMINFO: 63077551Sdd sysctlgatherstruct(addr, size, shminfo_scgsv); 63177551Sdd break; 63277551Sdd case X_SEMINFO: 63377551Sdd sysctlgatherstruct(addr, size, seminfo_scgsv); 63477551Sdd break; 63577551Sdd case X_MSGINFO: 63677551Sdd sysctlgatherstruct(addr, size, msginfo_scgsv); 63777551Sdd break; 63877551Sdd default: 63977551Sdd tsiz = size; 64077551Sdd rv = sysctlbyname(sym2sysctl[idx], addr, &tsiz, 64177551Sdd NULL, 0); 64277551Sdd if (rv == -1) 64377551Sdd err(1, "sysctlbyname: %s", sym2sysctl[idx]); 64477551Sdd if (tsiz != size) 64577551Sdd errx(1, "%s size mismatch " 64677551Sdd "(expected %d, got %d)", 64777551Sdd sym2sysctl[idx], size, tsiz); 64877551Sdd break; 64977551Sdd } 65077551Sdd } 65177551Sdd} 65277551Sdd 65377551Sddvoid 6542738Sdfrusage() 6552738Sdfr{ 6562731Sdfr 6572738Sdfr fprintf(stderr, 65877551Sdd "usage: ipcs [-abcmopqsty] [-C corefile] [-N namelist]\n"); 6592738Sdfr exit(1); 6602731Sdfr} 661