next up previous contents
Next: semstat: A semtool companion Up: semtool: An interactive semaphore Previous: Examples

The Source


/*****************************************************************************
  Excerpt from "Linux Programmer's Guide - Chapter 6"
  (C)opyright 1994-1995, Scott Burkett
  ***************************************************************************** 
  MODULE: semtool.c
  *****************************************************************************
  A command line tool for tinkering with SysV style Semaphore Sets
 
  *****************************************************************************/
 
 #include <stdio.h>
 #include <ctype.h>
 #include <stdlib.h>
 #include <sys/types.h>
 #include <sys/ipc.h>
 #include <sys/sem.h>
 
 #define SEM_RESOURCE_MAX        1       /* Initial value of all semaphores */
 
 void opensem(int *sid, key_t key);
 void createsem(int *sid, key_t key, int members);
 void locksem(int sid, int member);
 void unlocksem(int sid, int member);
 void removesem(int sid);
 unsigned short get_member_count(int sid);
 int getval(int sid, int member);
 void dispval(int sid, int member);
 void changemode(int sid, char *mode);
 void usage(void);
 
 int main(int argc, char *argv[])
 {
         key_t key;
         int   semset_id;
 
         if(argc == 1)
                 usage();
 
         /* Create unique key via call to ftok() */
         key = ftok(".", 's');
 
         switch(tolower(argv[1][0]))
         {
                 case 'c': if(argc != 3)
                                 usage();
                           createsem(&semset_id, key,  atoi(argv[2]));
                           break;
                 case 'l': if(argc != 3)
                                 usage();
                           opensem(&semset_id, key);
                           locksem(semset_id, atoi(argv[2]));
                           break;
                 case 'u': if(argc != 3)
                                 usage();
                           opensem(&semset_id, key);
                           unlocksem(semset_id, atoi(argv[2]));
                           break;
                 case 'd': opensem(&semset_id, key);
                           removesem(semset_id);
                           break;        
                 case 'm': opensem(&semset_id, key);
                           changemode(semset_id, argv[2]);
                           break;        
                  default: usage();
 
         }
         
         return(0);
 }
 
 void opensem(int *sid, key_t key)
 {
         /* Open the semaphore set - do not create! */
 
         if((*sid = semget(key, 0, 0666)) == -1) 
         {
                 printf("Semaphore set does not exist!\n");
                 exit(1);
         }
 
 }
 
 void createsem(int *sid, key_t key, int members)
 {
         int cntr;
         union semun semopts;
 
         if(members > SEMMSL) {
                 printf("Sorry, max number of semaphores in a set is %d\n",
                         SEMMSL);
                 exit(1);
         }
 
         printf("Attempting to create new semaphore set with %d members\n",
                                 members);
 
         if((*sid = semget(key, members, IPC_CREAT|IPC_EXCL|0666))
                         == -1) 
         {
                 fprintf(stderr, "Semaphore set already exists!\n");
                 exit(1);
         }
 
         semopts.val = SEM_RESOURCE_MAX;
         
         /* Initialize all members (could be done with SETALL) */        
         for(cntr=0; cntr<members; cntr++)
                 semctl(*sid, cntr, SETVAL, semopts);
 }
 
 void locksem(int sid, int member)
 {
         struct sembuf sem_lock={ 0, -1, IPC_NOWAIT};
 
         if( member<0 || member>(get_member_count(sid)-1))
         {
                 fprintf(stderr, "semaphore member %d out of range\n", member);
                 return;
         }
 
         /* Attempt to lock the semaphore set */
         if(!getval(sid, member))
         {
                 fprintf(stderr, "Semaphore resources exhausted (no lock)!\n");
                 exit(1);
         }
         
         sem_lock.sem_num = member;
         
         if((semop(sid, &sem_lock, 1)) == -1)
         {
                 fprintf(stderr, "Lock failed\n");
                 exit(1);
         }
         else
                 printf("Semaphore resources decremented by one (locked)\n");
 
         dispval(sid, member);
 }
 
 void unlocksem(int sid, int member)
 {
         struct sembuf sem_unlock={ member, 1, IPC_NOWAIT};
         int semval;
 
         if( member<0 || member>(get_member_count(sid)-1))
         {
                 fprintf(stderr, "semaphore member %d out of range\n", member);
                 return;
         }
 
         /* Is the semaphore set locked? */
         semval = getval(sid, member);
         if(semval == SEM_RESOURCE_MAX) {
                 fprintf(stderr, "Semaphore not locked!\n");
                 exit(1);
         }
 
         sem_unlock.sem_num = member;
 
         /* Attempt to lock the semaphore set */
         if((semop(sid, &sem_unlock, 1)) == -1)
         {
                 fprintf(stderr, "Unlock failed\n");
                 exit(1);
         }
         else
                 printf("Semaphore resources incremented by one (unlocked)\n");
 
         dispval(sid, member);
 }
 
 void removesem(int sid)
 {
         semctl(sid, 0, IPC_RMID, 0);
         printf("Semaphore removed\n");
 }
 
 unsigned short get_member_count(int sid)
 {
         union semun semopts;
         struct semid_ds mysemds;
 
         semopts.buf = &mysemds;
 
         /* Return number of members in the semaphore set */
         return(semopts.buf->sem_nsems);
 }
 
 int getval(int sid, int member)
 {
         int semval;
 
         semval = semctl(sid, member, GETVAL, 0);
         return(semval);
 }
 
 void changemode(int sid, char *mode)
 {
         int rc;
         union semun semopts;
         struct semid_ds mysemds;
 
         /* Get current values for internal data structure */
         semopts.buf = &mysemds;
 
         rc = semctl(sid, 0, IPC_STAT, semopts);
 
         if (rc == -1) {
                 perror("semctl");
                 exit(1);
         }
                 
         printf("Old permissions were %o\n", semopts.buf->sem_perm.mode);
                 
         /* Change the permissions on the semaphore */
         sscanf(mode, "%ho", &semopts.buf->sem_perm.mode);
 
         /* Update the internal data structure */
         semctl(sid, 0, IPC_SET, semopts);
 
         printf("Updated...\n");
 
 }
 
 void dispval(int sid, int member)
 {
         int semval;
 
         semval = semctl(sid, member, GETVAL, 0);
         printf("semval for member %d is %d\n", member, semval);
 }
 
 void usage(void)
 {
         fprintf(stderr, "semtool - A utility for tinkering with semaphores\n");
         fprintf(stderr, "\nUSAGE:  semtool4 (c)reate <semcount>\n");
         fprintf(stderr, "                 (l)ock <sem #>\n");
         fprintf(stderr, "                 (u)nlock <sem #>\n");
         fprintf(stderr, "                 (d)elete\n");
         fprintf(stderr, "                 (m)ode <mode>\n");
         exit(1);
 }



Converted on:
Fri Mar 29 14:43:04 EST 1996