]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
ipcs: clean up do_sem(), and add ipc_sem_get_info()
authorSami Kerola <kerolasa@iki.fi>
Sun, 11 Nov 2012 20:53:07 +0000 (20:53 +0000)
committerKarel Zak <kzak@redhat.com>
Fri, 23 Nov 2012 13:58:22 +0000 (14:58 +0100)
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
sys-utils/ipcs.c
sys-utils/ipcutils.c
sys-utils/ipcutils.h

index 4945d8dcc85fcc8faaa49f2a614f613438d97f3a..1180299ebb8533cfb2eb2419379741dc5ae2b723 100644 (file)
@@ -33,8 +33,8 @@
 
 static void do_shm (char format);
 static void print_shm (int id);
+static void do_sem (char format);
 
-void do_sem (char format);
 void do_msg (char format);
 void print_msg (int id);
 void print_sem (int id);
@@ -332,25 +332,16 @@ static void do_shm (char format)
        return;
 }
 
-void do_sem (char format)
+static void do_sem (char format)
 {
-       int maxid, semid, id;
-       struct semid_ds semary;
-       struct seminfo seminfo;
-       struct ipc_perm *ipcp = &semary.sem_perm;
        struct passwd *pw;
-       union semun arg;
-       struct ipc_limits lim;
-
-       arg.array = (ushort *)  (void *) &seminfo;
-       maxid = semctl (0, 0, SEM_INFO, arg);
-       if (maxid < 0) {
-               printf (_("kernel not configured for semaphores\n"));
-               return;
-       }
+       struct sem_data *semds, *semdsp;
 
        switch (format) {
        case LIMITS:
+       {
+               struct ipc_limits lim;
+
                printf (_("------ Semaphore Limits --------\n"));
                if (ipc_sem_get_limits(&lim))
                        return;
@@ -360,12 +351,21 @@ void do_sem (char format)
                printf (_("max ops per semop call = %d\n"), lim.semopm);
                printf (_("semaphore max value = %d\n"), lim.semvmx);
                return;
-
+       }
        case STATUS:
+       {
+               struct seminfo seminfo;
+               union semun arg;
+               arg.array = (ushort *)  (void *) &seminfo;
+               if (semctl (0, 0, SEM_INFO, arg) < 0) {
+                       printf (_("kernel not configured for semaphores\n"));
+                       return;
+               }
                printf (_("------ Semaphore Status --------\n"));
                printf (_("used arrays = %d\n"), seminfo.semusz);
                printf (_("allocated semaphores = %d\n"), seminfo.semaem);
                return;
+       }
 
        case CREATOR:
                printf (_("------ Semaphore Arrays Creators/Owners --------\n"));
@@ -389,48 +389,48 @@ void do_sem (char format)
                break;
        }
 
-       for (id = 0; id <= maxid; id++) {
-               arg.buf = (struct semid_ds *) &semary;
-               semid = semctl (id, 0, SEM_STAT, arg);
-               if (semid < 0)
-                       continue;
+       /*
+        * Print data
+        */
+       if (ipc_sem_get_info(-1, &semds) < 1)
+               return;
+       semdsp = semds;
+
+       for (semdsp = semds; semdsp->next != NULL; semdsp = semdsp->next) {
                if (format == CREATOR)  {
-                       print_perms (semid, ipcp);
+                       ipc_print_perms(stdout, &semdsp->sem_perm);
                        continue;
                }
-               pw = getpwuid(ipcp->uid);
+               pw = getpwuid(semdsp->sem_perm.uid);
                switch (format) {
                case TIME:
                        if (pw)
-                               printf ("%-8d %-10.10s", semid, pw->pw_name);
+                               printf ("%-8d %-10.10s", semdsp->sem_perm.id, pw->pw_name);
                        else
-                               printf ("%-8d %-10u", semid, ipcp->uid);
-                       printf ("  %-26.24s", semary.sem_otime
-                               ? ctime(&semary.sem_otime) : _("Not set"));
-                       printf (" %-26.24s\n", semary.sem_ctime
-                               ? ctime(&semary.sem_ctime) : _("Not set"));
+                               printf ("%-8d %-10u", semdsp->sem_perm.id, semdsp->sem_perm.uid);
+                       printf ("  %-26.24s", semdsp->sem_otime
+                               ? ctime(&semdsp->sem_otime) : _("Not set"));
+                       printf (" %-26.24s\n", semdsp->sem_ctime
+                               ? ctime(&semdsp->sem_ctime) : _("Not set"));
                        break;
                case PID:
                        break;
 
                default:
-                       printf("0x%08x ", ipcp->KEY);
+                       printf("0x%08x ", semdsp->sem_perm.key);
                        if (pw)
-                               printf ("%-10d %-10.10s", semid, pw->pw_name);
+                               printf ("%-10d %-10.10s", semdsp->sem_perm.id, pw->pw_name);
                        else
-                               printf ("%-10d %-10u", semid, ipcp->uid);
+                               printf ("%-10d %-10u", semdsp->sem_perm.id, semdsp->sem_perm.uid);
                        printf (" %-10o %-10ld\n",
-                               ipcp->mode & 0777,
-                               /*
-                                * glibc-2.1.3 and earlier has unsigned
-                                * short. glibc-2.1.91 has variation between
-                                * unsigned short and unsigned long. Austin
-                                * prescribes unsigned short.
-                                */
-                               (long) semary.sem_nsems);
+                               semdsp->sem_perm.mode & 0777,
+                               semdsp->sem_nsems);
                        break;
                }
        }
+
+       ipc_sem_free_info(semds);
+       return;
 }
 
 void do_msg (char format)
