Karim Vaes

Why chop at leaves, when one must dig at roots
  • Home
  • About me
    • Curriculum Vitae
  • Scripts
    • OWA Most Popular
  • Search
  • License
  • Contact

My own setlock program written in oldskool C

Following on my previous post on my own setlock code;

I found out that (even after some extra versions), the bash version was simply not solid enough to be used in production. So I’ve written the code in C, where I could use the “fcntl” directly.

The objectives for writing the program, was to extent the regular “setlock” program (from Daemon Tools) to:
- a freely usable code (without Copywright), thus “our own” code
- have an “override” feature (force option)

This program is used in a small framework where it’s architecture was setup in a way where one process periodically updates data. And that this data could be accessed from time to time to be manipulated.

The code:
[my_clearcase_view]kvaes@solaris:~/setlock cat setlock-nsn.c

#include 
#include 
#include 
#include 
#include 
#include 
#include 

int DoLock(int, int, int);
#define read_lock(LockFD) \
                        DoLock(LockFD, F_SETLK, F_RDLCK)
#define read_wait_lock(LockFD) \
                        DoLock(LockFD, F_SETLKW, F_RDLCK)
#define write_lock(LockFD) \
                        DoLock(LockFD, F_SETLK, F_WRLCK)
#define write_wait_lock(LockFD) \
                        DoLock(LockFD, F_SETLKW, F_WRLCK)
#define unlock(LockFD) \
                        DoLock(LockFD, F_SETLK, F_UNLCK)

pid_t PidLock(int, int);
#define readlocked(LockFD) \
                        PidLock(LockFD, F_RDLCK)
#define writelocked(LockFD) \
                        PidLock(LockFD, F_WRLCK)

int
main ( int argc, char *argv[] ){
  int LockFD;
  int EXIT;

  if ( argc < = 4 )
    {
        printf( "usage: %s lockfile nowait/wait/force read/write command [arg1 arg2 ... argN]\n", argv[0] );
        EXIT=-1;
    }
  else
  {
    LockFD = open(argv[1], O_RDWR);
    if (LockFD == -1)
    {
      printf( "Lockfile %s isn't accesible.\n", argv[1] );
      EXIT=-1;
    }
    else
    {
      int FOUND=0;
      int TYPE=0;
      int MATCHES=99;

      MATCHES = strcmp( argv[3], "write" );
      if ( MATCHES == 0 )
      {
        TYPE=1;
        MATCHES = strcmp( argv[2], "wait" );
        if ( MATCHES == 0 )
        {
          EXIT=write_wait_lock(LockFD);
          FOUND=1;
        }
        MATCHES = strcmp( argv[2], "nowait" );
        if ( MATCHES == 0 )
        {
          EXIT=write_lock(LockFD);
          FOUND=1;
        }
        MATCHES = strcmp( argv[2], "force" );
        if ( MATCHES == 0 )
        {
          int PID=0;
          PID=writelocked(LockFD);
          if ( PID > 0 )
          {
            EXIT=kill(PID,SIGTERM);
            if ( EXIT != 0 )
            {
              printf("Error while trying to kill pid $d.\n", PID);
              exit(errno);
            }
            EXIT=unlock(LockFD);
            if ( EXIT != 0 )
            {
              printf("Error while trying to unlock.\n");
              exit(errno);
            }
          }
          EXIT=write_lock(LockFD);
          FOUND=1;
        }
      }
      MATCHES = strcmp( argv[3], "read" );
      if ( MATCHES == 0 )
      {
        TYPE=2;
        MATCHES = strcmp( argv[2], "wait" );
        if ( MATCHES == 0 )
        {
          EXIT=read_wait_lock(LockFD);
          FOUND=1;
        }
        MATCHES = strcmp( argv[2], "nowait" );
        if ( MATCHES == 0 )
        {
          EXIT=read_lock(LockFD);
          FOUND=1;
        }
        MATCHES = strcmp( argv[2], "force" );
        if ( MATCHES == 0 )
        {
          printf("The option %s cannot be used here.\n", argv[2]);
          exit(-1);
        }
      }
      if ( FOUND == 0 ) {
        printf("Wrong wait type entered. (%s)\n", argv[2]);
        EXIT=-1;
      }
      else
      {
        if ( EXIT == 0 )
        {
          EXIT=execute(argc,argv);
          unlock(LockFD);
        }
        else
        {
          printf("Error while trying to use a %s lock.\n", argv[2]);
          exit(errno);
        }
      }
    }
  }
  exit(EXIT);
}

