home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / misc / volume35 / plod / part01 < prev    next >
Encoding:
Text File  |  1993-02-21  |  34.8 KB  |  1,129 lines

  1. Newsgroups: comp.sources.misc
  2. From: pomeranz@nas.nasa.gov (Hal R. Pomeranz)
  3. Subject: v35i085:  plod - keep track of the work you do, Part01/01
  4. Message-ID: <1993Feb22.042811.15797@sparky.imd.sterling.com>
  5. X-Md4-Signature: df218d063530789e86026e284721b05a
  6. Date: Mon, 22 Feb 1993 04:28:11 GMT
  7. Approved: kent@sparky.imd.sterling.com
  8.  
  9. Submitted-by: pomeranz@nas.nasa.gov (Hal R. Pomeranz)
  10. Posting-number: Volume 35, Issue 85
  11. Archive-name: plod/part01
  12. Environment: Perl
  13.  
  14. PLOD is a Perl program designed to help folks keep a record of the
  15. work they do.  Good journals help you solve recurring problems more
  16. quickly and impress the hell out of management around performance
  17. review time.
  18.  
  19. The interface for PLOD looks a lot like Berkeley mail (tilde escapes
  20. and all).  There's tons of customization switches, so check out
  21. the documentation.  An Emacs mode for PLOD is also included.
  22.  
  23. ===============================================================================
  24. Hal Pomeranz     Senior Member of Technical Staff     NASA Ames Research Center
  25.          pomeranz@nas.nasa.gov     pomeranz@cs.swarthmore.edu
  26. "I sit and stare with hardened eyes through a time when life's so hard."  --L&O
  27. ===============================================================================
  28.  
  29. #! /bin/sh
  30. # This is a shell archive.  Remove anything before this line, then unpack
  31. # it by saving it into a file and typing "sh file".  To overwrite existing
  32. # files, type "sh file -c".  You can also feed this as standard input via
  33. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  34. # will see the following message at the end:
  35. #        "End of shell archive."
  36. # Contents:  README plod plod.man plod.el
  37. # Wrapped by pomeranz@irving on Wed Feb  3 10:10:30 1993
  38. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  39. if test -f README -a "${1}" != "-c" ; then 
  40.   echo shar: Will not over-write existing file \"README\"
  41. else
  42. echo shar: Extracting \"README\" \(3586 characters\)
  43. sed "s/^X//" >README <<'END_OF_README'
  44. XPLOD is a tool designed to help administrators (and others) keep track
  45. Xof their daily activities.  Since your management will typically have
  46. Xno idea what you are doing to justify such an exorbitant salary (any
  47. Xamount of money they may be paying you being classified as
  48. X"exorbitant"), and since most people forget what they do themselves,
  49. Xit's good to keep a record.  Trot your logs out around performance
  50. Xreview time, and show them to your management (after suitable
  51. Xsanitization) on a regular basis.
  52. X
  53. XThe interface is designed to make it quick to dash off a simple note
  54. Xto yourself.  Since most folks who are going to use PLOD also use
  55. Xemail, I've based the interface on Berkeley mail-- tilde escapes and
  56. Xall (for a list of escapes, try ~h or ~?).  By default, your logs will
  57. Xbe encrypted using the /bin/crypt command-- not secure in the least,
  58. Xbut marginally safe from casual browsing (I tend to vent into my logs
  59. Xsometimes rather than at those who might be offended and fire me).
  60. XYou can turn off the encryption if you find it more a hassle than a
  61. Xcomfort.
  62. X
  63. XWhich brings us to the subject of customization.  Many escape
  64. Xsequences and variables have already been defined, but you can make
  65. Xyour own changes using your ~/.plodrc file.  This file is interpreted
  66. Xusing eval(), so any valid Perl syntax is acceptable.  Variables may
  67. Xbe customized by editing this script directly, setting an environment
  68. Xvariable with the same name as the PLOD variable, or by doing an
  69. Xassignment in your .plodrc (.plodrc value supersedes environment value
  70. Xwhich beats default value in script).  New tilde escapes may be
  71. Xdefined by assigning a type glob, say *foo, to the global array
  72. X%funcs-- the index of the type glob in the array being the character
  73. X(single chars only!) of the escape sequence.  &foo should be a
  74. Xfunction which performs the escape (any arguments after the escape are
  75. Xpassed in as a single string in @_), and $foo can be a descriptive
  76. Xhelp string (see &helpuser()).  Your functions may reference any of
  77. Xthe PLOD customization variables as well as the list @lines, which
  78. Xcontains all information in the current log entry (including the
  79. Xdate/time stamp PLOD adds to the beginning of each entry).  For
  80. Xexamples, consult the PLOD source code or the manual page.
  81. X
  82. XPLOD is a living, growing entity.  If you have suggestions for
  83. Ximprovements or new features, or find any bugs, please send them to me
  84. Xvia email.  Share and enjoy!
  85. X
  86. XHal Pomeranz, pomeranz@nas.nasa.gov
  87. X
  88. X===============================================================================
  89. X
  90. XHistory:
  91. X
  92. Xv1.0 (Original release to comp.lang.perl)
  93. X
  94. X
  95. Xv1.1 (Second release to comp.lang.perl)
  96. X** &pipetocmd() unlinks all temporary files it creates (Pomeranz)
  97. X
  98. X** Variable assignment idiom cleaned up (Rantapaa)
  99. X
  100. X** LOGDIR and HOME are only prepended to LOGFILE and DEADLOG after
  101. X   .plodrc has been eval-ed and if LOGFILE and DEADLOG are relative
  102. X   paths.  This means that you can change LOGDIR in your .plodrc and
  103. X   really affect where the log files go. (Rantapaa)
  104. X
  105. X** eval of .plodrc is done with "do" rather than "cat" (Rantapaa)
  106. X
  107. X** You can now do quick one-liner entries on the command line, e.g.
  108. X   "plod Completed modifications to PLOD" (Rantapaa)
  109. X
  110. X** Time/date stamp only printed if user is entering info directly from
  111. X   a tty (Rantapaa)
  112. X
  113. X** PLOD attempts to create logging directory if it does not exist (Ellis)
  114. X
  115. X
  116. Xv1.2 (not publicly released)
  117. X** Page/Edit/Visual log files from interactive mode or from the shell
  118. X   (Tizard)
  119. X
  120. X
  121. Xv1.3 (current release)
  122. X** Multi-line Perl input function, ~M (Crabb)
  123. X
  124. X** Manual page generated (Pomeranz)
  125. END_OF_README
  126. if test 3586 -ne `wc -c <README`; then
  127.     echo shar: \"README\" unpacked with wrong size!
  128. fi
  129. # end of overwriting check
  130. fi
  131. if test -f plod -a "${1}" != "-c" ; then 
  132.   echo shar: Will not over-write existing file \"plod\"
  133. else
  134. echo shar: Extracting \"plod\" \(15636 characters\)
  135. sed "s/^X//" >plod <<'END_OF_plod'
  136. X#!/usr/bin/perl
  137. X#
  138. X#    PLOD-- Personal LOgging Device, v1.3
  139. X#    Copyright (C), 1993, Hal Pomeranz (pomeranz@nas.nasa.gov)
  140. X#    All rights reserved.  No warranty expressed or implied.
  141. X#    PLOD is freely distributable under the same terms as Perl.
  142. X#    Inspired by Bill Mendyka (mendyka@dg-rtp.dg.com)
  143. X#    Suggestions/Bugfixes: 
  144. X#       David W Crabb (crabb@phoenix.Princeton.EDU)
  145. X#    John Ellis (ellis@rtsg.mot.com)
  146. X#    Erik E. Rantapaa (rantapaa@math.umn.edu)
  147. X#    James Tizard (james@ringo.ssn.flinders.edu.au)
  148. X#
  149. X######################### Begin Variable Declarations #########################
  150. X#
  151. X# All variables have default values which will be superceded by environment
  152. X# variables of the same name.  The user's .plodrc is read after all other
  153. X# variable assignments, so any assignments there take precedence.
  154. X#
  155. X# Note that $LOGFILE and $DEADLOG are used as absolute pathnames.  After
  156. X# the .plodrc has been evaluated, $LOGDIR or $HOME will be prepended to
  157. X# $LOGFILE and $DEADLOG respectively if either of these variables does not
  158. X# begin with a '/'.
  159. X#
  160. X# Set $CRYPTCMD to null if you don't want encryption to be performed.
  161. X#
  162. X# KEYVAL    key value used by CRYPTCMD
  163. X# CRYPTCMD    encryption command, set this to null for no encryption
  164. X# TMPFILE    file name to use for temporary holding
  165. X# EDITOR    editor called by ~e
  166. X# VISUAL    editor called by ~v
  167. X# PAGER         used by ~p and ~h when output longer than one page (see LINES)
  168. X# LINES        number of lines on the screen
  169. X# LOGDIR    directory containing log files
  170. X# LOGFILE    absolute path of log file
  171. X# HOME        user's home directory
  172. X# DEADLOG    place to drop dead.log file on abort or ~q, also used by ~d
  173. X
  174. X# Some variable values use date/time information
  175. X#
  176. X($ss, $mm, $hh, $DD, $MM, $YY) = localtime($^T); $MM++; 
  177. X
  178. X$KEYVAL = $ENV{'KEYVAL'} || sprintf("pl%d%dod", $YY, $MM);
  179. X$CRYPTCMD = defined($ENV{'CRYPTCMD'})? $ENV{'CRYPTCMD'} : "/bin/crypt";
  180. X$TMPFILE = $ENV{'TMPFILE'} || "/tmp/plodtmp$$";
  181. X$HOME = $ENV{'HOME'} || (getpwuid($<))[7];
  182. X$EDITOR = $ENV{'EDITOR'} || "/usr/local/bin/emacs";
  183. X$VISUAL = $ENV{'VISUAL'} || "/usr/local/bin/emacs";
  184. X$PAGER = $ENV{'PAGER'} || "/usr/local/bin/less";
  185. X$LINES = $ENV{'LINES'} || 24;
  186. X$LOGDIR = $ENV{'LOGDIR'} || "$HOME/.logdir";
  187. X$LOGFILE = $ENV{'LOGFILE'} || sprintf("%02d%02d", $YY, $MM);
  188. X$DEADLOG = $ENV{'DEADLOG'} || "dead.log";
  189. X
  190. X
  191. X########################## End Variable Declarations ##########################
  192. X######################### Begin Function Declarations #########################
  193. X
  194. X
  195. X# Printvar (~=): Output the value of one or more variables.
  196. X#
  197. Xsub printvar {
  198. X   local($vars) = @_;
  199. X   $, = ','; print eval "($vars)"; $, = '';
  200. X   print "\n";
  201. X   print "(continue composing note)\n";
  202. X}
  203. X$printvar = "\$var[, ...]\tOutput value of variables";
  204. X$funcs{'='} = *printvar;
  205. X
  206. X
  207. X# Bang (~!): Execute a command in the shell and then return to plod.
  208. X#
  209. Xsub bang {
  210. X   local($cmdline) = @_;
  211. X   system "$cmdline";
  212. X   print "(continue composing note)\n";
  213. X}
  214. X$bang = "cmdline\tExecute system command and return";
  215. X$funcs{'!'} = *bang;
  216. X
  217. X
  218. X# Redirect (~>): Pipe the output of a command into the current buffer.
  219. X#
  220. Xsub redirect {
  221. X   local($cmdline) = @_;
  222. X   local($count);
  223. X   if (!open(CMD, "$cmdline |")) {
  224. X      warn "*** Unable to execute: $cmdline\n";
  225. X      return;
  226. X   }
  227. X   &readit(CMD);
  228. X}
  229. X$redirect = "cmdline\tAdd output of given command to buffer";
  230. X$funcs{'>'} = *redirect;
  231. X
  232. X
  233. X# Pipetocmd (~|): Pipe the contents of the current buffer through a UNIX
  234. X# command line and replace the buffer with the result.
  235. X#
  236. Xsub pipetocmd {
  237. X   local($cmdline) = @_;
  238. X   local($header);
  239. X   if (!open(PIPELN, "| $cmdline >$TMPFILE 2>&1")) {    # output to tmp file
  240. X      warn "*** Unable to execute: $cmdline\n";
  241. X      return;
  242. X   }
  243. X   $header = shift @lines;                # don't include stamp
  244. X   print PIPELN @lines;
  245. X   close(PIPELN);
  246. X   if (!open(INP, "<$TMPFILE")) {
  247. X      warn "*** Unable to get command output\n";
  248. X      unshift(@lines, $header);
  249. X      unlink "$TMPFILE";
  250. X      return;
  251. X   }
  252. X   undef @lines;                    # replace buffer with
  253. X   @lines = <INP>;                    # contents of tmp file
  254. X   close(INP);
  255. X   unlink "$TMPFILE";
  256. X   unshift(@lines, $header);
  257. X   print "(continue composing note)\n";   
  258. X}
  259. X$pipetocmd = "cmdline\tPipe contents of buffer through cmdline";
  260. X$funcs{'|'} = *pipetocmd;
  261. X
  262. X
  263. X# Perlit (~X): Execute Perl code.
  264. X#
  265. Xsub perlit {
  266. X   local($code) = @_;
  267. X   eval "$code";
  268. X   warn $@ if $@;
  269. X   print "(continue composing note)\n";   
  270. X}
  271. X$perlit = "code\t\tExecute a line of Perl code";
  272. X$funcs{'X'} = *perlit;
  273. X
  274. X
  275. X# Longperl (~M): Edit then eval a multi-line Perl fragment
  276. X#
  277. Xsub longperl {
  278. X   local($bogus) = @_;
  279. X   return(&mistake) if ($bogus);
  280. X   if (@code) {
  281. X      if (!open(TMP, "> $TMPFILE")) {
  282. X         warn "*** Unable to create temporary file\n";
  283. X         return;
  284. X      }
  285. X      print TMP @code;
  286. X      close(TMP);
  287. X   }
  288. X   system("$EDITOR $TMPFILE");
  289. X   if (!open(TMP, "< $TMPFILE")) {
  290. X      warn "*** Unable to read buffer\n";
  291. X      return;
  292. X   }
  293. X   undef @code;
  294. X   @code = <TMP>;
  295. X   close(TMP);
  296. X   system("/bin/rm -f $TMPFILE*");
  297. X   eval "@code";
  298. X   warn $@ if $@;
  299. X   print "(continue composing note)\n";   
  300. X}
  301. X$longperl = "\t\tInvoke \$EDITOR on command buffer, then execute as Perl code";
  302. X$funcs{'M'} = *longperl;
  303. X
  304. X
  305. X# Appendfl (~a): Append contents of buffer to a file and return to plod.
  306. X# To overwrite a file with the contents of the buffer, see &writefl().
  307. X#
  308. Xsub appendfl {
  309. X   local($file) = @_;
  310. X   if (!open(OUTP, ">> $file")) {
  311. X      warn "*** Could not append to file $file\n";
  312. X      return;
  313. X   }
  314. X   print OUTP @lines;
  315. X   close(OUTP);
  316. X   print "Wrote ", scalar(@lines), " lines to file $file\n";
  317. X   print "(continue composing note)\n";
  318. X}
  319. X$appendfl = "file\t\tAppend contents of buffer to file";
  320. X$funcs{'a'} = *appendfl;
  321. X
  322. X
  323. X# Getdead (~d): Suck contents of DEADLOG file into buffer.
  324. X#
  325. Xsub getdead {
  326. X   local($bogus) = @_;
  327. X   return(&mistake) if ($bogus);
  328. X   if (!open(DEAD, "<$DEADLOG")) {
  329. X      warn "*** Unable to open $home/dead.log.\n";
  330. X      return;
  331. X   }
  332. X   &readit(DEAD, "$DEADLOG");
  333. X}
  334. X$getdead = "\t\tIncorporate contents of \$DEADLOG into buffer";
  335. X$funcs{'d'} = *getdead;
  336. X
  337. X
  338. X# Editbuf (~e) and Visualbuf (~v): Call appropriate editor on buffer.
  339. X#
  340. Xsub editbuf {
  341. X   local($bogus) = @_;
  342. X   return(&mistake) if ($bogus);
  343. X   &calledit($EDITOR);
  344. X}
  345. Xsub visualbuf {
  346. X   local($bogus) = @_;
  347. X   return(&mistake) if ($bogus);
  348. X   &calledit($VISUAL);
  349. X}
  350. X$editbuf = "\t\tEdit buffer with \$EDITOR";
  351. X$visualbuf = "\t\tEdit buffer with \$VISUAL";
  352. X$funcs{'e'} = *editbuf;
  353. X$funcs{'v'} = *visualbuf;
  354. X
  355. X
  356. X# Editlog (~E) and Visuallog (~V): Call appropriate editor on LOGFILE.
  357. X#
  358. Xsub editlog {
  359. X   local($args) = @_;
  360. X   &logedit($EDITOR, $args);
  361. X   print "(continue composing note)\n";
  362. X}
  363. Xsub visuallog {
  364. X   local($args) = @_;
  365. X   &logedit($VISUAL, $args);
  366. X   print "(continue composing note)\n";
  367. X}
  368. X$editlog = "[file [key]]\tEdit LOGFILE [or older log] with \$EDITOR";
  369. X$visuallog = "[file [key]]\tEdit LOGFILE [or older log] with \$VISUAL";
  370. X$funcs{'E'} = *editlog;
  371. X$funcs{'l'} = *editlog;
  372. X$funcs{'V'} = *visuallog;
  373. X
  374. X
  375. X# Helpuser (~h or ~?): Output a list of tilde escapes with associated
  376. X# help messages (found in the scalar values of the type globs in %funcs).
  377. X# Use the defined PAGER if the output would be more than LINES long.
  378. X#
  379. Xsub helpuser {
  380. X   $long = (scalar(keys %funcs) >= $LINES) && open(TMP, ">$TMPFILE");
  381. X   for (sort keys %funcs) {
  382. X      *info = $funcs{$_};
  383. X      if ($long) {
  384. X         print TMP "~$_ $info\n";
  385. X      }
  386. X      else { print "~$_ $info\n"; }
  387. X   }
  388. X   if ($long) {
  389. X      close(TMP);
  390. X      system("/bin/cat $TMPFILE | $PAGER");
  391. X      unlink "$TMPFILE";
  392. X   }
  393. X}
  394. X$helpuser = "\t\tPrint this message";
  395. X$funcs{'h'} = *helpuser;
  396. X$funcs{'?'} = *helpuser;
  397. X
  398. X
  399. X# Printout (~p):  cat back the current buffer for review.  Use PAGER if
  400. X# the buffer is longer than LINES.
  401. X#
  402. Xsub printout {
  403. X   local($bogus) = @_;
  404. X   return(&mistake) if ($bogus);
  405. X   if (@lines < $LINES-1 || !open(TMP, ">$TMPFILE")) {
  406. X      print "-----\n";
  407. X      print @lines;
  408. X   }
  409. X   else {
  410. X      print TMP @lines;
  411. X      close(TMP);
  412. X      system("/bin/cat $TMPFILE | $PAGER");
  413. X      unlink "$TMPFILE";
  414. X   }
  415. X   print "(continue composing note)\n";
  416. X}
  417. X$printout = "\t\tView contents of buffer, one page at a time";
  418. X$funcs{'p'} = *printout;
  419. X
  420. X
  421. X# Pagelog (~P): Page contents of LOGFILE.
  422. X#
  423. Xsub pagelog {
  424. X   local($args) = @_;
  425. X   &pageit($args);
  426. X   print "(continue composing note)\n";
  427. X}
  428. X$pagelog = "[file [key]]\tView contents of LOGFILE [or older log] with PAGER";
  429. X$funcs{'P'} = *pagelog;
  430. X$funcs{'L'} = *pagelog;
  431. X
  432. X
  433. X# Quitit (~q): Quit plod and attempt to save buffer in DEADLOG.  Also
  434. X# called on SIGINT and SIGQUIT via &trapit().
  435. X#
  436. Xsub quitit {
  437. X   local($bogus) = @_;
  438. X   return(&mistake) if ($bogus);
  439. X   open(DEAD, ">> $DEADLOG") || die "Can't open $DEADLOG\n";
  440. X   print DEAD @lines;
  441. X   close(DEAD);
  442. X   exit;
  443. X}
  444. X$quitit = "\t\tQuit, attempts to save buffer in \$DEADLOG";
  445. X$funcs{'q'} = *quitit;
  446. X
  447. X
  448. X# Readfile (~r): Append contents of file into buffer.
  449. X#
  450. Xsub readfile {
  451. X   local($file) = @_;
  452. X   if (!open(INPT, "<$file")) {
  453. X      warn "*** Unable to open $file.\n";
  454. X      return;
  455. X   }
  456. X   &readit(INPT, $file);
  457. X}
  458. X$readfile = "file\t\tRead contents of file into buffer";
  459. X$funcs{'r'} = *readfile;
  460. X
  461. X
  462. X# Writefl (~w): Overwrite file with contents of buffer.  To append to a
  463. X# given file, see &appendfl().
  464. X#
  465. Xsub writefl {
  466. X   local($file) = @_;
  467. X   if (!open(OUTP, "> $file")) {
  468. X      warn "*** Could not write to file $file\n";
  469. X      return;
  470. X   }
  471. X   print OUTP @lines;
  472. X   close(OUTP);
  473. X   print "Wrote ", scalar(@lines), " lines to file $file\n";
  474. X   print "(continue composing note)\n";
  475. X}
  476. X$writefl = "file\t\tOverwrite file with contents of buffer";
  477. X$funcs{'w'} = *writefl;
  478. X
  479. X
  480. X# Exitnow (~x): Exit plod without writing to DEADLOG or LOGFILE.
  481. X#
  482. Xsub exitnow {
  483. X   local($bogus) = @_;
  484. X   return(&mistake) if ($bogus);
  485. X   exit;
  486. X}
  487. X$exitnow = "\t\tExit without saving buffer";
  488. X$funcs{'x'} = *exitnow;
  489. X
  490. X
  491. X########################## End Function Declarations ##########################
  492. X############################# Begin Main Program ##############################
  493. X
  494. X
  495. X# Check for ~/.plodrc and eval() contents.  Exit with an error message if
  496. X# eval() complains for any reason.
  497. X#
  498. Xif (-e "$HOME/.plodrc") {
  499. X   eval { do "$HOME/.plodrc"; };
  500. X   die "*** Error in $HOME/.plodrc:\n$@" if $@;
  501. X}
  502. X
  503. X# Prepend parent directories unless we have explicit pathnames
  504. X#
  505. X$LOGFILE = "$LOGDIR/$LOGFILE" unless ($LOGFILE =~ /^\//);
  506. X$DEADLOG = "$HOME/$DEADLOG" unless ($DEADLOG =~ /^\//);
  507. X
  508. X# Extract dirname from $LOGFILE and make sure it exists
  509. X#
  510. X($dirname = $LOGFILE) =~ s,/[^/]*$,,;
  511. Xif (!(-d $dirname)) {
  512. X   warn "Attempting to create logging directory, $dirname\n";
  513. X   die "Attempt failed!\n" unless (mkdir($dirname, 0700));
  514. X}
  515. X
  516. X# Create time/date stamp and make it the first line of the buffer.
  517. X#
  518. X($ss, $mm, $hh, $DD, $MM, $YY) = localtime($^T); $MM++; 
  519. X$stamp = sprintf("%02d/%02d/%02d, %02d:%02d --", $MM, $DD, $YY, $hh, $mm);
  520. Xpush(@lines, "$stamp\n");
  521. X
  522. X# Log entry can appear on the command line, otherwise loop until end of
  523. X# STDIN or '.' recognized on a line by itself.
  524. X#
  525. Xif ($ARGV[0] eq "-P") { shift @ARGV; &pageit("@ARGV"); exit; }
  526. Xelsif ($ARGV[0] eq "-E") { shift @ARGV; &logedit($EDITOR, "@ARGV"); exit; }
  527. Xelsif ($ARGV[0] eq "-V") { shift @ARGV; &logedit($VISUAL, "@ARGV"); exit; }
  528. Xelsif (@ARGV) { push(@lines, "@ARGV\n"); }
  529. Xelse {
  530. X   if (-t STDIN) {
  531. X      print "$stamp\n";
  532. X      $SIG{'QUIT'} = trapit;
  533. X      $SIG{'INT'} = trapit;
  534. X   }
  535. X   while (<STDIN>) {
  536. X      if (/^~/) {                    # escape sequence:
  537. X         ($esc, $args) = /^~(\S)\s*(.*)$/;        # 1) parse line
  538. X         *glob = $funcs{$esc};                # 2) unpack type glob
  539. X         if (!defined(&glob)) {                # 3) check defined()
  540. X        warn "Unrecognized escape sequence: ~$esc\n";
  541. X            next;
  542. X         }
  543. X         &glob($args);                    # 4) call func w/ args
  544. X      }
  545. X      elsif (/^\.\s*$/) {                # lone dot means end 
  546. X         print "(eot)\n";                # of log entry
  547. X         last;
  548. X      }
  549. X      else {                        # else append line to
  550. X         push(@lines, $_);                # log buffer
  551. X      }
  552. X   }
  553. X}
  554. X$lines[$#lines] = "$lines[$#lines]\n" unless ($lines[$#lines] =~ /\n$/);
  555. X
  556. X# Completed log entry now in @lines.  If using encryption, call encryption
  557. X# command to decrypt previous log entries (if present).  If not encrypting,
  558. X# simply open log file to append.
  559. X#
  560. Xif ($CRYPTCMD) {                    # encrypting
  561. X   if (-e "$LOGFILE") {
  562. X      system "$CRYPTCMD $KEYVAL <$LOGFILE >$TMPFILE";
  563. X   }
  564. X   if (!open(LOGFILE, ">> $TMPFILE")) {
  565. X      unlink "$TMPFILE";
  566. X      warn "*** Unable to append new log entry\n";
  567. X      &quitit();
  568. X   }
  569. X}
  570. Xelse {                             # not encyrpting
  571. X   if (!open(LOGFILE, ">> $LOGFILE")) {
  572. X      warn "*** Unable to append new log entry\n";
  573. X      &quitit();
  574. X   }
  575. X}
  576. X
  577. X# Dump contents of buffer into plain text file.
  578. X#
  579. Xprint LOGFILE "-----\n";
  580. Xprint LOGFILE @lines;
  581. Xclose(LOGFILE);
  582. X
  583. X# If encrypting, replace old log file with new version.  Unlink plain
  584. X# text temporary file when done.
  585. X#
  586. Xif ($CRYPTCMD) {
  587. X   unlink "$LOGFILE";
  588. X   system "$CRYPTCMD $KEYVAL <$TMPFILE >$LOGFILE";
  589. X   chmod 0600, "$LOGFILE";
  590. X   unlink "$TMPFILE";
  591. X}
  592. X
  593. X
  594. X############################## End Main Program ###############################
  595. X########################### Miscellaneous Functions ###########################
  596. X
  597. X
  598. X# Append contents of file $fname (associated with file handle $fh) to buffer.
  599. X# Assume $fh is a pipe if $fname is null.  This function called by many tilde
  600. X# escapes.
  601. X#
  602. Xsub readit {
  603. X   local($fh, $fname) = @_;
  604. X   push(@lines, <$fh>);
  605. X   print STDOUT ($fname) ? "$fname: " : "Added ";
  606. X   print STDOUT "$. lines";
  607. X   print STDOUT ($fname) ? "\n" : " to buffer.\n";
  608. X   print STDOUT "(continue composing note)\n";
  609. X   close($fh);
  610. X}
  611. X
  612. X
  613. X# Call the editor $_[0] on the contents of the buffer.  Used by &editbuf()
  614. X# and &visualbuf().
  615. X#
  616. Xsub calledit {
  617. X   local($edit) = @_;
  618. X   if (!open(EDIT, ">$TMPFILE")) {
  619. X      warn "*** Unable to create file for editing\n";
  620. X      return;
  621. X   }
  622. X   print EDIT @lines;
  623. X   close(EDIT);
  624. X   chmod 0600, "$TMPFILE";
  625. X   system "$edit $TMPFILE";
  626. X   if (!open(EDIT, "<$TMPFILE")) {
  627. X      warn "*** Unable to read changes, returning to previous state.\n";
  628. X      system "/bin/rm -f $TMPFILE*";
  629. X      return;
  630. X   }
  631. X   undef @lines;
  632. X   @lines = <EDIT>;
  633. X   close(EDIT);
  634. X   system "/bin/rm -f $TMPFILE*";
  635. X   print "(continue composing note)\n";
  636. X}
  637. X
  638. X
  639. X# Call the appropriate editor on a log file.  Used by &editlog and &visualedit.
  640. X#
  641. Xsub logedit {
  642. X   local($edit, $args) = @_;
  643. X   local($file, $key) = split(/\s+/, $args);
  644. X   $key = $key || $KEYVAL;
  645. X   $file = $file || $LOGFILE;
  646. X   $file = "$LOGDIR/$file" unless ($file =~ /^\//);
  647. X   if ($CRYPTCMD) {
  648. X      if (!(-e "$file")) {
  649. X     warn "*** $file does not exist\n";
  650. X     return;
  651. X      }
  652. X      system("$CRYPTCMD $key <$file >$TMPFILE");
  653. X      chmod 0600, "$TMPFILE";
  654. X      system("$edit $TMPFILE");
  655. X      if (!(-e "$TMPFILE") || -z _) {
  656. X         warn "*** Modified file is empty-- restoring old version\n";
  657. X     unlink "$TMPFILE";
  658. X     return;
  659. X      }
  660. X      unlink "$file";
  661. X      system "$CRYPTCMD $key <$TMPFILE >$file";
  662. X      chmod 0600, "$file";
  663. X      unlink "$TMPFILE";
  664. X   }
  665. X   else { system("$edit $file"); }
  666. X}
  667. X
  668. X
  669. X# Page a log file.
  670. X#
  671. Xsub pageit {
  672. X   local($args) = @_;
  673. X   local($file, $key) = split(/\s+/, $args);
  674. X   local($cmd);
  675. X   $key = $key || $KEYVAL;
  676. X   $file = $file || $LOGFILE;
  677. X   $file = "$LOGDIR/$file" unless ($file =~ /^\//);
  678. X   $cmd = $CRYPTCMD ? "$CRYPTCMD $key < $file" : "/bin/cat $file";
  679. X   system("$cmd | $PAGER");
  680. X}
  681. X
  682. X
  683. X# Generic warning message called by all escapes that do not expect arguments
  684. X# when @_ is not empty.
  685. X#
  686. Xsub mistake {
  687. X   warn "*** Arguments are not expected for this escape.\n";
  688. X}
  689. X
  690. X
  691. X# Wrapper for &quitit()-- called on SIGINT and SIGQUIT.  Wrapper required
  692. X# because signal handlers get the signal as an argument and &quitit() does
  693. X# not appreciate arguments.
  694. X#
  695. Xsub trapit {
  696. X   &quitit();
  697. X}
  698. END_OF_plod
  699. if test 15636 -ne `wc -c <plod`; then
  700.     echo shar: \"plod\" unpacked with wrong size!
  701. fi
  702. chmod +x plod
  703. # end of overwriting check
  704. fi
  705. if test -f plod.man -a "${1}" != "-c" ; then 
  706.   echo shar: Will not over-write existing file \"plod.man\"
  707. else
  708. echo shar: Extracting \"plod.man\" \(8521 characters\)
  709. sed "s/^X//" >plod.man <<'END_OF_plod.man'
  710. X.nh
  711. X.de Sp
  712. X.if t .sp .5v
  713. X.if n .sp
  714. X..
  715. X.de Ip
  716. X.br
  717. X.ie \\n.$>=3 .ne \\$3
  718. X.el .ne 3
  719. X.IP "\\$1" \\$2
  720. X..
  721. X.TH PLOD 1 "2 February 1993" "PLOD"
  722. X.SH NAME
  723. XPLOD \- keep a log of your work
  724. X.SH SYNOPSIS
  725. X.B plod
  726. X\ [\ \fIone line message\fR\ ]
  727. X.br
  728. X.B plod
  729. X\ \fB-E\fR|\fB-P\fR|\fB-V\fR\ [\ \fIlogfile\fR\ [\ \fIkey\fR\ ]]
  730. X.SH DESCRIPTION
  731. X\fBPLOD\fR
  732. Xis a tool developed to help System/Network Administrators (and others)
  733. Xkeep track of the work that they do.  Good logs are useful both as a
  734. Xpersonal reference and to show to your management on a regular basis
  735. Xor around performance review time. By default, logs will be stored in
  736. Xan encrypted format in the directory \fI$HOME/.logdir\fR, but this
  737. Xbehavior is completely customizable (see \fBENVIRONMENT\fR and 
  738. X\fBCUSTOMIZATION\fR below).
  739. X
  740. XThe first form of the command will enter a short message on the command
  741. Xline into your log file.  If no message is present on the command line,
  742. Xa date/time stamp will be printed and \fBPLOD\fR
  743. Xwill go into an interactive mode reminiscent of BSD mail.  Many tilde
  744. Xescape sequences are supported (see \fBCOMMANDS\fR below or type 
  745. X\fI~h\fR or \fI~?\fR within interactive mode).  Enter a period on a
  746. Xline by itself to end your log entry.
  747. X
  748. XThe second mode allows you to review or edit your old log files.  The
  749. X\fB-P\fR option invokes the default \fBPAGER\fR defined in the \fBPLOD\fR
  750. Xsource, or as defined in your environment, on the current log file.  The
  751. X\fB-E\fR and \fB-V\fR flags invoke \fBEDITOR\fR and \fBVISUAL\fR respectively.
  752. XOlder log files may be accessed by specifying a file name and optional
  753. Xencryption key on the command line.
  754. X
  755. X.SH ENVIRONMENT
  756. X\fBPLOD\fR supports a number of variables which can be modified to customize
  757. Xits behavior.  The values of these variables may be changed by editing
  758. X\fBPLOD\fR directly, by creating an environment variable, or by assignment
  759. Xin the user's startup file (see \fBCUSTOMIZATION\fR below).  \fBPLOD\fR
  760. Xrecognizes the following environment variables:
  761. X.Ip "\fBEDITOR\fR" 4
  762. XThe user's preferred editor (used by the \fB-E\fR command line flag and the
  763. X\fB~e\fR, \fB~E\fR, and \fB~M\fR escape sequences).  Default is 
  764. X\fI/usr/local/bin/emacs\fR.
  765. X.Sp
  766. X.Ip "\fBVISUAL\fR" 4
  767. XThe user's preferred visual editor (used by \fB-V\fR, \fB~v\fR, and \fB~V\fR).
  768. XDefault is \fI/usr/local/bin/emacs\fR.
  769. X.Sp
  770. X.Ip "\fBPAGER\fR" 4
  771. XThe user's preferred pager (used by \fB-P\fR, \fB~p\fR, and \fB~P\fR).
  772. XDefault is \fI/usr/local/bin/less\fR.
  773. X.Sp
  774. X.Ip "\fBLINES\fR" 4
  775. XThe number of lines on the current display.  Used to determine when the
  776. X\fBPAGER\fR needs to be invoked. Default is \fI24\fR.
  777. X.Sp
  778. X.Ip "\fBCRYPTCMD\fR" 4
  779. XThe encryption command to be used.  If you do not wish to encrypt your
  780. Xlog files, set this to null.  The standard UNIX \fBcrypt\fR command is
  781. Xnot in the least secure, but does provide protection from casual browsing.
  782. XDefault is \fI/bin/crypt\fR.
  783. X.Sp
  784. X.Ip "\fBKEYVAL\fR" 4
  785. XThe key to be used with \fBCRYPTCMD\fR.  Default is \fIpl<yr><mn>od\fR.
  786. X.Sp
  787. X.Ip "\fBLOGDIR\fR" 4
  788. XWhere log files are placed.  Default is \fI$HOME/.logdir\fR.
  789. X.Sp
  790. X.Ip "\fBLOGFILE\fR" 4
  791. XThe name of the current log file.  \fBLOGDIR\fR will be prepended to this
  792. Xvalue if \fBLOGFILE\fR does not begin with a \fI/\fR.  Default is
  793. X\fI<yr><mn>\fR.
  794. X.Sp
  795. X.Ip "\fBHOME\fR" 4
  796. XThe user's home directory.  Default taken from user's password entry.
  797. X.Sp
  798. X.Ip "\fBDEADLOG\fR" 4
  799. XWhere interrupted log entries are placed.  \fBHOME\fR will be prepended
  800. Xto this value if \fBDEADLOG\fR does not begin with a \fI/\fR.  Default
  801. Xis \fIdead.log\fR.
  802. X.Sp
  803. X.Ip "\fBTMPFILE\fR" 4
  804. XScratch file used throughout execution of program.  Default is 
  805. X\fI/tmp/plodtmp<pid>\fR.
  806. X.Sp
  807. X
  808. X.SH COMMANDS
  809. XMany tilde escape sequences are supported under \fBPLOD\fR's interactive
  810. Xmode.  Users may also define their own escape sequences in \fBPLOD\fR's
  811. Xinitialization file (see \fBCUSTOMIZATION\fR below).  Currently defined
  812. Xsequences are:
  813. X.Ip "~h, ~?" 8
  814. XShow a list of all escape sequences with a short usage message.
  815. X.Sp
  816. X.Ip "~= var[, ...]" 8
  817. XDisplay the current value of one or more variables.
  818. X.Ip ~e 8
  819. XEdit the current buffer with \fB$EDITOR\fR.
  820. X.Sp
  821. X.Ip ~v 8
  822. XEdit the current buffer with \fB$VISUAL\fR.
  823. X.Sp
  824. X.Ip ~p 8
  825. XDisplay the contents of the current buffer (using \fB$PAGER\fR if necessary).
  826. X.Sp
  827. X.Ip "~V [\ logfile\ [\ key\ ]]" 8
  828. XCall \fB$VISUAL\fR on the current log file, or on some other log file as
  829. Xspecified.  An additional encryption key may also be supplied.
  830. X.Sp
  831. X.Ip "~E, ~l [\ logfile\ [\ key\ ]]" 8
  832. XSimilar to ~E except that \fB$EDITOR\fR is used.
  833. X.Sp
  834. X.Ip "~P, ~L [\ logfile\ [\ key\ ]]" 8
  835. XSame as ~E and ~V except that \fB$PAGER\fR is invoked.
  836. X.Sp
  837. X.Ip ~q 8
  838. XQuit \fBPLOD\fR, saving contents of buffer into \fB$DEADLOG\fR.
  839. X.Sp
  840. X.Ip ~x 8
  841. XQuit without attempting to save buffer.
  842. X.Sp
  843. X.Ip ~d 8
  844. XAppend contents of \fB$DEADLOG\fR to current buffer.
  845. X.Sp
  846. X.Ip "~r somefile" 8
  847. XAppend contents of file to current buffer.
  848. X.Sp
  849. X.Ip "~a somefile" 8
  850. XAppend contents of current buffer to file.
  851. X.Sp
  852. X.Ip "~w somefile" 8
  853. XOverwrite file with contents of current buffer.
  854. X.Sp
  855. X.Ip "~X Perl-code" 8
  856. XExecute a line of Perl code.
  857. X.Sp
  858. X.Ip ~M 8
  859. XInvoke \fB$EDITOR\fR and execute resulting file as Perl code.  Each successive
  860. Xinvocation of this escape will edit the previously executed Perl code so as
  861. Xto make it easier to go back and correct small errors.
  862. X.Sp
  863. X.Ip "~! command" 8
  864. XExecute a command in the shell and return.
  865. X.Sp
  866. X.Ip "~> command" 8
  867. XAppend the output of a command to the current buffer.
  868. X.Sp
  869. X.Ip "~| command" 8
  870. XPipe the current buffer through a command and replace the buffer with the
  871. Xresulting output.
  872. X.Sp
  873. X
  874. X.SH CUSTOMIZATION
  875. XLike most UNIX utilities, \fBPLOD\fR has an initialization file,
  876. Xthe \fI\.plodrc\fR,
  877. Xwhich is read at startup.  Unlike most UNIX utilities,
  878. Xthis file is interpreted as Perl code.  Thus, if you wished to assign
  879. Xa new value to a customization variable you would use the syntax
  880. X.RS
  881. X.PP
  882. X$LOGDIR = "$HOME/mylogs";
  883. X.RE
  884. X.PP
  885. XVariables set in the \fI\.plodrc\fR override default values and those
  886. Xfrom the environment.
  887. X
  888. XIt is also possible for the user to create their own tilde escapes.  First,
  889. Xcreate a subroutine which performs the desired function.  Then assign the
  890. Xtype glob which references that function to global array \fI%funcs\fR indexed
  891. Xby the character of the escape sequence.  Any arguments that the user enters
  892. Xafter the tilde escape will be passed into the function as a single string
  893. Xin \fI@_\fR.  The list \fI@lines\fR contains the current buffer.
  894. X
  895. XAs an example, here is the append to file function (~a) from the \fBPLOD\fR
  896. Xsource:
  897. X.RS
  898. X.PP
  899. X.nf
  900. Xsub appendfl {
  901. X   local($file) = @_;
  902. X   if (!open(OUTP, ">> $file")) {
  903. X      warn "*** Could not append to file $file\\n";
  904. X      return;
  905. X   }
  906. X   print OUTP @lines;
  907. X   close(OUTP);
  908. X   print "Wrote ", scalar(@lines), " lines to file $file\\n";
  909. X   print "(continue composing note)\\n";
  910. X}
  911. X$appendfl = "file\\t\\tAppend contents of buffer to file";
  912. X$funcs{'a'} = *appendfl;
  913. X.fi
  914. X.RE
  915. X.PP
  916. XThe scalar variable \fI$appendfl\fR is used by \fBPLOD\fR's help function
  917. X(~h or ~?) to provide a descriptive message about the escape sequence.
  918. XAs a further example, here is \fBPLOD\fR's help function
  919. X.RS
  920. X.PP
  921. X.nf
  922. Xsub helpuser {
  923. X   $long = (scalar(keys %funcs) >= $LINES)
  924. X           && open(TMP, ">$TMPFILE");
  925. X   for (sort keys %funcs) {
  926. X      *info = $funcs{$_};
  927. X      if ($long) {
  928. X         print TMP "~$_ $info\\n";
  929. X      }
  930. X      else { print "~$_ $info\\n"; }
  931. X   }
  932. X   if ($long) {
  933. X      close(TMP);
  934. X      system("/bin/cat $TMPFILE | $PAGER");
  935. X      unlink "$TMPFILE";
  936. X   }
  937. X}
  938. X$helpuser = "\\t\\tPrint this message";
  939. X$funcs{'h'} = *helpuser;
  940. X$funcs{'?'} = *helpuser;
  941. X.fi
  942. X.RE
  943. X.PP
  944. XNote the use of various customization variables as well as the assignment
  945. Xof the type glob to two different indices of the \fI%funcs\fR array.
  946. X
  947. X.SH FILES
  948. X.PP
  949. X.Ip $HOME/.plodrc 24
  950. XInitialization and startup file
  951. X.Sp
  952. X.PP
  953. XVarious other customizable file locations.
  954. X
  955. X.SH SEE ALSO
  956. X.BR perl (1)
  957. X
  958. X.SH AUTHORS
  959. XThe original idea for \fBPLOD\fR comes from Bill Mendyka
  960. X(\fBmendyka@dg-rtp.dg.com\fR).
  961. X
  962. XThe current Perl implementation was developed by Hal Pomeranz
  963. X(\fBpomeranz@nas.nasa.gov\fR).
  964. X
  965. XAn Emacs mode for \fBPLOD\fR was developed by Paul Foley
  966. X(\fBpaul@ascent.com\fR).
  967. X
  968. XAdditional improvements have been suggested/developed by:
  969. XDavid W Crabb (\fBcrabb@phoenix.Princeton.EDU\fR),
  970. XJohn Ellis (\fBellis@rtsg.mot.com\fR),
  971. XErik E. Rantapaa (\fBrantapaa@math.umn.edu\fR), and
  972. XJames Tizard (\fBjames@ringo.ssn.flinders.edu.au\fR).
  973. X
  974. X.SH BUGS
  975. XAny bug reports or suggestions for improvement should be submitted to
  976. XHal Pomeranz via email at \fBpomeranz@nas.nasa.gov\fR.
  977. END_OF_plod.man
  978. if test 8521 -ne `wc -c <plod.man`; then
  979.     echo shar: \"plod.man\" unpacked with wrong size!
  980. fi
  981. # end of overwriting check
  982. fi
  983. if test -f plod.el -a "${1}" != "-c" ; then 
  984.   echo shar: Will not over-write existing file \"plod.el\"
  985. else
  986. echo shar: Extracting \"plod.el\" \(3636 characters\)
  987. sed "s/^X//" >plod.el <<'END_OF_plod.el'
  988. XArticle 14984 of comp.lang.perl:
  989. XNewsgroups: comp.lang.perl
  990. XPath: data.nas.nasa.gov!ames!haven.umd.edu!uunet!ascent!ascent!paul
  991. XFrom: paul@ascent.com (Paul Foley)
  992. XSubject: Emacs interface to PLOD
  993. XMessage-ID: <PAUL.93Jan21125701@MountRushmore.ascent.com>
  994. XDate: 21 Jan 93 12:57:01
  995. XOrganization: Ascent Technology, Inc., Cambridge Massachusetts
  996. XLines: 119
  997. X
  998. XHere is an emacs-lisp interface to PLOD --- the Personal LOgging
  999. XDevice posted to comp.lang.perl a few days ago.
  1000. X
  1001. XSimplest way to use is M-x plod.
  1002. X
  1003. XThere is also an "alarm" interface that will switch you to a PLOD
  1004. Xbuffer every so often, in case you forget to invoke it yourself.
  1005. X
  1006. XEnjoy.
  1007. X
  1008. X------------------------------------------------------------------
  1009. X
  1010. X;;;;
  1011. X;;;; plod.el
  1012. X;;;;
  1013. X;;;; Emacs interface to PLOD --- A (Perl) tool to keep track of the work you do
  1014. X;;;; PLOD was written by pomeranz@irving.nas.nasa.gov (Hal R. Pomeranz).
  1015. X;;;;
  1016. X;;;; This software is FREE to all and may be used for any purpose as long as this 
  1017. X;;;; notice remains intact.  The author does not assume responsibility for anything.
  1018. X;;;; 
  1019. X;;;; Suggested addition to .emacs:
  1020. X;;;;     (load-library "plod")
  1021. X;;;;     (plod-alarm-on 60) ; once an hour
  1022. X;;;;
  1023. X;;;; When you are tired of PLODding use "M-x plod-alarm-off"
  1024. X;;;; 
  1025. X;;;; Alternately, use "M-x plod" whenever you want to log something.
  1026. X;;;; 
  1027. X;;;; paul@ascent.com (Paul Foley)    Wednesday January 20, 1993
  1028. X
  1029. X(require 'shell)
  1030. X
  1031. X;;;
  1032. X;;; Variables
  1033. X;;;
  1034. X
  1035. X;; Name of executable --- should be in your $PATH
  1036. X(defvar plod-program-name "plod")
  1037. X(defvar plod-buffer-name "*PLOD*")
  1038. X
  1039. X;;;
  1040. X;;; Manual Interface
  1041. X;;;
  1042. X
  1043. X(defvar plod-buffer-process nil)
  1044. X
  1045. X;; Interactive command to invoke PLOD in a shell-mode buffer.
  1046. X;;
  1047. X
  1048. X(defun plod ()
  1049. X  "Invoke PLOD."
  1050. X  (interactive)
  1051. X  ; restart PLOD if necessary
  1052. X  (if (not (get-buffer-process plod-buffer-name))
  1053. X      (setq plod-buffer-process (start-process "plod-process" plod-buffer-name plod-program-name)))
  1054. X  (switch-to-buffer plod-buffer-name t)
  1055. X  (if (not (eq major-mode 'shell-mode)) (shell-mode)))
  1056. X
  1057. X
  1058. X;;;
  1059. X;;; Alarm interface
  1060. X;;;
  1061. X
  1062. X(defvar plod-alarm-on-p nil)        ; t if alarm is on
  1063. X(defvar plod-alarm-process nil)
  1064. X
  1065. X;; run when plod-alarm-process is killed
  1066. X(defun plod-alarm-sentinel (proc reason)
  1067. X  (or (eq (process-status proc) 'run)
  1068. X      (setq plod-alarm-on-p nil)
  1069. X      (ding) 
  1070. X      (message "PLOD alarm off")))
  1071. X
  1072. X;; run every interval & at initial call to plod-alarm-on
  1073. X(defun plod-alarm-filter (proc string)
  1074. X  (if plod-alarm-on-p
  1075. X      (plod)
  1076. X    (setq plod-alarm-on-p t)))
  1077. X
  1078. X;; Set alarm to call PLOD every so often
  1079. X;;
  1080. X(defun plod-alarm-on (interval)
  1081. X  "Turn the Emacs PLOD alarm on.  The alarm goes off every INTERVAL minutes
  1082. Xand you will be switched to the PLOD buffer automatically.  
  1083. XUse plod-alarm-off to stop this behaviour."
  1084. X  (interactive "nEnter PLOD alarm interval (in minutes): ")
  1085. X  (let ((live (and plod-alarm-process
  1086. X           (eq (process-status plod-alarm-process) 'run))))
  1087. X    (if (not live)
  1088. X    (progn
  1089. X      (setq plod-alarm-on-p nil)
  1090. X      (if plod-alarm-process
  1091. X          (delete-process plod-alarm-process))
  1092. X      (let ((process-connection-type nil))
  1093. X        (setq plod-alarm-process
  1094. X          (start-process "plod-alarm" nil 
  1095. X                 (concat exec-directory "wakeup")
  1096. X                 ; convert minutes -> seconds for wakeup
  1097. X                 (int-to-string (* 60 interval)))))
  1098. X      (process-kill-without-query plod-alarm-process)
  1099. X      (set-process-sentinel plod-alarm-process 'plod-alarm-sentinel)
  1100. X      (set-process-filter plod-alarm-process 'plod-alarm-filter)))))
  1101. X
  1102. X;; Turn PLOD alarm off
  1103. X;;
  1104. X(defun plod-alarm-off ()
  1105. X  "Turn the Emacs PLOD alarm off."
  1106. X  (interactive)
  1107. X  (if plod-alarm-on-p (kill-process plod-alarm-process)))
  1108. X
  1109. X;;; End
  1110. X--
  1111. Xpaul@ascent.com
  1112. X...!uunet!ascent!paul
  1113. X
  1114. X
  1115. X
  1116. X
  1117. X
  1118. X
  1119. END_OF_plod.el
  1120. if test 3636 -ne `wc -c <plod.el`; then
  1121.     echo shar: \"plod.el\" unpacked with wrong size!
  1122. fi
  1123. # end of overwriting check
  1124. fi
  1125. echo shar: End of shell archive.
  1126. exit 0
  1127.  
  1128. exit 0 # Just in case...
  1129.