#!/bin/sh exec ${PERL-perl} -wSx $0 ${1+"$@"} #!perl # rlock --- acquire locked checkout of RCS-controlled file # Author: Noah Friedman # Created: 2001-11-18 # Public domain # $Id: rlock,v 2.1 2001/12/04 12:24:43 friedman Exp $ # Commentary: # This program encapsulates the task of checking out an RCS-controlled file # with an exclusive lock. The exit status from this script can be used by # the caller to determine whether the lock was successfully acquired. # Note that a lock will not be considered to be acquired if the working # file is already writable, even if it is writable by the same uid as the # caller of this script (another process might have the lock). # Code: use Getopt::Long; use Symbol; use strict; my $verbose = 0; my $progname = $0; $progname =~ s|.*/||; sub verbose (;@) { print $progname, ": ", join (": ", @_), "\n" if ($verbose); } sub message (;@) { return unless $verbose; my $prefix = shift; my $msg = join (" ", @_); $msg =~ s/^/$prefix: /mg; $msg =~ s/^([^:]+: )\1/$1/mg; print $msg; } sub errmsg (;@) { print STDERR join (": ", $progname, @_), "\n"; return undef; } sub spawn (@) { my ($orh, $owh) = (gensym, gensym); pipe ($orh, $owh); my $pid = fork; if ($pid == 0) { open (STDIN, "&=" . fileno ($owh)); open (STDERR, ">&=" . fileno ($owh)); close ($orh); close ($owh); exec (@_) || 0; # boolean avoids warning about unreachable statements errormsg ("exec", $_[0], $!); exit (1); } else { close ($owh); my $result = join ("", <$orh>); wait; my $exitstat = $? >> 8; close ($orh); message ($_[0], $result); return $exitstat; } } sub co ($) { return spawn ("co", "-l", shift); } sub revert ($) { my $file = shift; verbose ($file, "reverting RCS lock"); return spawn ("ci", "-u", $file); } sub rlock ($$) { my ($option, $file) = @_; my $result; my $try = 0; while (1) { $result = co ($file); if ($result == 0) { verbose ($file, "RCS lock obtained successfully"); return $result; } last if (++$try >= $option->{retry_count}); verbose ("Waiting $option->{retry_interval} seconds..."); sleep ($option->{retry_interval}); } verbose ($file, "RCS lock could not be obtained") if ($result != 0); return $result; } sub parse_options () { my %option = ( verbose => 0, retry_count => 3, retry_interval => 10, ); Getopt::Long::config ('bundling', 'autoabbrev'); GetOptions ("v|verbose", \$option{verbose}, "c|retry-count=i", \$option{retry_count}, "i|retry-interval=i", \$option{retry_interval}, "h|help", \&usage); return \%option; } sub usage (@) { errmsg (@_) if (@_); print STDERR "Usage: $progname {options} file\n Options are: -h, --help You're looking at it. -v, --verbose Display output from RCS \`co' command. -c, --retry-count COUNT If file is already locked, wait for a time and try again no more than COUNT times until lock succeeds. Default is 3 times. -i, --retry-interval SEC If file is already locked, wait SEC seconds and try again. Default is 10 seconds. Program exits with a status of 0 (success) if file was successfully locked. Program exits with a status of 1 (error) if lock could not be obtained on file.\n"; exit (1); } sub main () { my $option = parse_options (); $verbose = $option->{verbose}; usage ("Filename argument required") unless (@ARGV); my $result = rlock ($option, $ARGV[0]); exit ($result); } main (); # local variables: # mode: perl # eval: (auto-fill-mode 1) # end: # rlock ends here