ipcs.c revision 1.4 1 /*
2 * A fairly close approximation of ipcs with some extensions
3 *
4 * $Id: ipcs.c,v 1.4 1994/06/18 21:09:43 cgd Exp $
5 */
6
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <unistd.h>
10 #include <fcntl.h>
11 #include <paths.h>
12 #include <nlist.h>
13 #include <kvm.h>
14 #include <err.h>
15
16 #include <sys/types.h>
17 #include <sys/param.h>
18 #include <sys/proc.h>
19 #define KERNEL
20 #include <sys/ipc.h>
21 #include <sys/sem.h>
22 #include <sys/shm.h>
23 #include <sys/msg.h>
24
25 char *user_from_uid __P((uid_t, int));
26 char *group_from_gid __P((gid_t, int));
27 int semconfig __P((int,...));
28
29 static struct nlist symbols[] = {
30 {"_sema"},
31 #define X_SEMA 0
32 {"_seminfo"},
33 #define X_SEMINFO 1
34 {"_semu"},
35 #define X_SEMU 2
36 {"_msginfo"},
37 #define X_MSGINFO 3
38 {"_msqids"},
39 #define X_MSQIDS 4
40 {"_shminfo"},
41 #define X_SHMINFO 5
42 {"_shmsegs"},
43 #define X_SHMSEGS 6
44 {NULL}
45 };
46
47 static kvm_t *kd;
48
49 char *
50 fmt_perm(mode)
51 u_short mode;
52 {
53 static char buffer[100];
54
55 buffer[0] = '-';
56 buffer[1] = '-';
57 buffer[2] = ((mode & 0400) ? 'r' : '-');
58 buffer[3] = ((mode & 0200) ? 'w' : '-');
59 buffer[4] = ((mode & 0100) ? 'a' : '-');
60 buffer[5] = ((mode & 0040) ? 'r' : '-');
61 buffer[6] = ((mode & 0020) ? 'w' : '-');
62 buffer[7] = ((mode & 0010) ? 'a' : '-');
63 buffer[8] = ((mode & 0004) ? 'r' : '-');
64 buffer[9] = ((mode & 0002) ? 'w' : '-');
65 buffer[10] = ((mode & 0001) ? 'a' : '-');
66 buffer[11] = '\0';
67 return (&buffer[0]);
68 }
69
70 void
71 cvt_time(t, buf)
72 time_t t;
73 char *buf;
74 {
75 struct tm *tm;
76
77 if (t == 0) {
78 strcpy(buf, "no-entry");
79 } else {
80 tm = localtime(&t);
81 sprintf(buf, "%2d:%02d:%02d",
82 tm->tm_hour, tm->tm_min, tm->tm_sec);
83 }
84 }
85 #define SHMINFO 1
86 #define SHMTOTAL 2
87 #define MSGINFO 4
88 #define MSGTOTAL 8
89 #define SEMINFO 16
90 #define SEMTOTAL 32
91
92 #define BIGGEST 1
93 #define CREATOR 2
94 #define OUTSTANDING 4
95 #define PID 8
96 #define TIME 16
97
98 int
99 main(argc, argv)
100 int argc;
101 char *argv[];
102 {
103 int display = SHMINFO | MSGINFO | SEMINFO;
104 int option = 0;
105 char *core = NULL, *namelist = NULL;
106 int i;
107
108 while ((i = getopt(argc, argv, "MmQqSsabC:cN:optT")) != EOF)
109 switch (i) {
110 case 'M':
111 display = SHMTOTAL;
112 break;
113 case 'm':
114 display = SHMINFO;
115 break;
116 case 'Q':
117 display = MSGTOTAL;
118 break;
119 case 'q':
120 display = MSGINFO;
121 break;
122 case 'S':
123 display = SEMTOTAL;
124 break;
125 case 's':
126 display = SEMINFO;
127 break;
128 case 'T':
129 display = SHMTOTAL | MSGTOTAL | SEMTOTAL;
130 break;
131 case 'a':
132 option |= BIGGEST | CREATOR | OUTSTANDING | PID | TIME;
133 break;
134 case 'b':
135 option |= BIGGEST;
136 break;
137 case 'C':
138 core = optarg;
139 break;
140 case 'c':
141 option |= CREATOR;
142 break;
143 case 'N':
144 namelist = optarg;
145 break;
146 case 'o':
147 option |= OUTSTANDING;
148 break;
149 case 'p':
150 option |= PID;
151 break;
152 case 't':
153 option |= TIME;
154 break;
155 default:
156 errx(1, "usage: ipcs [-abcmopqst] [-C corefile] [-N namelist]\n");
157 }
158 if ((kd = kvm_open(namelist, core, NULL, O_RDONLY, "ipcs")) == NULL)
159 exit(1);
160
161 switch (kvm_nlist(kd, symbols)) {
162 case 0:
163 break;
164 case -1:
165 errx(1, "ipcs: unable to read kernel symbol table!\n");
166 default:
167 warnx("ipcs: nlist failed\n");
168 for (i = 0; symbols[i].n_name != NULL; i++) {
169 if (symbols[i].n_value == 0) {
170 warnx("\tsymbol %s not found\n", symbols[i].n_name);
171 }
172 }
173 break;
174 }
175
176 if ((display & (MSGINFO | MSGTOTAL)) &&
177 kvm_read(kd, symbols[X_MSGINFO].n_value, &msginfo, sizeof(msginfo))) {
178
179 if (display & MSGTOTAL) {
180 printf("msginfo:\n");
181 printf("\tmsgmax: %6d\t(max characters in a message)\n",
182 msginfo.msgmax);
183 printf("\tmsgmni: %6d\t(# of message queues)\n",
184 msginfo.msgmni);
185 printf("\tmsgmnb: %6d\t(max characters in a message queue)\n",
186 msginfo.msgmnb);
187 printf("\tmsgtql: %6d\t(max # of messages in system)\n",
188 msginfo.msgtql);
189 printf("\tmsgssz: %6d\t(size of a message segment)\n",
190 msginfo.msgssz);
191 printf("\tmsgseg: %6d\t(# of message segments in system)\n\n",
192 msginfo.msgseg);
193 }
194 if (display & MSGINFO) {
195 struct msqid_ds *xmsqids;
196
197 kvm_read(kd, symbols[X_MSQIDS].n_value, &msqids, sizeof(msqids));
198 xmsqids = malloc(sizeof(struct msqid_ds) * msginfo.msgmni);
199 kvm_read(kd, (u_long) msqids, xmsqids, sizeof(struct msqid_ds) * msginfo.msgmni);
200
201 printf("Message Queues:\n");
202 printf("T ID KEY MODE OWNER GROUP");
203 if (option & CREATOR)
204 printf(" CREATOR CGROUP");
205 if (option & OUTSTANDING)
206 printf(" CBYTES QNUM");
207 if (option & BIGGEST)
208 printf(" QBYTES");
209 if (option & PID)
210 printf(" LSPID LRPID");
211 if (option & TIME)
212 printf(" STIME RTIME CTIME");
213 printf("\n");
214 for (i = 0; i < msginfo.msgmni; i += 1) {
215 if (xmsqids[i].msg_qbytes != 0) {
216 char stime_buf[100], rtime_buf[100],
217 ctime_buf[100];
218 struct msqid_ds *msqptr = &xmsqids[i];
219
220 cvt_time(msqptr->msg_stime, stime_buf);
221 cvt_time(msqptr->msg_rtime, rtime_buf);
222 cvt_time(msqptr->msg_ctime, ctime_buf);
223
224 printf("q %6d %10d %s %8s %8s",
225 IXSEQ_TO_IPCID(i, msqptr->msg_perm),
226 msqptr->msg_perm.key,
227 fmt_perm(msqptr->msg_perm.mode),
228 user_from_uid(msqptr->msg_perm.uid, 0),
229 group_from_gid(msqptr->msg_perm.gid, 0));
230
231 if (option & CREATOR)
232 printf(" %8s %8s",
233 user_from_uid(msqptr->msg_perm.cuid, 0),
234 group_from_gid(msqptr->msg_perm.cgid, 0));
235
236 if (option & OUTSTANDING)
237 printf(" %6d %6d",
238 msqptr->msg_cbytes,
239 msqptr->msg_qnum);
240
241 if (option & BIGGEST)
242 printf(" %6d",
243 msqptr->msg_qbytes);
244
245 if (option & PID)
246 printf(" %6d %6d",
247 msqptr->msg_lspid,
248 msqptr->msg_lrpid);
249
250 if (option & TIME)
251 printf("%s %s %s",
252 stime_buf,
253 rtime_buf,
254 ctime_buf);
255
256 printf("\n");
257 }
258 }
259 printf("\n");
260 }
261 } else
262 if (display & (MSGINFO | MSGTOTAL)) {
263 fprintf(stderr,
264 "SVID messages facility not configured in the system\n");
265 }
266 if ((display & (SHMINFO | SHMTOTAL)) &&
267 kvm_read(kd, symbols[X_SHMINFO].n_value, &shminfo, sizeof(shminfo))) {
268 if (display & SHMTOTAL) {
269 printf("shminfo:\n");
270 printf("\tshmmax: %7d\t(max shared memory segment size)\n",
271 shminfo.shmmax);
272 printf("\tshmmin: %7d\t(min shared memory segment size)\n",
273 shminfo.shmmin);
274 printf("\tshmmni: %7d\t(max number of shared memory identifiers)\n",
275 shminfo.shmmni);
276 printf("\tshmseg: %7d\t(max shared memory segments per process)\n",
277 shminfo.shmseg);
278 printf("\tshmall: %7d\t(max amount of shared memory in pages)\n\n",
279 shminfo.shmall);
280 }
281 if (display & SHMINFO) {
282 struct shmid_ds *xshmids;
283
284 kvm_read(kd, symbols[X_SHMSEGS].n_value, &shmsegs, sizeof(shmsegs));
285 xshmids = malloc(sizeof(struct shmid_ds) * msginfo.msgmni);
286 kvm_read(kd, (u_long) shmsegs, xshmids, sizeof(struct shmid_ds) *
287 shminfo.shmmni);
288
289 printf("Shared Memory:\n");
290 printf("T ID KEY MODE OWNER GROUP");
291 if (option & CREATOR)
292 printf(" CREATOR CGROUP");
293 if (option & OUTSTANDING)
294 printf(" NATTCH");
295 if (option & BIGGEST)
296 printf(" SEGSZ");
297 if (option & PID)
298 printf(" CPID LPID");
299 if (option & TIME)
300 printf(" ATIME DTIME CTIME");
301 printf("\n");
302 for (i = 0; i < shminfo.shmmni; i += 1) {
303 if (xshmids[i].shm_perm.mode & 0x0800) {
304 char atime_buf[100], dtime_buf[100],
305 ctime_buf[100];
306 struct shmid_ds *shmptr = &xshmids[i];
307
308 cvt_time(shmptr->shm_atime, atime_buf);
309 cvt_time(shmptr->shm_dtime, dtime_buf);
310 cvt_time(shmptr->shm_ctime, ctime_buf);
311
312 printf("q %6d %10d %s %8s %8s",
313 IXSEQ_TO_IPCID(i, shmptr->shm_perm),
314 shmptr->shm_perm.key,
315 fmt_perm(shmptr->shm_perm.mode),
316 user_from_uid(shmptr->shm_perm.uid, 0),
317 group_from_gid(shmptr->shm_perm.gid, 0));
318
319 if (option & CREATOR)
320 printf(" %8s %8s",
321 user_from_uid(shmptr->shm_perm.cuid, 0),
322 group_from_gid(shmptr->shm_perm.cgid, 0));
323
324 if (option & OUTSTANDING)
325 printf(" %6d",
326 shmptr->shm_nattch);
327
328 if (option & BIGGEST)
329 printf(" %6d",
330 shmptr->shm_segsz);
331
332 if (option & PID)
333 printf(" %6d %6d",
334 shmptr->shm_cpid,
335 shmptr->shm_lpid);
336
337 if (option & TIME)
338 printf("%s %s %s",
339 atime_buf,
340 dtime_buf,
341 ctime_buf);
342
343 printf("\n");
344 }
345 }
346 printf("\n");
347 }
348 } else
349 if (display & (SHMINFO | SHMTOTAL)) {
350 fprintf(stderr,
351 "SVID shared memory facility not configured in the system\n");
352 }
353 if ((display & (SEMINFO | SEMTOTAL)) &&
354 kvm_read(kd, symbols[X_SEMINFO].n_value, &seminfo, sizeof(seminfo))) {
355 struct semid_ds *xsema;
356
357 if (display & SEMTOTAL) {
358 printf("seminfo:\n");
359 printf("\tsemmap: %6d\t(# of entries in semaphore map)\n",
360 seminfo.semmap);
361 printf("\tsemmni: %6d\t(# of semaphore identifiers)\n",
362 seminfo.semmni);
363 printf("\tsemmns: %6d\t(# of semaphores in system)\n",
364 seminfo.semmns);
365 printf("\tsemmnu: %6d\t(# of undo structures in system)\n",
366 seminfo.semmnu);
367 printf("\tsemmsl: %6d\t(max # of semaphores per id)\n",
368 seminfo.semmsl);
369 printf("\tsemopm: %6d\t(max # of operations per semop call)\n",
370 seminfo.semopm);
371 printf("\tsemume: %6d\t(max # of undo entries per process)\n",
372 seminfo.semume);
373 printf("\tsemusz: %6d\t(size in bytes of undo structure)\n",
374 seminfo.semusz);
375 printf("\tsemvmx: %6d\t(semaphore maximum value)\n",
376 seminfo.semvmx);
377 printf("\tsemaem: %6d\t(adjust on exit max value)\n\n",
378 seminfo.semaem);
379 }
380 if (display & SEMINFO) {
381 if (semconfig(SEM_CONFIG_FREEZE) != 0) {
382 perror("semconfig");
383 fprintf(stderr,
384 "Can't lock semaphore facility - winging it...\n");
385 }
386 kvm_read(kd, symbols[X_SEMA].n_value, &sema, sizeof(sema));
387 xsema = malloc(sizeof(struct semid_ds) * seminfo.semmni);
388 kvm_read(kd, (u_long) sema, xsema, sizeof(struct semid_ds) * seminfo.semmni);
389
390 printf("Semaphores:\n");
391 printf("T ID KEY MODE OWNER GROUP");
392 if (option & CREATOR)
393 printf(" CREATOR CGROUP");
394 if (option & BIGGEST)
395 printf(" NSEMS");
396 if (option & TIME)
397 printf(" OTIME CTIME");
398 printf("\n");
399 for (i = 0; i < seminfo.semmni; i += 1) {
400 if ((xsema[i].sem_perm.mode & SEM_ALLOC) != 0) {
401 char ctime_buf[100], otime_buf[100];
402 struct semid_ds *semaptr = &xsema[i];
403 int j, value;
404 union semun junk;
405
406 cvt_time(semaptr->sem_otime, otime_buf);
407 cvt_time(semaptr->sem_ctime, ctime_buf);
408
409 printf("q %6d %10d %s %8s %8s",
410 IXSEQ_TO_IPCID(i, semaptr->sem_perm),
411 semaptr->sem_perm.key,
412 fmt_perm(semaptr->sem_perm.mode),
413 user_from_uid(semaptr->sem_perm.uid, 0),
414 group_from_gid(semaptr->sem_perm.gid, 0));
415
416 if (option & CREATOR)
417 printf(" %8s %8s",
418 user_from_uid(semaptr->sem_perm.cuid, 0),
419 group_from_gid(semaptr->sem_perm.cgid, 0));
420
421 if (option & BIGGEST)
422 printf(" %6d",
423 semaptr->sem_nsems);
424
425 if (option & TIME)
426 printf("%s %s",
427 otime_buf,
428 ctime_buf);
429
430 printf("\n");
431 }
432 }
433
434 (void) semconfig(SEM_CONFIG_THAW);
435
436 printf("\n");
437 }
438 } else
439 if (display & (SEMINFO | SEMTOTAL)) {
440 fprintf(stderr, "SVID semaphores facility not configured in the system\n");
441 }
442 kvm_close(kd);
443
444 exit(0);
445 }
446