file_cmds-287.40.2.tar.gz
[apple/file_cmds.git] / ipcs / ipcs.c
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 <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>
43 #include <sysexits.h>
44
45 #include "sys/types.h"
46 #include <sys/ucred.h>
47 #include <sys/time.h>
48 #include <sys/proc.h>
49 #include <sys/param.h>
50 #include <sys/sysctl.h>
51 #include <errno.h>
52 #include "sys/ipcs.h"
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
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
63 #define IXSEQ_TO_IPCID(ix,perm) (((perm._seq) << 16L) | (ix & 0xffff))
64 #endif
65
66 static char *
67 fmt_perm(u_short mode, char write_char)
68 {
69 static char buffer[100];
70
71 buffer[0] = '-';
72 buffer[1] = '-';
73 buffer[2] = ((mode & 0400) ? 'r' : '-');
74 buffer[3] = ((mode & 0200) ? write_char : '-');
75 buffer[4] = '-';
76 buffer[5] = ((mode & 0040) ? 'r' : '-');
77 buffer[6] = ((mode & 0020) ? write_char : '-');
78 buffer[7] = '-';
79 buffer[8] = ((mode & 0004) ? 'r' : '-');
80 buffer[9] = ((mode & 0002) ? write_char : '-');
81 buffer[10] = '-';
82 buffer[11] = '\0';
83 return (&buffer[0]);
84 }
85
86 static void
87 cvt_time(time_t t, char *buf)
88 {
89 struct tm *tm;
90
91 if (t == 0) {
92 strcpy(buf, "no-entry");
93 } else {
94 tm = localtime(&t);
95 if (tm != NULL) {
96 sprintf(buf, "%2d:%02d:%02d",
97 tm->tm_hour, tm->tm_min, tm->tm_sec);
98 }
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
114 static void
115 usage(void)
116 {
117 errx(EX_USAGE, "%s","usage: ipcs [-abcmopqstMQST]\n");
118 }
119
120 int
121 main(argc, argv)
122 int argc;
123 char *argv[];
124 {
125 int display = 0;
126 int option = 0;
127 int exit_val = 0;
128 time_t now;
129 char datestring[100];
130 int i;
131
132 while ((i = getopt(argc, argv, "MmQqSsabcoptT")) != -1)
133 switch (i) {
134 case 'M':
135 display = SHMTOTAL;
136 break;
137 case 'm':
138 display |= SHMINFO;
139 break;
140 case 'Q':
141 display = MSGTOTAL;
142 break;
143 case 'q':
144 display |= MSGINFO;
145 break;
146 case 'S':
147 display = SEMTOTAL;
148 break;
149 case 's':
150 display |= SEMINFO;
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 }
176 if (display == 0)
177 display = SHMINFO | MSGINFO | SEMINFO;
178 now = time(0);
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))
185 errx(1, "strftime failed\n");
186 printf("IPC status from <running system> as of %s\n", datestring);
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
199 if (sysctlbyname(IPCS_MSG_SYSCTL, &ic, &ic_size, &ic, ic_size)) {
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
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;
225 struct __msqid_ds_new ds;
226 struct __msqid_ds_new *msqptr = &ds;
227 size_t ic_size = sizeof(ic);
228
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");
240 printf("\nMessage Queues:\n");
241
242 ic.ipcs_magic = IPCS_MAGIC;
243 ic.ipcs_op = IPCS_MSG_ITER;
244 ic.ipcs_cursor = 0; /* start */
245 ic.ipcs_datalen = sizeof(*msqptr);
246 ic.ipcs_data = msqptr;
247
248 memset(msqptr, 0, sizeof(*msqptr));
249
250 while(!(sysctlbyname(IPCS_MSG_SYSCTL, &ic, &ic_size, &ic, ic_size))) {
251 ic.ipcs_data = msqptr;
252
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
261 printf("q %6d 0x%08x %s %8s %8s",
262 IXSEQ_TO_IPCID((ic.ipcs_cursor-1), msqptr->msg_perm),
263 (int)msqptr->msg_perm._key,
264 fmt_perm(msqptr->msg_perm.mode, 'w'),
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 }
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));
305 }
306 printf("\n");
307 }
308 } else
309 if (display & (MSGINFO | MSGTOTAL)) {
310 errx(1, "%s", "SVID messages facility not configured in the system\n");
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
325 if (sysctlbyname(IPCS_SHM_SYSCTL, &ic, &ic_size, &ic, ic_size)) {
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 }
332 printf("shminfo:\n");
333 printf("\tshmmax: %7lld\t(max shared memory segment size)\n",
334 shminfo.shmmax);
335 printf("\tshmmin: %7lld\t(min shared memory segment size)\n",
336 shminfo.shmmin);
337 printf("\tshmmni: %7lld\t(max number of shared memory identifiers)\n",
338 shminfo.shmmni);
339 printf("\tshmseg: %7lld\t(max shared memory segments per process)\n",
340 shminfo.shmseg);
341 printf("\tshmall: %7lld\t(max amount of shared memory in pages)\n\n",
342 shminfo.shmall);
343 }
344 if (display & SHMINFO) {
345 struct IPCS_command ic;
346 struct __shmid_ds_new ds;
347 struct __shmid_ds_new *shmptr = &ds;
348 size_t ic_size = sizeof(ic);
349
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");
361 printf("\nShared Memory:\n");
362 { /* XXX */
363
364 ic.ipcs_magic = IPCS_MAGIC;
365 ic.ipcs_op = IPCS_SHM_ITER;
366 ic.ipcs_cursor = 0; /* start */
367 ic.ipcs_datalen = sizeof(*shmptr);
368 ic.ipcs_data = shmptr;
369 memset(shmptr, 0, sizeof(*shmptr));
370
371 while(!(sysctlbyname(IPCS_SHM_SYSCTL, &ic, &ic_size, &ic, ic_size))) {
372 ic.ipcs_data = shmptr; /* xnu workaround */
373
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
382 printf("m %6d 0x%08x %s %8s %8s",
383 IXSEQ_TO_IPCID((ic.ipcs_cursor-1), shmptr->shm_perm),
384 (int)shmptr->shm_perm._key,
385 fmt_perm(shmptr->shm_perm.mode, 'w'),
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)
399 printf(" %6ld",
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 }
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));
425 }
426 } /* XXX */
427 printf("\n");
428 }
429 }
430 else
431 if (display & (SHMINFO | SHMTOTAL)) {
432 errx(1, "%s", "SVID shared memory facility not configured in the system\n");
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
447 if (sysctlbyname(IPCS_SEM_SYSCTL, &ic, &ic_size, &ic, ic_size)) {
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
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;
481 struct __semid_ds_new ds;
482 struct __semid_ds_new *semaptr = &ds;
483 size_t ic_size = sizeof(ic);
484
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");
492 printf("\nSemaphores:\n");
493
494 ic.ipcs_magic = IPCS_MAGIC;
495 ic.ipcs_op = IPCS_SEM_ITER;
496 ic.ipcs_cursor = 0; /* start */
497 ic.ipcs_datalen = sizeof(*semaptr);
498 ic.ipcs_data = semaptr;
499
500 memset(semaptr, 0, sizeof(*semaptr));
501
502 while(!(sysctlbyname(IPCS_SEM_SYSCTL, &ic, &ic_size, &ic, ic_size))) {
503 ic.ipcs_data = semaptr; /* xnu workaround */
504
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
511 printf("s %6d 0x%08x %s %8s %8s",
512 IXSEQ_TO_IPCID((ic.ipcs_cursor-1), semaptr->sem_perm),
513 (int)semaptr->sem_perm._key,
514 fmt_perm(semaptr->sem_perm.mode, '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 }
534 memset(semaptr, 0, sizeof(*semaptr));
535 errno = 0;
536 }
537
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 }
545 printf("\n");
546 }
547 } else
548 if (display & (SEMINFO | SEMTOTAL)) {
549 errx(1, "%s", "SVID semaphores facility not configured in the system\n");
550 }
551
552 exit(exit_val);
553 }