junkmail - delete outdated mail automatically
sources-request at panda.UUCP
sources-request at panda.UUCP
Mon May 19 07:51:51 AEST 1986
Mod.sources: Volume 5, Issue 6
Submitted by: Wombat <pur-ee!pucc-j.Purdue.EDU!rsk>
# This is a shell archive.
# Remove everything above and including the cut line.
# Then run the rest of the file through sh.
#----cut here-----cut here-----cut here-----cut here----#
#!/bin/sh
# shar: Shell Archiver
# Run the following text with /bin/sh to create:
# README
# junkmail.8
# junkmail.c
# This archive created: Thu May 15 14:37:16 1986
# By: Wombat (Purdue University)
cat << \SHAR_EOF > README
Junkmail is designed to be run from "cron" or "at" on a regular basis
in order to keep the size of /usr/spool/mail within reasonable limits.
It deletes old/large mail according to criteria described in the manual
page, and settable at compile or run time.
It should be compatible with 4.x BSD; don't know about AT&T Unix.
It is also capable of deleting all mail from a specified user--a feature
which is occasionally handy when a malicious/naive user discovers mail.
Comments and bugs to:
Rich Kulawiec, pucc-j!rsk, rsk at asc.purdue.edu
README This file
junkmail.c Superfluous/malicious mail deletion program
(cc -O -DPUCC -DBSD4_2 -o junkmail junkmail.c)
junkmail.8l Manual page for above
(nroff -man junkmail.8l)
SHAR_EOF
cat << \SHAR_EOF > junkmail.8
.TH JUNKMAIL 8
.UC 4
.SH NAME
junkmail \- delete undesired mail from /usr/spool/mail
.SH SYNOPSIS
.B junkmail \fR[\fB-a\fR] [\fB-w\fR] [\fB-dn\fR[\fB-m\fR]] [\fB-u\fRusername] [directory]
.SH DESCRIPTION
.I Junkmail
is designed to cope with overuse of /usr/spool/mail.
It searches
/usr/spool/mail/*
for old and/or large letters and deletes them,
leaving a message informing the user of this action.
It may also be used to delete all mail from a specified user.
The following options are interpreted by
.I junkmail.
.TP
.B \-a
Select an audit trail.
.TP
.B \-w
Specifies that shortened files are to be written,
containing letters that indicate what has been deleted.
Otherwise, only an audit is performed.
.TP
.BI \-d n[-m]
Specifies that the following number
.I
n
or range of numbers
.I
n-m
defines the age of discarded letters.
A letter newer than
.I
n
days will only be discarded if the mail file
exceeds the limit by 100%.
A letter between
.I
n
and
.I
m
days old will be discarded if the mail file exceeds the size
limit.
A letter older than
.I
m
days will always be discarded.
.I
N
defaults to 7;
.I
m,
to 21.
If a single value is specified, it is taken to be
.I
m,
and
.I
n
is assumed to be 7.
Of course,
.I
m
must be greater than
.I
n.
.TP
.B \-u\fRusername
specifies that all mail originating from user
"username"
be deleted, whether or not it satisfies the aging constraints.
All other mail will be untouched, and no letter informing the
recipient(s) of the deletion will be left.
.TP
[directory]
is the optional mail directory name,
with "/usr/spool/mail" as the default.
.SH FILES
/usr/spool/mail/*
.SH "SEE ALSO"
mail(1)
.SH BUGS
When an individual username is selected,
.I
junkmail
cannot cope with large files and prints a message to that
effect rather than deleting the letters.
SHAR_EOF
cat << \SHAR_EOF > junkmail.c
/*==========================================================
*
* junkmail - delete undesired mail from /usr/spool/mail/*
*
* Copyright, Purdue University Computing Center, 1982, all
* rights reserved.
*
* Author: V. Abell
* Modifications: R. Kulawiec 8/83 added -u flag.
* Rewrote a lot of the code to handle buffering.
* R. Kulawiec 10/84 added audit trail for -u flag.
* added "reason for deletion"
* added extra line on rewritten headers
* R. Kulawiec 6/85 rewritten headers now conform to RFC822.
*
* junkmail [-a] [-w] [-dn[-m]] [-u username] [directory]
*
* -a selects an audit trail.
*
* -w specifies that shortened files are to
* be written, containing letters that
* indicate what has been deleted.
* Otherwise, only an audit is performed.
*
* -d specifies that the following number, n,
* or range of numbers, n-m, defines the
* age of discarded letters. A letter
* newer than n days will only be discarded
* if the mail file size exceeds the limit
* by 100%. A letter older than m days will
* be discarded. n defaults to 7; m, to 21.
* If a single value is specified, it is
* taken to be m, and n is assumed to be 7.
* Of course, m must be > n.
*
* -u username specifies that all mail from user
* "username" be deleted, regardless of age
* or size.
*
* [directory] is the optional mail directory
* name - "/usr/spool/mail" is the default.
*
*
*==========================================================
*/
#include <stdio.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/dir.h>
#include <sys/stat.h>
#include <time.h>
#define LINE_LEN 1024 /* Maximum length of a line */
#define LOC_TIME_ZONE 5*60 /* local time zone offset (EST) */
#define FILENAME_LEN 128 /* Length of individual filenames */
#define DIRECTORY_LEN 128 /* Length of directory name */
#define USERNAME_LEN 128 /* Maximum length of any originator */
#define FAILED -1 /* Failure return code from call */
#define FAILED_LONG -1l /* Failure return code from call */
#define SUCCEED 0 /* Success return code from call */
#define SUCCEED_LONG 0l /* Success return code from call */
#define DIRECT "/usr/spool/mail/" /* directory name for mail */
#define SENDER "MAILER-DAEMON" /* audit letter sender */
#define MAX_AGE 21L /* maximum letter age (default) */
#define MIN_AGE 7L /* minimum letter age (default) */
#define PROTECT_MODE 0600 /* protection mode */
#define MAX_SIZE 50000 /* nominal maximum mailbox size */
#define ABS_MAX_SIZE 2*MAX_SIZE /* absolute maximum mailbox size */
#define NEWLINE '\n' /* Ascii newline character */
char Selectname[USERNAME_LEN]; /* name of user whose mail to blast */
char Directory[DIRECTORY_LEN] = DIRECT; /* working directory (default) */
char Filename[FILENAME_LEN]; /* individual files as we go */
int audit_flag = 0; /* Audit trail is selected */
int rewrite_flag = 0; /* Rewriting of files will be done */
int select_flag = 0; /* Individual user has been selected */
int date_flag = 0; /* User has overridden a date(s) */
long max_age = MAX_AGE; /* maximum letter age */
long min_age = MIN_AGE; /* minimum letter age */
char *day_table[7] = {"Mon","Tue","Wed","Thu","Fri","Sat","Sun"};
int month_size[12] = {31,28,31,30,31,30,31,31,30,31,30,31};
char *month_table[12] = {"Jan","Feb","Mar","Apr","May","Jun",
"Jul","Aug","Sep","Oct","Nov","Dec"};
struct zone {
int hours_west; /* hours west of Greenwich */
char *st; /* standard time zone name */
char *dl; /* daylight time zone name */
} z_tab[] = {
4*60, "AST", "ADT", /* Atlantic */
5*60, "EST", "EDT", /* Eastern */
6*60, "CST", "CDT", /* Central */
7*60, "MST", "MDT", /* Mountain */
8*60, "PST", "PDT", /* Pacific */
0000, "GMT", "GMT", /* Greenwich */
-1 /* end of table indicator */
};
struct stat Sbuf; /* for return values from stat() call */
struct direct Dir_entry; /* directory structure */
#ifdef vax
DIR *Dfd;
#else
int Dfd; /* directory file descriptor */
#endif
FILE *Mfp; /* mail file pointer */
FILE *Tfp; /* temp file pointer */
char *Tempfile = "/tmp/junkXXXXXX"; /* Temporary file for copying */
char sndl[512]; /* "MAIL~SYSTEM" sender line */
int compare_length = USERNAME_LEN; /* longest originator length */
char Buffer[LINE_LEN]; /* Input/output mail buffer */
char Headbuf[LINE_LEN]; /* Save area for mail header */
long File_length = 0l; /* Length of input mail file */
char *ctime(); /* Time conversion */
char *mktemp(); /* Temporary filename maker */
#ifndef vax
char machine(); /* Machine identifier */
#endif
int Copy_flag = 1; /* Whether or not to copy bytes through */
long bytes_del; /* Number of bytes deleted from this file */
/* (or that could be deleted). Note that */
/* this does NOT account for bytes written */
/* by junkmail itself. */
long tot_bytes_del = 0; /* Total number of bytes deleted in run */
int files_short = 0; /* Total number of files shortened */
int files_del = 0; /* Total number of zero-length files deleted */
char Loginname[255]; /* The name of the file in /usr/spool/mail. */
/* Set to 255 to avoid unpleasant surprises */
/* should a filename > 8 chars creep in. */
main(argc, argv)
int argc;
char *argv[];
{
int i;
long time();
long time_buf;
char hoststr[32];
i = 1;
do {
if(argc != 0)
if(argc > 1 && strncmp(argv[i],"-",1) == 0 ) {
if(strncmp(argv[i],"-a",2) == 0) { /* audit */
audit_flag = 1;
continue;
}
if(strncmp(argv[i],"-w",2) == 0) { /* rewrite */
rewrite_flag = 1;
continue;
}
if(strncmp(argv[i],"-d",2) == 0) { /* date ch. */
date_flag = 1;
if( agerange(argv[i]) == FAILED)
usage();
continue;
}
if(strncmp(argv[i],"-u",2) == 0) { /* target */
if( get_selectname(argv[++i]) == FAILED )
usage();
select_flag = 1;
rewrite_flag = 1;
continue;
}
usage();
}
if(argc > 1) { /* chdir */
if( get_dirname(argv[i]) == FAILED )
usage();
continue;
}
}
while(++i < argc);
if(select_flag && date_flag) {
fprintf(stderr,"Use of -u and -d together not allowed\n");
usage();
}
time(&time_buf);
#ifdef vax
if(gethostname(hoststr,sizeof(hoststr)) == FAILED)
fprintf(stderr,"Gethostname() failed!\n");
#else
sprintf(hoststr,"pucc-%s",machine());
#endif
if(audit_flag)
printf("\n%s, %s\n",hoststr,ctime(&time_buf));
if(rewrite_flag)
sprintf(sndl,"From %s %sReceived: by %s, %sDate: %sFrom: <pucc> %s\nTo: ",SENDER,ctime(&time_buf),hoststr,ctime(&time_buf),ctime(&time_buf),SENDER);
if(rewrite_flag)
Tempfile = mktemp(Tempfile);
if(check_dirname() == FAILED)
usage();
if(select_flag)
printf("Deleting all mail from user %s\n\n",Selectname);
while( get_filename() != FAILED) {
if(select_flag) {
if(del_user()==FAILED)
exit(1);
}
else {
if(del_oldbig() == FAILED)
exit(1);
}
if(audit_flag && (bytes_del != 0) ) {
printf("\t%s",Filename);
if(rewrite_flag)
printf(" was shortened by ");
else
printf(" could be shortened by ");
printf("%ld bytes\n",bytes_del);
}
}
if(audit_flag) {
printf("----------\n");
printf("%d files",files_short);
if(rewrite_flag)
printf(" were shortened by ");
else
printf(" could be shortened by ");
printf("%ld bytes\n",tot_bytes_del);
if( !select_flag) {
printf("%d zero-length files",files_del);
if(rewrite_flag)
printf(" were deleted\n");
else
printf(" could be deleted\n");
}
printf("----------\n");
}
}
/*==================================================
*
* usage() - print argument usage message and exit.
*
*
*==================================================
*/
usage()
{
fprintf(stderr,"Usage: junkmail [-a] [-w] [-dn[-m]] [-u username] [directory]\n");
exit(1);
}
/*==================================================
*
* get_selectname(p) - Get the username pointed to.
*
*
*==================================================
*/
get_selectname(p)
char *p;
{
if(strlen(p) > USERNAME_LEN) /* Username can't be more */
return(FAILED); /* than this long */
if(strlen(p) <= 0 ) /* Username can't this */
return(FAILED); /* long either */
else {
strcpy(Selectname,p);
return(SUCCEED);
}
}
/*==================================================
*
* get_dirname(p) - Get the directory name pointed to.
*
*
*==================================================
*/
get_dirname(p)
char *p;
{
if(strlen(p) > DIRECTORY_LEN) /* Username can't be more */
return(FAILED); /* than this long */
if(strlen(p) <= 0 ) /* Username can't this */
return(FAILED); /* long either */
else {
strcpy(Directory,p);
return(SUCCEED);
}
}
/*==========================================================
*
* agerange(p) - assemble the age range represented by the
* characters at (p).
*
* exit return = 0 if range assembled
* -1 if assembly error detected
* (min_age) = minimum age
* (max_age) = maximum age
*
*==========================================================
*/
agerange(p)
char *p;
{
int n; /* number being assembled */
/*
* Assemble first number.
*/
p += 2; /* Skip over the "-d" flag */
for(n = 0; *p >= '0' && *p <= '9'; p++)
n = 10 * n + *p - '0';
if(*p != '\0') {
if(*p++ != '-')
return(FAILED);
/*
* If the first number is terminated by a minus sign ("-"),
* assemble the second number of an "n-m" range.
*/
min_age = (long) n;
for(n = 0; *p >= '0' && *p <= '9'; p++)
n = 10 * n + *p - '0';
}
max_age = (long) n;
if(min_age <= 0l || max_age <= 0l || min_age >= max_age)
return(FAILED);
return(SUCCEED);
}
/*======================================================================
*
* long dysince(a) - convert the ctime() format date, addressed by (a)
* to the number of days since that date.
*
* exit return = -1L if the date cannot be converted
*
*======================================================================
*/
long dysince(a)
char *a;
{
int day; /* day */
int hours; /* hours */
int minutes; /* minutes */
int month; /* month */
int seconds; /* seconds */
int year; /* year */
int z = LOC_TIME_ZONE; /* time zone offset */
long time_buf; /* time buffer */
long time_sec = 0l; /* time in seconds */
register int i; /* temporary index */
/*
* Check and skip day of week.
*/
if(ckalpha(a,3) == 0)
return(FAILED_LONG);
for(i = 0; i < 7; i++)
if(strncmp(a,day_table[i],3) == 0)
break;
if(i > 6)
return(FAILED_LONG);
a += 3;
if(*a++ != ' ')
return(FAILED_LONG);
/*
* Check month and convert to integer.
*/
if(ckalpha(a,3) == 0)
return(FAILED_LONG);
for(month = 0; month < 12; month++)
if(strncmp(a,month_table[month],3) == 0)
break;
if(month > 11)
return(FAILED_LONG);
a += 3;
while(*a == ' ') {
if(*a == '\0')
return(FAILED_LONG);
a++;
}
/*
* Convert day number.
*/
day = atoi(a);
while(*a >= '0' && *a <= '9')
a++;
while(*a == ' ') {
if(*a == '\0')
return(FAILED_LONG);
a++;
}
/*
* Convert time.
*/
hours = atoi(a);
while(*a >= '0' && *a <= '9')
a++;
if(hours < 0 || hours > 23 || *a++ != ':')
return(FAILED_LONG);
minutes = atoi(a);
while(*a >= '0' && *a <= '9')
a++;
if(minutes < 0 || minutes > 59 || *a++ != ':')
return(FAILED_LONG);
seconds = atoi(a);
while(*a >= '0' && *a <= '9')
a++;
if(seconds < 0 || seconds > 59 || *a++ != ' ')
return(FAILED_LONG);
/*
* Convert time zone and year.
*/
if((*a >= 'a' && *a <= 'z') || (*a >= 'A' && *a <= 'Z')) {
if(ckalpha(a,3) == 0)
return(FAILED_LONG);
for(i = 0; (z = z_tab[i].hours_west) >= 0; i++) {
if(strncmp(a,z_tab[i].st,3) == 0
|| strncmp(a,z_tab[i].dl,3) == 0)
break;
}
if(z == -1)
return(FAILED_LONG);
while(*a < '0' || *a > '9') {
if(*a == '\0')
return(FAILED_LONG);
a++;
}
}
minutes += z;
year = atoi(a);
/*
* Check year.
*/
if(year < 1970)
return(FAILED_LONG);
/*
* Cope with February in leap/non-leap years.
*/
if(leap(year))
month_size[1] = 29;
else
month_size[1] = 28;
if(day < 1 || day > month_size[month])
return(FAILED_LONG);
/*
* Calculate seconds since the epoch.
*/
for(i = 1970; i < year; i++)
time_sec += (leap(i) ? 366 : 365);
while(--month >= 0)
time_sec += month_size[month];
time_sec += (long) day - 1l;
time_sec = time_sec*24l + (long) hours;
time_sec = time_sec*60l + (long) minutes;
time_sec = time_sec*60l + (long) seconds;
/*
* Return days from today as (seconds from today).
* ------------------
* 24 * 60 * 60
*/
time(&time_buf);
if(time_sec > time_buf)
return(FAILED_LONG);
return((time_buf - time_sec) / 86400l);
}
/*=============================================
*
* leap(y) - test (y) for a leap year
*
* exit return = 0 if not a leap year
* 1 if a leap year
*
*=============================================
*/
leap(y)
int y;
{
return(y%4 == 0 && y%100 != 0 || y%400 == 0);
}
/*====================================================================
*
* ckalpha(a,n) - check for n consecutive alpha characters, starting
* at (a).
*
* exit return = 0 if non-alpha character encountered
* 1 if characters available
*
*====================================================================
*/
ckalpha(a,n)
char *a;
int n;
{
register int i; /* temporary index */
for(i = 0; i < n; i++)
if( (! isascii(*a)) || (! isalpha(*a)) )
return(0);
return(1);
}
/*====================================================================
*
* check_dirname() - Verify that "Directory" exists, is a
* directory, and is readable.
*
* exit return = 0 if a legitimate directory has been found
* -1 otherwise
*
*====================================================================
*/
check_dirname()
{
if( stat(Directory,&Sbuf) == FAILED) {
fprintf(stderr,"Can't stat %s\n",Directory);
return(FAILED);
}
if( ((Sbuf.st_mode & S_IFDIR) == 0) || Sbuf.st_ino == 0 ) {
fprintf(stderr,"%s is not a directory\n",Directory);
return(FAILED);
}
#ifdef vax
if( (Dfd = opendir(Directory)) == NULL) {
#else
if( (Dfd = open(Directory,0)) == FAILED) {
#endif
fprintf(stderr,"Can't open directory %s\n",Directory);
return(FAILED);
}
return(SUCCEED);
}
/*====================================================================
*
* get_filename() - Get the next file in directory "Directory".
*
* exit return = 0 if a legitimate file has been found
* -1 otherwise
*
* Note: "Reads through" '.' and '..' transparently.
*
*====================================================================
*/
get_filename()
{
int pathlength;
#ifdef vax
struct direct *dirent;
#endif
/* Add tailing slash to directory name if user forgot it */
if(Directory[strlen(Directory)-1] != '/')
strcat(Directory,"/");
strcpy(Filename,Directory);
pathlength = strlen(Filename);
#ifdef vax
while( (dirent = readdir(Dfd)) != NULL) {
if(dirent->d_ino == 0) /* File has been deleted */
continue;
if(strncmp(dirent->d_name,".",1) == 0) /* Skip "." */
continue;
if(strncmp(dirent->d_name,"..",2) == 0) /* Skip ".." */
continue;
strncpy(&Filename[pathlength],dirent->d_name,sizeof(dirent->d_name));
strcpy(Loginname,dirent->d_name);
return(SUCCEED);
}
closedir(Dfd);
return(FAILED);
#else
while(read(Dfd,&Dir_entry,sizeof(Dir_entry)) > 0) {
if(Dir_entry.d_ino == 0) /* File has been deleted */
continue;
if(strncmp(Dir_entry.d_name,".",1) == 0) /* Skip "." */
continue;
if(strncmp(Dir_entry.d_name,"..",2) == 0) /* Skip ".." */
continue;
strncpy(&Filename[pathlength],Dir_entry.d_name,sizeof(Dir_entry.d_name));
strcpy(Loginname,Dir_entry.d_name);
return(SUCCEED);
}
if( close(Dfd) == FAILED)
fprintf(stderr,"Couldn't close %s\n",Directory);
return(FAILED); /* Have read entire dir. */
#endif
}
/*==================================================
*
* del_oldbig() - remove letters that are either too old or too big.
* remove mailboxes that are zero length.
* exit - 0 if no problems encountered
* 1 if couldn't open or other nastiness
*
*==================================================
*/
del_oldbig()
{
long finalsize;
long size_date();
long filemark; /* Marks beginning of current letter */
int onetrip; /* Whether or not we've made first */
/* trip through mail scanning loop */
int copy; /* Temporary loop index for saving */
/* mail headers */
int wrote_sndl; /* Whether or not we've written our */
/* "From" line to temp file */
if( stat(Filename,&Sbuf) == FAILED) {
fprintf(stderr,"Can't stat %s\n",Filename);
return(FAILED);
}
/* Reset delete counter in case we exit before setting it below */
bytes_del = 0l;
/* If file is zero length, mark it for deletion */
if(Sbuf.st_size == 0) {
++files_del;
if(rewrite_flag)
unlink(Filename);
if(audit_flag && rewrite_flag)
printf("\t%s was zero-length, deleted\n",Filename);
if(audit_flag && !rewrite_flag)
printf("\t%s is zero-length\n",Filename);
return(SUCCEED);
}
/* Determine what the final size for this file should be */
if( (finalsize = size_date()) == FAILED_LONG) {
fprintf(stderr,"Error determining date/size of %s\n",Filename);
return(FAILED);
}
if(Sbuf.st_size <= finalsize) /* File is smaller than it */
return(SUCCEED); /* has to be, no problem. */
++files_short; /* Another one shortened */
File_length = Sbuf.st_size;
filemark = File_length;
onetrip = FAILED;
wrote_sndl = FAILED;
if( (Mfp = fopen(Filename,"r+")) == NULL) {
fprintf(stderr,"Can't open %s\n",Filename);
return(FAILED);
}
if(rewrite_flag) {
if( (Tfp = fopen(Tempfile,"w+")) == NULL) {
fprintf(stderr,"Can't open tempfile %s\n",Tempfile);
return(FAILED);
}
}
while( readline() == SUCCEED && File_length > finalsize) {
if(is_a_header() == SUCCEED) {
if(rewrite_flag && (from_system() == FAILED) ) {
if(wrote_sndl == FAILED) {
fprintf(Tfp,"%s",sndl);
if( rindex(Filename,'/') == NULL) {
fprintf(Tfp,"%s\nSubject: Mail deleted by MAILER-DAEMON\n\n",Filename);
}
else {
fprintf(Tfp,"%s\nSubject: Mail deleted by MAILER-DAEMON\n\n",rindex(Filename,'/') + (char *) (1));
}
wrote_sndl = SUCCEED;
}
fprintf(Tfp," Letter deleted: ");
writeline();
}
if(audit_flag && (onetrip == SUCCEED) ) {
printf("%s: ",Loginname);
printf("%8ld bytes: ",filemark-File_length);
filemark = File_length;
printhead();
}
if (audit_flag) {
for(copy=0 ; copy < LINE_LEN ; copy++) {
Headbuf[copy]= Buffer[copy];
}
}
onetrip = SUCCEED;
}
}
/* Eat up rest of last message deleted; wait for next letter header */
while(readline() == SUCCEED && is_a_header() == FAILED);
bytes_del = Sbuf.st_size - File_length;
tot_bytes_del += bytes_del;
/* Write out this new header, but be careful to check that */
/* it definitely is one. (I.e., one-line loop above may have */
/* exited due to EOF and not a "From" line. */
/* Also make sure to add a newline at the end of our message */
/* so as not to confuse any mailers. */
if(rewrite_flag && is_a_header() == SUCCEED ) {
if(finalsize == 0)
fprintf(Tfp,"\n Reason: system mailbox older than %d days\n\n",max_age);
else if (finalsize == MAX_SIZE)
fprintf(Tfp,"\n Reason: system mailbox older than %d days and larger than %ld bytes\n\n",min_age,MAX_SIZE);
else if (finalsize == ABS_MAX_SIZE)
fprintf(Tfp,"\n Reason: system mailbox larger than %ld bytes\n\n",ABS_MAX_SIZE);
else
fprintf(Tfp,"\n Reason: unknown\n\n");
writeline();
}
if(audit_flag) {
printf("%s: ",Loginname);
printf("%8ld bytes: ",filemark-File_length);
filemark = File_length;
printhead();
for(copy=0 ; copy < LINE_LEN ; copy++) {
Headbuf[copy]= Buffer[copy];
}
}
while(readline() == SUCCEED) {
if(rewrite_flag)
writeline();
}
if(cleanup() == FAILED)
return(FAILED);
return(SUCCEED);
}
/*==================================================
*
* from_system() - returns true if this letter was
* from a previous invocation of this
* program; causes mail files to decay
* to zero length eventually.
*
*==================================================
*/
from_system()
{
if( strncmp(&Buffer[5],&sndl[5],strlen(SENDER) ) == 0)
return(SUCCEED);
else
return(FAILED);
}
/*==================================================
*
*
* del_user() - remove letters that are from user "Selectname"
* exit - 0 if no problems encountered
* 1 if couldn't open or other nastiness
*
*
*==================================================
*/
del_user()
{
int file_trunc; /* Set if this file truncated */
long mark_beg; /* marks beginning of current letter */
long mark_end; /* marks end of current letter */
int copy; /* Temporary loop index for saving */
/* mail headers */
file_trunc = 0; /* Zero out audit counters */
bytes_del = 0;
if( stat(Filename,&Sbuf) == FAILED) {
fprintf(stderr,"Can't stat %s\n",Filename);
return(FAILED);
}
/* If file is zero length, don't bother with it. */
if(Sbuf.st_size == 0)
return(SUCCEED);
if( (Mfp = fopen(Filename,"r+")) == NULL) {
fprintf(stderr,"Can't open %s\n",Filename);
return(FAILED);
}
if( (Tfp = fopen(Tempfile,"w+")) == NULL) {
fprintf(stderr,"Can't open tempfile %s\n",Tempfile);
return(FAILED);
}
File_length = Sbuf.st_size;
mark_beg = File_length;
mark_end = File_length;
Copy_flag = 1;
/* The idea of mark_beg and mark_end is that mark_end continually */
/* keeps track of the end of the previous line, and that mark_beg */
/* keeps track of the end of the last line of the last letter, so */
/* the distance between reflects the number of bytes deep we are */
/* into the current letter. When we finish with a letter, we know */
/* how long it was. */
while(readline() == SUCCEED) {
if(is_a_header() == SUCCEED) {
if(audit_flag && !Copy_flag) {
printf("%s: ", Loginname);
printf("%8ld bytes: ", mark_beg - mark_end);
printhead();
bytes_del += (mark_beg - mark_end);
mark_beg = mark_end;
}
if(audit_flag && Copy_flag)
mark_beg = mark_end;
if(is_from_user() == SUCCEED) {
Copy_flag = 0;
file_trunc = 1;
if(audit_flag)
for(copy = 0; copy < LINE_LEN; copy++)
Headbuf[copy] = Buffer[copy];
}
else
Copy_flag = 1;
}
if(Copy_flag)
writeline();
mark_end = File_length;
}
if( !Copy_flag) { /* Last letter was hit */
if(audit_flag) {
printf("%s: ", Loginname);
printf("%8ld bytes: ", mark_beg - mark_end);
printhead();
bytes_del += (mark_beg - mark_end);
}
}
if(file_trunc == 1)
++files_short;
tot_bytes_del += bytes_del;
if(cleanup() == FAILED)
return(FAILED);
return(SUCCEED);
}
/*
*******************************************************************
* readline() - read a line from input mail file
* returns 0 if line successfully read
* -1 if out of characters to read
*******************************************************************
*/
readline()
{
int how_many_read = 0;
char *bufptr = Buffer;
char c;
if(File_length == 0)
return(FAILED);
do{
c = getc(Mfp);
*bufptr++ = c;
++how_many_read;
}
while( (c != NEWLINE)
&& (how_many_read < LINE_LEN)
&& (how_many_read < File_length) );
File_length -= how_many_read;
return(SUCCEED);
}
/*
*******************************************************************
* writeline() - Write out a line to the temp file.
* returns 0 ALWAYS
*******************************************************************
*/
writeline()
{
int i;
char *bufptr = Buffer;
char c;
for( i = 0; i < LINE_LEN; i++) {
c = *bufptr++;
putc(c,Tfp);
if(c == NEWLINE)
return(SUCCEED);
}
return(SUCCEED);
}
/*
*******************************************************************
* printhead() - Write out a line to stdout.
* returns 0 ALWAYS
*******************************************************************
*/
printhead()
{
int i;
char *bufptr = Headbuf;
char c;
for( i = 0; i < LINE_LEN; i++) {
c = *bufptr++;
putchar(c);
if(c == NEWLINE)
return(SUCCEED);
}
return(SUCCEED);
}
/*
*******************************************************************
* is_a_header() - Is this line a mail letter header?
* (i.e. Does it begin with "From "?
* returns 0 if it is
* -1 if not
*******************************************************************
*/
is_a_header()
{
if( Buffer[0] != 'F' )
return(FAILED);
if( Buffer[1] == 'r'
&& Buffer[2] == 'o'
&& Buffer[3] == 'm'
&& Buffer[4] == ' ') /* If succeeds, must be header */
return(SUCCEED);
else
return(FAILED);
}
/*
*******************************************************************
* is_from_user() - Is this file from user "Selectname"?
* returns 0 if it is
* -1 if not
*******************************************************************
*/
is_from_user()
{
int j;
for(j=0;j<strlen(Selectname);j++)
if(Buffer[j+5] != Selectname[j])
return(FAILED);
return(SUCCEED);
}
/*
*******************************************************************
* size_date() - Look at modify time and size of this file
* to determine to what length it should be cut.
* returns 0 if everything goes ok
* -1 if time didn't make sense.
*******************************************************************
*/
long
size_date()
{
long finalsize;
long days_elapsed;
char *filetime;
filetime = ctime(&Sbuf.st_mtime);
days_elapsed = dysince(filetime);
if(days_elapsed > max_age)
finalsize = 0;
if(days_elapsed <= max_age && days_elapsed > min_age)
finalsize = MAX_SIZE;
if(days_elapsed <= min_age && days_elapsed >= 0l)
finalsize = ABS_MAX_SIZE;
if(days_elapsed < 0l)
return(FAILED_LONG);
return(finalsize);
}
/*
*******************************************************************
* cleanup() - Copy results back to original, blast temp file.
* returns 0 if everything goes ok
* -1 if closes/(un)links/chown/chmod fail
*******************************************************************
*/
cleanup()
{
int c; /* Character for copying */
if( !rewrite_flag) { /* If not writing, then stop here */
if( fclose(Mfp) != SUCCEED) {
fprintf(stderr,"Couldn't close %s\n",Filename);
return(FAILED);
}
return(SUCCEED);
}
if( fflush(Mfp) != SUCCEED) {
fprintf(stderr,"Couldn't fflush %s\n",Filename);
return(FAILED);
}
if( fflush(Tfp) != SUCCEED) {
fprintf(stderr,"Couldn't fflush tempfile %s\n",Tempfile);
return(FAILED);
}
if( (Mfp=freopen(Filename,"w",Mfp)) == NULL) {
fprintf(stderr,"Couldn't freopen %s\n",Filename);
return(FAILED);
}
if( rewind(Tfp) != SUCCEED) {
fprintf(stderr,"Couldn't rewind tempfile %s\n",Tempfile);
return(FAILED);
}
while( (c=getc(Tfp)) != EOF)
putc(c,Mfp);
if( fclose(Mfp) != SUCCEED) {
fprintf(stderr,"Couldn't close %s\n",Filename);
return(FAILED);
}
if( fclose(Tfp) != SUCCEED) {
fprintf(stderr,"Couldn't close tempfile %s\n",Tempfile);
return(FAILED);
}
if( unlink(Tempfile) == FAILED) {
fprintf(stderr,"Couldn't unlink tempfile %s\n",Tempfile);
return(FAILED);
}
return(SUCCEED);
}
SHAR_EOF
# End of shell archive
exit 0
More information about the Mod.sources
mailing list