mmuegel
上传用户:xu_441
上传日期:2007-01-04
资源大小:1640k
文件大小:67k
源码类别:

Email客户端

开发平台:

Unix_Linux

  1. From: "Michael S. Muegel" <mmuegel@cssun6.corp.mot.com>
  2. Message-Id: <199307280818.AA08111@cssun6.corp.mot.com>
  3. Subject: Re: contributed software
  4. To: eric@cs.berkeley.edu (Eric Allman)
  5. Date: Wed, 28 Jul 1993 03:18:02 -0500 (CDT)
  6. In-Reply-To: <199307221853.LAA04266@mastodon.CS.Berkeley.EDU> from "Eric Allman" at Jul 22, 93 11:53:47 am
  7. X-Mailer: ELM [version 2.4 PL22]
  8. Mime-Version: 1.0
  9. Content-Type: text/plain; charset=US-ASCII
  10. Content-Transfer-Encoding: 7bit
  11. Content-Length: 69132     
  12. OK. Here is a new shell archive.
  13. Cheers,
  14. -Mike
  15. ---- Cut Here and feed the following to sh ----
  16. #!/bin/sh
  17. # This is a shell archive (produced by shar 3.49)
  18. # To extract the files from this archive, save it to a file, remove
  19. # everything above the "!/bin/sh" line above, and type "sh file_name".
  20. #
  21. # made 07/28/1993 08:13 UTC by mmuegel@mot.com (Michael S. Muegel)
  22. # Source directory /home/ustart/NeXT/src/mail-tools/dist/foo
  23. #
  24. # existing files will NOT be overwritten unless -c is specified
  25. #
  26. # This shar contains:
  27. # length  mode       name
  28. # ------ ---------- ------------------------------------------
  29. #   4308 -r--r--r-- README
  30. #  12339 -r--r--r-- libs/date.pl
  31. #   3198 -r--r--r-- libs/elapsed.pl
  32. #   4356 -r--r--r-- libs/mail.pl
  33. #   6908 -r--r--r-- libs/mqueue.pl
  34. #   7024 -r--r--r-- libs/newgetopts.pl
  35. #   4687 -r--r--r-- libs/strings1.pl
  36. #   1609 -r--r--r-- libs/timespec.pl
  37. #   5212 -r--r--r-- man/cqueue.1
  38. #   2078 -r--r--r-- man/postclip.1
  39. #   6647 -r-xr-xr-x src/cqueue
  40. #   1836 -r-xr-xr-x src/postclip
  41. #
  42. # ============= README ==============
  43. if test -f 'README' -a X"$1" != X"-c"; then
  44. echo 'x - skipping README (File already exists)'
  45. else
  46. echo 'x - extracting README (Text)'
  47. sed 's/^X//' << 'SHAR_EOF' > 'README' &&
  48. -------------------------------------------------------------------------------
  49. Document Revision Control Information:
  50. X   mmuegel
  51. X   /usr/local/ustart/src/mail-tools/dist/foo/README,v
  52. X   1.1 of 1993/07/28 08:12:53
  53. -------------------------------------------------------------------------------
  54. X
  55. 1. Introduction
  56. ---------------
  57. X
  58. These tools may be of use to those sites using sendmail. Both are written in
  59. Perl. Our site, Mot.COM, receives a ton of mail being a top-level domain
  60. gateway. We have over 24 domains under us. Needless to say, we must have
  61. a robust mail system or my head, and others, would be on the chopping block.
  62. X
  63. 2. Description
  64. --------------
  65. X
  66. The first tool, cqueue, checks the sendmail queue for problems. We use
  67. it to flag problems with subdomain mail servers (and even our own servers
  68. once in a while ;-). We run it via a cron job every hour during the day.
  69. You may find this too frequent, however. 
  70. X
  71. The other program, postclip, is used to "filter" non-deliverable NDNs that
  72. get sent to our Postmaster account now and then. This ensures privacy of
  73. e-mail and helps avoid disk problems from huge NDNs. It is different than
  74. a brute force "just keep the header" approach because it tries hard to keep
  75. other parts of the message that look like non-delivery information.
  76. X
  77. Both have been used for some time at our site with no problems. Everything 
  78. you need should be in this distribution: source, manual pages, and support 
  79. libs. See the manual pages for a complete description of each tool.
  80. X
  81. 3. Installation
  82. ---------------
  83. X
  84. No fancy Makefile simply because these tools are all under a large
  85. hierarchy at my site. Installation should be a snap, however. Install
  86. the nroff(1) man(5) manual pages from the man subdirectory to the
  87. appropriate directory on your system. This might be something like
  88. /usr/local/man/man1.
  89. X
  90. Next, install all of the Perl libraries located in the lib subdirectory
  91. to your Perl library area. /usr/local/lib/perl is a good bet. The person
  92. who installed Perl at your site will be able to tell you for sure. 
  93. X
  94. Finally, you need to install the programs. Note that cqueue wants to
  95. run setuid root by default. This is because the sendmail queue is normally
  96. only readable by root or some special group. In order to let any user
  97. run this suidperl is used. suidperl allows a Perl program to run with the
  98. privileges of another user. 
  99. X
  100. You will have to edit both the cqueue and postclip programs to change
  101. the #! line at the top of each. Just change the pathname to whatever is
  102. appropriate on your system. Note that Larry Wall's fixin program from
  103. the Camel book can also be used to do this. It is very handy. It changes
  104. #! lines by looking at your PATH.
  105. X
  106. If you do not have suidperl on your system change the #! line in cqueue
  107. to reference perl instead of suidperl.
  108. X
  109. You may also wish to change some constants in cqueue. $DEF_QUEUE should be
  110. changed to your queue directory if it is not /usr/spool/mqueue. $DEF_TIME
  111. could be changed easy enough also. It is the time spec for the time duration
  112. after which a mail message will be reported on if the -a option has not been
  113. specified. See the manual page for more information and the format of this
  114. constant (same as the -t argument). Then again, neither of these has to
  115. be changed. Command line options are there to override their default
  116. values.
  117. X
  118. After you have edited the programs as necessary, all that remains is to
  119. install them to some executable directory. Install postclip mode 555
  120. and cqueue mode 4555 with owner root (if using suidperl) or mode 555
  121. (if not using suidperl).
  122. X
  123. 4. Gripes, Comments, Etc
  124. ------------------------
  125. X
  126. If you start using either of these let me know. I have other mail tools I
  127. will likely post in the future if these prove useful. Also, if you think
  128. something is just plain dumb/wrong/stupid let me know!
  129. X
  130. Cheers,
  131. -Mike
  132. X
  133. --
  134. +----------------------------------------------------------------------------+
  135. | Michael S. Muegel                    | Internet E-Mail:    mmuegel@mot.com |
  136. | UNIX Applications Startup Group      | Moto Dist E-Mail:   X10090          |
  137. | Corporate Information Office         | Voice:              (708) 576-0507  |
  138. | Motorola                             | Fax:                (708) 576-4153  |
  139. +----------------------------------------------------------------------------+
  140. SHAR_EOF
  141. chmod 0444 README ||
  142. echo 'restore of README failed'
  143. Wc_c="`wc -c < 'README'`"
  144. test 4308 -eq "$Wc_c" ||
  145. echo 'README: original size 4308, current size' "$Wc_c"
  146. fi
  147. # ============= libs/date.pl ==============
  148. if test ! -d 'libs'; then
  149.     echo 'x - creating directory libs'
  150.     mkdir 'libs'
  151. fi
  152. if test -f 'libs/date.pl' -a X"$1" != X"-c"; then
  153. echo 'x - skipping libs/date.pl (File already exists)'
  154. else
  155. echo 'x - extracting libs/date.pl (Text)'
  156. sed 's/^X//' << 'SHAR_EOF' > 'libs/date.pl' &&
  157. ;#
  158. ;# Name
  159. ;# date.pl - Perl emulation of (the output side of) date(1)
  160. ;#
  161. ;# Synopsis
  162. ;# require "date.pl";
  163. ;# $Date = &date(time);
  164. ;# $Date = &date(time, $format);
  165. ;#
  166. ;# Description
  167. ;# This package implements the output formatting functions of date(1) in
  168. ;# Perl.  The format options are based on those supported by Ultrix 4.0
  169. ;# plus a couple of additions from SunOS 4.1.1 and elsewhere:
  170. ;#
  171. ;# %a abbreviated weekday name - Sun to Sat
  172. ;# %A full weekday name - Sunday to Saturday
  173. ;# %b abbreviated month name - Jan to Dec
  174. ;# %B full month name - January to December
  175. ;# %c date and time in local format [+]
  176. ;# %C date and time in long local format [+]
  177. ;# %d day of month - 01 to 31
  178. ;# %D date as mm/dd/yy
  179. ;# %e day of month (space padded) - ` 1' to `31'
  180. ;# %E day of month (with suffix: 1st, 2nd, 3rd...)
  181. ;# %f month of year (space padded) - ` 1' to `12'
  182. ;# %h abbreviated month name - Jan to Dec
  183. ;# %H hour - 00 to 23
  184. ;# %i hour (space padded) - ` 1' to `12'
  185. ;# %I hour - 01 to 12
  186. ;# %j day of the year (Julian date) - 001 to 366
  187. ;# %k hour (space padded) - ` 0' to `23'
  188. ;# %l date in ls(1) format
  189. ;# %m month of year - 01 to 12
  190. ;# %M minute - 00 to 59
  191. ;# %n insert a newline character
  192. ;# %p ante-meridiem or post-meridiem indicator (AM or PM)
  193. ;# %r time in AM/PM notation
  194. ;# %R time as HH:MM
  195. ;# %S second - 00 to 59
  196. ;# %t insert a tab character
  197. ;# %T time as HH:MM:SS
  198. ;# %u date/time in date(1) required format
  199. ;# %U week number, Sunday as first day of week - 00 to 53
  200. ;# %V date-time in SysV touch format (mmddHHMMyy)
  201. ;# %w day of week - 0 (Sunday) to 6
  202. ;# %W week number, Monday as first day of week - 00 to 53
  203. ;# %x date in local format [+]
  204. ;# %X time in local format [+]
  205. ;# %y last 2 digits of year - 00 to 99
  206. ;# %Y all 4 digits of year ~ 1700 to 2000 odd ?
  207. ;# %z time zone from TZ environment variable w/ a trailing space
  208. ;# %Z time zone from TZ environment variable
  209. ;# %% insert a `%' character
  210. ;# %+ insert a `+' character
  211. ;#
  212. ;# [+]:  These may need adjustment to fit local conventions, see below.
  213. ;#
  214. ;# For the sake of compatibility, a leading `+' in the format
  215. ;# specificaiton is removed if present.
  216. ;#
  217. ;# Remarks
  218. ;# This is version 3.4 of date.pl
  219. ;#
  220. ;# An extension of `ctime.pl' by Waldemar Kebsch (kebsch.pad@nixpbe.UUCP),
  221. ;# as modified by Marion Hakanson (hakanson@ogicse.ogi.edu).
  222. ;#
  223. ;#  Unlike date(1), unknown format tags are silently replaced by "".
  224. ;#
  225. ;#  defaultTZ is a blatant hack, but I wanted to be able to get date(1)
  226. ;# like behaviour by default and there does'nt seem to be an easy (read
  227. ;# portable) way to get the local TZ name back...
  228. ;#
  229. ;# For a cheap date, try...
  230. ;#
  231. ;# #!/usr/local/bin/perl
  232. ;# require "date.pl";
  233. ;# exit print (&date(time, shift @ARGV) . "n") ? 0 : 1;
  234. ;#
  235. ;# This package is redistributable under the same terms as apply to
  236. ;# the Perl 4.0 release.  See the COPYING file in your Perl kit for
  237. ;# more information.
  238. ;#
  239. ;# Please send any bug reports or comments to tmcgonigal@gallium.com
  240. ;#
  241. ;# Modification History
  242. ;# Nmemonic Version Date Who
  243. ;#
  244. ;# NONE 1.0 02feb91 Terry McGonigal (tmcgonigal@gallium.com)
  245. ;# Created from ctime.pl
  246. ;#
  247. ;# NONE 2.0 07feb91 tmcgonigal
  248. ;# Added some of Marion Hakanson (hakanson@ogicse.ogi.edu)'s ctime.pl
  249. ;# TZ handling changes.
  250. ;#
  251. ;# NONE 2.1 09feb91 tmcgonigal
  252. ;# Corrected week number calculations.
  253. ;#
  254. ;# NONE 2.2 21oct91 tmcgonigal
  255. ;# Added ls(1) date format, `%l'.
  256. ;#
  257. ;# NONE 2.3 06nov91 tmcgonigal
  258. ;# Added SysV touch(1) date-time format, `%V' (pretty thin as
  259. ;# mnemonics go, I know, but `t' and `T' were both gone already!)
  260. ;#
  261. ;# NONE 2.4 05jan92 tmcgonigal
  262. ;# Corrected slight (cosmetic) problem with %V replacment string
  263. ;#
  264. ;# NONE 3.0 09jul92 tmcgonigal
  265. ;# Fixed a couple of problems with &ls as pointed out by
  266. ;# Thomas Richter (richter@ki1.chemie.fu-berlin.de), thanks Thomas!
  267. ;# Also added a couple of SunOS 4.1.1 strftime-ish formats, %i and %k
  268. ;# for space padded hours (` 1' to `12' and ` 0' to `23' respectivly),
  269. ;# and %C for locale long date/time format.  Changed &ampmH to take a
  270. ;# pad char parameter to make to evaled code for %i and %k simpler. 
  271. ;# Added %E for suffixed day-of-month (ie 1st, 3rd, 4th etc).
  272. ;#
  273. ;# NONE 3.1 16jul92 tmcgonigal
  274. ;# Added `%u' format to generate date/time in date(1) required
  275. ;# format (ie '%y%m%d%H%M.%S').
  276. ;#
  277. ;# NONE 3.2 23jan93 tmcgonigal
  278. ;# Added `%f' format to generate space padded month numbers, added
  279. ;# `%E' to the header comments, it seems to have been left out (and
  280. ;# I'm sure I wanted to use it at some point in the past...).
  281. ;#
  282. ;# NONE 3.3 03feb93 tmcgonigal
  283. ;# Corrected some problems with AM/PM handling pointed out by
  284. ;# Michael S. Muegel (mmuegel@mot.com).  Thanks Michael, I hope
  285. ;# this is the behaviour you were looking for, it seems more
  286. ;# correct to me...
  287. ;#
  288. ;# NONE 3.4 26jul93 tmcgonigal
  289. ;# Incorporated some fixes provided by DaviD W. Sanderson
  290. ;# (dws@ssec.wisc.edu): February was spelled incorrectly and
  291. ;# &wkno() was always using the current year while calculating
  292. ;# week numbers, regardless of year implied by the time value
  293. ;# passed to &date().  DaviD also contributed an improved &date()
  294. ;# test script, thanks DaviD, I appreciate the effort.  Finally,
  295. ;# changed my mailling address from @gvc.com to @gallium.com
  296. ;# to reflect, well, my new address!
  297. ;#
  298. ;# SccsId = "%W% %E%"
  299. ;#
  300. require 'timelocal.pl';
  301. package date;
  302. X
  303. # Months of the year
  304. @MoY = ('January', 'February', 'March', 'April', 'May', 'June',
  305. X 'July', 'August', 'September','October', 'November', 'December');
  306. X
  307. # days of the week
  308. @DoW = ('Sunday', 'Monday', 'Tuesday', 'Wednesday',
  309. X 'Thursday', 'Friday', 'Saturday');
  310. X
  311. # CUSTOMIZE - defaults
  312. $defaultTZ = 'CST'; # time zone (hack!)
  313. $defaultFMT = '%a %h %e %T %z%Y'; # format (ala date(1))
  314. X
  315. # CUSTOMIZE - `local' formats
  316. $locTF = '%T'; # time (as HH:MM:SS)
  317. $locDF = '%D'; # date (as mm/dd/yy)
  318. $locDTF = '%a %b %d %T %Y'; # date/time (as dow mon dd HH:MM:SS yyyy)
  319. $locLDTF = '%i:%M:%S %p %A %B %E %Y'; # long date/time (as HH:MM:SS a/p day month dom yyyy)
  320. X
  321. # Time zone info
  322. $TZ; # wkno needs this info too
  323. X
  324. # define the known format tags as associative keys with their associated
  325. # replacement strings as values.  Each replacement string should be
  326. # an eval-able expresion assigning a value to $rep.  These expressions are
  327. # eval-ed, then the value of $rep is substituted into the supplied
  328. # format (if any).
  329. %Tags = ( '%a', q|($rep = $DoW[$wday])=~ s/^(...).*/1/|, # abbr. weekday name - Sun to Sat
  330. X   '%A', q|$rep = $DoW[$wday]|, # full weekday name - Sunday to Saturday
  331. X   '%b', q|($rep = $MoY[$mon]) =~ s/^(...).*/1/|, # abbr. month name - Jan to Dec
  332. X   '%B', q|$rep = $MoY[$mon]|, # full month name - January to December
  333. X   '%c', q|$rep = $locDTF; 1|, # date/time in local format
  334. X   '%C', q|$rep = $locLDTF; 1|, # date/time in local long format
  335. X   '%d', q|$rep = &date'pad($mday, 2, "0")|, # day of month - 01 to 31
  336. X   '%D', q|$rep = '%m/%d/%y'|, # date as mm/dd/yy
  337. X   '%e', q|$rep = &date'pad($mday, 2, " ")|, # day of month (space padded) ` 1' to `31'
  338. X   '%E', q|$rep = &date'dsuf($mday)|, # day of month (w/suffix) `1st' to `31st'
  339. X   '%f', q|$rep = &date'pad($mon+1, 2, " ")|, # month of year (space padded) ` 1' to `12'
  340. X   '%h', q|$rep = '%b'|, # abbr. month name (same as %b)
  341. X   '%H', q|$rep = &date'pad($hour, 2, "0")|, # hour - 00 to 23
  342. X   '%i', q|$rep = &date'ampmH($hour, " ")|, # hour (space padded ` 1' to `12'
  343. X   '%I', q|$rep = &date'ampmH($hour, "0")|, # hour - 01 to 12
  344. X   '%j', q|$rep = &date'pad($yday+1, 3, "0")|, # Julian date 001 - 366
  345. X   '%k', q|$rep = &date'pad($hour, 2, " ")|, # hour (space padded) ` 0' to `23'
  346. X   '%l', q|$rep = '%b %d ' . &date'ls($year)|, # ls(1) style date
  347. X   '%m', q|$rep = &date'pad($mon+1, 2, "0")|, # month of year - 01 to 12
  348. X   '%M', q|$rep = &date'pad($min, 2, "0")|, # minute - 00 to 59
  349. X   '%n', q|$rep = "n"|, # insert a newline
  350. X   '%p', q|$rep = &date'ampmD($hour)|, # insert `AM' or `PM'
  351. X   '%r', q|$rep = '%I:%M:%S %p'|, # time in AM/PM notation
  352. X   '%R', q|$rep = '%H:%M'|, # time as HH:MM
  353. X   '%S', q|$rep = &date'pad($sec, 2, "0")|, # second - 00 to 59
  354. X   '%t', q|$rep = "t"|, # insert a tab
  355. X   '%T', q|$rep = '%H:%M:%S'|, # time as HH:MM:SS
  356. X   '%u', q|$rep = '%y%m%d%H%M.%S'|, # daaate/time in date(1) required format
  357. X   '%U', q|$rep = &date'wkno($year, $yday, 0)|, # week number (weeks start on Sun) - 00 to 53
  358. X   '%V', q|$rep = '%m%d%H%M%y'|, # SysV touch(1) date-time format (mmddHHMMyy)
  359. X   '%w', q|$rep = $wday; 1|, # day of week - Sunday = 0
  360. X   '%W', q|$rep = &date'wkno($year, $yday, 1)|, # week number (weeks start on Mon) - 00 to 53
  361. X   '%x', q|$rep = $locDF; 1|, # date in local format
  362. X   '%X', q|$rep = $locTF; 1|, # time in local format
  363. X   '%y', q|($rep = $year) =~ s/..(..)/1/|, # last 2 digits of year - 00 to 99
  364. X   '%Y', q|$rep = "$year"; 1|, # full year ~ 1700 to 2000 odd
  365. X   '%z', q|$rep = $TZ eq "" ? "" : "$TZ "|, # time zone from TZ env var (w/trail. space)
  366. X   '%Z', q|$rep = $TZ; 1|, # time zone from TZ env. var.
  367. X   '%%', q|$rep = '%'; $adv=1|, # insert a `%'
  368. X   '%+', q|$rep = '+'| # insert a `+'
  369. );
  370. X
  371. sub main'date {
  372. X local($time, $format) = @_;
  373. X local($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst);
  374. X local($pos, $tag, $rep, $adv) = (0, "", "", 0);
  375. X
  376. X # default to date/ctime format or strip leading `+'...
  377. X if ($format eq "") {
  378. X $format = $defaultFMT;
  379. X } elsif ($format =~ /^+/) {
  380. X $format = $';
  381. X }
  382. X
  383. X # Use local time if can't find a TZ in the environment
  384. X $TZ = defined($ENV{'TZ'}) ? $ENV{'TZ'} : $defaultTZ;
  385. X ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = 
  386. X &gettime ($TZ, $time);
  387. X
  388. X # Hack to deal with 'PST8PDT' format of TZ
  389. X # Note that this can't deal with all the esoteric forms, but it
  390. X # does recognize the most common: [:]STDoff[DST[off][,rule]]
  391. X if ($TZ =~ /^([^:d+-,]{3,})([+-]?d{1,2}(:d{1,2}){0,2})([^d+-,]{3,})?/) {
  392. X $TZ = $isdst ? $4 : $1;
  393. X }
  394. X
  395. X # watch out in 2070...
  396. X $year += ($year < 70) ? 2000 : 1900;
  397. X
  398. X # now loop throught the supplied format looking for tags...
  399. X while (($pos = index ($format, '%')) != -1) {
  400. X
  401. X # grab the format tag
  402. X $tag = substr($format, $pos, 2);
  403. X $adv = 0; # for `%%' processing
  404. X
  405. X # do we have a replacement string?
  406. X if (defined $Tags{$tag}) {
  407. X
  408. X # trap dead evals...
  409. X if (! eval $Tags{$tag}) {
  410. X print STDERR "date.pl: internal error: eval for $tag failed: $@n";
  411. X return "";
  412. X }
  413. X } else {
  414. X $rep = "";
  415. X }
  416. X
  417. X # do the substitution
  418. X substr ($format, $pos, 2) =~ s/$tag/$rep/;
  419. X $pos++ if ($adv);
  420. X }
  421. X
  422. X $format;
  423. }
  424. X
  425. # dsuf - add `st', `nd', `rd', `th' to a date (ie 1st, 22nd, 29th)
  426. sub dsuf {
  427. X local ($mday) = @_;
  428. X
  429. X return $mday . 'st' if ($mday =~ m/.*1$/);
  430. X return $mday . 'nd' if ($mday =~ m/.*2$/);
  431. X return $mday . 'rd' if ($mday =~ m/.*3$/);
  432. X return $mday . 'th';
  433. }
  434. X
  435. # weekno - figure out week number
  436. sub wkno {
  437. X local ($year, $yday, $firstweekday) = @_;   
  438. X local ($jan1, @jan1, $wks);
  439. X
  440. X # figure out the `time' value for January 1 of the given year
  441. X $jan1 = &maketime ($TZ, 0, 0, 0, 1, 0, $year-1900);
  442. X
  443. X # figure out what day of the week January 1 was
  444. X @jan1= &gettime ($TZ, $jan1);
  445. X
  446. X # and calculate the week number
  447. X $wks = (($yday + ($jan1[6] - $firstweekday)) + 1)/ 7;
  448. X $wks += (($wks - int($wks) > 0.0) ? 1 : 0);
  449. X
  450. X # supply zero padding
  451. X &pad (int($wks), 2, "0");
  452. }
  453. X
  454. # ampmH - figure out am/pm (1 - 12) mode hour value, padded with $p (0 or ' ')
  455. sub ampmH { local ($h, $p) = @_;  &pad($h>12 ? $h-12 : ($h ? $h : 12), 2, $p); }
  456. X
  457. # ampmD - figure out am/pm designator
  458. sub ampmD { shift @_ >= 12 ? "PM" : "AM"; }
  459. X
  460. # gettime - get the time via {local,gmt}time
  461. sub gettime { ((shift @_) eq 'GMT') ? gmtime(shift @_) : localtime(shift @_); }
  462. X
  463. # maketime - make a time via time{local,gmt}
  464. sub maketime { ((shift @_) eq 'GMT') ? &main'timegm(@_) : &main'timelocal(@_); }
  465. X
  466. # ls - generate the time/year portion of an ls(1) style date
  467. sub ls {
  468. X return ((&gettime ($TZ, time))[5] == @_[0]) ? "%R" : " %Y";
  469. }
  470. X
  471. # pad - pad $in with leading $pad until lenght $len
  472. sub pad {
  473. X local ($in, $len, $pad) = @_;
  474. X local ($out) = "$in";
  475. X
  476. X $out = $pad . $out until (length ($out) == $len);
  477. X return $out;
  478. }
  479. X
  480. 1;
  481. SHAR_EOF
  482. chmod 0444 libs/date.pl ||
  483. echo 'restore of libs/date.pl failed'
  484. Wc_c="`wc -c < 'libs/date.pl'`"
  485. test 12339 -eq "$Wc_c" ||
  486. echo 'libs/date.pl: original size 12339, current size' "$Wc_c"
  487. fi
  488. # ============= libs/elapsed.pl ==============
  489. if test -f 'libs/elapsed.pl' -a X"$1" != X"-c"; then
  490. echo 'x - skipping libs/elapsed.pl (File already exists)'
  491. else
  492. echo 'x - extracting libs/elapsed.pl (Text)'
  493. sed 's/^X//' << 'SHAR_EOF' > 'libs/elapsed.pl' &&
  494. ;# NAME
  495. ;#    elapsed.pl - convert seconds to elapsed time format
  496. ;#
  497. ;# AUTHOR
  498. ;#    Michael S. Muegel <mmuegel@mot.com>
  499. ;#
  500. ;# RCS INFORMATION
  501. ;#    mmuegel
  502. ;#    /usr/local/ustart/src/mail-tools/dist/foo/libs/elapsed.pl,v
  503. ;#    1.1 of 1993/07/28 08:07:19
  504. X
  505. package elapsed;
  506. X
  507. # Time field types
  508. $DAYS = 1;
  509. $HOURS = 2;
  510. $MINUTES = 3;
  511. $SECONDS = 4;
  512. X
  513. # The array contains four records each with four fields. The fields are,
  514. # in order:
  515. #
  516. #    Type Specifies what kind of time field this is. Once of
  517. # $DAYS, $HOURS, $MINUTES, or $SECONDS.
  518. #
  519. #    Multiplier Specifies what time field this is via the minimum
  520. # number of seconds this time field may specify. For
  521. # example, the minutes field would be non-zero
  522. # when there are 60 or more seconds.
  523. #
  524. #    Separator How to separate this time field from the next
  525. # *greater* field.
  526. #
  527. #    Format sprintf() format specifier on how to print this
  528. # time field.
  529. @MULT_AND_SEPS = ($DAYS, 60 * 60 * 24, "+", "%d",
  530. X                  $HOURS, 60 * 60, ":", "%d",
  531. X                  $MINUTES, 60, ":", "%02d",
  532. X                  $SECONDS, 1, "", "%02d"
  533. X                 );
  534. X
  535. ;###############################################################################
  536. ;# Seconds_To_Elapsed
  537. ;#
  538. ;# Coverts a seconds count to form [d+]h:mm:ss. If $Collapse
  539. ;# is true then the result is compacted somewhat. The string returned
  540. ;# will be of the form [d+][[h:]mm]:ss.
  541. ;#
  542. ;# Arguments:
  543. ;#    $Seconds, $Collapse
  544. ;#
  545. ;# Examples:
  546. ;#    &Seconds_To_Elapsed (0, 0)  -> 0:00:00
  547. ;#    &Seconds_To_Elapsed (0, 1)  -> :00
  548. ;#
  549. ;#    &Seconds_To_Elapsed (119, 0)  -> 0:01:59
  550. ;#    &Seconds_To_Elapsed (119, 1)  -> 01:59
  551. ;#
  552. ;#    &Seconds_To_Elapsed (3601, 0)  -> 1:00:01
  553. ;#    &Seconds_To_Elapsed (3601, 1)  -> 1:00:01
  554. ;#
  555. ;#    &Seconds_To_Elapsed (86401, 0)  -> 1+0:00:01
  556. ;#    &Seconds_To_Elapsed (86401, 1)  -> 1+:01
  557. ;#
  558. ;# Returns:
  559. ;#    $Elapsed
  560. ;###############################################################################
  561. sub main'Seconds_To_Elapsed
  562. {
  563. X   local ($Seconds, $Collapse) = @_;
  564. X   local ($Type, $Multiplier, @Multipliers, $Separator, $DHMS_Used, 
  565. X          $Elapsed, @Mult_And_Seps, $Print_Field);
  566. X
  567. X   $Multiplier = 1;
  568. X   @Mult_And_Seps = @MULT_AND_SEPS;
  569. X
  570. X   # Keep subtracting the number of seconds corresponding to a time field
  571. X   # from the number of seconds passed to the function.
  572. X   while (1)
  573. X   {
  574. X      ($Type, $Multiplier, $Separator, $Format) = splice (@Mult_And_Seps, 0, 4);
  575. X      last if (! $Multiplier);
  576. X      $Seconds -= $DHMS_Used * $Multiplier 
  577. X         if ($DHMS_Used = int ($Seconds / $Multiplier));
  578. X
  579. X      # Figure out if we should print this field
  580. X      if ($Type == $DAYS)
  581. X      {
  582. X  $Print_Field = $DHMS_Used;
  583. X      }
  584. X
  585. X      elsif ($Collapse)
  586. X      {
  587. X  if ($Type == $HOURS)
  588. X  {
  589. X     $Print_Field = $DHMS_Used;
  590. X  }
  591. X  elsif ($Type == $MINUTES)
  592. X  {
  593. X     $Print_Field = $DHMS_Used || $Printed_Field {$HOURS};
  594. X  }
  595. X  else
  596. X  {
  597. X     $Format = ":%02d" 
  598. X        if (! $Printed_Field {$MINUTES});
  599. X     $Print_Field = 1;
  600. X  };
  601. X      }
  602. X
  603. X      else
  604. X      {
  605. X  $Print_Field = 1;
  606. X      };
  607. X
  608. X      $Printed_Field {$Type} = $Print_Field;
  609. X      $Elapsed .= sprintf ("$Format%s", $DHMS_Used, $Separator) 
  610. X  if ($Print_Field);
  611. X   };
  612. X
  613. X   return ($Elapsed);
  614. };
  615. X
  616. 1;
  617. SHAR_EOF
  618. chmod 0444 libs/elapsed.pl ||
  619. echo 'restore of libs/elapsed.pl failed'
  620. Wc_c="`wc -c < 'libs/elapsed.pl'`"
  621. test 3198 -eq "$Wc_c" ||
  622. echo 'libs/elapsed.pl: original size 3198, current size' "$Wc_c"
  623. fi
  624. # ============= libs/mail.pl ==============
  625. if test -f 'libs/mail.pl' -a X"$1" != X"-c"; then
  626. echo 'x - skipping libs/mail.pl (File already exists)'
  627. else
  628. echo 'x - extracting libs/mail.pl (Text)'
  629. sed 's/^X//' << 'SHAR_EOF' > 'libs/mail.pl' &&
  630. ;# NAME
  631. ;#    mail.pl - perl function(s) to handle mail processing
  632. ;#
  633. ;# AUTHOR
  634. ;#    Michael S. Muegel (mmuegel@mot.com)
  635. ;#
  636. ;# RCS INFORMATION
  637. ;#    mmuegel
  638. ;#    /usr/local/ustart/src/mail-tools/dist/foo/libs/mail.pl,v 1.1 1993/07/28 08:07:19 mmuegel Exp
  639. X
  640. package mail;
  641. X
  642. # Mailer statement to eval. $Users, $Subject, and $Verbose are substituted 
  643. # via eval
  644. $BIN_MAILER  = "/usr/ucb/mail $Verbose -s '$Subject' $Users";
  645. X
  646. # Sendmail command to use when $Use_Sendmail is true.
  647. $SENDMAIL = '/usr/lib/sendmail $Verbose $Users';
  648. X
  649. ;###############################################################################
  650. ;# Send_Mail
  651. ;#
  652. ;# Sends $Message to $Users with a subject of $Subject. If $Message_Is_File
  653. ;# is true then $Message is assumed to be a filename pointing to the mail
  654. ;# message. This is a new option and thus the backwards-compatible hack.
  655. ;# $Users should be a space separated list of mail-ids.
  656. ;#
  657. ;# If everything went OK $Status will be 1 and $Error_Msg can be ignored; 
  658. ;# otherwise, $Status will be 0 and $Error_Msg will contain an error message.
  659. ;# 
  660. ;# If $Use_Sendmail is 1 then sendmail is used to send the message. Normally
  661. ;# a mailer such as Mail is used. By specifiying this you can include 
  662. ;# headers in addition to text in either $Message or $Message_Is_File.
  663. ;# If either $Message or $Message_Is_File contain a Subject: header then
  664. ;# $Subject is ignored; otherwise, a Subject: header is automatically created.
  665. ;# Similar to the Subject: header, if a To: header does not exist one
  666. ;# is automatically created from the $Users argument. The mail is still
  667. ;# sent, however, to the recipients listed in $Users. This is keeping with
  668. ;# normal sendmail usage (header vs. envelope).
  669. ;# 
  670. ;# In both bin mailer and sendmail modes $Verbose will turn on verbose mode
  671. ;# (normally just sendmail verbose mode output).
  672. ;#
  673. ;# Arguments:
  674. ;#    $Users, $Subject, $Message, $Message_Is_File, $Verbose, $Use_Sendmail
  675. ;#
  676. ;# Returns:
  677. ;#    $Status, $Error_Msg
  678. ;###############################################################################
  679. sub main'Send_Mail
  680. {
  681. X   local ($Users, $Subject, $Message, $Message_Is_File, $Verbose, 
  682. X   $Use_Sendmail) = @_;
  683. X   local ($BIN_MAILER_HANDLE, $Mailer_Command, $Header_Found, %Header_Map,
  684. X   $Header_Extra, $Mailer);
  685. X
  686. X   # If the message is contained in a file read it in so we can have one
  687. X   # consistent interface
  688. X   if ($Message_Is_File)
  689. X   {
  690. X      undef $/;
  691. X      $Message_Is_File = 0;
  692. X      open (Message) || return (0, "error reading $Message: $!");
  693. X      $Message = <Message>;
  694. X      close (Message);
  695. X   };
  696. X
  697. X   # If sendmail mode see if we need to add some headers
  698. X   if ($Use_Sendmail)
  699. X   {
  700. X      # Determine if a header block is included in the message and what headers
  701. X      # are there
  702. X      foreach (split (/n/, $Message))
  703. X      {
  704. X  last if ($_ eq "");
  705. X  $Header_Found = $Header_Map {$1} = 1 if (/^([A-Z]S*): /);
  706. X      };
  707. X
  708. X      # Add some headers?
  709. X      if (! $Header_Map {"To"})
  710. X      {
  711. X  $Header_Extra .= "To: " . join (", ", $Users) . "n";
  712. X      };
  713. X      if (($Subject ne "") && (! $Header_Map {"Subject"}))
  714. X      {
  715. X  $Header_Extra .= "Subject: $Subjectn";
  716. X      };
  717. X
  718. X      # Add the required blank line between header/body if there where no
  719. X      # headers to begin with
  720. X      if ($Header_Found)
  721. X      {
  722. X         $Message = "$Header_Extra$Message";
  723. X      }
  724. X      else
  725. X      {
  726. X  $Message = "$Header_Extran$Message";
  727. X      };
  728. X   };
  729. X
  730. X   # Get a string that is the mail command
  731. X   $Verbose = ($Verbose) ? "-v" : "";
  732. X   $Mailer = ($Use_Sendmail) ? $SENDMAIL : $BIN_MAILER;
  733. X   eval "$Mailer = "$Mailer"";
  734. X   return (0, "error setting $Mailer: $@") if ($@);
  735. X
  736. X   # need to catch SIGPIPE in case the $Mailer call fails
  737. X   $SIG {'PIPE'} = "mail'Cleanup";
  738. X
  739. X   # Open mailer
  740. X   return (0, "can not open mail program: $Mailer") if (! open (MAILER, "| $Mailer"));
  741. X   
  742. X   # Send off the mail!
  743. X   print MAILER $Message;
  744. X   close (MAILER);
  745. X   return (0, "error running mail program: $Mailer") if ($?);
  746. X   
  747. X   # Everything must have went AOK
  748. X   return (1);
  749. };
  750. X
  751. ;###############################################################################
  752. ;# Cleanup
  753. ;#
  754. ;# Simply here so we can catch SIGPIPE and not exit.
  755. ;#
  756. ;# Globals:
  757. ;#    None
  758. ;#
  759. ;# Arguments:
  760. ;#    None
  761. ;#
  762. ;# Returns:
  763. ;#    Nothing exciting
  764. ;###############################################################################
  765. sub Cleanup
  766. {
  767. };
  768. X
  769. 1;
  770. SHAR_EOF
  771. chmod 0444 libs/mail.pl ||
  772. echo 'restore of libs/mail.pl failed'
  773. Wc_c="`wc -c < 'libs/mail.pl'`"
  774. test 4356 -eq "$Wc_c" ||
  775. echo 'libs/mail.pl: original size 4356, current size' "$Wc_c"
  776. fi
  777. # ============= libs/mqueue.pl ==============
  778. if test -f 'libs/mqueue.pl' -a X"$1" != X"-c"; then
  779. echo 'x - skipping libs/mqueue.pl (File already exists)'
  780. else
  781. echo 'x - extracting libs/mqueue.pl (Text)'
  782. sed 's/^X//' << 'SHAR_EOF' > 'libs/mqueue.pl' &&
  783. ;# NAME
  784. ;#    mqueue.pl - functions to work with the sendmail queue
  785. ;#
  786. ;# DESCRIPTION
  787. ;#    Both Get_Queue_IDs and Parse_Control_File are available to get 
  788. ;#    information about the sendmail queue. The cqueue program is a good
  789. ;#    example of how these functions work.
  790. ;#
  791. ;# AUTHOR
  792. ;#    Michael S. Muegel (mmuegel@mot.com)  
  793. ;#
  794. ;# RCS INFORMATION
  795. ;#    mmuegel
  796. ;#    /usr/local/ustart/src/mail-tools/dist/foo/libs/mqueue.pl,v
  797. ;#    1.1 of 1993/07/28 08:07:19
  798. X
  799. package mqueue;
  800. X
  801. ;###############################################################################
  802. ;# Get_Queue_IDs
  803. ;#
  804. ;# Will figure out the queue IDs in $Queue that have both control and data
  805. ;# files. They are returned in @Valid_IDs. Those IDs that have a
  806. ;# control file and no data file are saved to the array globbed by 
  807. ;# *Missing_Control_IDs. Likewise, those IDs that have a data file and no 
  808. ;# control file are saved to the array globbed by *Missing_Data_IDs.
  809. ;#
  810. ;# If $Skip_Locked is true they a message that has a lock file is skipped
  811. ;# and will not show up in any of the arrays.
  812. ;#
  813. ;# If everything went AOK then $Status is 1; otherwise, $Status is 0 and
  814. ;# $Msg tells what went wrong.
  815. ;#
  816. ;# Globals:
  817. ;#    None
  818. ;#
  819. ;# Arguments:
  820. ;#    $Queue, $Skip_Locked, *Missing_Control_IDs, *Missing_Data_IDs
  821. ;#
  822. ;# Returns:
  823. ;#    $Status, $Msg, @Valid_IDs
  824. ;###############################################################################
  825. sub main'Get_Queue_IDs
  826. {
  827. X   local ($Queue, $Skip_Locked, *Missing_Control_IDs, 
  828. X          *Missing_Data_IDs) = @_;
  829. X   local (*QUEUE, @Files, %Lock_IDs, %Data_IDs, %Control_IDs, $_);
  830. X
  831. X   # Make sure that the * argument @arrays ar empty
  832. X   @Missing_Control_IDs = @Missing_Data_IDs = ();
  833. X
  834. X   # Save each data, lock, and queue file in @Files
  835. X   opendir (QUEUE, $Queue) || return (0, "error getting directory listing of $Queue");
  836. X   @Files = grep (/^(df|lf|qf)/, readdir (QUEUE));
  837. X   closedir (QUEUE);
  838. X   
  839. X   # Create indexed list of data and control files. IF $Skip_Locked is true
  840. X   # then skip either if there is a lock file present.
  841. X   if ($Skip_Locked)
  842. X   {
  843. X      grep ((s/^lf//) && ($Lock_IDs {$_} = 1), @Files);
  844. X      grep ((s/^df//) && (! $Lock_IDs {$_}) && ($Data_IDs {$_} = 1), @Files);
  845. X      grep ((s/^qf//) && (! $Lock_IDs {$_}) && ($Control_IDs {$_} = 1), @Files);
  846. X   }
  847. X   else
  848. X   {
  849. X      grep ((s/^df//) && ($Data_IDs {$_} = 1), @Files);
  850. X      grep ((s/^qf//) && ($Control_IDs {$_} = 1), @Files);
  851. X   };
  852. X   
  853. X   # Find missing control and data files and remove them from the lists of each
  854. X   @Missing_Control_IDs = sort (grep ((! $Control_IDs {$_}) && (delete $Data_IDs {$_}), keys (%Data_IDs)));
  855. X   @Missing_Data_IDs = sort (grep ((! $Data_IDs {$_} && (delete $Control_IDs {$_})), keys (%Control_IDs)));
  856. X   
  857. X   
  858. X   # Return the IDs in an appartently random order
  859. X   return (1, "", keys (%Control_IDs));
  860. };
  861. X
  862. X
  863. ;###############################################################################
  864. ;# Parse_Control_File
  865. ;#
  866. ;# Will pase a sendmail queue control file for useful information. See the
  867. ;# Sendmail Installtion and Operation Guide (SMM:07) for a complete
  868. ;# explanation of each field.
  869. ;#
  870. ;# The following globbed variables are set (or cleared) by this function:
  871. ;#
  872. ;#    $Sender           The sender's address. 
  873. ;#
  874. ;#    @Recipients       One or more addresses for the recipient of the mail.
  875. ;#
  876. ;#    @Errors_To        One or more addresses for addresses to which mail
  877. ;#                      delivery errors should be sent.
  878. ;#
  879. ;#    $Creation_Time    The job creation time in time(3) format. That is,
  880. ;#                      seconds since 00:00:00 GMT 1/1/70.
  881. ;#
  882. ;#    $Priority         An integer representing the current message priority.
  883. ;#                      This is used to order the queue. Higher numbers mean 
  884. ;#                      lower priorities.
  885. ;#
  886. ;#    $Status_Message   The status of the mail message. It can contain any
  887. ;#                      text.
  888. ;#
  889. ;#    @Headers          Message headers unparsed but in their original order.
  890. ;#                      Headers that span multiple lines are not mucked with,
  891. ;#                      embedded ns will be evident.
  892. ;#
  893. ;# In all e-mail addresses bounding <> pairs are stripped.
  894. ;#
  895. ;# If everything went AOK then $Status is 1. If the message with queue ID
  896. ;# $Queue_ID just does not exist anymore -1 is returned. This is very
  897. ;# possible and should be allowed for. Otherwise, $Status is 0 and $Msg 
  898. ;# tells what went wrong.
  899. ;#
  900. ;# Globals:
  901. ;#    None
  902. ;#
  903. ;# Arguments:
  904. ;#    $Queue, $Queue_ID, *Sender, *Recipients, *Errors_To, *Creation_Time, 
  905. ;#    *Priority, *Status_Message, *Headers
  906. ;#
  907. ;# Returns:
  908. ;#    $Status, $Msg
  909. ;###############################################################################
  910. sub main'Parse_Control_File
  911. {
  912. X   local ($Queue, $Queue_ID, *Sender, *Recipients, *Errors_To, *Creation_Time,
  913. X          *Priority, *Status_Message, *Headers) = @_;
  914. X   local (*Control, $_, $Not_Empty);
  915. X
  916. X   # Required variables and the associated control. If empty at the end of
  917. X   # parsing we return a bad status.
  918. X   @REQUIRED_INFO = ('$Creation_Time', 'T', '$Sender', 'S', '@Recipients', 'R',
  919. X      '$Priority', 'P');
  920. X
  921. X   # Open up the control file for read
  922. X   $Control = "$Queue/qf$Queue_ID";
  923. X   if (! open (Control)) 
  924. X   {
  925. X      return (-1) if ((-x $Queue) && (! -f "$Queue/qf$Queue_ID") &&
  926. X       (! -f "$Queue/df$Queue_ID"));
  927. X      return (0, "error opening $Control for read: $!");
  928. X   };
  929. X
  930. X   # Reset the globbed variables just in case
  931. X   $Sender = $Creation_Time = $Priority = $Status_Message = "";
  932. X   @Recipients = @Errors_To = @Headers = ();
  933. X
  934. X   # Look for a few things in the control file
  935. X   READ: while (<Control>)
  936. X   {
  937. X      $Not_Empty = 1;
  938. X      chop;
  939. X
  940. X      PARSE:
  941. X      {
  942. X         if (/^T(d+)$/)
  943. X         {
  944. X            $Creation_Time = $1;
  945. X         }
  946. X         elsif (/^S(<)?([^>]+)/)
  947. X         {
  948. X            $Sender = $2;
  949. X         }
  950. X         elsif (/^R(<)?([^>]+)/)
  951. X         {
  952. X            push (@Recipients, $2);
  953. X         }
  954. X         elsif (/^E(<)?([^>]+)/)
  955. X         {
  956. X            push (@Errors_To, $2);
  957. X         }
  958. X         elsif (/^M(.*)/)
  959. X         {
  960. X            $Status_Message = $1;
  961. X         }
  962. X         elsif (/^P(d+)$/)
  963. X         {
  964. X            $Priority = $1;
  965. X         }
  966. X         elsif (/^H(.*)/)
  967. X         {
  968. X            $Header = $1;
  969. X            while (<Control>)
  970. X            {
  971. X               chop;
  972. X               last if (/^[A-Z]/);
  973. X               $Header .= "n$_";
  974. X            };
  975. X            push (@Headers, $Header);
  976. X     redo PARSE if ($_);
  977. X     last if (eof);
  978. X         };
  979. X      };
  980. X   };
  981. X
  982. X   # If the file was empty scream bloody murder
  983. X   return (0, "empty control file") if (! $Not_Empty);
  984. X
  985. X   # Yell if we could not find a required field
  986. X   while (($Var, $Control) = splice (@REQUIRED_INFO, 0, 2))
  987. X   {
  988. X      eval "return (0, 'required control field $Control not found')
  989. X        if (! $Var)";
  990. X      return (0, "error checking $Var: $@") if ($@);
  991. X   };
  992. X
  993. X   # Everything went AOK
  994. X   return (1);
  995. };
  996. X
  997. 1;
  998. SHAR_EOF
  999. chmod 0444 libs/mqueue.pl ||
  1000. echo 'restore of libs/mqueue.pl failed'
  1001. Wc_c="`wc -c < 'libs/mqueue.pl'`"
  1002. test 6908 -eq "$Wc_c" ||
  1003. echo 'libs/mqueue.pl: original size 6908, current size' "$Wc_c"
  1004. fi
  1005. # ============= libs/newgetopts.pl ==============
  1006. if test -f 'libs/newgetopts.pl' -a X"$1" != X"-c"; then
  1007. echo 'x - skipping libs/newgetopts.pl (File already exists)'
  1008. else
  1009. echo 'x - extracting libs/newgetopts.pl (Text)'
  1010. sed 's/^X//' << 'SHAR_EOF' > 'libs/newgetopts.pl' &&
  1011. ;# NAME
  1012. ;#    newgetopts.pl - a better newgetopt (which is a better getopts which is
  1013. ;#                    a better getopt ;-)
  1014. ;#
  1015. ;# AUTHOR
  1016. ;#    Mike Muegel (mmuegel@mot.com)
  1017. ;#
  1018. ;# mmuegel
  1019. ;# /usr/local/ustart/src/mail-tools/dist/foo/libs/newgetopts.pl,v 1.1 1993/07/28 08:07:19 mmuegel Exp
  1020. X
  1021. ;###############################################################################
  1022. ;# New_Getopts
  1023. ;#
  1024. ;# Does not care about order of switches, options, and arguments like 
  1025. ;# getopts.pl. Thus all non-switches/options will be kept in ARGV even if they
  1026. ;# are not at the end. If $Pass_Invalid is set all unkown options will be
  1027. ;# passed back to the caller by keeping them in @ARGV. This is useful when
  1028. ;# parsing a command line for your script while ignoring options that you
  1029. ;# may pass to another script. If this is set New_Getopts tries to maintain 
  1030. ;# the switch clustering on the unkown switches.
  1031. ;#
  1032. ;# Accepts the special argument -usage to print the Usage string. Also accepts 
  1033. ;# the special option -version which prints the contents of the string 
  1034. ;# $VERSION. $VERSION may or may not have an embeded n in it. If -usage 
  1035. ;# or -version are specified a status of -1 is returned. Note that the usage
  1036. ;# option is only accepted if the usage string is not null.
  1037. ;# 
  1038. ;# $Switches is just like the formal arguemnt of getopts.pl. $Usage is a usage
  1039. ;# string with or without a trailing n. *Switch_To_Order is an optional
  1040. ;# pointer to the name of an associative array which will contain a mapping of
  1041. ;# switch names to the order in which (if at all) the argument was entered.
  1042. ;#
  1043. ;# For example, if @ARGV contains -v, -x, test:
  1044. ;#
  1045. ;#    $Switch_To_Order {"v"} = 1;
  1046. ;#    $Switch_To_Order {"x"} = 2;
  1047. ;#
  1048. ;# Note that in the case of multiple occurances of an option $Switch_To_Order
  1049. ;# will store each occurance of the argument via a string that emulates
  1050. ;# an array. This is done by using join ($;, ...). You can retrieve the
  1051. ;# array by using split (/$;/, ...).
  1052. ;#
  1053. ;# *Split_ARGV is an optional pointer to an array which will conatin the
  1054. ;# original switches along with their values. For the example used above 
  1055. ;# Split_ARGV would contain:
  1056. ;#
  1057. ;#   @Split_ARGV = ("v", "", "x", "test");
  1058. ;#
  1059. ;# Another exciting ;-) feature that newgetopts has. Along with creating the 
  1060. ;# normal $opt_ scalars for the last value of an argument the list @opt_ is 
  1061. ;# created. It is an array which contains all the values of arguments to the 
  1062. ;# basename of the variable. They are stored in the order which they occured 
  1063. ;# on the command line starting with $[. Note that blank arguments are stored 
  1064. ;# as "". Along with providing support for multiple options on the command 
  1065. ;# line this also provides a method of counting the number of times an option 
  1066. ;# was specified via $#opt_.
  1067. ;#
  1068. ;# Automatically resets all $opt_, @opt_, %Switch_To_Order, and @Split_ARGV
  1069. ;# variables so that New_Getopts may be called more than once from within
  1070. ;# the same program. Thus, if $opt_v is set upon entry to New_Getopts and 
  1071. ;# -v is not in @ARGV $opt_v will not be set upon exit.
  1072. ;#
  1073. ;# Arguments:
  1074. ;#    $Switches, $Usage, $Pass_Invalid, *Switch_To_Order, *Split_ARGV
  1075. ;#
  1076. ;# Returns:
  1077. ;#    -1, 0, or 1 depending on status (printed Usage/Version, OK, not OK)
  1078. ;###############################################################################
  1079. sub New_Getopts 
  1080. {
  1081. X    local($taint_argumentative, $Usage, $Pass_Invalid, *Switch_To_Order,
  1082. X          *Split_ARGV) = @_;
  1083. X    local(@args,$_,$first,$rest,$errs, @leftovers, @current_leftovers,
  1084. X          %Switch_Found);
  1085. X    local($[, $*, $Script_Name, $argumentative);
  1086. X
  1087. X    # Untaint the argument cluster so that we can use this with taintperl
  1088. X    $taint_argumentative =~ /^(.*)$/;
  1089. X    $argumentative = $1;
  1090. X
  1091. X    # Clear anything that might still be set from a previous New_Getopts
  1092. X    # call.
  1093. X    @Split_ARGV = ();
  1094. X
  1095. X    # Get the basename of the calling script
  1096. X    ($Script_Name = $0) =~ s/.*///;
  1097. X    
  1098. X    # Make Usage have a trailing n
  1099. X    $Usage .= "n" if ($Usage !~ /n$/);
  1100. X
  1101. X    @args = split( / */, $argumentative );
  1102. X
  1103. X    # Clear anything that might still be set from a previous New_Getopts call.
  1104. X    foreach $first (@args)
  1105. X    {
  1106. X       next if ($first eq ":");
  1107. X       delete $Switch_Found {$first};
  1108. X       delete $Switch_To_Order {$first};
  1109. X       eval "undef @opt_$first; undef $opt_$first;";
  1110. X    };
  1111. X
  1112. X    while (@ARGV)
  1113. X    {
  1114. X        # Let usage through
  1115. X        if (($ARGV[0] eq "-usage") && ($Usage ne "n"))
  1116. X        {
  1117. X           print $Usage;
  1118. X           exit (-1);
  1119. X        }
  1120. X
  1121. X        elsif ($ARGV[0] eq "-version")
  1122. X        {
  1123. X           if ($VERSION)
  1124. X           {
  1125. X              print $VERSION;
  1126. X              print "n" if ($VERSION !~ /n$/);
  1127. X           }
  1128. X           else
  1129. X           {
  1130. X              warn "${Script_Name}: no version information available, sorryn";
  1131. X           }
  1132. X           exit (-1);
  1133. X        }
  1134. X
  1135. X        elsif (($_ = $ARGV[0]) =~ /^-(.)(.*)/)
  1136. X        {
  1137. X           ($first,$rest) = ($1,$2);
  1138. X           $pos = index($argumentative,$first);
  1139. X
  1140. X           $Switch_To_Order {$first} = join ($;, split (/$;/, $Switch_To_Order {$first}), ++$Order);
  1141. X
  1142. X           if($pos >= $[) 
  1143. X           {
  1144. X               if($args[$pos+1] eq ':') 
  1145. X               {
  1146. X                   shift(@ARGV);
  1147. X                   if($rest eq '') 
  1148. X                   {
  1149. X                       $rest = shift(@ARGV);
  1150. X                   }
  1151. X
  1152. X                   eval "$opt_$first = $rest;";
  1153. X                   eval "push (@opt_$first, $rest);";
  1154. X                   push (@Split_ARGV, $first, $rest);
  1155. X               }
  1156. X               else 
  1157. X               {
  1158. X                   eval "$opt_$first = 1";
  1159. X                   eval "push (@opt_$first, '');";
  1160. X                   push (@Split_ARGV, $first, "");
  1161. X
  1162. X                   if($rest eq '') 
  1163. X                   {
  1164. X                       shift(@ARGV);
  1165. X                   }
  1166. X                   else 
  1167. X                   {
  1168. X                       $ARGV[0] = "-$rest";
  1169. X                   }
  1170. X               }
  1171. X           }
  1172. X
  1173. X           else 
  1174. X           {
  1175. X               # Save any other switches if $Pass_Valid
  1176. X               if ($Pass_Invalid)
  1177. X               {
  1178. X                  push (@current_leftovers, $first);
  1179. X               }
  1180. X               else
  1181. X               {
  1182. X                  warn "${Script_Name}: unknown option: $firstn";
  1183. X                  ++$errs;
  1184. X               };
  1185. X               if($rest ne '') 
  1186. X               {
  1187. X                   $ARGV[0] = "-$rest";
  1188. X               }
  1189. X               else 
  1190. X               {
  1191. X                   shift(@ARGV);
  1192. X               }
  1193. X           }
  1194. X        }
  1195. X
  1196. X        else
  1197. X        {
  1198. X           push (@leftovers, shift (@ARGV));
  1199. X        };
  1200. X
  1201. X        # Save any other switches if $Pass_Valid
  1202. X        if ((@current_leftovers) && ($rest eq ''))
  1203. X        {
  1204. X           push (@leftovers, "-" . join ("", @current_leftovers));
  1205. X           @current_leftovers = ();
  1206. X        };
  1207. X    };
  1208. X
  1209. X    # Automatically print Usage if a warning was given
  1210. X    @ARGV = @leftovers;
  1211. X    if ($errs != 0)
  1212. X    {
  1213. X       warn $Usage;
  1214. X       return (0);
  1215. X    }
  1216. X    else
  1217. X    {
  1218. X       return (1);
  1219. X    }
  1220. X       
  1221. }
  1222. X
  1223. 1;
  1224. SHAR_EOF
  1225. chmod 0444 libs/newgetopts.pl ||
  1226. echo 'restore of libs/newgetopts.pl failed'
  1227. Wc_c="`wc -c < 'libs/newgetopts.pl'`"
  1228. test 7024 -eq "$Wc_c" ||
  1229. echo 'libs/newgetopts.pl: original size 7024, current size' "$Wc_c"
  1230. fi
  1231. # ============= libs/strings1.pl ==============
  1232. if test -f 'libs/strings1.pl' -a X"$1" != X"-c"; then
  1233. echo 'x - skipping libs/strings1.pl (File already exists)'
  1234. else
  1235. echo 'x - extracting libs/strings1.pl (Text)'
  1236. sed 's/^X//' << 'SHAR_EOF' > 'libs/strings1.pl' &&
  1237. ;# NAME
  1238. ;#    strings1.pl - FUN with strings #1
  1239. ;#
  1240. ;# NOTES
  1241. ;#    I wrote Format_Text_Block when I just started programming Perl so
  1242. ;#    it is probably not very Perlish code. Center is more like it :-).
  1243. ;#
  1244. ;# AUTHOR
  1245. ;#    Michael S. Muegel (mmuegel@mot.com)
  1246. ;#
  1247. ;# RCS INFORMATION
  1248. ;#    mmuegel
  1249. ;#    /usr/local/ustart/src/mail-tools/dist/foo/libs/strings1.pl,v 1.1 1993/07/28 08:07:19 mmuegel Exp
  1250. X
  1251. package strings1;
  1252. X
  1253. ;###############################################################################;# Center
  1254. ;#
  1255. ;# Center $Text assuming the output should be $Columns wide. $Text can span
  1256. ;# multiple lines, of course :-). Lines within $Text that contain only 
  1257. ;# whitespace are not centered and are instead collapsed. This may save time 
  1258. ;# when printing them later.
  1259. ;#
  1260. ;# Arguments:
  1261. ;#    $Text, $Columns
  1262. ;#
  1263. ;# Returns:
  1264. ;#    $Centered_Text
  1265. ;###############################################################################
  1266. sub main'Center
  1267. {
  1268. X   local ($_, $Columns) = @_;
  1269. X   local ($*) = 1;
  1270. X
  1271. X   s@^(.*)$@" " x (($Columns - length ($1)) / 2) . $1@eg;
  1272. X   s/^[t ]*$//g;
  1273. X   return ($_);
  1274. };
  1275. X
  1276. ;###############################################################################
  1277. ;# Format_Text_Block
  1278. ;#
  1279. ;# Formats a text string to be printed to the display or other similar device.
  1280. ;# Text in $String will be fomratted such that the following hold:
  1281. ;#
  1282. ;#    + $String contains the (possibly) multi-line text to print. It is
  1283. ;# automatically word-wrapped to fit in $Columns. 
  1284. ;#
  1285. ;#    + n'd are maintained and are not folded.
  1286. ;#
  1287. ;#    + $Offset is pre-pended before each separate line of text. 
  1288. ;#
  1289. ;#    + If $Offset_Once is $TRUE $Offset will only appear on the first line.
  1290. ;#      All other lines will be indented to match the amount of whitespace of
  1291. ;#      $Offset.
  1292. ;#
  1293. ;#    + If $Bullet_Indent is $TRUE $Offset will only be applied to the begining
  1294. ;#      of lines as they occured in the original $String. Lines that are created
  1295. ;#      by this routine will always be indented by blank spaces.
  1296. ;#
  1297. ;#    + If $Columns is 0 no word-wrap is done. This might be useful to still
  1298. ;#      to offset each line in a buffer.
  1299. ;#
  1300. ;#    + If $Split_Expr is supplied the string is split on it. If not supplied
  1301. ;#      the string is split on " t/-,." by default.
  1302. ;#
  1303. ;#    + If $Offset_Blank is $TRUE then empty lines will have $Offset pre-pended
  1304. ;#      to them. Otherwise, they will still empty.
  1305. ;#
  1306. ;# This is a realy workhorse routine that I use in many places because of its
  1307. ;# veratility.
  1308. ;#
  1309. ;# Arguments:
  1310. ;#    $String, $Offset, $Offset_Once, $Bullet_Indent, $Columns, $Split_Expr,
  1311. ;#    $Offset_Blank
  1312. ;#
  1313. ;# Returns:
  1314. ;#    $Buffer
  1315. ;###############################################################################
  1316. sub main'Format_Text_Block
  1317. {
  1318. X   local ($String, $Real_Offset, $Offset_Once, $Bullet_Indent, $Columns, 
  1319. X      $Split_Expr, $Offset_Blank) = @_;
  1320. X
  1321. X   local ($New_Line, $Line, $Chars_Per_Line, $Space_Offset, $Buffer,
  1322. X      $Next_New_Line, $Num_Lines, $Num_Offsets, $Offset);
  1323. X   local ($*) = 0;
  1324. X   local ($BLANK_TAG) = "__FORMAT_BLANK__";
  1325. X   local ($Blank_Offset) = $Real_Offset if ($Offset_Blank);
  1326. X
  1327. X   # What should we split on?
  1328. X   $Split_Expr = " \t\/\-\,\." if (! $Split_Expr);
  1329. X
  1330. X   # Pre-process the string - convert blank lines to __FORMAT_BLANK__ sequence
  1331. X   $String =~ s/nn/n$BLANK_TAGn/g;
  1332. X   $String =~ s/^n/$BLANK_TAGn/g;
  1333. X   $String =~ s/n$/n$BLANK_TAG/g;
  1334. X
  1335. X   # If bad $Columns/$Offset combo or no $Columns make a VERRRYYY wide $Column
  1336. X   $Offset = $Real_Offset;
  1337. X   $Chars_Per_Line = 16000 if (($Chars_Per_Line = $Columns - length ($Offset)) <= 0);
  1338. X   $Space_Offset = " " x length ($Offset);
  1339. X
  1340. X   # Get a buffer
  1341. X   foreach $Line (split ("n", $String))
  1342. X   {
  1343. X      $Offset = $Real_Offset if ($Bullet_Indent);
  1344. X
  1345. X      # Find where to split the line
  1346. X      if ($Line ne $BLANK_TAG)
  1347. X      { 
  1348. X         $New_Line = "";
  1349. X         while ($Line =~ /^([$Split_Expr]*)([^$Split_Expr]+)/)
  1350. X         {
  1351. X            if (length ("$New_Line$&") >= $Chars_Per_Line)
  1352. X            {
  1353. X               $Next_New_Line = $+;
  1354. X               $New_Line = "$Offset$New_Line$1";
  1355. X               $Buffer .= "n" if ($Num_Lines++);
  1356. X               $Buffer .= $New_Line;
  1357. X               $Offset = $Space_Offset if (($Offset) && ($Offset_Once));
  1358. X               $New_Line = $Next_New_Line;
  1359. X               ++$Num_Lines;
  1360. X            }
  1361. X            else
  1362. X            {
  1363. X               $New_Line .= $&;
  1364. X            };
  1365. X            $Line = $';
  1366. X         };
  1367. X
  1368. X         $Buffer .= "n" if ($Num_Lines++);
  1369. X         $Buffer .= "$Offset$New_Line$Line";
  1370. X         $Offset = $Space_Offset if (($Offset) && ($Offset_Once));
  1371. X      }
  1372. X
  1373. X      else
  1374. X      {
  1375. X         $Buffer .= "n$Blank_Offset";
  1376. X      };
  1377. X   };
  1378. X
  1379. X   return ($Buffer);
  1380. X
  1381. };
  1382. X
  1383. 1;
  1384. SHAR_EOF
  1385. chmod 0444 libs/strings1.pl ||
  1386. echo 'restore of libs/strings1.pl failed'
  1387. Wc_c="`wc -c < 'libs/strings1.pl'`"
  1388. test 4687 -eq "$Wc_c" ||
  1389. echo 'libs/strings1.pl: original size 4687, current size' "$Wc_c"
  1390. fi
  1391. # ============= libs/timespec.pl ==============
  1392. if test -f 'libs/timespec.pl' -a X"$1" != X"-c"; then
  1393. echo 'x - skipping libs/timespec.pl (File already exists)'
  1394. else
  1395. echo 'x - extracting libs/timespec.pl (Text)'
  1396. sed 's/^X//' << 'SHAR_EOF' > 'libs/timespec.pl' &&
  1397. ;# NAME
  1398. ;#    timespec.pl - convert a pre-defined time specifyer to seconds
  1399. ;#
  1400. ;# AUTHOR
  1401. ;#    Michael S. Muegel (mmuegel@mot.com)
  1402. ;#
  1403. ;# RCS INFORMATION
  1404. ;#    mmuegel
  1405. ;#    /usr/local/ustart/src/mail-tools/dist/foo/libs/timespec.pl,v 1.1 1993/07/28 08:07:19 mmuegel Exp
  1406. X
  1407. package timespec;
  1408. X
  1409. %TIME_SPEC_TO_SECONDS  = ("s", 1,
  1410. X         "m", 60,
  1411. X         "h", 60 * 60,
  1412. X         "d", 60 * 60 * 24
  1413. X         );
  1414. X
  1415. $VALID_TIME_SPEC_EXPR  = "[" . join ("", keys (%TIME_SPEC_TO_SECONDS)) . "]";
  1416. X
  1417. ;###############################################################################
  1418. ;# Time_Spec_To_Seconds
  1419. ;#
  1420. ;# Converts a string of the form:
  1421. ;#
  1422. ;#    (<number>(s|m|h|d))+
  1423. ;#
  1424. ;# to seconds. The second part of the time spec specifies seconds, minutes, 
  1425. ;# hours, or days, respectfully. The first part is the number of those untis. 
  1426. ;# There can be any number of such specifiers. As an example, 1h30m means 1 
  1427. ;# hour and 30 minutes.
  1428. ;#
  1429. ;# If the parsing went OK then $Status is 1, $Msg is undefined, and $Seconds
  1430. ;# is $Time_Spec converted to seconds. If something went wrong then $Status
  1431. ;# is 0 and $Msg explains what went wrong.
  1432. ;#
  1433. ;# Arguments:
  1434. ;#    $Time_Spec
  1435. ;#
  1436. ;# Returns:
  1437. ;#    $Status, $Msg, $Seconds
  1438. ;###############################################################################
  1439. sub main'Time_Spec_To_Seconds
  1440. {
  1441. X   $Time_Spec = $_[0];
  1442. X
  1443. X   $Seconds = 0;
  1444. X   while ($Time_Spec =~ /^(d+)($VALID_TIME_SPEC_EXPR)/)
  1445. X   {
  1446. X      $Seconds += $1 * $TIME_SPEC_TO_SECONDS {$2};
  1447. X      $Time_Spec = $';
  1448. X   };
  1449. X
  1450. X   return (0, "error parsing time spec: $Time_Spec") if ($Time_Spec ne "");
  1451. X   return (1, "", $Seconds);
  1452. X
  1453. };
  1454. X
  1455. X
  1456. 1;
  1457. SHAR_EOF
  1458. chmod 0444 libs/timespec.pl ||
  1459. echo 'restore of libs/timespec.pl failed'
  1460. Wc_c="`wc -c < 'libs/timespec.pl'`"
  1461. test 1609 -eq "$Wc_c" ||
  1462. echo 'libs/timespec.pl: original size 1609, current size' "$Wc_c"
  1463. fi
  1464. # ============= man/cqueue.1 ==============
  1465. if test ! -d 'man'; then
  1466.     echo 'x - creating directory man'
  1467.     mkdir 'man'
  1468. fi
  1469. if test -f 'man/cqueue.1' -a X"$1" != X"-c"; then
  1470. echo 'x - skipping man/cqueue.1 (File already exists)'
  1471. else
  1472. echo 'x - extracting man/cqueue.1 (Text)'
  1473. sed 's/^X//' << 'SHAR_EOF' > 'man/cqueue.1' &&
  1474. .TH CQUEUE 1L
  1475. "
  1476. " mmuegel
  1477. " /usr/local/ustart/src/mail-tools/dist/foo/man/cqueue.1,v 1.1 1993/07/28 08:08:25 mmuegel Exp
  1478. "
  1479. .ds mp fBcqueuefR
  1480. .de IB
  1481. .IP (bu 2
  1482. ..
  1483. .SH NAME
  1484. *(mp - check sendmail queue for problems
  1485. .SH SYNOPSIS
  1486. .IP *(mp 7 
  1487. [ fB-abdmsfR ] [ fB-qfR fIqueue-dirfI ] [ fB-tfR fItimefR ] 
  1488. [ fB-ufR fIusersfR ] [ fB-wfR fIwidthfR ]
  1489. .SH DESCRIPTION
  1490. Reports on problems in the sendmail queue. With no options this simply
  1491. means listing messages that have been in the queue longer than a default
  1492. period along with a summary of queue mail by host and status message.
  1493. .SH OPTIONS
  1494. .IP fB-afR 14
  1495. Report on all messages in the queue. This is equivalent to saying fB-tfR 0s.
  1496. You may like this command so much that you use it as a replacement for
  1497. fBmqueuefR. For example:
  1498. .sp 1
  1499. .RS
  1500. .RS
  1501. fBalias mqueue cqueue -afR
  1502. .RE
  1503. .RE
  1504. .IP fB-bfR 14
  1505. Also report on bogus queue files. Those are files that
  1506. have data files and no control files or vice versa.
  1507. .IP fB-dfR
  1508. Print a detailed report of mail messages that have been queued longer than
  1509. the specified or default time. Information that is presented includes:
  1510. .RS
  1511. .RS
  1512. .IB
  1513. Sendmail queue identifier.
  1514. .IB
  1515. Date the message was first queued.
  1516. .IB
  1517. Sender of the message.
  1518. .IB
  1519. One or more recipients of the message.
  1520. .IB
  1521. An optional status of the message. This usually indicates why the message
  1522. has not been delivered.
  1523. .RE
  1524. .RE
  1525. .IP fB-mfR 14
  1526. Mail off the results if any problems were found.
  1527. Normaly results are printed to stdout. If this option
  1528. is specified they are mailed to one or more users. Results
  1529. are not printed to stdout in this case. Results are fBonlyfR
  1530. mailed if *(mp found something wrong.
  1531. .IP "fB-qfR fIqueue-dirfI"
  1532. The sendmail mail queue directory. Default is fB/usr/spool/mqueuefR or
  1533. some other site configured value.
  1534. .IP "fB-tfR fItimefR"
  1535. List messages that have been in the queue longer than
  1536. fItimefR. Time should of the form:
  1537. .sp 1
  1538. .RS
  1539. .RS
  1540. (<number>(s|m|h|d))+
  1541. .sp 1
  1542. .RE
  1543. .RE
  1544. .RS 14
  1545. The second portion of the above definition
  1546. specifies seconds, minutes, hours, or
  1547. days, respectfully. The first portion is the number of
  1548. those units. There can be any number of such specifiers.
  1549. As an example, 1h30m means 1 hour and 30 minutes.
  1550. .sp 1
  1551. The default is 2 hours.
  1552. .RE
  1553. .IP fB-sfR 14
  1554. Print a summary of messages that have been queued longer than
  1555. the specified or default time. Two separate types of summaries are printed.
  1556. The first summarizes the queue messages by destination host. The host name
  1557. is gleaned from the recipient addresses for each message.
  1558. Thus the actual host names for this summary should be taken with a grain
  1559. of salt since ruleset 0 has not been applied to the address the host was
  1560. taken from nor were MX records consulted. It would be possible to add
  1561. this; however, the execution time of the script would increase 
  1562. dramatically. The second summary is by status message.
  1563. .IP "fB-ufR fIusersfR"
  1564. Specify list of users to send a mail report to other than
  1565. the invoker. This option is only valid when fB-mfR has been
  1566. specified. Multiple recipients may be separated by spaces.
  1567. .IP "fB-wfR fIwidthfR"
  1568. Specify the page width to which the output should tailored. fIwidthfR
  1569. should be an integer representing some character position. The default is
  1570. 80 or some other site configured value. Output is folded neatly to match 
  1571. fIwidthfR.
  1572. .SH EXAMPLES
  1573. .nf
  1574. % fBdatefR
  1575. Tue Jan 19 12:07:20 CST 1993
  1576. X
  1577. % fBcqueue -t 21h45m -w 70fR
  1578. X
  1579. Summary of messages in queue longer than 21:45:00 by destination 
  1580. host:
  1581. X
  1582. X   Number of
  1583. X   Messages    Destination Host
  1584. X   ---------   ----------------
  1585. X   2           cigseg.rtsg.mot.com
  1586. X   1           mnesouth.corp.mot.com
  1587. X   ---------
  1588. X   3
  1589. X
  1590. Summary of messages in queue longer than 21:45:00 by status message:
  1591. X
  1592. X   Number of
  1593. X   Messages    Status Message
  1594. X   ---------   --------------
  1595. X   1           Deferred: Connection refused by mnesouth.corp.mot.com
  1596. X   2           Deferred: Host Name Lookup Failure
  1597. X   ---------
  1598. X   3
  1599. X
  1600. Detail of messages in queue longer than 21:45:00 sorted by creation 
  1601. date:
  1602. X
  1603. X   ID:        AA20573
  1604. X   Date:      02:09:27 PM 01/18/93
  1605. X   Sender:    melrose-place-owner@ferkel.ucsb.edu
  1606. X   Recipient: pbaker@cigseg.rtsg.mot.com
  1607. X   Status:    Deferred: Host Name Lookup Failure
  1608. X
  1609. X   ID:        AA20757
  1610. X   Date:      02:11:30 PM 01/18/93
  1611. X   Sender:    90210-owner@ferkel.ucsb.edu
  1612. X   Recipient: pbaker@cigseg.rtsg.mot.com
  1613. X   Status:    Deferred: Host Name Lookup Failure
  1614. X
  1615. X   ID:        AA21110
  1616. X   Date:      02:17:01 PM 01/18/93
  1617. X   Sender:    rd_lap_wg@mdd.comm.mot.com
  1618. X   Recipient: jim_mathis@mnesouth.corp.mot.com
  1619. X   Status:    Deferred: Connection refused by mnesouth.corp.mot.com
  1620. .fi
  1621. .SH AUTHOR
  1622. .nf
  1623. Michael S. Muegel (mmuegel@mot.com)
  1624. UNIX Applications Startup Group
  1625. Corporate Information Office, Schaumburg, IL
  1626. Motorola, Inc.
  1627. .fi
  1628. .SH COPYRIGHT NOTICE
  1629. Copyright 1993, Motorola, Inc.
  1630. .sp 1
  1631. Permission to use, copy, modify and distribute without charge this
  1632. software, documentation, etc. is granted, provided that this
  1633. comment and the author's name is retained.  The author nor Motorola assume any
  1634. responsibility for problems resulting from the use of this software.
  1635. .SH SEE ALSO
  1636. .nf
  1637. fBsendmail(8)fR
  1638. fISendmail Installation and Operation GuidefR.
  1639. .fi
  1640. SHAR_EOF
  1641. chmod 0444 man/cqueue.1 ||
  1642. echo 'restore of man/cqueue.1 failed'
  1643. Wc_c="`wc -c < 'man/cqueue.1'`"
  1644. test 5212 -eq "$Wc_c" ||
  1645. echo 'man/cqueue.1: original size 5212, current size' "$Wc_c"
  1646. fi
  1647. # ============= man/postclip.1 ==============
  1648. if test -f 'man/postclip.1' -a X"$1" != X"-c"; then
  1649. echo 'x - skipping man/postclip.1 (File already exists)'
  1650. else
  1651. echo 'x - extracting man/postclip.1 (Text)'
  1652. sed 's/^X//' << 'SHAR_EOF' > 'man/postclip.1' &&
  1653. .TH POSTCLIP 1L
  1654. "
  1655. " mmuegel
  1656. " /usr/local/ustart/src/mail-tools/dist/foo/man/postclip.1,v 1.1 1993/07/28 08:08:25 mmuegel Exp
  1657. "
  1658. .ds mp fBpostclipfR
  1659. .SH NAME
  1660. *(mp - send only the headers to Postmaster
  1661. .SH SYNOPSIS
  1662. *(mp [ fB-vfR ] [ fItofR ... ]
  1663. .SH DESCRIPTION
  1664. *(mp  will forward non-delivery reports to a postmaster after deleting the body
  1665. of the message. This keeps bounced mail private and helps to avoid disk space problems. *(mp tries its best to keep as much of the header trail as possible.
  1666. Hopefully only the original body of the message will be filtered. Only messages
  1667. that have a subject that begins with 'Returned mail:' are filtered. This
  1668. ensures that other mail is not accidently mucked with. Finally, note that
  1669. fBsendmailfR is used to deliver the message after it has been (possibly)
  1670. filtered. All of the original headers will remain intact.
  1671. .sp 1 
  1672. You can use this with any fBsendmailfR by modifying the Postmaster alias.
  1673. If you use IDA fBsendmailfR you could add the following to <machine>.m4:
  1674. .sp 1
  1675. .RS
  1676. define(POSTMASTERBOUNCE, mailer-errors)
  1677. .RE
  1678. .sp 1
  1679. In the aliases file, add a line similar to the following:
  1680. .sp 1
  1681. .RS
  1682. mailer-errors: "|/usr/local/bin/postclip postmaster"
  1683. .RE
  1684. .SH OPTIONS
  1685. .IP fB-vfR
  1686. Be verbose about delivery. Probably only useful when debugging *(mp.
  1687. .IP fItofR
  1688. A list of one or more e-mail ids to send the modified
  1689. Postmaster messages to. If none are specified postmaster
  1690. is used.
  1691. .SH AUTHOR
  1692. .nf
  1693. Michael S. Muegel (mmuegel@mot.com)
  1694. UNIX Applications Startup Group
  1695. Corporate Information Office, Schaumburg, IL
  1696. Motorola, Inc.
  1697. .fi
  1698. .SH CREDITS
  1699. The original idea to filter Postmaster mail was taken from a script by 
  1700. Christopher Davis <ckd@eff.org>.
  1701. .SH COPYRIGHT NOTICE
  1702. Copyright 1992, Motorola, Inc.
  1703. .sp 1
  1704. Permission to use, copy, modify and distribute without charge this
  1705. software, documentation, etc. is granted, provided that this
  1706. comment and the author's name is retained.  The author nor Motorola assume any
  1707. responsibility for problems resulting from the use of this software.
  1708. .SH SEE ALSO
  1709. .nf
  1710. fBsendmail(8)fR
  1711. .fi
  1712. SHAR_EOF
  1713. chmod 0444 man/postclip.1 ||
  1714. echo 'restore of man/postclip.1 failed'
  1715. Wc_c="`wc -c < 'man/postclip.1'`"
  1716. test 2078 -eq "$Wc_c" ||
  1717. echo 'man/postclip.1: original size 2078, current size' "$Wc_c"
  1718. fi
  1719. # ============= src/cqueue ==============
  1720. if test ! -d 'src'; then
  1721.     echo 'x - creating directory src'
  1722.     mkdir 'src'
  1723. fi
  1724. if test -f 'src/cqueue' -a X"$1" != X"-c"; then
  1725. echo 'x - skipping src/cqueue (File already exists)'
  1726. else
  1727. echo 'x - extracting src/cqueue (Text)'
  1728. sed 's/^X//' << 'SHAR_EOF' > 'src/cqueue' &&
  1729. #!/usr/local/ustart/bin/suidperl
  1730. X
  1731. # NAME
  1732. #    cqueue - check sendmail queue for problems
  1733. #
  1734. # SYNOPSIS
  1735. #    Type cqueue -usage
  1736. #
  1737. # AUTHOR
  1738. #    Michael S. Muegel <mmuegel@mot.com>
  1739. #
  1740. # RCS INFORMATION
  1741. #    mmuegel
  1742. #    /usr/local/ustart/src/mail-tools/dist/foo/src/cqueue,v 1.1 1993/07/28 08:09:02 mmuegel Exp
  1743. X
  1744. # So that date.pl does not yell (Domain/OS version does a ``)
  1745. $ENV{'PATH'}    = "";
  1746. X
  1747. # A better getopts routine
  1748. require "newgetopts.pl";
  1749. require "timespec.pl";
  1750. require "mail.pl";
  1751. require "date.pl";
  1752. require "mqueue.pl";
  1753. require "strings1.pl";
  1754. require "elapsed.pl";
  1755. X
  1756. ($Script_Name = $0) =~ s/.*///;
  1757. X         
  1758. # Some defaults you may want to change
  1759. $DEF_TIME = "2h";
  1760. $DEF_QUEUE      = "/usr/spool/mqueue";
  1761. $DEF_COLUMNS = 80;
  1762. $DATE_FORMAT    = "%r %D";
  1763. X
  1764. # Constants that probably should not be changed
  1765. $USAGE          = "Usage: $Script_Name [ -abdms ] [ -q queue-dir ] [ -t time ] [ -u user ] [ -w width ]n";
  1766. $VERSION        = "${Script_Name} by mmuegel; 1.1 of 1993/07/28 08:09:02";
  1767. $SWITCHES       = "abdmst:u:q:w:";
  1768. $SPLIT_EXPR = 's,.@!%:';
  1769. $ADDR_PART_EXPR = '[^!@%]+';
  1770. X
  1771. # Let getopts parse for switches
  1772. $Status = &New_Getopts ($SWITCHES, $USAGE);
  1773. exit (0) if ($Status == -1);
  1774. exit (1) if (! $Status);
  1775. X
  1776. # Check args 
  1777. die "${Script_Name}: -u only valid with -mn" if (($opt_u) && (! $opt_m));
  1778. die "${Script_Name}: -a not valid with -t optionn" if ($opt_a && $opt_t);
  1779. $opt_u = getlogin || (getpwuid ($<))[0] || $ENV{"USER"} || die "${Script_Name}: can not determine who you are!n" if (! $opt_u);
  1780. X
  1781. # Set defaults
  1782. $opt_t = "0s" if ($opt_a);
  1783. $opt_t = $DEF_TIME if ($opt_t eq "");
  1784. $opt_w = $DEF_COLUMNS if ($opt_w eq "");
  1785. $opt_q = $DEF_QUEUE if ($opt_q eq "");
  1786. $opt_s = $opt_d = 1 if (! ($opt_s || $opt_d));
  1787. X
  1788. # Untaint the users to mail to
  1789. $opt_u =~ /^(.*)$/;
  1790. $Users = $1;
  1791. X
  1792. # Convert time option to seconds and seconds to elapsed form
  1793. die "${Script_Name}: $Msgn" if (! (($Status, $Msg, $Seconds) = &Time_Spec_To_Seconds ($opt_t))[0]);
  1794. $Elapsed = &Seconds_To_Elapsed ($Seconds, 1);
  1795. $Time_Info = " longer than $Elapsed" if ($Seconds);
  1796. X
  1797. # Get the current time
  1798. $Current_Time = time;
  1799. $Current_Date = &date ($Current_Time, $DATE_FORMAT);
  1800. X
  1801. ($Status, $Msg, @Queue_IDs) = &Get_Queue_IDs ($opt_q, 1, @Missing_Control_IDs,
  1802. X   @Missing_Data_IDs);
  1803. die "$Script_Name: $Msgn" if (! $Status);
  1804. X
  1805. # Yell about missing data/control files?
  1806. if ($opt_b)
  1807. {
  1808. X
  1809. X   $Report = "nMessages missing control files:nn   " . 
  1810. X             join ("n   ", @Missing_Control_IDs) . 
  1811. X             "n" 
  1812. X      if (@Missing_Control_IDs);
  1813. X
  1814. X   $Report .= "nMessages missing data files:nn   " . 
  1815. X              join ("n   ", @Missing_Data_IDs) . 
  1816. X              "n"
  1817. X      if (@Missing_Data_IDs);
  1818. };
  1819. X
  1820. # See if any mail messages are older than $Seconds
  1821. foreach $Queue_ID (@Queue_IDs)
  1822. {
  1823. X   # Get lots of info about this sendmail message via the control file
  1824. X   ($Status, $Msg) = &Parse_Control_File ($opt_q, $Queue_ID, *Sender, 
  1825. X      *Recipients, *Errors_To, *Creation_Time, *Priority, *Status_Message, 
  1826. X      *Headers);
  1827. X   next if ($Status == -1);
  1828. X   if (! $Status)
  1829. X   {
  1830. X      warn "$Script_Name: $Queue_ID: $Msgn";
  1831. X      next;
  1832. X   };
  1833. X
  1834. X   # Report on message if it is older than $Seconds
  1835. X   if ($Current_Time - $Creation_Time >= $Seconds)
  1836. X   {
  1837. X      # Build summary by host information. Keep track of each host destination
  1838. X      # encountered.
  1839. X      if ($opt_s)
  1840. X      {
  1841. X         %Host_Map = ();
  1842. X         foreach (@Recipients)
  1843. X         {
  1844. X     if ((/@($ADDR_PART_EXPR)$/) || (/($ADDR_PART_EXPR)!$ADDR_PART_EXPR$/))
  1845. X            {
  1846. X        ($Host = $1) =~ tr/A-Z/a-z/;
  1847. X               $Host_Map {$Host} = 1;
  1848. X     }
  1849. X     else
  1850. X     {
  1851. X        warn "$Script_Name: could not find host part from $_; contact authorn";
  1852. X     };
  1853. X         };
  1854. X
  1855. X         # For each unique target host add to its stats
  1856. X         grep ($Host_Queued {$_}++, keys (%Host_Map));
  1857. X
  1858. X         # Build summary by message information.
  1859. X         $Message_Queued {$Status_Message}++ if ($Status_Message);
  1860. X      };
  1861. X
  1862. X      # Build long report information for this creation time (there may be
  1863. X      # more than one message created at the same time)
  1864. X      if ($opt_d)
  1865. X      {
  1866. X         $Creation_Date = &date ($Creation_Time, $DATE_FORMAT);
  1867. X         $Recipient_Info = &Format_Text_Block (join (", ", @Recipients), 
  1868. X     "   Recipient: ", 1, 0, $opt_w, $SPLIT_EXPR);
  1869. X         $Time_To_Report {$Creation_Time} .= <<"EOS";
  1870. X
  1871. X   ID:        $Queue_ID
  1872. X   Date:      $Creation_Date
  1873. X   Sender:    $Sender
  1874. $Recipient_Info
  1875. EOS
  1876. X
  1877. X         # Add the status message if available to long report
  1878. X         if ($Status_Message)
  1879. X         {
  1880. X     $Time_To_Report {$Creation_Time} .= &Format_Text_Block ($Status_Message, 
  1881. X           "   Status:    ", 1, 0, $opt_w, $SPLIT_EXPR) . "n";
  1882. X         };
  1883. X      };
  1884. X   };
  1885. X
  1886. };
  1887. X
  1888. # Add the summary report by target host?
  1889. if ($opt_s)
  1890. {
  1891. X   foreach $Host (sort (keys (%Host_Queued)))
  1892. X   {
  1893. X      $Host_Report .= &Format_Text_Block ($Host, 
  1894. X         sprintf ("   %-9d   ", $Host_Queued{$Host}), 1, 0, $opt_w,
  1895. X         $SPLIT_EXPR) . "n";
  1896. X      $Num_Hosts += $Host_Queued{$Host};
  1897. X   };
  1898. X   if ($Host_Report)
  1899. X   {
  1900. X      chop ($Host_Report);
  1901. X      $Report .= &Format_Text_Block("nSummary of messages in queue$Time_Info by destination host:n", "", 0, 0, $opt_w);
  1902. X
  1903. X      $Report .= <<"EOS";
  1904. X
  1905. X   Number of
  1906. X   Messages    Destination Host
  1907. X   ---------   ----------------
  1908. $Host_Report
  1909. X   ---------
  1910. X   $Num_Hosts
  1911. EOS
  1912. X   };
  1913. };
  1914. X
  1915. # Add the summary by message report?
  1916. if ($opt_s)
  1917. {
  1918. X   foreach $Message (sort (keys (%Message_Queued)))
  1919. X   {
  1920. X      $Message_Report .= &Format_Text_Block ($Message, 
  1921. X         sprintf ("   %-9d   ", $Message_Queued{$Message}), 1, 0, $opt_w, 
  1922. X         $SPLIT_EXPR) . "n";
  1923. X      $Num_Messages += $Message_Queued{$Message};
  1924. X   };
  1925. X   if ($Message_Report)
  1926. X   {
  1927. X      chop ($Message_Report);
  1928. X      $Report .= &Format_Text_Block ("nSummary of messages in queue$Time_Info by status message:n", "", 0, 0, $opt_w);
  1929. X
  1930. X      $Report .= <<"EOS";
  1931. X
  1932. X   Number of
  1933. X   Messages    Status Message
  1934. X   ---------   --------------
  1935. $Message_Report
  1936. X   ---------
  1937. X   $Num_Messages
  1938. EOS
  1939. X   };
  1940. };
  1941. X
  1942. # Add the detailed message reports?
  1943. if ($opt_d)
  1944. {
  1945. X   foreach $Time (sort { $a <=> $b} (keys (%Time_To_Report)))
  1946. X   {
  1947. X      $Report .= &Format_Text_Block ("nDetail of messages in queue$Time_Info sorted by creation date:n","", 0, 0, $opt_w) if (! $Detailed_Header++);
  1948. X      $Report .= $Time_To_Report {$Time};
  1949. X   };
  1950. };
  1951. X
  1952. # Now mail or print the report
  1953. if ($Report)
  1954. {
  1955. X   $Report .= "n";
  1956. X   if ($opt_m)
  1957. X   {
  1958. X      ($Status, $Msg) = &Send_Mail ($Users, "sendmail queue report for $Current_Date", $Report, 0);
  1959. X      die "${Script_Name}: $Msg" if (! $Status);
  1960. X   }
  1961. X
  1962. X   else
  1963. X   {
  1964. X      print $Report;
  1965. X   };
  1966. X
  1967. };
  1968. X
  1969. # I am outta here...
  1970. exit (0);
  1971. SHAR_EOF
  1972. chmod 0555 src/cqueue ||
  1973. echo 'restore of src/cqueue failed'
  1974. Wc_c="`wc -c < 'src/cqueue'`"
  1975. test 6647 -eq "$Wc_c" ||
  1976. echo 'src/cqueue: original size 6647, current size' "$Wc_c"
  1977. fi
  1978. # ============= src/postclip ==============
  1979. if test -f 'src/postclip' -a X"$1" != X"-c"; then
  1980. echo 'x - skipping src/postclip (File already exists)'
  1981. else
  1982. echo 'x - extracting src/postclip (Text)'
  1983. sed 's/^X//' << 'SHAR_EOF' > 'src/postclip' &&
  1984. #!/usr/local/bin/perl
  1985. X
  1986. # NAME
  1987. #    postclip - send only the headers to Postmaster
  1988. #
  1989. # SYNOPSIS
  1990. #    postclip [ -v ] [ to ... ]
  1991. #
  1992. # AUTHOR
  1993. #    Michael S. Muegel <mmuegel@mot.com>
  1994. #
  1995. # RCS INFORMATION
  1996. #    /usr/local/ustart/src/mail-tools/dist/foo/src/postclip,v
  1997. #    1.1 of 1993/07/28 08:09:02
  1998. X
  1999. # We use this to send off the mail
  2000. require "newgetopts.pl";
  2001. require "mail.pl";
  2002. X
  2003. # Get the basename of the script
  2004. ($Script_Name = $0) =~ s/.*///;
  2005. X
  2006. # Some famous constants
  2007. $USAGE          = "Usage: $Script_Name [ -v ] [ to ... ]n";
  2008. $VERSION        = "${Script_Name} by mmuegel; 1.1 of 1993/07/28 08:09:02";
  2009. $SWITCHES       = "v";
  2010. X
  2011. # Let getopts parse for switches
  2012. $Status = &New_Getopts ($SWITCHES, $USAGE);
  2013. exit (0) if ($Status == -1);
  2014. exit (1) if (! $Status);
  2015. X
  2016. # Who should we send the modified mail to?
  2017. @ARGV = ("postmaster") if (! @ARGV);
  2018. $Users = join (" ", @ARGV);
  2019. @ARGV = ();
  2020. X
  2021. # Suck in the original header and save a few interesting lines
  2022. while (<>) 
  2023. {
  2024. X    $Buffer .= $_ if (! /^From /);
  2025. X    $Subject = $1 if (/^Subject:s+(.*)$/);
  2026. X    $From = $1 if (/^From:s+(.*)$/);
  2027. X    last if (/^$/);
  2028. };
  2029. X
  2030. # Do not filter the message unless it has a subject and the subject indicates
  2031. # it is an NDN
  2032. if ($Subject && ($Subject =~ /^returned mail/i))
  2033. {
  2034. X   # Slurp input by paragraph. Keep track of the last time we saw what
  2035. X   # appeared to be NDN text. We keep this.
  2036. X   $/ = "nn";
  2037. X   $* = 1;
  2038. X   while (<>)
  2039. X   {
  2040. X      push (@Paragraphs, $_);
  2041. X      $Last_Error_Para = $#Paragraphs 
  2042. X  if (/unsent message follows/i || /was not delivered because/);
  2043. X   };
  2044. X
  2045. X   # Now save the NDN text into $Buffer
  2046. X   $Buffer .= join ("", @Paragraphs [0..$Last_Error_Para]);
  2047. }
  2048. X
  2049. else
  2050. {
  2051. X   undef $/;
  2052. X   $Buffer .= <>;
  2053. };
  2054. X
  2055. # Send off the (possibly) modified mail
  2056. ($Status, $Msg) = &Send_Mail ($Users, "", $Buffer, 0, $opt_v, 1);
  2057. die "$Script_Name: $Msgn" if (! $Status);
  2058. SHAR_EOF
  2059. chmod 0555 src/postclip ||
  2060. echo 'restore of src/postclip failed'
  2061. Wc_c="`wc -c < 'src/postclip'`"
  2062. test 1836 -eq "$Wc_c" ||
  2063. echo 'src/postclip: original size 1836, current size' "$Wc_c"
  2064. fi
  2065. exit 0
  2066. --
  2067. +----------------------------------------------------------------------------+
  2068. | Michael S. Muegel                    | Internet E-Mail:    mmuegel@mot.com |
  2069. | UNIX Applications Startup Group      | Moto Dist E-Mail:   X10090          |
  2070. | Corporate Information Office         | Voice:              (708) 576-0507  |
  2071. | Motorola                             | Fax:                (708) 576-4153  |
  2072. +----------------------------------------------------------------------------+
  2073.       "I'm disturbed, I'm depressed, I'm inadequate -- I've got it all!"
  2074.   -- George from _Seinfeld_