Magellan Linux

Annotation of /trunk/mkinitrd-magellan/busybox/util-linux/ipcs.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 532 - (hide annotations) (download)
Sat Sep 1 22:45:15 2007 UTC (16 years, 9 months ago) by niro
File MIME type: text/plain
File size: 16965 byte(s)
-import if magellan mkinitrd; it is a fork of redhats mkinitrd-5.0.8 with all magellan patches and features; deprecates magellan-src/mkinitrd

1 niro 532 /* vi: set sw=4 ts=4: */
2     /*
3     * ipcs.c -- provides information on allocated ipc resources.
4     *
5     * 01 Sept 2004 - Rodney Radford <rradford@mindspring.com>
6     * Adapted for busybox from util-linux-2.12a.
7     *
8     * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
9     */
10    
11     #include "busybox.h"
12     #include <errno.h>
13     #include <time.h>
14     #include <pwd.h>
15     #include <grp.h>
16    
17     /* X/OPEN tells us to use <sys/{types,ipc,sem}.h> for semctl() */
18     /* X/OPEN tells us to use <sys/{types,ipc,msg}.h> for msgctl() */
19     /* X/OPEN tells us to use <sys/{types,ipc,shm}.h> for shmctl() */
20     #include <sys/types.h>
21     #include <sys/ipc.h>
22     #include <sys/sem.h>
23     #include <sys/msg.h>
24     #include <sys/shm.h>
25    
26    
27    
28     /*-------------------------------------------------------------------*/
29     /* SHM_DEST and SHM_LOCKED are defined in kernel headers,
30     but inside #ifdef __KERNEL__ ... #endif */
31     #ifndef SHM_DEST
32     /* shm_mode upper byte flags */
33     #define SHM_DEST 01000 /* segment will be destroyed on last detach */
34     #define SHM_LOCKED 02000 /* segment will not be swapped */
35     #endif
36    
37     /* For older kernels the same holds for the defines below */
38     #ifndef MSG_STAT
39     #define MSG_STAT 11
40     #define MSG_INFO 12
41     #endif
42    
43     #ifndef SHM_STAT
44     #define SHM_STAT 13
45     #define SHM_INFO 14
46     struct shm_info {
47     int used_ids;
48     ulong shm_tot; /* total allocated shm */
49     ulong shm_rss; /* total resident shm */
50     ulong shm_swp; /* total swapped shm */
51     ulong swap_attempts;
52     ulong swap_successes;
53     };
54     #endif
55    
56     #ifndef SEM_STAT
57     #define SEM_STAT 18
58     #define SEM_INFO 19
59     #endif
60    
61     /* Some versions of libc only define IPC_INFO when __USE_GNU is defined. */
62     #ifndef IPC_INFO
63     #define IPC_INFO 3
64     #endif
65     /*-------------------------------------------------------------------*/
66    
67     /* The last arg of semctl is a union semun, but where is it defined?
68     X/OPEN tells us to define it ourselves, but until recently
69     Linux include files would also define it. */
70     #if defined (__GNU_LIBRARY__) && !defined(_SEM_SEMUN_UNDEFINED)
71     /* union semun is defined by including <sys/sem.h> */
72     #else
73     /* according to X/OPEN we have to define it ourselves */
74     union semun {
75     int val;
76     struct semid_ds *buf;
77     unsigned short int *array;
78     struct seminfo *__buf;
79     };
80     #endif
81    
82     /* X/OPEN (Jan 1987) does not define fields key, seq in struct ipc_perm;
83     libc 4/5 does not mention struct ipc_term at all, but includes
84     <linux/ipc.h>, which defines a struct ipc_perm with such fields.
85     glibc-1.09 has no support for sysv ipc.
86     glibc 2 uses __key, __seq */
87     #if defined (__GNU_LIBRARY__) && __GNU_LIBRARY__ > 1
88     #define KEY __key
89     #else
90     #define KEY key
91     #endif
92    
93     #define LIMITS 1
94     #define STATUS 2
95     #define CREATOR 3
96     #define TIME 4
97     #define PID 5
98    
99     static char format;
100    
101     static void print_perms(int id, struct ipc_perm *ipcp)
102     {
103     struct passwd *pw;
104     struct group *gr;
105    
106     printf("%-10d %-10o", id, ipcp->mode & 0777);
107    
108     if ((pw = getpwuid(ipcp->cuid)))
109     printf(" %-10s", pw->pw_name);
110     else
111     printf(" %-10d", ipcp->cuid);
112     if ((gr = getgrgid(ipcp->cgid)))
113     printf(" %-10s", gr->gr_name);
114     else
115     printf(" %-10d", ipcp->cgid);
116    
117     if ((pw = getpwuid(ipcp->uid)))
118     printf(" %-10s", pw->pw_name);
119     else
120     printf(" %-10d", ipcp->uid);
121     if ((gr = getgrgid(ipcp->gid)))
122     printf(" %-10s\n", gr->gr_name);
123     else
124     printf(" %-10d\n", ipcp->gid);
125     }
126    
127    
128     static void do_shm(void)
129     {
130     int maxid, shmid, id;
131     struct shmid_ds shmseg;
132     struct shm_info shm_info;
133     struct shminfo shminfo;
134     struct ipc_perm *ipcp = &shmseg.shm_perm;
135     struct passwd *pw;
136    
137     maxid = shmctl(0, SHM_INFO, (struct shmid_ds *) (void *) &shm_info);
138     if (maxid < 0) {
139     printf("kernel not configured for %s\n", "shared memory");
140     return;
141     }
142    
143     switch (format) {
144     case LIMITS:
145     printf("------ Shared Memory %s --------\n", "Limits");
146     if ((shmctl(0, IPC_INFO, (struct shmid_ds *) (void *) &shminfo)) < 0)
147     return;
148     /* glibc 2.1.3 and all earlier libc's have ints as fields
149     of struct shminfo; glibc 2.1.91 has unsigned long; ach */
150     printf("max number of segments = %lu\n"
151     "max seg size (kbytes) = %lu\n"
152     "max total shared memory (pages) = %lu\n"
153     "min seg size (bytes) = %lu\n",
154     (unsigned long) shminfo.shmmni,
155     (unsigned long) (shminfo.shmmax >> 10),
156     (unsigned long) shminfo.shmall,
157     (unsigned long) shminfo.shmmin);
158     return;
159    
160     case STATUS:
161     printf("------ Shared Memory %s --------\n", "Status");
162     printf( "segments allocated %d\n"
163     "pages allocated %ld\n"
164     "pages resident %ld\n"
165     "pages swapped %ld\n"
166     "Swap performance: %ld attempts\t%ld successes\n",
167     shm_info.used_ids,
168     shm_info.shm_tot,
169     shm_info.shm_rss,
170     shm_info.shm_swp,
171     shm_info.swap_attempts, shm_info.swap_successes);
172     return;
173    
174     case CREATOR:
175     printf("------ Shared Memory %s --------\n", "Segment Creators/Owners");
176     printf( "%-10s %-10s %-10s %-10s %-10s %-10s\n",
177     "shmid", "perms", "cuid", "cgid", "uid", "gid");
178     break;
179    
180     case TIME:
181     printf("------ Shared Memory %s --------\n", "Attach/Detach/Change Times");
182     printf( "%-10s %-10s %-20s %-20s %-20s\n",
183     "shmid", "owner", "attached", "detached", "changed");
184     break;
185    
186     case PID:
187     printf("------ Shared Memory %s --------\n", "Creator/Last-op");
188     printf( "%-10s %-10s %-10s %-10s\n",
189     "shmid", "owner", "cpid", "lpid");
190     break;
191    
192     default:
193     printf("------ Shared Memory %s --------\n", "Segments");
194     printf( "%-10s %-10s %-10s %-10s %-10s %-10s %-12s\n",
195     "key", "shmid", "owner", "perms", "bytes", "nattch",
196     "status");
197     break;
198     }
199    
200     for (id = 0; id <= maxid; id++) {
201     shmid = shmctl(id, SHM_STAT, &shmseg);
202     if (shmid < 0)
203     continue;
204     if (format == CREATOR) {
205     print_perms(shmid, ipcp);
206     continue;
207     }
208     pw = getpwuid(ipcp->uid);
209     switch (format) {
210     case TIME:
211     if (pw)
212     printf("%-10d %-10.10s", shmid, pw->pw_name);
213     else
214     printf("%-10d %-10d", shmid, ipcp->uid);
215     /* ctime uses static buffer: use separate calls */
216     printf(" %-20.16s", shmseg.shm_atime
217     ? ctime(&shmseg.shm_atime) + 4 : "Not set");
218     printf(" %-20.16s", shmseg.shm_dtime
219     ? ctime(&shmseg.shm_dtime) + 4 : "Not set");
220     printf(" %-20.16s\n", shmseg.shm_ctime
221     ? ctime(&shmseg.shm_ctime) + 4 : "Not set");
222     break;
223     case PID:
224     if (pw)
225     printf("%-10d %-10.10s", shmid, pw->pw_name);
226     else
227     printf("%-10d %-10d", shmid, ipcp->uid);
228     printf(" %-10d %-10d\n", shmseg.shm_cpid, shmseg.shm_lpid);
229     break;
230    
231     default:
232     printf("0x%08x ", ipcp->KEY);
233     if (pw)
234     printf("%-10d %-10.10s", shmid, pw->pw_name);
235     else
236     printf("%-10d %-10d", shmid, ipcp->uid);
237     printf(" %-10o %-10lu %-10ld %-6s %-6s\n", ipcp->mode & 0777,
238     /*
239     * earlier: int, Austin has size_t
240     */
241     (unsigned long) shmseg.shm_segsz,
242     /*
243     * glibc-2.1.3 and earlier has unsigned short;
244     * Austin has shmatt_t
245     */
246     (long) shmseg.shm_nattch,
247     ipcp->mode & SHM_DEST ? "dest" : " ",
248     ipcp->mode & SHM_LOCKED ? "locked" : " ");
249     break;
250     }
251     }
252     }
253    
254    
255     static void do_sem(void)
256     {
257     int maxid, semid, id;
258     struct semid_ds semary;
259     struct seminfo seminfo;
260     struct ipc_perm *ipcp = &semary.sem_perm;
261     struct passwd *pw;
262     union semun arg;
263    
264     arg.array = (ushort *) (void *) &seminfo;
265     maxid = semctl(0, 0, SEM_INFO, arg);
266     if (maxid < 0) {
267     printf("kernel not configured for %s\n", "semaphores");
268     return;
269     }
270    
271     switch (format) {
272     case LIMITS:
273     printf("------ Semaphore %s --------\n", "Limits");
274     arg.array = (ushort *) (void *) &seminfo; /* damn union */
275     if ((semctl(0, 0, IPC_INFO, arg)) < 0)
276     return;
277     printf("max number of arrays = %d\n"
278     "max semaphores per array = %d\n"
279     "max semaphores system wide = %d\n"
280     "max ops per semop call = %d\n"
281     "semaphore max value = %d\n",
282     seminfo.semmni,
283     seminfo.semmsl,
284     seminfo.semmns, seminfo.semopm, seminfo.semvmx);
285     return;
286    
287     case STATUS:
288     printf("------ Semaphore %s --------\n", "Status");
289     printf( "used arrays = %d\n"
290     "allocated semaphores = %d\n",
291     seminfo.semusz, seminfo.semaem);
292     return;
293    
294     case CREATOR:
295     printf("------ Semaphore %s --------\n", "Arrays Creators/Owners");
296     printf( "%-10s %-10s %-10s %-10s %-10s %-10s\n",
297     "semid", "perms", "cuid", "cgid", "uid", "gid");
298     break;
299    
300     case TIME:
301     printf("------ Shared Memory %s --------\n", "Operation/Change Times");
302     printf( "%-8s %-10s %-26.24s %-26.24s\n",
303     "shmid", "owner", "last-op", "last-changed");
304     break;
305    
306     case PID:
307     break;
308    
309     default:
310     printf("------ Semaphore %s --------\n", "Arrays");
311     printf( "%-10s %-10s %-10s %-10s %-10s\n",
312     "key", "semid", "owner", "perms", "nsems");
313     break;
314     }
315    
316     for (id = 0; id <= maxid; id++) {
317     arg.buf = (struct semid_ds *) &semary;
318     semid = semctl(id, 0, SEM_STAT, arg);
319     if (semid < 0)
320     continue;
321     if (format == CREATOR) {
322     print_perms(semid, ipcp);
323     continue;
324     }
325     pw = getpwuid(ipcp->uid);
326     switch (format) {
327     case TIME:
328     if (pw)
329     printf("%-8d %-10.10s", semid, pw->pw_name);
330     else
331     printf("%-8d %-10d", semid, ipcp->uid);
332     /* ctime uses static buffer: use separate calls */
333     printf(" %-26.24s", semary.sem_otime
334     ? ctime(&semary.sem_otime) : "Not set");
335     printf(" %-26.24s\n", semary.sem_ctime
336     ? ctime(&semary.sem_ctime) : "Not set");
337     break;
338     case PID:
339     break;
340    
341     default:
342     printf("0x%08x ", ipcp->KEY);
343     if (pw)
344     printf("%-10d %-10.9s", semid, pw->pw_name);
345     else
346     printf("%-10d %-9d", semid, ipcp->uid);
347     printf(" %-10o %-10ld\n", ipcp->mode & 0777,
348     /*
349     * glibc-2.1.3 and earlier has unsigned short;
350     * glibc-2.1.91 has variation between
351     * unsigned short and unsigned long
352     * Austin prescribes unsigned short.
353     */
354     (long) semary.sem_nsems);
355     break;
356     }
357     }
358     }
359    
360    
361     static void do_msg(void)
362     {
363     int maxid, msqid, id;
364     struct msqid_ds msgque;
365     struct msginfo msginfo;
366     struct ipc_perm *ipcp = &msgque.msg_perm;
367     struct passwd *pw;
368    
369     maxid = msgctl(0, MSG_INFO, (struct msqid_ds *) (void *) &msginfo);
370     if (maxid < 0) {
371     printf("kernel not configured for %s\n", "message queues");
372     return;
373     }
374    
375     switch (format) {
376     case LIMITS:
377     if ((msgctl(0, IPC_INFO, (struct msqid_ds *) (void *) &msginfo)) < 0)
378     return;
379     printf("------ Message%s --------\n", "s: Limits");
380     printf( "max queues system wide = %d\n"
381     "max size of message (bytes) = %d\n"
382     "default max size of queue (bytes) = %d\n",
383     msginfo.msgmni, msginfo.msgmax, msginfo.msgmnb);
384     return;
385    
386     case STATUS:
387     printf("------ Message%s --------\n", "s: Status");
388     printf( "allocated queues = %d\n"
389     "used headers = %d\n"
390     "used space = %d bytes\n",
391     msginfo.msgpool, msginfo.msgmap, msginfo.msgtql);
392     return;
393    
394     case CREATOR:
395     printf("------ Message%s --------\n", " Queues: Creators/Owners");
396     printf( "%-10s %-10s %-10s %-10s %-10s %-10s\n",
397     "msqid", "perms", "cuid", "cgid", "uid", "gid");
398     break;
399    
400     case TIME:
401     printf("------ Message%s --------\n", " Queues Send/Recv/Change Times");
402     printf( "%-8s %-10s %-20s %-20s %-20s\n",
403     "msqid", "owner", "send", "recv", "change");
404     break;
405    
406     case PID:
407     printf("------ Message%s --------\n", " Queues PIDs");
408     printf( "%-10s %-10s %-10s %-10s\n",
409     "msqid", "owner", "lspid", "lrpid");
410     break;
411    
412     default:
413     printf("------ Message%s --------\n", " Queues");
414     printf( "%-10s %-10s %-10s %-10s %-12s %-12s\n",
415     "key", "msqid", "owner", "perms", "used-bytes", "messages");
416     break;
417     }
418    
419     for (id = 0; id <= maxid; id++) {
420     msqid = msgctl(id, MSG_STAT, &msgque);
421     if (msqid < 0)
422     continue;
423     if (format == CREATOR) {
424     print_perms(msqid, ipcp);
425     continue;
426     }
427     pw = getpwuid(ipcp->uid);
428     switch (format) {
429     case TIME:
430     if (pw)
431     printf("%-8d %-10.10s", msqid, pw->pw_name);
432     else
433     printf("%-8d %-10d", msqid, ipcp->uid);
434     printf(" %-20.16s", msgque.msg_stime
435     ? ctime(&msgque.msg_stime) + 4 : "Not set");
436     printf(" %-20.16s", msgque.msg_rtime
437     ? ctime(&msgque.msg_rtime) + 4 : "Not set");
438     printf(" %-20.16s\n", msgque.msg_ctime
439     ? ctime(&msgque.msg_ctime) + 4 : "Not set");
440     break;
441     case PID:
442     if (pw)
443     printf("%-8d %-10.10s", msqid, pw->pw_name);
444     else
445     printf("%-8d %-10d", msqid, ipcp->uid);
446     printf(" %5d %5d\n", msgque.msg_lspid, msgque.msg_lrpid);
447     break;
448    
449     default:
450     printf("0x%08x ", ipcp->KEY);
451     if (pw)
452     printf("%-10d %-10.10s", msqid, pw->pw_name);
453     else
454     printf("%-10d %-10d", msqid, ipcp->uid);
455     printf(" %-10o %-12ld %-12ld\n", ipcp->mode & 0777,
456     /*
457     * glibc-2.1.3 and earlier has unsigned short;
458     * glibc-2.1.91 has variation between
459     * unsigned short, unsigned long
460     * Austin has msgqnum_t
461     */
462     (long) msgque.msg_cbytes, (long) msgque.msg_qnum);
463     break;
464     }
465     }
466     }
467    
468    
469     static void print_shm(int shmid)
470     {
471     struct shmid_ds shmds;
472     struct ipc_perm *ipcp = &shmds.shm_perm;
473    
474     if (shmctl(shmid, IPC_STAT, &shmds) == -1) {
475     bb_perror_msg("shmctl");
476     return;
477     }
478    
479     printf("\nShared memory Segment shmid=%d\n"
480     "uid=%d\tgid=%d\tcuid=%d\tcgid=%d\n"
481     "mode=%#o\taccess_perms=%#o\n"
482     "bytes=%ld\tlpid=%d\tcpid=%d\tnattch=%ld\n",
483     shmid,
484     ipcp->uid, ipcp->gid, ipcp->cuid, ipcp->cgid,
485     ipcp->mode, ipcp->mode & 0777,
486     (long) shmds.shm_segsz, shmds.shm_lpid, shmds.shm_cpid,
487     (long) shmds.shm_nattch);
488     printf("att_time=%-26.24s\n",
489     shmds.shm_atime ? ctime(&shmds.shm_atime) : "Not set");
490     printf("det_time=%-26.24s\n",
491     shmds.shm_dtime ? ctime(&shmds.shm_dtime) : "Not set");
492     printf("change_time=%-26.24s\n\n", ctime(&shmds.shm_ctime));
493     }
494    
495    
496     static void print_msg(int msqid)
497     {
498     struct msqid_ds buf;
499     struct ipc_perm *ipcp = &buf.msg_perm;
500    
501     if (msgctl(msqid, IPC_STAT, &buf) == -1) {
502     bb_perror_msg("msgctl");
503     return;
504     }
505    
506     printf("\nMessage Queue msqid=%d\n"
507     "uid=%d\tgid=%d\tcuid=%d\tcgid=%d\tmode=%#o\n"
508     "cbytes=%ld\tqbytes=%ld\tqnum=%ld\tlspid=%d\tlrpid=%d\n",
509     msqid, ipcp->uid, ipcp->gid, ipcp->cuid, ipcp->cgid, ipcp->mode,
510     /*
511     * glibc-2.1.3 and earlier has unsigned short;
512     * glibc-2.1.91 has variation between
513     * unsigned short, unsigned long
514     * Austin has msgqnum_t (for msg_qbytes)
515     */
516     (long) buf.msg_cbytes, (long) buf.msg_qbytes,
517     (long) buf.msg_qnum, buf.msg_lspid, buf.msg_lrpid);
518    
519     printf("send_time=%-26.24s\n",
520     buf.msg_stime ? ctime(&buf.msg_stime) : "Not set");
521     printf("rcv_time=%-26.24s\n",
522     buf.msg_rtime ? ctime(&buf.msg_rtime) : "Not set");
523     printf("change_time=%-26.24s\n\n",
524     buf.msg_ctime ? ctime(&buf.msg_ctime) : "Not set");
525     }
526    
527     static void print_sem(int semid)
528     {
529     struct semid_ds semds;
530     struct ipc_perm *ipcp = &semds.sem_perm;
531     union semun arg;
532     unsigned int i;
533    
534     arg.buf = &semds;
535     if (semctl(semid, 0, IPC_STAT, arg)) {
536     bb_perror_msg("semctl");
537     return;
538     }
539    
540     printf("\nSemaphore Array semid=%d\n"
541     "uid=%d\t gid=%d\t cuid=%d\t cgid=%d\n"
542     "mode=%#o, access_perms=%#o\n"
543     "nsems = %ld\n"
544     "otime = %-26.24s\n",
545     semid,
546     ipcp->uid, ipcp->gid, ipcp->cuid, ipcp->cgid,
547     ipcp->mode, ipcp->mode & 0777,
548     (long) semds.sem_nsems,
549     semds.sem_otime ? ctime(&semds.sem_otime) : "Not set");
550     printf("ctime = %-26.24s\n"
551     "%-10s %-10s %-10s %-10s %-10s\n",
552     ctime(&semds.sem_ctime),
553     "semnum", "value", "ncount", "zcount", "pid");
554    
555     arg.val = 0;
556     for (i = 0; i < semds.sem_nsems; i++) {
557     int val, ncnt, zcnt, pid;
558    
559     val = semctl(semid, i, GETVAL, arg);
560     ncnt = semctl(semid, i, GETNCNT, arg);
561     zcnt = semctl(semid, i, GETZCNT, arg);
562     pid = semctl(semid, i, GETPID, arg);
563     if (val < 0 || ncnt < 0 || zcnt < 0 || pid < 0) {
564     bb_perror_msg_and_die("semctl");
565     }
566     printf("%-10d %-10d %-10d %-10d %-10d\n", i, val, ncnt, zcnt, pid);
567     }
568     puts("");
569     }
570    
571     int ipcs_main(int argc, char **argv)
572     {
573     int id = 0;
574     unsigned flags = 0;
575     unsigned opt;
576     char *opt_i;
577     #define flag_print (1<<0)
578     #define flag_msg (1<<1)
579     #define flag_sem (1<<2)
580     #define flag_shm (1<<3)
581    
582     opt = getopt32(argc, argv, "i:aqsmtcplu", &opt_i);
583     if (opt & 0x1) { // -i
584     id = xatoi(opt_i);
585     flags |= flag_print;
586     }
587     if (opt & 0x2) flags |= flag_msg | flag_sem | flag_shm; // -a
588     if (opt & 0x4) flags |= flag_msg; // -q
589     if (opt & 0x8) flags |= flag_sem; // -s
590     if (opt & 0x10) flags |= flag_shm; // -m
591     if (opt & 0x20) format = TIME; // -t
592     if (opt & 0x40) format = CREATOR; // -c
593     if (opt & 0x80) format = PID; // -p
594     if (opt & 0x100) format = LIMITS; // -l
595     if (opt & 0x200) format = STATUS; // -u
596    
597     if (flags & flag_print) {
598     if (flags & flag_shm) {
599     print_shm(id);
600     fflush_stdout_and_exit(0);
601     }
602     if (flags & flag_sem) {
603     print_sem(id);
604     fflush_stdout_and_exit(0);
605     }
606     if (flags & flag_msg) {
607     print_msg(id);
608     fflush_stdout_and_exit(0);
609     }
610     bb_show_usage();
611     }
612    
613     if (!(flags & (flag_shm | flag_msg | flag_sem)))
614     flags |= flag_msg | flag_shm | flag_sem;
615     puts("");
616    
617     if (flags & flag_shm) {
618     do_shm();
619     puts("");
620     }
621     if (flags & flag_sem) {
622     do_sem();
623     puts("");
624     }
625     if (flags & flag_msg) {
626     do_msg();
627     puts("");
628     }
629     fflush_stdout_and_exit(0);
630     }