ipcs.c revision 1.10.6.1 1 /* $NetBSD: ipcs.c,v 1.10.6.1 1996/06/07 01:53:47 thorpej Exp $ */
2
3 /*
4 * Copyright (c) 1994 SigmaSoft, Th. Lockert <tholo (at) sigmasoft.com>
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by SigmaSoft, Th. Lockert.
18 * 4. The name of the author may not be used to endorse or promote products
19 * derived from this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
22 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
23 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
24 * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
27 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
30 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33 #include <sys/types.h>
34 #include <sys/param.h>
35 #include <sys/time.h>
36 #include <sys/proc.h>
37 #define _KERNEL
38 #include <sys/ipc.h>
39 #include <sys/sem.h>
40 #include <sys/shm.h>
41 #include <sys/msg.h>
42 #undef _KERNEL
43
44 #include <err.h>
45 #include <fcntl.h>
46 #include <kvm.h>
47 #include <limits.h>
48 #include <nlist.h>
49 #include <paths.h>
50 #include <stdio.h>
51 #include <stdlib.h>
52 #include <string.h>
53 #include <unistd.h>
54
55 int semconfig __P((int, ...));
56 void usage __P((void));
57
58 extern char *__progname; /* from crt0.o */
59
60 static struct nlist symbols[] = {
61 {"_sema"},
62 #define X_SEMA 0
63 {"_seminfo"},
64 #define X_SEMINFO 1
65 {"_semu"},
66 #define X_SEMU 2
67 {"_msginfo"},
68 #define X_MSGINFO 3
69 {"_msqids"},
70 #define X_MSQIDS 4
71 {"_shminfo"},
72 #define X_SHMINFO 5
73 {"_shmsegs"},
74 #define X_SHMSEGS 6
75 {NULL}
76 };
77
78 static kvm_t *kd;
79
80 char *
81 fmt_perm(mode)
82 u_short mode;
83 {
84 static char buffer[100];
85
86 buffer[0] = '-';
87 buffer[1] = '-';
88 buffer[2] = ((mode & 0400) ? 'r' : '-');
89 buffer[3] = ((mode & 0200) ? 'w' : '-');
90 buffer[4] = ((mode & 0100) ? 'a' : '-');
91 buffer[5] = ((mode & 0040) ? 'r' : '-');
92 buffer[6] = ((mode & 0020) ? 'w' : '-');
93 buffer[7] = ((mode & 0010) ? 'a' : '-');
94 buffer[8] = ((mode & 0004) ? 'r' : '-');
95 buffer[9] = ((mode & 0002) ? 'w' : '-');
96 buffer[10] = ((mode & 0001) ? 'a' : '-');
97 buffer[11] = '\0';
98 return (&buffer[0]);
99 }
100
101 void
102 cvt_time(t, buf)
103 time_t t;
104 char *buf;
105 {
106 struct tm *tm;
107
108 if (t == 0) {
109 strcpy(buf, "no-entry");
110 } else {
111 tm = localtime(&t);
112 sprintf(buf, "%2d:%02d:%02d",
113 tm->tm_hour, tm->tm_min, tm->tm_sec);
114 }
115 }
116 #define SHMINFO 1
117 #define SHMTOTAL 2
118 #define MSGINFO 4
119 #define MSGTOTAL 8
120 #define SEMINFO 16
121 #define SEMTOTAL 32
122
123 #define BIGGEST 1
124 #define CREATOR 2
125 #define OUTSTANDING 4
126 #define PID 8
127 #define TIME 16
128
129 int
130 main(argc, argv)
131 int argc;
132 char *argv[];
133 {
134 int display = SHMINFO | MSGINFO | SEMINFO;
135 int option = 0;
136 char *core = NULL, *namelist = NULL;
137 char errbuf[_POSIX2_LINE_MAX];
138 int i;
139
140 while ((i = getopt(argc, argv, "MmQqSsabC:cN:optT")) != EOF)
141 switch (i) {
142 case 'M':
143 display = SHMTOTAL;
144 break;
145 case 'm':
146 display = SHMINFO;
147 break;
148 case 'Q':
149 display = MSGTOTAL;
150 break;
151 case 'q':
152 display = MSGINFO;
153 break;
154 case 'S':
155 display = SEMTOTAL;
156 break;
157 case 's':
158 display = SEMINFO;
159 break;
160 case 'T':
161 display = SHMTOTAL | MSGTOTAL | SEMTOTAL;
162 break;
163 case 'a':
164 option |= BIGGEST | CREATOR | OUTSTANDING | PID | TIME;
165 break;
166 case 'b':
167 option |= BIGGEST;
168 break;
169 case 'C':
170 core = optarg;
171 break;
172 case 'c':
173 option |= CREATOR;
174 break;
175 case 'N':
176 namelist = optarg;
177 break;
178 case 'o':
179 option |= OUTSTANDING;
180 break;
181 case 'p':
182 option |= PID;
183 break;
184 case 't':
185 option |= TIME;
186 break;
187 default:
188 usage();
189 }
190
191 /*
192 * Discard setgid privelidges if not the running kernel so that
193 * bad guys can't print interesting stuff from kernel memory.
194 */
195 if (namelist != NULL || core != NULL)
196 setgid(getgid());
197
198 if ((kd = kvm_openfiles(namelist, core, NULL, O_RDONLY,
199 errbuf)) == NULL)
200 errx(1, "can't open kvm: %s", errbuf);
201
202 switch (kvm_nlist(kd, symbols)) {
203 case 0:
204 break;
205 case -1:
206 errx(1, "%s: unable to read symbol table.",
207 namelist == NULL ? _PATH_UNIX : namelist);
208 default:
209 #ifdef notdef /* they'll be told more civilly later */
210 warnx("nlist failed");
211 for (i = 0; symbols[i].n_name != NULL; i++)
212 if (symbols[i].n_value == 0)
213 warnx("symbol %s not found",
214 symbols[i].n_name);
215 break;
216 #endif
217 }
218
219 if ((display & (MSGINFO | MSGTOTAL)) &&
220 (kvm_read(kd, symbols[X_MSGINFO].n_value,
221 &msginfo, sizeof(msginfo)) == sizeof(msginfo))) {
222
223 if (display & MSGTOTAL) {
224 printf("msginfo:\n");
225 printf("\tmsgmax: %6d\t(max characters in a message)\n",
226 msginfo.msgmax);
227 printf("\tmsgmni: %6d\t(# of message queues)\n",
228 msginfo.msgmni);
229 printf("\tmsgmnb: %6d\t(max characters in a message queue)\n",
230 msginfo.msgmnb);
231 printf("\tmsgtql: %6d\t(max # of messages in system)\n",
232 msginfo.msgtql);
233 printf("\tmsgssz: %6d\t(size of a message segment)\n",
234 msginfo.msgssz);
235 printf("\tmsgseg: %6d\t(# of message segments in system)\n\n",
236 msginfo.msgseg);
237 }
238 if (display & MSGINFO) {
239 struct msqid_ds *xmsqids;
240
241 if (kvm_read(kd, symbols[X_MSQIDS].n_value,
242 &msqids, sizeof(msqids)) != sizeof(msqids))
243 errx(1, "kvm_read (%s): %s",
244 symbols[X_MSQIDS].n_name, kvm_geterr(kd));
245
246 xmsqids = malloc(sizeof(struct msqid_ds) *
247 msginfo.msgmni);
248
249 if (kvm_read(kd, (u_long)msqids, xmsqids,
250 sizeof(struct msqid_ds) * msginfo.msgmni) !=
251 sizeof(struct msqid_ds) * msginfo.msgmni)
252 errx(1, "kvm_read (msqids): %s",
253 kvm_geterr(kd));
254
255 printf("Message Queues:\n");
256 printf("T ID KEY MODE OWNER GROUP");
257 if (option & CREATOR)
258 printf(" CREATOR CGROUP");
259 if (option & OUTSTANDING)
260 printf(" CBYTES QNUM");
261 if (option & BIGGEST)
262 printf(" QBYTES");
263 if (option & PID)
264 printf(" LSPID LRPID");
265 if (option & TIME)
266 printf(" STIME RTIME CTIME");
267 printf("\n");
268 for (i = 0; i < msginfo.msgmni; i += 1) {
269 if (xmsqids[i].msg_qbytes != 0) {
270 char stime_buf[100], rtime_buf[100],
271 ctime_buf[100];
272 struct msqid_ds *msqptr = &xmsqids[i];
273
274 cvt_time(msqptr->msg_stime, stime_buf);
275 cvt_time(msqptr->msg_rtime, rtime_buf);
276 cvt_time(msqptr->msg_ctime, ctime_buf);
277
278 printf("q %6d %10d %s %8s %8s",
279 IXSEQ_TO_IPCID(i, msqptr->msg_perm),
280 msqptr->msg_perm.key,
281 fmt_perm(msqptr->msg_perm.mode),
282 user_from_uid(msqptr->msg_perm.uid, 0),
283 group_from_gid(msqptr->msg_perm.gid, 0));
284
285 if (option & CREATOR)
286 printf(" %8s %8s",
287 user_from_uid(msqptr->msg_perm.cuid, 0),
288 group_from_gid(msqptr->msg_perm.cgid, 0));
289
290 if (option & OUTSTANDING)
291 printf(" %6d %6d",
292 msqptr->msg_cbytes,
293 msqptr->msg_qnum);
294
295 if (option & BIGGEST)
296 printf(" %6d",
297 msqptr->msg_qbytes);
298
299 if (option & PID)
300 printf(" %6d %6d",
301 msqptr->msg_lspid,
302 msqptr->msg_lrpid);
303
304 if (option & TIME)
305 printf("%s %s %s",
306 stime_buf,
307 rtime_buf,
308 ctime_buf);
309
310 printf("\n");
311 }
312 }
313 printf("\n");
314 }
315 } else
316 if (display & (MSGINFO | MSGTOTAL)) {
317 fprintf(stderr,
318 "SVID messages facility not configured in the system\n");
319 }
320 if ((display & (SHMINFO | SHMTOTAL)) &&
321 (kvm_read(kd, symbols[X_SHMINFO].n_value, &shminfo,
322 sizeof(shminfo)) == sizeof(shminfo))) {
323
324 if (display & SHMTOTAL) {
325 printf("shminfo:\n");
326 printf("\tshmmax: %7d\t(max shared memory segment size)\n",
327 shminfo.shmmax);
328 printf("\tshmmin: %7d\t(min shared memory segment size)\n",
329 shminfo.shmmin);
330 printf("\tshmmni: %7d\t(max number of shared memory identifiers)\n",
331 shminfo.shmmni);
332 printf("\tshmseg: %7d\t(max shared memory segments per process)\n",
333 shminfo.shmseg);
334 printf("\tshmall: %7d\t(max amount of shared memory in pages)\n\n",
335 shminfo.shmall);
336 }
337 if (display & SHMINFO) {
338 struct shmid_ds *xshmids;
339
340 if (kvm_read(kd, symbols[X_SHMSEGS].n_value, &shmsegs,
341 sizeof(shmsegs)) != sizeof(shmsegs))
342 errx(1, "kvm_read (%s): %s",
343 symbols[X_SHMSEGS].n_name, kvm_geterr(kd));
344
345 xshmids = malloc(sizeof(struct shmid_ds) *
346 msginfo.msgmni);
347
348 if (kvm_read(kd, (u_long)shmsegs, xshmids,
349 sizeof(struct shmid_ds) * shminfo.shmmni) !=
350 sizeof(struct shmid_ds) * shminfo.shmmni)
351 errx(1, "kvm_read (shmsegs): %s",
352 kvm_geterr(kd));
353
354 printf("Shared Memory:\n");
355 printf("T ID KEY MODE OWNER GROUP");
356 if (option & CREATOR)
357 printf(" CREATOR CGROUP");
358 if (option & OUTSTANDING)
359 printf(" NATTCH");
360 if (option & BIGGEST)
361 printf(" SEGSZ");
362 if (option & PID)
363 printf(" CPID LPID");
364 if (option & TIME)
365 printf(" ATIME DTIME CTIME");
366 printf("\n");
367 for (i = 0; i < shminfo.shmmni; i += 1) {
368 if (xshmids[i].shm_perm.mode & 0x0800) {
369 char atime_buf[100], dtime_buf[100],
370 ctime_buf[100];
371 struct shmid_ds *shmptr = &xshmids[i];
372
373 cvt_time(shmptr->shm_atime, atime_buf);
374 cvt_time(shmptr->shm_dtime, dtime_buf);
375 cvt_time(shmptr->shm_ctime, ctime_buf);
376
377 printf("m %6d %10d %s %8s %8s",
378 IXSEQ_TO_IPCID(i, shmptr->shm_perm),
379 shmptr->shm_perm.key,
380 fmt_perm(shmptr->shm_perm.mode),
381 user_from_uid(shmptr->shm_perm.uid, 0),
382 group_from_gid(shmptr->shm_perm.gid, 0));
383
384 if (option & CREATOR)
385 printf(" %8s %8s",
386 user_from_uid(shmptr->shm_perm.cuid, 0),
387 group_from_gid(shmptr->shm_perm.cgid, 0));
388
389 if (option & OUTSTANDING)
390 printf(" %6d",
391 shmptr->shm_nattch);
392
393 if (option & BIGGEST)
394 printf(" %6d",
395 shmptr->shm_segsz);
396
397 if (option & PID)
398 printf(" %6d %6d",
399 shmptr->shm_cpid,
400 shmptr->shm_lpid);
401
402 if (option & TIME)
403 printf("%s %s %s",
404 atime_buf,
405 dtime_buf,
406 ctime_buf);
407
408 printf("\n");
409 }
410 }
411 printf("\n");
412 }
413 } else
414 if (display & (SHMINFO | SHMTOTAL)) {
415 fprintf(stderr,
416 "SVID shared memory facility not configured in the system\n");
417 }
418 if ((display & (SEMINFO | SEMTOTAL)) &&
419 (kvm_read(kd, symbols[X_SEMINFO].n_value, &seminfo,
420 sizeof(seminfo)) == sizeof(seminfo))) {
421 struct semid_ds *xsema;
422
423 if (display & SEMTOTAL) {
424 printf("seminfo:\n");
425 printf("\tsemmap: %6d\t(# of entries in semaphore map)\n",
426 seminfo.semmap);
427 printf("\tsemmni: %6d\t(# of semaphore identifiers)\n",
428 seminfo.semmni);
429 printf("\tsemmns: %6d\t(# of semaphores in system)\n",
430 seminfo.semmns);
431 printf("\tsemmnu: %6d\t(# of undo structures in system)\n",
432 seminfo.semmnu);
433 printf("\tsemmsl: %6d\t(max # of semaphores per id)\n",
434 seminfo.semmsl);
435 printf("\tsemopm: %6d\t(max # of operations per semop call)\n",
436 seminfo.semopm);
437 printf("\tsemume: %6d\t(max # of undo entries per process)\n",
438 seminfo.semume);
439 printf("\tsemusz: %6d\t(size in bytes of undo structure)\n",
440 seminfo.semusz);
441 printf("\tsemvmx: %6d\t(semaphore maximum value)\n",
442 seminfo.semvmx);
443 printf("\tsemaem: %6d\t(adjust on exit max value)\n\n",
444 seminfo.semaem);
445 }
446 if (display & SEMINFO) {
447 if (semconfig(SEM_CONFIG_FREEZE) != 0) {
448 perror("semconfig");
449 fprintf(stderr,
450 "Can't lock semaphore facility - winging it...\n");
451 }
452 if (kvm_read(kd, symbols[X_SEMA].n_value, &sema,
453 sizeof(sema)) != sizeof(sema))
454 errx(1, "kvm_read (%s): %s",
455 symbols[X_SEMA].n_name, kvm_geterr(kd));
456
457 xsema = malloc(sizeof(struct semid_ds) *
458 seminfo.semmni);
459
460 if (kvm_read(kd, (u_long)sema, xsema,
461 sizeof(struct semid_ds) * seminfo.semmni) !=
462 sizeof(struct semid_ds) * seminfo.semmni)
463 errx(1, "kvm_read (sema): %s",
464 kvm_geterr(kd));
465
466 printf("Semaphores:\n");
467 printf("T ID KEY MODE OWNER GROUP");
468 if (option & CREATOR)
469 printf(" CREATOR CGROUP");
470 if (option & BIGGEST)
471 printf(" NSEMS");
472 if (option & TIME)
473 printf(" OTIME CTIME");
474 printf("\n");
475 for (i = 0; i < seminfo.semmni; i += 1) {
476 if ((xsema[i].sem_perm.mode & SEM_ALLOC) != 0) {
477 char ctime_buf[100], otime_buf[100];
478 struct semid_ds *semaptr = &xsema[i];
479 int j, value;
480 union semun junk;
481
482 cvt_time(semaptr->sem_otime, otime_buf);
483 cvt_time(semaptr->sem_ctime, ctime_buf);
484
485 printf("s %6d %10d %s %8s %8s",
486 IXSEQ_TO_IPCID(i, semaptr->sem_perm),
487 semaptr->sem_perm.key,
488 fmt_perm(semaptr->sem_perm.mode),
489 user_from_uid(semaptr->sem_perm.uid, 0),
490 group_from_gid(semaptr->sem_perm.gid, 0));
491
492 if (option & CREATOR)
493 printf(" %8s %8s",
494 user_from_uid(semaptr->sem_perm.cuid, 0),
495 group_from_gid(semaptr->sem_perm.cgid, 0));
496
497 if (option & BIGGEST)
498 printf(" %6d",
499 semaptr->sem_nsems);
500
501 if (option & TIME)
502 printf("%s %s",
503 otime_buf,
504 ctime_buf);
505
506 printf("\n");
507 }
508 }
509
510 (void) semconfig(SEM_CONFIG_THAW);
511
512 printf("\n");
513 }
514 } else
515 if (display & (SEMINFO | SEMTOTAL)) {
516 fprintf(stderr, "SVID semaphores facility not configured in the system\n");
517 }
518 kvm_close(kd);
519
520 exit(0);
521 }
522
523 void
524 usage()
525 {
526
527 fprintf(stderr,
528 "usage: %s [-abcmopqst] [-C corefile] [-N namelist]\n",
529 __progname);
530 exit(1);
531 }
532