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