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