dotfiles/bin/motdedit
michener 83d40113d2 First import
git-svn-id: http://photonzero.com/dotfiles/trunk@1 23f722f6-122a-0410-8cef-c75bd312dd78
2007-03-19 06:17:17 +00:00

184 lines
4.6 KiB
Perl
Executable file
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/local/bin/perl
#
# DESC:
# Program is used to sychronize write access to public motd file.
# Program acquires advisory exclusive lock, then brings up editor
# to edit file. On return from editor, motd file will be unlocked.
# If program cannot acquire exclusive lock, it prints out the current
# user holding exclusive lock.
#
# WRITTEN BY:
# Andrew Choi
# Fixed by:
# Ben Scott
# Arvin Hsu
use strict;
use Fcntl ':flock';
use Errno;
use Getopt::Std;
use File::Copy;
my $motd = "/etc/motd.public";
my $motdbackup = "/tmp/motd.public.b.$>.$$"; # EUID + PID
my $motdcurrent = "/tmp/motd.public.r.$>.$$"; # EUID + PID
my $motdtemp = "/tmp/motd.public.t.$>.$$"; # EUID + PID
my $motdmerged = "/tmp/motd.public.m.$>.$$"; # EUID + PID
$motd = "/csua/tmp/motd.kinney" if (getpwuid($<))[0] eq 'kinney';
my $editor = $ENV{MOTDEDITOR};
$editor ||= $ENV{VISUAL};
$editor ||= $ENV{EDITOR};
$editor ||= "/usr/bin/ed";
my %opt;
$opt{t} = 600;
getopts("mnst:h?",\%opt);
&Usage if $opt{h};
## Set environment vars for vi users
## Thanks, jon.
$ENV{NEXINIT} ||= $ENV{EXINIT};
unless ( $ENV{NEXINIT} ) {
unless (open (EXRC,"$ENV{HOME}/.nexrc")) {
unless (open (EXRC,"$ENV{HOME}/.exrc")) {
$ENV{NEXINIT} = "set nolock";
}
}
unless ($ENV{NEXINIT}) {
($ENV{NEXINIT} = join ("",<EXRC>)) && close EXRC;
}
}
$ENV{NEXINIT} .= "\nset nolock\n";
# Set alarm for being locked too damn long
$SIG{ALRM} = \&Unlock;
alarm $opt{t};
# Open file as append so that lock can be used on it
open(M, "$motd") || die "open $motd: $!";
# Lock file. If success, execute edit command and exit
flock(M, LOCK_EX|LOCK_NB);
if ($!{EWOULDBLOCK}) {
if ($opt{n}) {
print "Motd currently locked. Editing anyways.";
&Edit;
}
else {
flock (M, LOCK_UN);
print "Motd currently locked\nWait to acquire lock [y/N] ";
chomp(my $ans = <>);
if ($ans =~ /^y$/i) {
flock(M, LOCK_EX);
&Edit;
}
}
} else {
&Edit;
}
close M;
system "/csua/bin/mtd";
exit 0;
sub Unlock {
flock(M, LOCK_UN);
print
"\r*** MOTD GOD PRONOUNCES: *** \r\n*** You have locked the motd for too long, you idle hoser... *** \r\n*** Your lock has been removed. *** \r\n";
}
sub Usage {
print STDERR
"$0 Edit /etc/motd.public with locking and merge.
Usage: $0 [-m] [-s] [-t n]
-t n Set timeout for releasing lock to n seconds (default $opt{t})
-m Turns auto-merging off.
-s If merge fails, will stomp over other changes.
-n Does not wait for lock before allowing edit.
(the other person may overwrite your post)
";
exit 2;
}
sub Edit {
alarm $opt{t};
print "";
#check if merge option is desired
if (!$opt{m}) {
copy($motd,$motdbackup);
copy($motd,$motdcurrent);
my $lastmodtime = (stat($motd))[9];
system("$editor $motdcurrent");
my $currmodtime = (stat($motd))[9];
if ($currmodtime > $lastmodtime) {
&Merge;
}
else {
copy($motdcurrent,$motd);
}
unlink </tmp/motd.public.*>;
}
else {
system("$editor $motd");
}
}
# Attempts to auto-merge using "merge, diff -c | patch, diff | patch"
# If auto-merge fails, allows manual merge
# Saves final version as $motd
sub Merge {
copy($motd,$motdmerged);
system("merge -p -q -L \"Other Changes Below\" -L \"Original MOTD\" -L \"Your Changes Above\" $motd $motdbackup $motdcurrent > $motdtemp");
# Check to see if merge failed. if fail, try diff -c | patch
if (($? >> 8) > 0) {
system("diff -c $motdbackup $motdcurrent | patch -s -f $motdmerged 2> /dev/null");
# Check to see if diff -c | patch, if fail, try diff | patch
if (($? >> 8) > 0) {
system("diff $motdbackup $motdcurrent | patch -s -f $motdmerged 2> /dev/null");
# If everything has failed, put the merge notation in, and let the user edit.
if (($? >> 8) > 0) {
if ($opt{s}) {
copy($motdcurrent,$motdmerged);
}
else {
print "CONCURRENT CHANGES\r\nAll merge & patch attempts have failed.\r\nMerge Manually? [y/n]";
chomp(my $answ = <>);
if ($answ =~ /^y$/i) {
copy($motdtemp,$motdcurrent);
copy($motd,$motdbackup);
my $lastmodtime = (stat($motd))[9];
system("$editor $motdcurrent");
my $currmodtime = (stat($motd))[9];
if ($currmodtime > $lastmodtime) {
&Merge;
}
else {
copy($motdcurrent,$motdmerged);
}
}
else {
print "Stomp on other people's changes? [y/n]";
chomp(my $answ = <>);
if ($answ =~ /^y$/i) {
copy($motdcurrent,$motdmerged);
}
}
}
}
}
}
else {
# Merge was successful, copy it over.
copy($motdtemp,$motdmerged);
}
copy($motdmerged,$motd);
}