ipcs.c revision 1.15 1 /* $NetBSD: ipcs.c,v 1.15 1998/04/01 21:10:30 kleink 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 <grp.h>
47 #include <kvm.h>
48 #include <limits.h>
49 #include <nlist.h>
50 #include <paths.h>
51 #include <pwd.h>
52 #include <stdio.h>
53 #include <stdlib.h>
54 #include <string.h>
55 #include <time.h>
56 #include <unistd.h>
57
58 void cvt_time __P((time_t, char *, int));
59 char *fmt_perm __P((u_short));
60 int main __P((int, char **));
61 int semconfig __P((int, ...));
62 void usage __P((void));
63
64 extern char *__progname; /* from crt0.o */
65
66 static struct nlist symbols[] = {
67 {"_sema"},
68 #define X_SEMA 0
69 {"_seminfo"},
70 #define X_SEMINFO 1
71 {"_semu"},
72 #define X_SEMU 2
73 {"_msginfo"},
74 #define X_MSGINFO 3
75 {"_msqids"},
76 #define X_MSQIDS 4
77 {"_shminfo"},
78 #define X_SHMINFO 5
79 {"_shmsegs"},
80 #define X_SHMSEGS 6
81 {NULL}
82 };
83
84 static kvm_t *kd;
85
86 char *
87 fmt_perm(mode)
88 u_short mode;
89 {
90 static char buffer[100];
91
92 buffer[0] = '-';
93 buffer[1] = '-';
94 buffer[2] = ((mode & 0400) ? 'r' : '-');
95 buffer[3] = ((mode & 0200) ? 'w' : '-');
96 buffer[4] = ((mode & 0100) ? 'a' : '-');
97 buffer[5] = ((mode & 0040) ? 'r' : '-');
98 buffer[6] = ((mode & 0020) ? 'w' : '-');
99 buffer[7] = ((mode & 0010) ? 'a' : '-');
100 buffer[8] = ((mode & 0004) ? 'r' : '-');
101 buffer[9] = ((mode & 0002) ? 'w' : '-');
102 buffer[10] = ((mode & 0001) ? 'a' : '-');
103 buffer[11] = '\0';
104 return (&buffer[0]);
105 }
106
107 void
108 cvt_time(t, buf, buflen)
109 time_t t;
110 char *buf;
111 int buflen;
112 {
113 struct tm *tm;
114
115 if (t == 0) {
116 (void)strncpy(buf, "no-entry", buflen - 1);
117 } else {
118 tm = localtime(&t);
119 (void)snprintf(buf, buflen, "%2d:%02d:%02d",
120 tm->tm_hour, tm->tm_min, tm->tm_sec);
121 }
122 }
123 #define SHMINFO 1
124 #define SHMTOTAL 2
125 #define MSGINFO 4
126 #define MSGTOTAL 8
127 #define SEMINFO 16
128 #define SEMTOTAL 32
129
130 #define BIGGEST 1
131 #define CREATOR 2
132 #define OUTSTANDING 4
133 #define PID 8
134 #define TIME 16
135
136 int
137 main(argc, argv)
138 int argc;
139 char *argv[];
140 {
141 int display = SHMINFO | MSGINFO | SEMINFO;
142 int option = 0;
143 char *core = NULL, *namelist = NULL;
144 char errbuf[_POSIX2_LINE_MAX];
145 int i;
146
147 while ((i = getopt(argc, argv, "MmQqSsabC:cN:optT")) != -1)
148 switch (i) {
149 case 'M':
150 display = SHMTOTAL;
151 break;
152 case 'm':
153 display = SHMINFO;
154 break;
155 case 'Q':
156 display = MSGTOTAL;
157 break;
158 case 'q':
159 display = MSGINFO;
160 break;
161 case 'S':
162 display = SEMTOTAL;
163 break;
164 case 's':
165 display = SEMINFO;
166 break;
167 case 'T':
168 display = SHMTOTAL | MSGTOTAL | SEMTOTAL;
169 break;
170 case 'a':
171 option |= BIGGEST | CREATOR | OUTSTANDING | PID | TIME;
172 break;
173 case 'b':
174 option |= BIGGEST;
175 break;
176 case 'C':
177 core = optarg;
178 break;
179 case 'c':
180 option |= CREATOR;
181 break;
182 case 'N':
183 namelist = optarg;
184 break;
185 case 'o':
186 option |= OUTSTANDING;
187 break;
188 case 'p':
189 option |= PID;
190 break;
191 case 't':
192 option |= TIME;
193 break;
194 default:
195 usage();
196 }
197
198 /*
199 * Discard setgid privelidges if not the running kernel so that
200 * bad guys can't print interesting stuff from kernel memory.
201 */
202 if (namelist != NULL || core != NULL)
203 setgid(getgid());
204
205 if ((kd = kvm_openfiles(namelist, core, NULL, O_RDONLY,
206 errbuf)) == NULL)
207 errx(1, "can't open kvm: %s", errbuf);
208
209 switch (kvm_nlist(kd, symbols)) {
210 case 0:
211 break;
212 case -1:
213 errx(1, "%s: unable to read symbol table.",
214 namelist == NULL ? _PATH_UNIX : namelist);
215 default:
216 #ifdef notdef /* they'll be told more civilly later */
217 warnx("nlist failed");
218 for (i = 0; symbols[i].n_name != NULL; i++)
219 if (symbols[i].n_value == 0)
220 warnx("symbol %s not found",
221 symbols[i].n_name);
222 break;
223 #endif
224 }
225
226 if ((display & (MSGINFO | MSGTOTAL)) &&
227 (kvm_read(kd, symbols[X_MSGINFO].n_value,
228 &msginfo, sizeof(msginfo)) == sizeof(msginfo))) {
229
230 if (display & MSGTOTAL) {
231 printf("msginfo:\n");
232 printf("\tmsgmax: %6d\t(max characters in a message)\n",
233 msginfo.msgmax);
234 printf("\tmsgmni: %6d\t(# of message queues)\n",
235 msginfo.msgmni);
236 printf("\tmsgmnb: %6d\t(max characters in a message queue)\n",
237 msginfo.msgmnb);
238 printf("\tmsgtql: %6d\t(max # of messages in system)\n",
239 msginfo.msgtql);
240 printf("\tmsgssz: %6d\t(size of a message segment)\n",
241 msginfo.msgssz);
242 printf("\tmsgseg: %6d\t(# of message segments in system)\n\n",
243 msginfo.msgseg);
244 }
245 if (display & MSGINFO) {
246 struct msqid_ds *xmsqids;
247
248 if (kvm_read(kd, symbols[X_MSQIDS].n_value,
249 &msqids, sizeof(msqids)) != sizeof(msqids))
250 errx(1, "kvm_read (%s): %s",
251 symbols[X_MSQIDS].n_name, kvm_geterr(kd));
252
253 xmsqids = malloc(sizeof(struct msqid_ds) *
254 msginfo.msgmni);
255
256 if (kvm_read(kd, (u_long)msqids, xmsqids,
257 sizeof(struct msqid_ds) * msginfo.msgmni) !=
258 sizeof(struct msqid_ds) * msginfo.msgmni)
259 errx(1, "kvm_read (msqids): %s",
260 kvm_geterr(kd));
261
262 printf("Message Queues:\n");
263 printf("T ID KEY MODE OWNER GROUP");
264 if (option & CREATOR)
265 printf(" CREATOR CGROUP");
266 if (option & OUTSTANDING)
267 printf(" CBYTES QNUM");
268 if (option & BIGGEST)
269 printf(" QBYTES");
270 if (option & PID)
271 printf(" LSPID LRPID");
272 if (option & TIME)
273 printf(" STIME RTIME CTIME");
274 printf("\n");
275 for (i = 0; i < msginfo.msgmni; i += 1) {
276 if (xmsqids[i].msg_qbytes != 0) {
277 char stime_buf[100], rtime_buf[100],
278 ctime_buf[100];
279 struct msqid_ds *msqptr = &xmsqids[i];
280
281 cvt_time(msqptr->msg_stime, stime_buf,
282 sizeof stime_buf);
283 cvt_time(msqptr->msg_rtime, rtime_buf,
284 sizeof rtime_buf);
285 cvt_time(msqptr->msg_ctime, ctime_buf,
286 sizeof ctime_buf);
287
288 printf("q %6d %10ld %s %8s %8s",
289 IXSEQ_TO_IPCID(i, msqptr->msg_perm),
290 (long)msqptr->msg_perm.key,
291 fmt_perm(msqptr->msg_perm.mode),
292 user_from_uid(msqptr->msg_perm.uid, 0),
293 group_from_gid(msqptr->msg_perm.gid, 0));
294
295 if (option & CREATOR)
296 printf(" %8s %8s",
297 user_from_uid(msqptr->msg_perm.cuid, 0),
298 group_from_gid(msqptr->msg_perm.cgid, 0));
299
300 if (option & OUTSTANDING)
301 printf(" %6ld %6ld",
302 (long)msqptr->msg_cbytes,
303 (long)msqptr->msg_qnum);
304
305 if (option & BIGGEST)
306 printf(" %6ld",
307 (long)msqptr->msg_qbytes);
308
309 if (option & PID)
310 printf(" %6d %6d",
311 msqptr->msg_lspid,
312 msqptr->msg_lrpid);
313
314 if (option & TIME)
315 printf("%s %s %s",
316 stime_buf,
317 rtime_buf,
318 ctime_buf);
319
320 printf("\n");
321 }
322 }
323 printf("\n");
324 }
325 } else
326 if (display & (MSGINFO | MSGTOTAL)) {
327 fprintf(stderr,
328 "SVID messages facility not configured in the system\n");
329 }
330 if ((display & (SHMINFO | SHMTOTAL)) &&
331 (kvm_read(kd, symbols[X_SHMINFO].n_value, &shminfo,
332 sizeof(shminfo)) == sizeof(shminfo))) {
333
334 if (display & SHMTOTAL) {
335 printf("shminfo:\n");
336 printf("\tshmmax: %7d\t(max shared memory segment size)\n",
337 shminfo.shmmax);
338 printf("\tshmmin: %7d\t(min shared memory segment size)\n",
339 shminfo.shmmin);
340 printf("\tshmmni: %7d\t(max number of shared memory identifiers)\n",
341 shminfo.shmmni);
342 printf("\tshmseg: %7d\t(max shared memory segments per process)\n",
343 shminfo.shmseg);
344 printf("\tshmall: %7d\t(max amount of shared memory in pages)\n\n",
345 shminfo.shmall);
346 }
347 if (display & SHMINFO) {
348 struct shmid_ds *xshmids;
349
350 if (kvm_read(kd, symbols[X_SHMSEGS].n_value, &shmsegs,
351 sizeof(shmsegs)) != sizeof(shmsegs))
352 errx(1, "kvm_read (%s): %s",
353 symbols[X_SHMSEGS].n_name, kvm_geterr(kd));
354
355 xshmids = malloc(sizeof(struct shmid_ds) *
356 shminfo.shmmni);
357
358 if (kvm_read(kd, (u_long)shmsegs, xshmids,
359 sizeof(struct shmid_ds) * shminfo.shmmni) !=
360 sizeof(struct shmid_ds) * shminfo.shmmni)
361 errx(1, "kvm_read (shmsegs): %s",
362 kvm_geterr(kd));
363
364 printf("Shared Memory:\n");
365 printf("T ID KEY MODE OWNER GROUP");
366 if (option & CREATOR)
367 printf(" CREATOR CGROUP");
368 if (option & OUTSTANDING)
369 printf(" NATTCH");
370 if (option & BIGGEST)
371 printf(" SEGSZ");
372 if (option & PID)
373 printf(" CPID LPID");
374 if (option & TIME)
375 printf(" ATIME DTIME CTIME");
376 printf("\n");
377 for (i = 0; i < shminfo.shmmni; i += 1) {
378 if (xshmids[i].shm_perm.mode & 0x0800) {
379 char atime_buf[100], dtime_buf[100],
380 ctime_buf[100];
381 struct shmid_ds *shmptr = &xshmids[i];
382
383 cvt_time(shmptr->shm_atime, atime_buf,
384 sizeof atime_buf);
385 cvt_time(shmptr->shm_dtime, dtime_buf,
386 sizeof dtime_buf);
387 cvt_time(shmptr->shm_ctime, ctime_buf,
388 sizeof ctime_buf);
389
390 printf("m %6d %10ld %s %8s %8s",
391 IXSEQ_TO_IPCID(i, shmptr->shm_perm),
392 (long)shmptr->shm_perm.key,
393 fmt_perm(shmptr->shm_perm.mode),
394 user_from_uid(shmptr->shm_perm.uid, 0),
395 group_from_gid(shmptr->shm_perm.gid, 0));
396
397 if (option & CREATOR)
398 printf(" %8s %8s",
399 user_from_uid(shmptr->shm_perm.cuid, 0),
400 group_from_gid(shmptr->shm_perm.cgid, 0));
401
402 if (option & OUTSTANDING)
403 printf(" %6d",
404 shmptr->shm_nattch);
405
406 if (option & BIGGEST)
407 printf(" %6d",
408 shmptr->shm_segsz);
409
410 if (option & PID)
411 printf(" %6d %6d",
412 shmptr->shm_cpid,
413 shmptr->shm_lpid);
414
415 if (option & TIME)
416 printf("%s %s %s",
417 atime_buf,
418 dtime_buf,
419 ctime_buf);
420
421 printf("\n");
422 }
423 }
424 printf("\n");
425 }
426 } else
427 if (display & (SHMINFO | SHMTOTAL)) {
428 fprintf(stderr,
429 "SVID shared memory facility not configured in the system\n");
430 }
431 if ((display & (SEMINFO | SEMTOTAL)) &&
432 (kvm_read(kd, symbols[X_SEMINFO].n_value, &seminfo,
433 sizeof(seminfo)) == sizeof(seminfo))) {
434 struct semid_ds *xsema;
435
436 if (display & SEMTOTAL) {
437 printf("seminfo:\n");
438 printf("\tsemmap: %6d\t(# of entries in semaphore map)\n",
439 seminfo.semmap);
440 printf("\tsemmni: %6d\t(# of semaphore identifiers)\n",
441 seminfo.semmni);
442 printf("\tsemmns: %6d\t(# of semaphores in system)\n",
443 seminfo.semmns);
444 printf("\tsemmnu: %6d\t(# of undo structures in system)\n",
445 seminfo.semmnu);
446 printf("\tsemmsl: %6d\t(max # of semaphores per id)\n",
447 seminfo.semmsl);
448 printf("\tsemopm: %6d\t(max # of operations per semop call)\n",
449 seminfo.semopm);
450 printf("\tsemume: %6d\t(max # of undo entries per process)\n",
451 seminfo.semume);
452 printf("\tsemusz: %6d\t(size in bytes of undo structure)\n",
453 seminfo.semusz);
454 printf("\tsemvmx: %6d\t(semaphore maximum value)\n",
455 seminfo.semvmx);
456 printf("\tsemaem: %6d\t(adjust on exit max value)\n\n",
457 seminfo.semaem);
458 }
459 if (display & SEMINFO) {
460 if (semconfig(SEM_CONFIG_FREEZE) != 0) {
461 perror("semconfig");
462 fprintf(stderr,
463 "Can't lock semaphore facility - winging it...\n");
464 }
465 if (kvm_read(kd, symbols[X_SEMA].n_value, &sema,
466 sizeof(sema)) != sizeof(sema))
467 errx(1, "kvm_read (%s): %s",
468 symbols[X_SEMA].n_name, kvm_geterr(kd));
469
470 xsema = malloc(sizeof(struct semid_ds) *
471 seminfo.semmni);
472
473 if (kvm_read(kd, (u_long)sema, xsema,
474 sizeof(struct semid_ds) * seminfo.semmni) !=
475 sizeof(struct semid_ds) * seminfo.semmni)
476 errx(1, "kvm_read (sema): %s",
477 kvm_geterr(kd));
478
479 printf("Semaphores:\n");
480 printf("T ID KEY MODE OWNER GROUP");
481 if (option & CREATOR)
482 printf(" CREATOR CGROUP");
483 if (option & BIGGEST)
484 printf(" NSEMS");
485 if (option & TIME)
486 printf(" OTIME CTIME");
487 printf("\n");
488 for (i = 0; i < seminfo.semmni; i += 1) {
489 if ((xsema[i].sem_perm.mode & SEM_ALLOC) != 0) {
490 char ctime_buf[100], otime_buf[100];
491 struct semid_ds *semaptr = &xsema[i];
492
493 cvt_time(semaptr->sem_otime, otime_buf,
494 sizeof otime_buf);
495 cvt_time(semaptr->sem_ctime, ctime_buf,
496 sizeof ctime_buf);
497
498 printf("s %6d %10ld %s %8s %8s",
499 IXSEQ_TO_IPCID(i, semaptr->sem_perm),
500 (long)semaptr->sem_perm.key,
501 fmt_perm(semaptr->sem_perm.mode),
502 user_from_uid(semaptr->sem_perm.uid, 0),
503 group_from_gid(semaptr->sem_perm.gid, 0));
504
505 if (option & CREATOR)
506 printf(" %8s %8s",
507 user_from_uid(semaptr->sem_perm.cuid, 0),
508 group_from_gid(semaptr->sem_perm.cgid, 0));
509
510 if (option & BIGGEST)
511 printf(" %6d",
512 semaptr->sem_nsems);
513
514 if (option & TIME)
515 printf("%s %s",
516 otime_buf,
517 ctime_buf);
518
519 printf("\n");
520 }
521 }
522
523 (void) semconfig(SEM_CONFIG_THAW);
524
525 printf("\n");
526 }
527 } else
528 if (display & (SEMINFO | SEMTOTAL)) {
529 fprintf(stderr, "SVID semaphores facility not configured in the system\n");
530 }
531 kvm_close(kd);
532
533 exit(0);
534 }
535
536 void
537 usage()
538 {
539
540 fprintf(stderr,
541 "usage: %s [-abcmopqst] [-C corefile] [-N namelist]\n",
542 __progname);
543 exit(1);
544 }
545