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