int execute(int argc, char *argv[])
{
  int ret = 0;
  char *cmd[argc-4];
  char *prog;

  int i = 0;
  int j = 0;
  for ( i = 0; i < argc; ++i )
  {
    switch ( i ) {
      case 0:
        //executable name
        break;
      case 1:
        //lock file
        break;
      case 2:
        //how do we wait?
        break;
      case 3:
        //read or write?
        break;;
      case 4:
        prog=argv[i];
        cmd[j]=argv[i];
        j++;
        break;
      default:
        cmd[j]=argv[i];
        j++;
        break;
    }
  }
  cmd[j]=(char *)0;

  ret = execvp(prog, cmd);
  return ret;
}

pid_t PidLock(int LockFD, int type)
{
  struct flock lock;
  lock.l_type = type;
  lock.l_start = 0;
  lock.l_whence = SEEK_SET;
  lock.l_len = 1;
  if (fcntl(LockFD,F_GETLK,&lock) < 0)
  {
    perror("fcntl");
    exit(1);
  }
  if (lock.l_type == F_UNLCK)
  {
    return(0);
  }
  return(lock.l_pid);
}

int DoLock(int LockFD, int cmd, int type)
{
  struct flock lock;
  lock.l_type = type;
  lock.l_start = 0;
  lock.l_whence = SEEK_SET;
  lock.l_len = 1;
  return(fcntl(LockFD, cmd, &lock));
}

Comments
No Comments »
Categories
Unix/Linux
Comments rss Comments rss
Trackback Trackback
1 Star2 Stars3 Stars4 Stars5 Stars (No Ratings Yet)
Loading ... Loading ...

Linux vs Solaris Runlevels

