#!/usr/bin/perl -w # # $Id: blog,v 1.7 2008/01/19 22:31:03 vogelke Exp $ # # Original by Simon Cozens # http://simon-cozens.org/programmer/releases/secret/blog # # Read STDIN if anything is on it, store in properly-named file. # Optional first arg is subject; default is 'New post'. # Changing the "Date:" line will change the post timestamp. use strict; use File::Temp qw/tempfile/; use English; $ENV{'PATH'} = "/bin:/usr/bin:/usr/local/bin:$ENV{'HOME'}/bin"; umask(022); my ($in, $fh, $entry); ($fh, $entry) = tempfile(); my $subject = join(' ', @ARGV) || "New post"; my $date = scalar localtime(time); print $fh "To: vogelke-blog\n"; print $fh "Subject: $subject\n"; print $fh "Date: $date\n\n"; print $fh "Posting starts here.\n"; # If anything is coming in via STDIN, use it. if (!interactive()) { open($in, "<&STDIN") or die "can't read stdin: $!\n"; print $fh while <$in>; close($in); } close($fh); system("vim", $entry); # If the file is empty, dump it. my $size = -s $entry; if (defined($size) && $size <= 1) { unlink($entry) if defined($size) && $size <= 1; print "discarding\n"; } else { unlink($entry) if sendmail($entry); } exit(0); #--------------------------------------------------------------------- # Test for STDIN being something other than a TTY. # Taken from "Perl Best Practices", p219. There's a CPAN module # to do this, but Scalar::Util comes standard with perl. sub interactive { use Scalar::Util qw(openhandle); # Not interactive if output is not to terminal... return 0 if not -t *STDOUT; # If *ARGV is opened, we're interactive if... if (openhandle * ARGV) { # ...it's currently opened to the magic '-' file return -t *STDIN if $ARGV eq '-'; # ...it's at end-of-file and the next file is the # magic '-' file return @ARGV > 0 && $ARGV[0] eq '-' && -t *STDIN if eof *ARGV; # ...it's directly attached to the terminal return -t *ARGV; } # If *ARGV isn't opened, it will be interactive if *STDIN is # attached to a terminal and either there are no files specified # on the command line or if there are one or more files and the # first is the magic '-' file. return -t *STDIN && (@ARGV == 0 || $ARGV[0] eq '-'); } #--------------------------------------------------------------------- # Send file via mail. sub sendmail { my ($file) = @_; my @command = ("/usr/lib/sendmail", "-t"); my $sleep_count = 0; my $sleep_time = 3; my $pid; do { $pid = open(KID_TO_WRITE, "|-"); unless (defined $pid) { warn "cannot fork: $!"; die "bailing out" if $sleep_count++ > 6; sleep $sleep_time; } } until defined $pid; $SIG{ALRM} = sub { die "whoops, $command[0] pipe broke" }; if ($pid) { # parent my $ofh; open($ofh, "< $file") or die "can't read $file: $!\n"; print KID_TO_WRITE while <$ofh>; close($ofh); if (close(KID_TO_WRITE)) { return (1); } else { warn "kid exited $?"; return (0); } } else { # child ($EUID, $EGID) = ($UID, $GID); my $program = shift(@command); exec($program, @command) || die "can't exec $program: $!"; # NOTREACHED } }