home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / languages / perl / tutorial / eg / now-what < prev    next >
Encoding:
Text File  |  1990-03-11  |  10.8 KB  |  488 lines

  1. #!/usr/bin/perl
  2.  
  3. ($program = $0) =~ s,.*/,,;
  4.  
  5. $| = 1;
  6.  
  7. &source('sys/ioctl.pl');
  8.  
  9.  
  10. @SW = ( '-draftmessage draftmessage',
  11.               '-draftfolder +folder',
  12.               '-nodraftfolder',
  13.               '-editor editor',
  14.               '-noeditor',
  15.               '-prompt prompt',
  16.               '-help'
  17.       );
  18.  
  19.  
  20. %cmds = (
  21.     ' ',    'help',
  22.     "\n",    'help',
  23.     '?',    'help',
  24.     'E',    'switch-editor',
  25.     'L',    'display-alternate',
  26.     'Q',    'quit-delete',
  27.     's',    'spell',
  28.     'd',    'quit-delete',
  29.     'e',    'edit',
  30.     'h',    'header',
  31.     't',    'type',
  32.     'l',    'list',
  33.     'p',    'push',
  34.     'q',    'quit',
  35.     'r',    'refile',
  36.     'S',    'send',
  37.     'w',    'whom',
  38.     'W',    'watch',
  39.     'y',    'syslog',
  40.     '!',    'shell'    
  41. );
  42.  
  43. #print "args are $0 $ARGS\n";
  44. #print "environment:\n";
  45. #for $key ( sort grep(/^[a-z]+$/, keys %ENV)) {
  46.     #printf "\t%%-12s = %s\n", $key, $ENV{$key};
  47. #} 
  48.  
  49. if ($ENV{'mhaltmsg'}) {
  50.     unlink '@';
  51.     symlink($ENV{'mhaltmsg'}, '@'); 
  52.     $linked = 1;
  53. }
  54.  
  55. while (($cmd, $fun) = each %cmds) {
  56.     $fun =~ s/-/_/g;
  57.     if (eval "!defined &$fun") {
  58.     print $program, ": warning: key `", $cmd, 
  59.         "' bound to undefined function `",$fun, "'\n";
  60.     } 
  61.  
  62. ($draftmessage = $ENV{'mhdraft'});
  63.  
  64. &mh_profile; 
  65.  
  66. if ($MH{$program}) {
  67.     unshift(@ARGV,split(' ',$MH{$program}));
  68. }
  69.  
  70. &mh_parse;
  71.  
  72. if ($MH{'msg-protect'}) {
  73.     $mask = oct($MH{'msg-protect'});
  74.     umask (~$mask & 0777);
  75.  
  76. die "$program: only one draft at a time!\n" 
  77.     if $#ARGV > 0;
  78.  
  79. $draftmessage = shift if $#ARGV == 0;
  80.  
  81. ($editor = $SW{'editor'}) || 
  82. ($editor = $ENV   {'mheditor'})  ||
  83. ($editor = $MH    {'editor'}) || 
  84. ($editor = $ENV   {'EDITOR'}) ||
  85. ($editor = 'vi');
  86.  
  87. ($pager = $MH{'listproc'})  ||
  88. ($pager = $ENV{'PAGER'})    ||
  89. ($pager = 'more');
  90.  
  91. $SW{'nodraftfolder'} ||
  92.     ($draftfolder = $SW{'draftfolder'}) || 
  93.     ($draftfolder = $MH    {'draft-folder'});
  94.  
  95. $SW{'noeditor'} = 1 unless $draftmessage;
  96.  
  97. if ($draftfolder) {
  98.     $draftmessage = &mhpath($draftfolder, 
  99.         $SW{'draftmessage'} ? $SW{'draftmessage'} : 'last')
  100.         unless $draftmessage;
  101. } else {
  102.     $draftmessage = $MH{'path'} . '/' . 'drafts'
  103.         unless $draftmessage;
  104.  
  105. $SIG{'TERM'} = 'quit';
  106.  
  107. &edit unless $SW{'noeditor'};
  108.  
  109. $prompt = 'What now' unless $prompt = $SW{'prompt'};
  110.  
  111. $SIG{'CONT'} = 'continue';
  112.  
  113. for (;;) {
  114.     print "\n$prompt? ";
  115.     $cmd = &readtty;
  116.     ($fun = $cmds{$cmd}) =~ s/-/_/g;
  117.     if (defined $cmds{$cmd}) {
  118.     if (eval "defined &$fun") {
  119.         print $cmds{$cmd}, "\n";
  120.         &$fun;
  121.     } else {
  122.         print "$program: can't call undefined subroutine $fun\n";
  123.     }
  124.     } else {
  125.     printf "$cmd -- unknown command: `%s' (0x%02x)\n", $cmd, ord($cmd);
  126.     } 
  127.  
  128. exit (0);
  129.  
  130.  
  131. # ----------------------------------------------------------------------
  132. sub mh_parse {
  133.     local(@argdesc) =  @SW;
  134.     local($wantarg);
  135.  
  136.     grep(s/(\W)/\\$1/g, @argdesc);
  137.  
  138.     while ($ARGV[0] =~ /^-.+/) {
  139.     $ARGV = shift @ARGV;
  140.  
  141.     unless (@matches = grep(/$ARGV/, @argdesc)) {
  142.         print "$program: unknown option: $ARGV\n";
  143.         exit 1;
  144.         &usage;
  145.     } 
  146.  
  147.     for (@matches) { s/\\(\W)/$1/g; } 
  148.  
  149.     if ($#matches > $[) {
  150.         print "$program: ambiguous switch $ARGV matches:\n";
  151.         for (@matches) { 
  152.         print "\    ", $_, "\n"; 
  153.         }
  154.         exit 1;
  155.     } 
  156.  
  157.     ($switch,$wantarg) = $matches[$[] =~ /^-(\S+)\s*(\S*)/;
  158.  
  159.     $SW{$switch} = $wantarg ? shift @ARGV : 1;
  160.     if ($SW{$switch} =~ /^(['"]).*$/ && $SW{$switch} !~ /^(['"]).*\1$/) {
  161.         do {
  162.         $SW{$switch} .= ' ' . (shift @ARGV);
  163.         } until $#ARGV < 0 || $SW{$switch} =~ /^(['"]).*\1$/;
  164.         $SW{$switch} =~ s/^(['"])(.*)\1$/$2/;
  165.     } 
  166.     }
  167. }
  168.  
  169. # ----------------------------------------------------------------------
  170. sub source {
  171.     local($file) = @_;
  172.     local($return) = 0;
  173.  
  174.     $return = do $file;
  175.     die "couldn't do \"$file\": $!" unless defined $return;
  176.     die "couldn't parse \"$file\": $@" if $@;
  177.     die "couldn't run \"$file\"" unless $return;
  178.  
  179. # ----------------------------------------------------------------------
  180. sub usage {
  181.     # global $SW
  182.     $pos = 0;
  183.  
  184.     print "syntax: $0 [switches] [files]\n   switches are:\n    ";
  185.     $pos = 4;
  186.  
  187.     for (@SW) {
  188.     if (($pos += length) > 80)  {
  189.         print "\n    ";
  190.         $pos = 4 + length;
  191.     } 
  192.     print $_, " ";
  193.     $pos++;
  194.     } 
  195.     print "\n";
  196.     exit(1);
  197.  
  198. # ----------------------------------------------------------------------
  199. sub mh_profile {
  200.     local($PROFILE);
  201.  
  202.     ($PROFILE = $ENV{"MH"}) || ($PROFILE = $ENV{"HOME"} . "/.mh_profile");
  203.  
  204.     open PROFILE || "$0: can't read mh_profile $PROFILE: $!\n";
  205.  
  206.     while (<PROFILE>) {
  207.     next if /^#/;
  208.     next unless ($key, $value) = /([^:\s]+):\s*(.+)/;
  209.     $key =~ tr/A-Z/a-z/;
  210.     $MH{$key} = $value;
  211.     } 
  212.     close PROFILE;
  213.     $MH{'path'} = $ENV{'HOME'} . '/' . $MH{'path'};
  214.  
  215. # ----------------------------------------------------------------------
  216. sub mhpath {
  217.     local($folder, $msg) = ($_[0], $_[1]);
  218.     local($biggest) = 0;
  219.  
  220.     $folder =~ s/^\+//;
  221.  
  222.     $folder = $MH{'path'} . '/' . $folder 
  223.     unless $folder =~ m!^/!;
  224.  
  225.     if (-d $folder) {
  226.     if ($msg eq 'new' || $msg eq 'last') {
  227.         opendir(FOLDER, $folder) 
  228.         || die "$program: can't opendir $folder: $!\n";
  229.         while ($msg = readdir(FOLDER)) {
  230.         next unless $msg =~ /^\d+$/;
  231.         $biggest = $msg if $msg > $biggest;
  232.         } 
  233.         closedir FOLDER;
  234.         $msg = $biggest + (($msg eq 'new') ? 1 : 0);
  235.     } 
  236.     } else {
  237.     if (-t) {{
  238.         print "Create folder \"$folder\"? ";
  239.         chop($answer = <STDIN>);
  240.         last     if 'yes' =~ /^$answer/i;
  241.         &exit(0)    if 'no' =~ /^$answer/;
  242.         print "$answer: unknown response\n";
  243.         redo;
  244.     }}
  245.     if (defined $MH{'folder-protect'}) {
  246.         $mode = oct($MH{'folder-protect'});
  247.     } else {
  248.         $mode = 0755;
  249.     } 
  250.     mkdir($folder,$mode) || die "program: can't mkdir $folder: $!\n";
  251.     } 
  252.  
  253.     $folder . '/' . $msg;
  254.  
  255. # ----------------------------------------------------------------------
  256. sub readtty {
  257.     local($cmd);
  258.     &cbreak;
  259.     $cmd = getc(STDIN);
  260.  
  261.  
  262. # ----------------------------------------------------------------------
  263. sub continue { 
  264.     print "$prompt? ";
  265.     &cbreak; 
  266. }
  267.  
  268. # ----------------------------------------------------------------------
  269. sub cbreak {
  270.     &set_cbreak(1);
  271.  
  272. # ----------------------------------------------------------------------
  273. sub cooked {
  274.     &set_cbreak(0);
  275.  
  276. # ----------------------------------------------------------------------
  277. sub set_cbreak {
  278.     local($on) = $_[0];
  279.     local($sgttyb);
  280.  
  281.     $sgttyb_t   = 'C4 S' unless $sgttyb_t;
  282.  
  283.     ioctl(STDIN,$TIOCGETP,$sgttyb) 
  284.     || die "Can't ioctl TIOCGETP: $!";
  285.  
  286.  
  287.     @ary = unpack($sgttyb_t,$sgttyb);
  288.     if ($on) {
  289.     $ary[4] |= $CBREAK;
  290.     $ary[4] &= ~$ECHO;
  291.     } else {
  292.     $ary[4] &= ~$CBREAK;
  293.     $ary[4] |= $ECHO;
  294.     }
  295.     $sgttyb = pack($sgttyb_t,@ary);
  296.     ioctl(STDIN,$TIOCSETP,$sgttyb)
  297.         || die "Can't ioctl TIOCSETP: $!";
  298.  
  299. }
  300.  
  301. # ----------------------------------------------------------------------
  302. sub help {
  303.     print "Key\tRoutine\n";
  304.     for $key (sort keys %cmds) {
  305.     next if $key =~ /\s/;
  306.     $fun = $cmds{$key};
  307.     $fun =~ s/_/-/g;
  308.     print "$key\t$fun\n";
  309.     }
  310.  
  311. # ----------------------------------------------------------------------)
  312. sub quit {
  313.     $SIG{'TTOU'} = "IGNORE";
  314.     print "$program: draft left on $draftmessage\n"
  315.     if -e $draftmessage;
  316.     &cooked;
  317.     &exit(0);
  318.  
  319. sub exit {
  320.     unlink '@' if $linked;
  321.     exit $_[0];
  322. # ----------------------------------------------------------------------
  323. sub edit {
  324.     local($status, $sigs, $next);
  325.     $status = &run($editor,$draftmessage);
  326.     $sigs = $status & 0xff;;
  327.     $status >>= 8;
  328.     if ($status == 255) {
  329.     print "$program: couldn't exec $editor: $!\n";
  330.     return $status;
  331.     } 
  332.     $editor = $next if $next = $MH{$editor.'-next'};
  333.     return 0 unless $status;
  334.     print "$program: problems with edit--$draftmessage ", 
  335.     $sigs ? "preserved" : "deleted", ".\n" if $status;
  336.     unlink $draftmessage if $status && !$sigs;
  337.     exit 1;
  338.  
  339. # ----------------------------------------------------------------------
  340. sub switch_editor {
  341.     local($neweditor);
  342.     if ($neweditor = &prompt('New editor')) { 
  343.     $editor = $neweditor;
  344.     &edit;
  345.     } else {
  346.     print "(editor still $editor)\n";
  347.     } 
  348.  
  349. # ----------------------------------------------------------------------
  350. sub list {
  351.     &run($pager,$draftmessage);
  352.  
  353. # ----------------------------------------------------------------------
  354. sub intr { } 
  355. sub run {
  356.     local(@cmd);
  357.     $SIG{'INT'} = $SIG{'QUIT'} = 'intr';
  358.     &cooked;
  359.     @cmd = split(' ',"@_");
  360.     $status = system @cmd;
  361.     &cbreak;
  362.     $mystat = ($status >> 8) & 0xff;
  363.     if ($mystat == 0xff) {
  364.     print "$program: couldn't run \"@_\": $!\n";
  365.     } else {
  366.     print "$program: \"@_\" returned $mystat\n"
  367.         if $mystat;
  368.     } 
  369.     $SIG{'INT'} = $SIG{'QUIT'} = 'DEFAULT';
  370.     return $status;
  371.  
  372.  
  373. # ----------------------------------------------------------------------
  374. sub quit_delete {
  375.     unlink($draftmessage) 
  376.     || warn "$program: unable to unlink $draftmessage: $!\n";
  377.     &quit;
  378.  
  379. # ----------------------------------------------------------------------
  380. sub push {
  381.     &exit(&run('send','-push', $draftmessage));
  382.  
  383. # ----------------------------------------------------------------------
  384. sub refile {
  385.      local($folder);
  386.      return unless $folder = &prompt("Refile into");
  387.      &run('refile',$folder);
  388.  
  389. # ----------------------------------------------------------------------
  390. sub send {
  391.     &exit(&run('send',$draftmessage));
  392.  
  393. # ----------------------------------------------------------------------
  394. sub spell {
  395.     local($spell) = $MH{'spellproc'};
  396.     $spell = 'spell' unless $spell;
  397.     &run($spell, $draftmessage);
  398.  
  399. # ----------------------------------------------------------------------
  400. sub display_alternate {
  401.     local($alt) = $ENV{'mhaltmsg'};
  402.     if (! $alt) {
  403.     print "No alternate message to display\n";
  404.     } else {
  405.     &run($pager,$alt);
  406.     } 
  407.  
  408. # ----------------------------------------------------------------------
  409. sub prompt {
  410.     local($prompt) = $_[0];
  411.     local($retval);
  412.     &cooked;
  413.     print "$prompt? ";
  414.     chop($retval = <STDIN>);
  415.     return $retval;
  416.  
  417. # ----------------------------------------------------------------------
  418. sub whom {
  419.     &run('whom', $draftmessage);
  420.  
  421. # ----------------------------------------------------------------------
  422. sub watch {
  423.     &exit(&run('send -nopush -watch -verbose', $draftmessage));
  424.  
  425. # ----------------------------------------------------------------------
  426. sub syslog {
  427.     &run('tail -f /usr/spool/mqueue/syslog');
  428.  
  429. # ----------------------------------------------------------------------
  430. sub header {
  431.     if (!open draftmessage) {
  432.     warn "$program: no $draft message\n";
  433.     return;
  434.     } 
  435.     while (<draftmessage>) {
  436.     last if /^-*$/;
  437.     print;
  438.     } 
  439.     close draftmessage;
  440.  
  441. # ----------------------------------------------------------------------
  442. sub type {
  443.     if (!open draftmessage) {
  444.     warn "$program: no $draft message\n";
  445.     return;
  446.     } 
  447.  
  448.     print while <draftmessage>;
  449.  
  450.     close draftmessage;
  451.  
  452. # ----------------------------------------------------------------------
  453. sub shell {
  454.     local($cmd);
  455.     return unless $cmd = &prompt('Shell command');
  456.     &run($cmd);
  457.