]>
Commit | Line | Data |
---|---|---|
c59d3020 A |
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 | ||
30 | #include <assert.h> | |
31 | #include <err.h> | |
32 | #include <fcntl.h> | |
33 | #include <grp.h> | |
34 | #include <kvm.h> | |
35 | #include <nlist.h> | |
36 | #include <limits.h> | |
37 | #include <paths.h> | |
38 | #include <pwd.h> | |
39 | #include <stddef.h> | |
40 | #include <stdio.h> | |
41 | #include <stdlib.h> | |
42 | #include <string.h> | |
43 | #include <unistd.h> | |
44 | ||
45 | #include <sys/types.h> | |
46 | #include <sys/ucred.h> | |
47 | #include <sys/proc.h> | |
48 | #include <sys/param.h> | |
49 | #include <sys/time.h> | |
50 | #include <sys/sysctl.h> | |
51 | ||
52 | #define KERNEL | |
53 | ||
54 | #include <sys/ipc.h> | |
55 | #include <sys/sem_internal.h> | |
56 | #include <sys/shm_internal.h> | |
57 | #include <sys/msg.h> | |
58 | ||
59 | #include "sys/ipcs.h" | |
60 | ||
61 | /* The following is a kludge, until the problem of multiple inclusions | |
62 | of ipc.h is taken care of. */ | |
63 | #ifndef IXSEQ_TO_IPCID | |
64 | #define IXSEQ_TO_IPCID(ix,perm) (((perm.seq) << 16) | (ix & 0xffff)) | |
65 | #endif | |
66 | ||
67 | char * | |
68 | fmt_perm(mode) | |
69 | u_short mode; | |
70 | { | |
71 | static char buffer[100]; | |
72 | ||
73 | buffer[0] = '-'; | |
74 | buffer[1] = '-'; | |
75 | buffer[2] = ((mode & 0400) ? 'r' : '-'); | |
76 | buffer[3] = ((mode & 0200) ? 'w' : '-'); | |
77 | buffer[4] = ((mode & 0100) ? 'a' : '-'); | |
78 | buffer[5] = ((mode & 0040) ? 'r' : '-'); | |
79 | buffer[6] = ((mode & 0020) ? 'w' : '-'); | |
80 | buffer[7] = ((mode & 0010) ? 'a' : '-'); | |
81 | buffer[8] = ((mode & 0004) ? 'r' : '-'); | |
82 | buffer[9] = ((mode & 0002) ? 'w' : '-'); | |
83 | buffer[10] = ((mode & 0001) ? 'a' : '-'); | |
84 | buffer[11] = '\0'; | |
85 | return (&buffer[0]); | |
86 | } | |
87 | ||
88 | void | |
89 | cvt_time(t, buf) | |
90 | time_t t; | |
91 | char *buf; | |
92 | { | |
93 | struct tm *tm; | |
94 | ||
95 | if (t == 0) { | |
96 | strcpy(buf, "no-entry"); | |
97 | } else { | |
98 | tm = localtime(&t); | |
99 | sprintf(buf, "%2d:%02d:%02d", | |
100 | tm->tm_hour, tm->tm_min, tm->tm_sec); | |
101 | } | |
102 | } | |
103 | #define SHMINFO 1 | |
104 | #define SHMTOTAL 2 | |
105 | #define MSGINFO 4 | |
106 | #define MSGTOTAL 8 | |
107 | #define SEMINFO 16 | |
108 | #define SEMTOTAL 32 | |
109 | ||
110 | #define BIGGEST 1 | |
111 | #define CREATOR 2 | |
112 | #define OUTSTANDING 4 | |
113 | #define PID 8 | |
114 | #define TIME 16 | |
115 | ||
116 | int | |
117 | main(argc, argv) | |
118 | int argc; | |
119 | char *argv[]; | |
120 | { | |
121 | int display = SHMINFO | MSGINFO | SEMINFO; | |
122 | int option = 0; | |
123 | char kvmoferr[_POSIX2_LINE_MAX]; /* Error buf for kvm_openfiles. */ | |
124 | int i; | |
125 | ||
126 | while ((i = getopt(argc, argv, "MmQqSsabcoptT")) != -1) | |
127 | switch (i) { | |
128 | case 'M': | |
129 | display = SHMTOTAL; | |
130 | break; | |
131 | case 'm': | |
132 | display = SHMINFO; | |
133 | break; | |
134 | case 'Q': | |
135 | display = MSGTOTAL; | |
136 | break; | |
137 | case 'q': | |
138 | display = MSGINFO; | |
139 | break; | |
140 | case 'S': | |
141 | display = SEMTOTAL; | |
142 | break; | |
143 | case 's': | |
144 | display = SEMINFO; | |
145 | break; | |
146 | case 'T': | |
147 | display = SHMTOTAL | MSGTOTAL | SEMTOTAL; | |
148 | break; | |
149 | case 'a': | |
150 | option |= BIGGEST | CREATOR | OUTSTANDING | PID | TIME; | |
151 | break; | |
152 | case 'b': | |
153 | option |= BIGGEST; | |
154 | break; | |
155 | case 'c': | |
156 | option |= CREATOR; | |
157 | break; | |
158 | case 'o': | |
159 | option |= OUTSTANDING; | |
160 | break; | |
161 | case 'p': | |
162 | option |= PID; | |
163 | break; | |
164 | case 't': | |
165 | option |= TIME; | |
166 | break; | |
167 | default: | |
168 | usage(); | |
169 | } | |
170 | ||
171 | if ((display & (MSGINFO | MSGTOTAL))) { | |
172 | if (display & MSGTOTAL) { | |
173 | struct IPCS_command ic; | |
174 | struct msginfo msginfo; | |
175 | size_t ic_size = sizeof(ic); | |
176 | ||
177 | ic.ipcs_magic = IPCS_MAGIC; | |
178 | ic.ipcs_op = IPCS_MSG_CONF; | |
179 | ic.ipcs_cursor = 0; /* 0 for fw. compat. */ | |
180 | ic.ipcs_data = &msginfo; | |
181 | ic.ipcs_datalen = sizeof(msginfo); | |
182 | ||
183 | sysctlbyname(IPCS_MSG_SYSCTL, &ic, &ic_size, &ic, ic_size); | |
184 | printf("msginfo:\n"); | |
185 | printf("\tmsgmax: %6d\t(max characters in a message)\n", | |
186 | msginfo.msgmax); | |
187 | printf("\tmsgmni: %6d\t(# of message queues)\n", | |
188 | msginfo.msgmni); | |
189 | printf("\tmsgmnb: %6d\t(max characters in a message queue)\n", | |
190 | msginfo.msgmnb); | |
191 | printf("\tmsgtql: %6d\t(max # of messages in system)\n", | |
192 | msginfo.msgtql); | |
193 | printf("\tmsgssz: %6d\t(size of a message segment)\n", | |
194 | msginfo.msgssz); | |
195 | printf("\tmsgseg: %6d\t(# of message segments in system)\n\n", | |
196 | msginfo.msgseg); | |
197 | } | |
198 | if (display & MSGINFO) { | |
199 | struct IPCS_command ic; | |
200 | struct msqid_ds ds; | |
201 | struct msqid_ds *msqptr = &ds; | |
202 | size_t ic_size = sizeof(ic); | |
203 | ||
204 | printf("Message Queues:\n"); | |
205 | printf("T ID KEY MODE OWNER GROUP"); | |
206 | if (option & CREATOR) | |
207 | printf(" CREATOR CGROUP"); | |
208 | if (option & OUTSTANDING) | |
209 | printf(" CBYTES QNUM"); | |
210 | if (option & BIGGEST) | |
211 | printf(" QBYTES"); | |
212 | if (option & PID) | |
213 | printf(" LSPID LRPID"); | |
214 | if (option & TIME) | |
215 | printf(" STIME RTIME CTIME"); | |
216 | printf("\n"); | |
217 | ||
218 | ic.ipcs_magic = IPCS_MAGIC; | |
219 | ic.ipcs_op = IPCS_MSG_ITER; | |
220 | ic.ipcs_cursor = 0; /* start */ | |
221 | ic.ipcs_data = msqptr; | |
222 | ic.ipcs_datalen = sizeof(*msqptr); | |
223 | ||
224 | while(!(sysctlbyname(IPCS_MSG_SYSCTL, &ic, &ic_size, &ic, ic_size))) { | |
225 | if (msqptr->msg_qbytes != 0) { | |
226 | char stime_buf[100], rtime_buf[100], | |
227 | ctime_buf[100]; | |
228 | ||
229 | cvt_time(msqptr->msg_stime, stime_buf); | |
230 | cvt_time(msqptr->msg_rtime, rtime_buf); | |
231 | cvt_time(msqptr->msg_ctime, ctime_buf); | |
232 | ||
233 | printf("q %6d %10d %s %8s %8s", | |
234 | IXSEQ_TO_IPCID(i, msqptr->msg_perm), | |
235 | (int)msqptr->msg_perm.key, | |
236 | fmt_perm(msqptr->msg_perm.mode), | |
237 | user_from_uid(msqptr->msg_perm.uid, 0), | |
238 | group_from_gid(msqptr->msg_perm.gid, 0)); | |
239 | ||
240 | if (option & CREATOR) | |
241 | printf(" %8s %8s", | |
242 | user_from_uid(msqptr->msg_perm.cuid, 0), | |
243 | group_from_gid(msqptr->msg_perm.cgid, 0)); | |
244 | ||
245 | if (option & OUTSTANDING) | |
246 | printf(" %6lu %6lu", | |
247 | msqptr->msg_cbytes, | |
248 | msqptr->msg_qnum); | |
249 | ||
250 | if (option & BIGGEST) | |
251 | printf(" %6lu", | |
252 | msqptr->msg_qbytes); | |
253 | ||
254 | if (option & PID) | |
255 | printf(" %6d %6d", | |
256 | msqptr->msg_lspid, | |
257 | msqptr->msg_lrpid); | |
258 | ||
259 | if (option & TIME) | |
260 | printf(" %s %s %s", | |
261 | stime_buf, | |
262 | rtime_buf, | |
263 | ctime_buf); | |
264 | ||
265 | printf("\n"); | |
266 | } | |
267 | } | |
268 | printf("\n"); | |
269 | } | |
270 | } else | |
271 | if (display & (MSGINFO | MSGTOTAL)) { | |
272 | fprintf(stderr, | |
273 | "SVID messages facility not configured in the system\n"); | |
274 | } | |
275 | ||
276 | if ((display & (SHMINFO | SHMTOTAL))) { | |
277 | if (display & SHMTOTAL) { | |
278 | struct IPCS_command ic; | |
279 | struct shminfo shminfo; | |
280 | size_t ic_size = sizeof(ic); | |
281 | ||
282 | ic.ipcs_magic = IPCS_MAGIC; | |
283 | ic.ipcs_op = IPCS_SHM_CONF; | |
284 | ic.ipcs_cursor = 0; /* 0 for fw. compat. */ | |
285 | ic.ipcs_data = &shminfo; | |
286 | ic.ipcs_datalen = sizeof(shminfo); | |
287 | ||
288 | sysctlbyname(IPCS_SHM_SYSCTL, &ic, &ic_size, &ic, ic_size); | |
289 | printf("shminfo:\n"); | |
290 | printf("\tshmmax: %7d\t(max shared memory segment size)\n", | |
291 | shminfo.shmmax); | |
292 | printf("\tshmmin: %7d\t(min shared memory segment size)\n", | |
293 | shminfo.shmmin); | |
294 | printf("\tshmmni: %7d\t(max number of shared memory identifiers)\n", | |
295 | shminfo.shmmni); | |
296 | printf("\tshmseg: %7d\t(max shared memory segments per process)\n", | |
297 | shminfo.shmseg); | |
298 | printf("\tshmall: %7d\t(max amount of shared memory in pages)\n\n", | |
299 | shminfo.shmall); | |
300 | } | |
301 | if (display & SHMINFO) { | |
302 | struct IPCS_command ic; | |
303 | struct shmid_ds ds; | |
304 | struct shmid_ds *shmptr = &ds; | |
305 | size_t ic_size = sizeof(ic); | |
306 | ||
307 | printf("Shared Memory:\n"); | |
308 | printf("T ID KEY MODE OWNER GROUP"); | |
309 | if (option & CREATOR) | |
310 | printf(" CREATOR CGROUP"); | |
311 | if (option & OUTSTANDING) | |
312 | printf(" NATTCH"); | |
313 | if (option & BIGGEST) | |
314 | printf(" SEGSZ"); | |
315 | if (option & PID) | |
316 | printf(" CPID LPID"); | |
317 | if (option & TIME) | |
318 | printf(" ATIME DTIME CTIME"); | |
319 | printf("\n"); | |
320 | { /* XXX */ | |
321 | ||
322 | ic.ipcs_magic = IPCS_MAGIC; | |
323 | ic.ipcs_op = IPCS_SHM_ITER; | |
324 | ic.ipcs_cursor = 0; /* start */ | |
325 | ic.ipcs_data = shmptr; | |
326 | ic.ipcs_datalen = sizeof(*shmptr); | |
327 | ||
328 | while(!(sysctlbyname(IPCS_SHM_SYSCTL, &ic, &ic_size, &ic, ic_size))) { | |
329 | if (shmptr->shm_perm.mode & 0x0800) { | |
330 | char atime_buf[100], dtime_buf[100], | |
331 | ctime_buf[100]; | |
332 | ||
333 | cvt_time(shmptr->shm_atime, atime_buf); | |
334 | cvt_time(shmptr->shm_dtime, dtime_buf); | |
335 | cvt_time(shmptr->shm_ctime, ctime_buf); | |
336 | ||
337 | printf("m %6d %10d %s %8s %8s", | |
338 | IXSEQ_TO_IPCID(i, shmptr->shm_perm), | |
339 | (int)shmptr->shm_perm.key, | |
340 | fmt_perm(shmptr->shm_perm.mode), | |
341 | user_from_uid(shmptr->shm_perm.uid, 0), | |
342 | group_from_gid(shmptr->shm_perm.gid, 0)); | |
343 | ||
344 | if (option & CREATOR) | |
345 | printf(" %8s %8s", | |
346 | user_from_uid(shmptr->shm_perm.cuid, 0), | |
347 | group_from_gid(shmptr->shm_perm.cgid, 0)); | |
348 | ||
349 | if (option & OUTSTANDING) | |
350 | printf(" %6d", | |
351 | shmptr->shm_nattch); | |
352 | ||
353 | if (option & BIGGEST) | |
354 | printf(" %6d", | |
355 | shmptr->shm_segsz); | |
356 | ||
357 | if (option & PID) | |
358 | printf(" %6d %6d", | |
359 | shmptr->shm_cpid, | |
360 | shmptr->shm_lpid); | |
361 | ||
362 | if (option & TIME) | |
363 | printf(" %s %s %s", | |
364 | atime_buf, | |
365 | dtime_buf, | |
366 | ctime_buf); | |
367 | ||
368 | printf("\n"); | |
369 | } | |
370 | } | |
371 | } /* XXX */ | |
372 | printf("\n"); | |
373 | } | |
374 | } | |
375 | else | |
376 | if (display & (SHMINFO | SHMTOTAL)) { | |
377 | fprintf(stderr, | |
378 | "SVID shared memory facility not configured in the system\n"); | |
379 | } | |
380 | ||
381 | if ((display & (SEMINFO | SEMTOTAL))) { | |
382 | if (display & SEMTOTAL) { | |
383 | struct IPCS_command ic; | |
384 | struct seminfo seminfo; | |
385 | size_t ic_size = sizeof(ic); | |
386 | ||
387 | ic.ipcs_magic = IPCS_MAGIC; | |
388 | ic.ipcs_op = IPCS_SEM_CONF; | |
389 | ic.ipcs_cursor = 0; /* 0 for fw. compat. */ | |
390 | ic.ipcs_data = &seminfo; | |
391 | ic.ipcs_datalen = sizeof(seminfo); | |
392 | ||
393 | sysctlbyname(IPCS_SEM_SYSCTL, &ic, &ic_size, &ic, ic_size); | |
394 | printf("seminfo:\n"); | |
395 | printf("\tsemmap: %6d\t(# of entries in semaphore map)\n", | |
396 | seminfo.semmap); | |
397 | printf("\tsemmni: %6d\t(# of semaphore identifiers)\n", | |
398 | seminfo.semmni); | |
399 | printf("\tsemmns: %6d\t(# of semaphores in system)\n", | |
400 | seminfo.semmns); | |
401 | printf("\tsemmnu: %6d\t(# of undo structures in system)\n", | |
402 | seminfo.semmnu); | |
403 | printf("\tsemmsl: %6d\t(max # of semaphores per id)\n", | |
404 | seminfo.semmsl); | |
405 | printf("\tsemopm: %6d\t(max # of operations per semop call)\n", | |
406 | seminfo.semopm); | |
407 | printf("\tsemume: %6d\t(max # of undo entries per process)\n", | |
408 | seminfo.semume); | |
409 | printf("\tsemusz: %6d\t(size in bytes of undo structure)\n", | |
410 | seminfo.semusz); | |
411 | printf("\tsemvmx: %6d\t(semaphore maximum value)\n", | |
412 | seminfo.semvmx); | |
413 | printf("\tsemaem: %6d\t(adjust on exit max value)\n\n", | |
414 | seminfo.semaem); | |
415 | } | |
416 | if (display & SEMINFO) { | |
417 | struct IPCS_command ic; | |
418 | struct semid_ds ds; | |
419 | struct semid_ds *semaptr = &ds; | |
420 | size_t ic_size = sizeof(ic); | |
421 | ||
422 | printf("Semaphores:\n"); | |
423 | printf("T ID KEY MODE OWNER GROUP"); | |
424 | if (option & CREATOR) | |
425 | printf(" CREATOR CGROUP"); | |
426 | if (option & BIGGEST) | |
427 | printf(" NSEMS"); | |
428 | if (option & TIME) | |
429 | printf(" OTIME CTIME"); | |
430 | printf("\n"); | |
431 | ||
432 | ic.ipcs_magic = IPCS_MAGIC; | |
433 | ic.ipcs_op = IPCS_SEM_ITER; | |
434 | ic.ipcs_cursor = 0; /* start */ | |
435 | ic.ipcs_data = semaptr; | |
436 | ic.ipcs_datalen = sizeof(*semaptr); | |
437 | ||
438 | while(!(sysctlbyname(IPCS_SEM_SYSCTL, &ic, &ic_size, &ic, ic_size))) { | |
439 | if ((semaptr->sem_perm.mode & SEM_ALLOC) != 0) { | |
440 | char ctime_buf[100], otime_buf[100]; | |
441 | ||
442 | cvt_time(semaptr->sem_otime, otime_buf); | |
443 | cvt_time(semaptr->sem_ctime, ctime_buf); | |
444 | ||
445 | printf("s %6d %10d %s %8s %8s", | |
446 | IXSEQ_TO_IPCID(i, semaptr->sem_perm), | |
447 | (int)semaptr->sem_perm.key, | |
448 | fmt_perm(semaptr->sem_perm.mode), | |
449 | user_from_uid(semaptr->sem_perm.uid, 0), | |
450 | group_from_gid(semaptr->sem_perm.gid, 0)); | |
451 | ||
452 | if (option & CREATOR) | |
453 | printf(" %8s %8s", | |
454 | user_from_uid(semaptr->sem_perm.cuid, 0), | |
455 | group_from_gid(semaptr->sem_perm.cgid, 0)); | |
456 | ||
457 | if (option & BIGGEST) | |
458 | printf(" %6d", | |
459 | semaptr->sem_nsems); | |
460 | ||
461 | if (option & TIME) | |
462 | printf(" %s %s", | |
463 | otime_buf, | |
464 | ctime_buf); | |
465 | ||
466 | printf("\n"); | |
467 | } | |
468 | } | |
469 | ||
470 | printf("\n"); | |
471 | } | |
472 | } else | |
473 | if (display & (SEMINFO | SEMTOTAL)) { | |
474 | fprintf(stderr, "SVID semaphores facility not configured in the system\n"); | |
475 | } | |
476 | ||
477 | exit(0); | |
478 | } | |
479 | ||
480 | usage() | |
481 | { | |
482 | ||
483 | fprintf(stderr, | |
484 | "usage: ipcs [-abcmopqstMQST]\n"); | |
485 | exit(1); | |
486 | } |