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));
}







Recent Comments