index 3b52a7e6b8d3c9e9b834d00e3966cb5e66dd87f5..61671c1285a952c6f9913239fd3d2e4a920a4aad 100644 (file)
@@ -211,6 +211,115 @@ void ipc_shm_free_info(struct shm_data *shmds)
        }
 }
 
+int ipc_sem_get_info(int id, struct sem_data **semds)
+{
+       FILE *f;
+       int i, maxid;
+       struct sem_data *p;
+       struct seminfo dummy;
+       union semun arg;
+
+       p = *semds = xcalloc(1, sizeof(struct sem_data));
+       p->next = NULL;
+
+       f = path_fopen("r", 0, _PATH_PROC_SYSV_SEM);
+       if (!f)
+               goto sem_fallback;
+
+       while (fgetc(f) != '\n') ;      /* skip header */
+
+       while (feof(f) == 0) {
+               if (fscanf(f,
+                          "%d %d  %o %" SCNu64 " %u %u %u %u %" SCNu64 " %" SCNu64 "\n",
+                          &p->sem_perm.key,
+                          &p->sem_perm.id,
+                          &p->sem_perm.mode,
+                          &p->sem_nsems,
+                          &p->sem_perm.uid,
+                          &p->sem_perm.gid,
+                          &p->sem_perm.cuid,
+                          &p->sem_perm.cgid,
+                          &p->sem_otime,
+                          &p->sem_ctime) != 10)
+                       continue;
+
+               if (id > -1) {
+                       /* ID specified */
+                       if (id == p->sem_perm.id) {
+                               i = 1;
+                               break;
+                       } else
+                               continue;
+               }
+
+               p->next = xcalloc(1, sizeof(struct sem_data));
+               p = p->next;
+               p->next = NULL;
+               i++;
+       }
+
+       if (i == 0)
+               free(*semds);
+       fclose(f);
+       return i;
+
+       /* Fallback; /proc or /sys file(s) missing. */
+ sem_fallback:
+       i = id < 0 ? 0 : id;
+
+       arg.array = (ushort *) (void *)&dummy;
+       maxid = semctl(0, 0, SEM_INFO, arg);
+       if (maxid < 0)
+               return 0;
+
+       while (i <= maxid) {
+               int semid;
+               struct semid_ds semseg;
+               struct ipc_perm *ipcp = &semseg.sem_perm;
+               arg.buf = (struct semid_ds *)&semseg;
+
+               semid = semctl(i, 0, SEM_STAT, arg);
+               if (semid < 0) {
+                       if (-1 < id) {
+                               free(*semds);
+                               return 0;
+                       }
+                       i++;
+                       continue;
+               }
+
+               p->sem_perm.key = ipcp->KEY;
+               p->sem_perm.id = semid;
+               p->sem_perm.mode = ipcp->mode;
+               p->sem_nsems = semseg.sem_nsems;
+               p->sem_perm.uid = ipcp->uid;
+               p->sem_perm.gid = ipcp->gid;
+               p->sem_perm.cuid = ipcp->cuid;
+               p->sem_perm.cgid = ipcp->cuid;
+               p->sem_otime = semseg.sem_otime;
+               p->sem_ctime = semseg.sem_ctime;
+
+               if (id < 0) {
+                       p->next = xcalloc(1, sizeof(struct sem_data));
+                       p = p->next;
+                       p->next = NULL;
+                       i++;
+               } else
+                       return 1;
+       }
+
+       return i;
+}
+
+void ipc_sem_free_info(struct sem_data *semds)
+{
+       while (semds) {
+               struct sem_data *next = semds->next;
+               free(semds);
+               semds = next;
+       }
+}
+
 void ipc_print_perms(FILE *f, struct ipc_stat *is)
 {
        struct passwd *pw;
index 45a75d84f80da6ce38008cbfd23519777abc1669..3ab5da0cac3168fc6c3bb07f3b3248abb5ec38ef 100644 (file)
@@ -132,4 +132,19 @@ struct shm_data {
 extern int ipc_shm_get_info(int id, struct shm_data **shmds);
 extern void ipc_shm_free_info(struct shm_data *shmds);
 
+/* See 'struct sem_array' in kernel sources
+ */
+struct sem_data {
+       struct ipc_stat sem_perm;
+
+       time_t          sem_ctime;
+       time_t          sem_otime;
+       uint64_t        sem_nsems;
+
+       struct sem_data *next;
+};
+
+extern int ipc_sem_get_info(int id, struct sem_data **semds);
+extern void ipc_sem_free_info(struct sem_data *semds);
+
 #endif /* UTIL_LINUX_IPCUTILS_H */