Linux

  • Runlevel 0 is reserved for the “shutdown” phase. Entering init 0 from the shell prompt will shutdown the system and usually power off the machine.
  • Runlevel 1 is usually for very basic commands. This is the equivalent to “safe mode” used by Windows. This level is usually only used to asses repairs or maintenance to the system. This is a single-user mode and does not allow other users to login to the machine.
  • Runlevel 2 is used to start most of the machines services. However, it does not start the network file sharing service (SMB, NFS). This will allows multiple users to login to the machine.
  • Runlevel 3 is commonly used by servers. This loads all services except the X windows system. This means the system will boot to the equivalent of DOS. No GUIs (KDE, Gnome) will start. This level allows multiple users to login to the machine.
  • Runlevel 4 is usually a “custom” level. By default it will start a few more services than level 3. This level is usually only used under special circumstances.
  • Runlevel 5 is everything! This will start any GUIs, extra services for printing, and 3rd party services. Full multi-users support also. This runlevel is generally used on by workstations.
  • Runlevel 6 is reserved for “reboot” only. Be carefully when running this command. Once you have entered init 6, there is no stopping it!
  • Solaris

  • S, s – Single user mode. Doesn’t require properly formated /etc/inittab. Filesystems required for basic system operation are mounted.
  • 0 – Go into firmware (sparc)
  • 1 – System Administrator mode. All local filesystems are mounted. Small set of essential system processes are running. Also a single user mode.
  • 2 – Put the system in multi-user mode. All multi-user environment terminal processes and daemons are spawned.
  • 3 – Extend multi-user mode by making local resources available over the network.
  • 4 -Is available to be defined as an alternative multi-user environment configuration. It is not necessary for system operation and is usually not used.
  • 5 – Shut the machine down so that it is safe to remove the power. Have the machine remove power, if possible.
  • 6 – Reboot
  • Notice Runlevel 5… so don’t mix them up ;-)

    Comments
    1 Comment »
    Categories
    Unix/Linux
    Comments rss Comments rss
    Trackback Trackback
    1 Star2 Stars3 Stars4 Stars5 Stars (1 votes, average: 5.00 out of 5)
    Loading ... Loading ...

    OpenAds: Managing ads on multiple sites

    I’ve been using OpenAds for about a small month now. Where I have to tell you that it’s great! OpenAds is an Ad framework which enables you to control the ads displayed on your site kinda like an ad network (like Adsense) does.

    Each ad network has it benefits, but also it’s downsides. So in most cases it’s nice to combine them. This is where OpenAds becomes a key component.

    You setup a certain ad zone on your site, which you populate with content generated by the OpenAds framework. In this framework you add the banners (in which type you want!) to be shown in this zone. But you can put restrictions on the behavior of when ads should be shown.

    For example:
    I mainly use TradeDoubler & Adsense. TradeDoubler gives me more regional banners, but the target audience for this blog is mainly international. So I configured my OpenAds to only show the TradeDoubler banners when the browser “locale” was set to Dutch.

    This is only one of the many examples where OpenAds becomes a great product to use. Try it yourself! And you’ll see that it has a great effect on your ad revenue.

    Comments
    No Comments »
    Categories
    Web
    Comments rss Comments rss
    Trackback Trackback
    1 Star2 Stars3 Stars4 Stars5 Stars (No Ratings Yet)
    Loading ... Loading ...

    my own setlock source code

    I’ve added the “force” options, as I needed it for the project I’m working on.

    #!/bin/bash
    
    usage()
    {
      echo "usage: setlock [ -fFnN ] [ -xX ] [ -v ] [ -V ] file program [ arg ... ]"
      echo " Options"
      echo "    -f: No delay. If fn is locked by another process, try to force ownership by trying to kill the process that has the lock."
      echo "    -F: No delay. If fn is locked by another process, bruteforce ownership by killing the process that has the lock (-9)."
      echo "    -n: No delay. If fn is locked by another process, setlock gives up."
      echo "    -N: (Default.) Delay. If fn is locked by another process, setlock waits until it can obtain a new lock."
      echo "    -x: If fn cannot be created or locked, setlock exits zero."
      echo "    -X: (Default.) If fn cannot be created or locked, setlock prints an error message and exits nonzero."
      echo "    -v: Verbose messaging"
      echo "    -V: Show the version"
      exit 1
    }
    version()
    {
      echo "Version 0.1"
      usage
    }
    verbose()
    {
      if [ "$VERBOSE" = "y" ] ; then
        echo "$1"
      fi
    }
    cleanup()
    {
      if [ "$SETLOCK" = "y" ] ; then
        killlock
        clear_lock
      fi
    }
    trap "cleanup"
    set_lock()
    {
      verbose "set lock"
      echo $$ >> $LOCK
      SETLOCK=y
    }
    clear_lock()
    {
      verbose "Clear lock"
      rm $LOCK >/dev/null 2>&1
    }
    killlock()
    {
      pids=`cat $LOCK 2>/dev/null`
      for pid in $pids
      do
        verbose "Kill $1 on process $pid"
        kill $1 $pid >/dev/null 2>&1
      done
    }
    run_command()
    {
      set_lock
      verbose "Running command"
      eval bash -c \"$CMD\"
      RET=$?
      verbose "Command done - exit value = $RET"
      clear_lock
      RET=$?
      exit $RET
    }
    no_wait()
    {
      verbose "No waiting"
      exit $EXITCODE
    }
    wait_nice()
    {
      verbose "Waiting nice"
      while [ -f "$LOCK" ] ; do
        sleep 1
      done
      run_command
    }
    force_kill()
    {
      killlock
      run_command
    }
    force_brute()
    {
      killlock -9
      run_command
    }
    
    FORCE=n
    DELAY=y
    EXITCODE=1
    VERBOSE=n
    OPTS=0
    while getopts "f F n N x X v V" o ; do
      case $o in
        f) FORCE=y DELAY=n;;
        F) FORCE=b DELAY=n;;
        n) DELAY=n;;
        N) DELAY=y;;
        x) EXITCODE=0;;
        X) EXITCODE=1;;
        v) VERBOSE=y;;
        V) version;;
      esac
      let OPTS=$OPTS+1
    done
    
    if [ $# -lt 2 ] ; then
      verbose "Not enough parameters given"
      usage
    fi
    
    APTS=0
    while [ $APTS -lt $OPTS ]  ; do
      shift
      let APTS=$APTS+1
    done
    
    LOCK=$1
    shift
    CMD=$*
    
    if [ -z "$LOCK" ] ; then
      verbose "No lockfile given"
      usage
    fi
    
    if [ -z "$CMD" ] ; then
      verbose "No command given"
      usage
    fi
    
    if [ -f "$LOCK" ] ; then
      if [ "$DELAY" = "y" ] ; then
        wait_nice
      else
        case "$FORCE" in
          "n") no_wait;;
          "y") force_kill;;
          "b") force_brute;;
          *) exit 99;;
        esac
      fi
    else
      run_command
    fi

    Feel free to use it, yet I’m publishing it here under the GPL license

    Comments
    No Comments »
    Categories
    Bash, Unix/Linux
    Comments rss Comments rss
    Trackback Trackback
    1 Star2 Stars3 Stars4 Stars5 Stars (No Ratings Yet)
    Loading ... Loading ...

    bash : locking issues – example with setlock

    Something that kept me busy for a while. An internal (bash) framework sometimes (Isn’t that great! -sigh-) gave unexpected results. Sometimes the timings were too long, and sometimes data was missing. In the end, it was due to a locking issue. A program tried to execute something while forcing an internal lock. Yet the program was waiting until the lock was released. But when in some cases when two programs do this, this causes a deadlock.

    The code below is a way to get around this deadlock. It’s an example using “setlock”, yet it shows the concept. Instead of waiting for the program to release the lock (default behaviour with “setlock”), you can script a small loop that comes back after a few seconds. Yet you have to setup the locking mechanism in a manner that it won’t wait for the lock (option -n for “setlock”).

    SUME="bash -c "
    SETLOCK="path-to-setlock"
    EXECUTE="your-script"
    PARAMETERS="your-parameters"
    ID="your-unique-id-for-locking"
    # usage of a control structure with non-wait locking
    # this is done to avoid locking issues ^^
    var0=0
    LIMIT=3
    SNOOZE=5
    while [ "$var0" -lt "$LIMIT" ]
    do
      var0=`expr $var0 + 1`
      eval $SUME \"$SETLOCK -n $TMPDIR/lock_$ID $EXECUTE $PARAMETERS 2>/dev/null \"  2>/dev/null
      EC=$?
      if [ $EC -eq 0 ] ; then
         var0=`expr $LIMIT + 1`
      else
         sleep $SNOOZE
      fi
    done
    exit $EC
    Comments
    No Comments »
    Categories
    Bash, Unix/Linux
    Comments rss Comments rss
    Trackback Trackback
    1 Star2 Stars3 Stars4 Stars5 Stars (No Ratings Yet)
    Loading ... Loading ...

    « Previous Entries Next Entries »

    Recent Posts

    • Treating the root cause to cancer
    • Is “entrepreneur” a bad word?
    • Where physics meets marketing
    • Where USSR meets IT?
    • Accepting our limitations, is giving us the opportunity to overcome them!

    Similar Posts

    • my own setlock source code
    • bash : locking issues – example with setlock
    • Business modelling in lesser times…
    • bash getopts
    • Protecting your Laptop, or better finding the thief!

    Recent Comments

    • dailyhowto on WordPress widget : Most popular posts
    • Karim Vaes on Accept every offer!
    • Danny on The teachings of Budo in Business
    • Pascal on The Service Catalog
    • Shubert on WordPress widget : Most popular posts

    Commercial

    Categories

    2.0 Ads Agile Bash Blogroll Book Brain Business Career Change CIO Collaboration Communication Corner Creative CRM Culture Desktop Development Dreambox Drupal Education Entrepreneur F5 Firefox Food Freelance Fun General Green Growth High Availability Human Resources Idea Infrastructure Insightful Interesting IT ITIL Java Lesson License Life Malware Management Mind Model Motivation MythTV Network NLP OpenSource Performance PHP PM Presentation Project Proverb Quote Remote Scrum Security SEO Social Spam Storage Stress Tactical Team Tech TED Time Management Tip Tool TV Ubuntu Unix/Linux Vids Vim Virtual VmWare Voip Web Wordpress

    Archives

    • August 2010
    • July 2010
    • May 2010
    • April 2010
    • January 2010
    • December 2009
    • November 2009
    • October 2009
    • August 2009
    • July 2009
    • June 2009
    • April 2009
    • March 2009
    • February 2009
    • January 2009
    • December 2008
    • November 2008
    • October 2008
    • September 2008
    • August 2008
    • July 2008
    • June 2008
    • May 2008
    • April 2008
    • March 2008
    • February 2008
    • January 2008
    • December 2007
    • November 2007
    • October 2007
    • September 2007
    • August 2007
    • July 2007
    • June 2007
    • May 2007
    • April 2007
    rss Comments rss valid xhtml 1.1 design by jide licensed as Creative Commons Attribution