Path: kddlab!cs.titech!wnoc-tyo-news!sh.wide!sun-barr!cs.utexas.edu!usc!news.service.uci.edu!ucivax!gateway From: wohler@sap-ag.de (Bill Wohler) Subject: mailarch-1.4: archive MH mail Message-ID: <9301231852.AA22117@sap-ag.de> Newsgroups: comp.mail.mh Organization: SAP AG Walldorf, Germany Lines: 769 Date: 23 Jan 93 19:03:08 GMT Phone: +49 6227-341658 Home: +49 6221-163255 this is mailarch 1.4, a program to archive MH mail. it tars and compresses mh directories for substantial disk savings (inodes too). for example: [wohler@is0001:510]% du -s 1992/mar 1992/mar.tar.Z 6528 1992/mar 1360 1992/mar.tar.Z the idea of mailarch is to move certain folders into an archive area monthly. older archives are tarred and compressed. the programs seek and extract (enclosed) are used to extract messages from the archive. please read the headers of the scripts for more information. if you use these, let me know and i'll place you on my mailing list. if you find the documentation in the headers non-illuminating, i want to know about it. note: mailarch is a csh script and seek and extract are ksh scripts. the PATH in these scripts may have to be updated for your environment. known to work on aix and hpux. changes in mailarch since 1.3: * Updated documentation for MH 6.8. * Works on hpux. * Extract's default output folder now +hold (instead on +hold$$). * Bug fixes. changes in mailarch since 1.2: * Create replacement folders with desired permissions. (Major new feature in the user interface.) * Use mhparam to get .mh_profile components. * Updated documentation. * Check to ensure that a folder exists before processing. On some errors, either mailarch would hang, or bogus folders would get created. --bw #! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh 'extract' <<'END_OF_FILE' X#! /bin/ksh X# X# $Id: extract,v 1.6 1993/01/23 18:22:53 wohler Exp $ X# X# NAME X# extract - extract mail messages from archives X# X# SYNOPSIS X# extract [-c new-folder] year folder [msg ...] X# X# DESCRIPTION X# In the case that no specific messages are designated, extract will extract X# all messages in the year in the specified folder. The folder in this case X# is relative to the mail directory (ie +a/others). X# X# If specific messages are specified, then only those messages are X# extracted. In this case, the folder specified must also include the year X# and month (ie. +1991/jan/a/others). The message list "all" is also X# supported and extracts all messages from the folder. X# X# The year argument is essentially an archive directory in the Mail X# directory. This program assumes that this archive contains the X# subdirectories "jan," "feb," etc. as created by the mailarch program. X# X# OPTIONS X# -c new-folder specify the folder to hold the extracted messages X# (default: +hold). X# X# RETURNS X# 0 normally; 1 upon error. X# X# BUGS X# In pre-MH-6.8 versions that lack the mhparam command, use the X# commented out setting of the "mail" variable below. X# X# AUTHOR X# Bill Wohler SAP AG 22 July 1992 X X# Constants (variables that do not change during runtime). X X# Defaults (variables that may be affected by arguments). Xnewfolder=hold X X# Initializations (internal variables that need to be set to something). XPATH=/usr/local/bin/mh:/bin:/usr/bin # set minimum search path Xcmd=${0##*/} # name by which command called Xexitstatus=0 # upon error, set to non-zero Xinterrupt=0 # upon interrupt, set to 1 X#mail=$HOME/$(awk '/^Path/{print $2}' $HOME/.mh_profile) Xmail=$HOME/$(mhparam Path) Xmonths="jan feb mar apr may jun jul aug sep oct nov dec" X X# Functions X Xusage () X{ X echo "Usage: $cmd [-c new-folder] year folder [msg ...]" X bye 1 X} X Xintr () X{ X echo "" X interrupt=1 X bye 1 X} X X# Usage: bye [exit status] [exit message] Xbye () X{ X if [ $# -gt 0 ]; then X exitstatus=$1 X shift X fi X if [ $# -gt 0 ]; then X echo "$*" X elif [ $interrupt -eq 1 ]; then X echo "" X elif [ $exitstatus -eq 0 ]; then X echo "Done." X fi X exit $exitstatus X} X X# Parse arguments Xwhile [ $# != 0 ]; do X case "$1" in X -c) shift; newfolder=$1;; X -v) print=1;; X -*) usage;; X *) break;; X esac X shift Xdone X Xif [ $# -lt 2 ]; then X usage Xfi X Xtrap intr 2 X Xyear=$1 Xfolder=${2#+} Xshift; shift Xmsgs=$* X X[ ! -d $mail/$year ] && bye 1 "$mail/$year does not exist." X[ -z "$newfolder" ] && usage X Xfolder +$mail/$newfolder /dev/null || bye 1 Xcd $mail/$year || bye 1 X Xecho "Extracting mail from archives." Xif [ -z "$msgs" ]; then X # No messages given; extract all messages in folder for all months. X for mon in $months; do X if [ -f $mon.tar.Z ]; then X zcat $mon.tar.Z | tar xvf - $year/$mon/$folder X if [ -d $(mhpath +./$year/$mon/$folder) ]; then X folder +./$year/$mon/$folder > /dev/null X refile all +$newfolder X fi X fi X done Xelse X # Extract the named messages. X if [ "$msgs" = all ]; then X msglist=$folder X else X for i in $msgs; do X msglist="$msglist $folder/$i" X done X fi X mon=${folder#*/} # strip junk to left of month X mon=${mon%%/*} # strip junk to right of month X if [ -f $mon.tar.Z ]; then X zcat $mon.tar.Z | tar xvf - $msglist X if [ -d $(mhpath +./$folder) ]; then X folder +./$folder > /dev/null X refile all +$newfolder X fi X else X bye 1 "$mon.tar.Z does not exist." X fi Xfi X Xif [ ! -d $year ]; then X bye 0 "No files extracted." Xelse X # We can remove the now empty folders. X rm -rf $mail/$year/$year Xfi X Xecho "Sorting mail." Xsortm +$newfolder X Xecho "Messages in +$newfolder." X Xbye X X# Local Variables: X# mode: sh X# End: END_OF_FILE if test 3687 -ne `wc -c <'extract'`; then echo shar: \"'extract'\" unpacked with wrong size! fi chmod +x 'extract' # end of 'extract' fi if test -f 'mailarch' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'mailarch'\" else echo shar: Extracting \"'mailarch'\" \(9675 characters\) sed "s/^X//" >'mailarch' <<'END_OF_FILE' X#! /bin/csh -f X# X# $Id: mailarch,v 1.6 1993/01/23 18:26:04 wohler Exp $ X# X# NAME X# mailarch - archive MH mail folders X# X# SYNOPSIS X# mailarch [-a folders] [-f folders] [-m mail] [options] [-s] [-v] X# thismonth [lastmonth] X# X# DESCRIPTION X# After a period of time one's mail folders get quite full with X# material that is rarely looked at. This program is an attempt to X# organize old mail. The idea is that selected folders are moved X# into a different place, usually at monthly intervals. The first X# time, the folder hierarchy is preserved. The second time this X# program is called, a month later, the old hierarchy is packed X# (currently with tar) and compressed. The mail itself can then be X# easily stored on tape and the index saved on disk for searching X# for old mail. X# X# Usage is straightforward. First create the MH profile components X# "Archive" and "Parent-Folders" described below. If one is X# archiving mail from March, 1991, then the usage would be: X# X# mailarch 1991/mar 1991/feb X# X# This will move selected folders in your mail directory to the X# folder 1991/mar. This name is arbitrary and any intermediary X# directories will be automatically created. But, since it is a X# folder, it will be created relative to your mail directory. X# X# This archived folder is then rid of .mh_sequences files and X# folders are sorted. An index of all the messages is also created. X# An opportunity to edit or remove large, unwanted files is also X# given. The older folder is packed (currently with tar) into a single X# file and removed. The packed folder and its index are then X# compressed. X# X# Only parts of this process can be run by using the -o flags. X# X# The names of the folders to be archived are found in the MH profile X# "Archive"; names are separated by whitespace. X# X# Pre-MH 6.7.1 versions could not create arbitrarily nested folders, so if X# folders that contain subfolders are archived, then it is necessary to X# recreate folder trees for them. This MH profile is called X# "Parent-Folders". Folders listed may be suffixed by ":mode" in order to X# override the default folder creation mode. This "mode" is as in the X# chmod(1) command (ie. can be either absolute or symbolic). For example: X# X# Archive: maillists friends out X# Parent-Folders: maillists friends:700 out:700 X# X# This archives and recreates the "maillists", "friends", and "out" folders. X# The friends and out folders are not accessible by members of the group or X# others since they may contain sensitive mails. X# X# OPTIONS X# -a folders X# Override the MH profile value of "Archive" with "folders." X# Surround multiple folders with double quotes. X# X# -f folders X# Override the MH profile value of "Parent-Folders" with "folders." X# Surround multiple folders with double quotes. X# X# -m mail X# Set the name of the mail directory. The default is the value X# of the MH profile entry "Path." X# X# -s size X# Specify the size of file (in K) that should be edited or X# removed (default is 25K). X# X# -v X# Display each of the steps. X# X# By default, all of the following actions are performed in the X# order listed. If any of these options are specified, then no X# other actions will be performed that are not also listed. X# X# -om X# Move the current folders into the new archive. X# -os X# Sort messages of the new archive. X# -oi X# Make an index of the new archive. X# -op X# Pack and compress the old archive. X# X# ENVIRONMENT X# MH If set, used instead of ~/.mh_profile. X# X# PROFILE COMPONENTS X# Path mail directory (must be relative to home directory). X# Archive folders to archive X# Parent-Folders folders to recreate X# X# BUGS X# If your MH is pre-MH-6.8, uncomment the non-"mhparam" versions of setting X# variables below. X# X# I have to investigate whether or not files might be accidently X# removed if you run out of disk space while packing files. X# X# Various scan and sortm messages are displayed (ie. "no messages in folder") X# These should be suppressed. X# X# The archive folder name should be able to created automatically so that X# this script can be cronned! An idea would be to say that if it is after X# the 15th of month B and before the 15th of month C, then the current month X# is month B and last month is month A. X# X# AUTHOR X# Bill Wohler SAP AG 1 March 1988 X# X X# Defaults Xset all = 1 # perform all operations Xset movefolders = 0 # move folders into old directory Xset sort = 0 # sort messages Xset mkindex = 0 # make an index Xset pack = 0 # pack and compress folder Xset mail = ~/`mhparam Path` # mail directory Xset folders = `mhparam Archive` # folders to archive Xset mkfolders = `mhparam Parent-Folders` # folders to recreate Xset size = 25 # file size (kbytes) to edit or remove X X# In pre-MH.6.8 installations, uncomment these, and comment out like X# variables above. mhprofile not needed in MH.6.8 or later. X#if ($?MH) then # file containing archive config X# set mhprofile = $MH X#else X# set mhprofile = ~/.mh_profile X#endif X#set mail = ~/`awk '/^Path/{print $2}' $mhprofile` X#set folders = `awk '/^Archive/{for(i=2;i<=NF;i++)print $i}' $mhprofile` X#set mkfolders = `awk '/^Parent-Folders/{for(i=2;i<=NF;i++)print $i}' $mhprofile` X X# Initializations Xset cmd = $0 # name by which command called Xset exitstatus = 0 # upon error, set to non-zero and exit Xset lastmonth oldarchive X X# If either no args, or just the directory, parsing args will get X# "Subscript out of range." Xif ($#argv == 0) \ X goto usage X X# Parse arguments Xwhile ("$argv[1]" =~ -*) X switch ("$argv[1]") X case "-a": X shift X set folders = ($argv[1]) X breaksw X X case "-f": X shift X set mkfolders = ($argv[1]) X breaksw X X case "-m": X shift X set mail = $argv[1] X breaksw X X case "-oi": X set mkindex = 1 X set all = 0 X breaksw X X case "-op": X set pack = 1 X set all = 0 X breaksw X X case "-om": X set movefolders = 1 X set all = 0 X breaksw X X case "-os": X set sort = 1 X set all = 0 X breaksw; X X case "-s": X shift X set size = $argv[1] X breaksw X X case "-v": X set print = 1 X breaksw X X default: X goto usage X endsw X shift X if ($#argv == 0) \ X break Xend X Xif ($#argv < 1) \ X goto usage X Xset archive = $argv[1] X Xif ($#argv > 1) then X set lastmonth = $argv[2] Xendif X X# Now check that each needed variable is non-nil. X Xif (! -e $mail) then X echo "${mail}: No such directory." X set exitstatus = 1 X goto bye Xendif Xif ($lastmonth != "" && ! -e $mail/$lastmonth) then X echo "${lastmonth}: No such directory." X set exitstatus = 1 X goto bye Xendif Xif ("$folders" == "") then X echo "No folders to archive." X set exitstatus = 1 X goto bye Xendif X Xskipargs: Xonintr intr X X X# Move folders to archive and then create folders that must always exist. Xif ($movefolders || $all) then X if ($?print) \ X echo "Moving ($folders) to $archive" X cd $mail || exit 1 X mkdir `echo $mail/$archive|awk -F/ '{for(i=2;i<=NF;i++){for(j=2;j<=i;j++)printf"/%s",$j;printf"\n"}}'` >& /dev/null X mv $folders $archive X X # Recreate folders with non-default permissions if desired. X if ("$mkfolders" != "") then X if ($?print) \ X echo "Recreating $mkfolders" X foreach i ($mkfolders) X set folder = `echo $i | sed 's/:.*$//'` X set mode = `echo $i | sed 's/^.*://'` X # The redirection here is to keep the folder command X # from being interactive. X folder +$folder /dev/null X if ($folder != $mode) then X if ($?print) \ X echo chmod $mode `mhpath +$folder` X chmod $mode `mhpath +$folder` X endif X end X endif Xendif X X# Sort messages in archive. Xif ($sort || $all) then X # Make sure we don't archive postings of sources... X cd $mail/$archive || exit 1 X set large = `find . -size +$size -print` X if ("$large" != "") then X echo "Edit large files, or remove later." X sleep 2 X vi $large X echo "Interactively remove large files." X foreach i ($large) X grep ^Subject $i X rm -i $i X end X endif X X foreach i (`folders -recurse -fast +$archive`) X if (! -d $mail/$i) \ X continue X if ($?print) \ X echo "Sorting $i..." X sortm +$i X folder -pack +$i >/dev/null>! $index X scan -header +$i >>! $index X # if no messages, should just have a small mesg X # on same line as the echo $i. X end Xendif X X# Now, tar and compress last month's archive if given. Xif (($pack || $all) && "$lastmonth" != "") then X if ("$oldarchive" == "") \ X set oldarchive = $lastmonth.tar X set oldindex = $lastmonth.idx X cd $mail/$lastmonth || exit 1 X if ($?print) \ X echo "Cleaning $lastmonth..." X find . -name .mh_sequences -exec rm {} \; X if ($?print) \ X echo "Creating $oldarchive..." X cd $mail X rm -f $oldarchive X tar -cf $oldarchive $lastmonth X if ($status == 0) \ X rm -rf $lastmonth X if ($?print) \ X echo "Compressing $oldarchive and $oldindex..." X chmod 444 $oldarchive $oldindex X compress $oldarchive $oldindex Xendif X Xgoto bye X Xusage: X echo "Usage: $cmd:t [-a folders ] [-f folders] [-m mail] [options] [-s size] [-v] thismonth [lastmonth]" X echo "Options:" X echo " -om move the current folders into the current month" X echo " -os sort messages of the current month" X echo " -oi make an index of the current month" X echo " -op pack and compress the last month" X exit(1) X Xintr: X echo "" X set interrupt exitstatus = 1 X # Fall through! X Xbye: X if ($?print) \ X echo "Done." X exit($exitstatus) END_OF_FILE if test 9675 -ne `wc -c <'mailarch'`; then echo shar: \"'mailarch'\" unpacked with wrong size! fi chmod +x 'mailarch' # end of 'mailarch' fi if test -f 'seek' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'seek'\" else echo shar: Extracting \"'seek'\" \(2796 characters\) sed "s/^X//" >'seek' <<'END_OF_FILE' X#! /bin/ksh X# X# $Id: seek,v 1.6 1993/01/23 18:25:18 wohler Exp $ X# X# NAME X# seek -- find names or subjects from archives X# X# SYNOPSIS X# seek search-string [year ...] X# X# DESCRIPTION X# Seek searches the indexes for the desired string. If there is white space X# within the string, enclose the string in quotes. X# X# Multiple years can be specified; if the year is omitted, the current year X# is used. X# X# The year argument is essentially an archive directory in the Mail X# directory. This program assumes that this archive contains the X# indices "jan.idx.Z," "feb.idx.Z," etc. as created by the mailarch X# program. X# X# OPTIONS X# X# RETURNS X# 0 normally; 1 upon error. X# X# BUGS X# In pre-MH-6.8 versions that lack the mhparam command, use the X# commented out setting of the "mail" variable below. X# X# AUTHOR X# Bill Wohler SAP AG 18 May 92 X X# Constants (variables that do not change during runtime). X X# Defaults (variables that may be affected by arguments). X X# Initializations (internal variables that need to be set to something). XPATH=/usr/local/bin/mh:/bin:/usr/bin:/usr/ucb # set minimum search path Xcmd=${0##*/} # name by which command called Xmail=$HOME/$(mhparam Path) # mail folder X#mail=$HOME/$(awk '/^Path/{print $2}' $HOME/.mh_profile) Xmonths="jan feb mar apr may jun jul aug sep oct nov dec" Xexitstatus=0 # upon error, set to non-zero and exit Xinterrupt=0 # upon interrupt, set to 1 X X# Functions X Xusage () { X echo "Usage: $cmd search-string [year ...]" X bye 1 X} X Xintr () X{ X echo "" X interrupt=1 X bye 1 X} X Xbye () X{ X if [ $# -gt 0 ]; then X exitstatus=$1 X shift X fi X if [ $# -gt 0 ]; then X echo "$*" X elif [ $interrupt -eq 1 ]; then X echo "" X elif [ $exitstatus -eq 0 ]; then X echo "Done." X fi X exit $exitstatus X} X X# Usage: find pattern Xsearch () X{ X if [ $# -ne 1 ]; then X echo "Internal error: search() usage incorrect." X return; X fi X X pattern=$1 X X awk ' X /^Folder/ { X header = $0 X header_printed = 0 X next X } X X /'$pattern'/ { X if (! header_printed) { X print header X header_printed = 1 X } X print $0 X } X X { X next X } X ' X} X X# Parse arguments Xwhile [ $# != 0 ]; do X case "$1" in X -v) print=1;; X -*) usage;; X *) break;; X esac X shift Xdone Xif [ $# -lt 1 ]; then X usage Xfi Xsearch=$1 Xshift Xyear=$* X Xif [ -z "$year" ]; then X if whence uname > /dev/null; then X [ "$(uname -s)" = HP-UX ] && machine=hp X fi X case "$machine" in X hp) year=$(date | awk '{print $6}');; X *) year=$(date | awk '{print $5}');; X esac Xfi X Xtrap intr 2 X Xfor i in $year; do X cd $mail/$i || continue X for j in $months; do X if [ -f $j.idx.Z ]; then X zcat $j.idx.Z | search "$search" X elif [ -f $j.idx ]; then X cat $j.idx | search "$search" X else X echo "No index for $j." X fi X done Xdone X Xbye X X# Local Variables: X# mode: sh X# End: END_OF_FILE if test 2796 -ne `wc -c <'seek'`; then echo shar: \"'seek'\" unpacked with wrong size! fi chmod +x 'seek' # end of 'seek' fi echo shar: End of archive 1 \(of 1\). cp /dev/null ark1isdone MISSING="" for I in 1 ; do if test ! -f ark${I}isdone ; then MISSING="${MISSING} ${I}" fi done if test "${MISSING}" = "" ; then echo You have the archive. rm -f ark[1-9]isdone else echo You still need to unpack the following archives: echo " " ${MISSING} fi ## End of shell archive. exit 0