home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
misc
/
volume26
/
em
/
part01
/
em.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-11-25
|
9KB
|
527 lines
/*
** em: expire mail messages
**
**
** Options:
**
** -a age
** Specify how many days old an 'expired' message is. Default
** is 180 (six months).
** -d
** Debug. Only generates an audit trail. No actual removal takes
** place. More 'd's, more debugging information.
** -o
** Do not remove mailboxes just because they're older than 'age'
** days. Instead, explicitly scan the mailbox to ensure that all
** messages have expired. The default is for em to remove any
** mailboxes that have modification times older than 'age' days.
** -u username
** Secify that only messages from 'username' will be considered
** for expiration. Useful for removing messages from an offensive
** user.
** -v
** Be verbose. This option produces the same output as the debug
** option but all actions are followed through. That is, messages
** are expired, mailboxes are removed, etc.
** -z
** Do not remove mailboxes of zero length.
**
**
** Author:
**
** Steve Mitchell
** California State University, Fresno
** steve_mitchell@csufresno.edu
**
**
** NOTICE:
**
** THE AUTHOR OFFERS NO WARRANTY FOR THE PERFORMANCE OF THIS SOFTWARE.
** (In other words, use at your own risk)
**
**
** Version History:
**
** 09/12/91: first version
**
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <ctype.h>
#include <sys/time.h>
#include <stdio.h>
#include <fcntl.h>
#ifdef UTIME
#ifdef sun
#include <utime.h>
#endif
#endif
#ifndef S_ISREG
#define S_ISREG(m) (((m)&S_IFMT) == S_IFREG)
#endif
int aged = 160;
int sec_aged;
int debug = 0;
int verbose = 0;
int oldflag = 1;
int zeroflag = 1;
char *fromwho = (char *)0;
char *myname;
char *whoami;
time_t currtime;
#ifdef UTIME
struct utimbuf tv;
#else
struct timeval tv[2];
#endif
int mbox_id;
void usage();
time_t time();
char *getlogin();
char *strrchr();
time_t mystrptime();
void resettimes();
struct msg {
char *from;
time_t time;
};
main(argc,argv)
int argc;
char *argv[];
{
FILE *mfp;
FILE *ofp;
char *mailbox;
int c;
int errflg = 0;
int num_expired = 0;
extern char *optarg;
extern int optind;
struct stat sbuf;
char tname[BUFSIZ];
char *p;
myname = argv[0];
whoami = getlogin();
while((c = getopt(argc,argv,"a:dou:vz")) != -1)
switch(c) {
case 'a':
aged = atoi(optarg);
break;
case 'd':
debug++;
break;
case 'o':
oldflag = 0;
break;
case 'u':
fromwho = optarg;
break;
case 'v':
verbose = 1;
break;
case 'z':
zeroflag = 0;
break;
default:
errflg++;
}
if(errflg || optind == argc) {
usage();
return(1);
}
sec_aged = aged * 86400;
(void)time(&currtime);
for(;optind < argc; optind++) {
mailbox = argv[optind];
if(stat(mailbox,&sbuf) < 0) {
perror(mailbox);
continue;
}
#ifdef UTIME
tv.actime = sbuf.st_atime;
tv.modtime = sbuf.st_mtime;
#else
tv[0].tv_sec = sbuf.st_atime;
tv[1].tv_sec = sbuf.st_mtime;
#endif
mbox_id = sbuf.st_uid;
p = strrchr(mailbox,'.');
if(p)
if(!strcmp(p,".lock"))
continue;
if(locked(mailbox)) {
(void)fprintf(stderr,"%s: locked\n",mailbox);
continue;
}
#ifdef S_ISREG
if(!S_ISREG(sbuf.st_mode)) {
(void)fprintf(stderr,"%s: not a regular file\n",
mailbox);
continue;
}
#endif
if(debug >= 1 || verbose >= 1)
(void)printf("%s:\n",mailbox);
if(currtime - sbuf.st_mtime > sec_aged && oldflag) {
if(debug >= 1 || verbose >= 1)
(void)printf(
"\tolder than %d days - remove\n",aged);
if(!debug)
if(unlink(mailbox) < 0)
perror(mailbox);
continue;
}
if(sbuf.st_size == 0 && zeroflag) {
if(debug >= 1 || verbose >= 1)
(void)printf("\tzero length - remove\n");
if(!debug)
if(unlink(mailbox) < 0)
perror(mailbox);
continue;
}
if(!lock(mailbox)) {
(void)fprintf(stderr,"%s: can't lock\n",mailbox);
continue;
}
if((mfp = fopen(mailbox,"r")) == NULL) {
perror(mailbox);
continue;
}
p = strrchr(mailbox,'/');
if(p)
p++;
else
p = mailbox;
(void)sprintf(tname,"/tmp/%s.expire",p);
if((ofp = fopen(tname,"w")) == NULL) {
perror(tname);
(void)fclose(mfp);
resettimes(mailbox);
(void)unlock(mailbox);
continue;
}
num_expired = do_msgs(mfp,ofp);
if(stat(tname,&sbuf) < 0) {
perror(tname);
(void)unlock(mailbox);
continue;
}
if(sbuf.st_size == 0 && zeroflag) {
if(debug >= 1 || verbose >= 1) {
(void)printf("\tzero length - remove\n");
resettimes(mailbox);
}
if(!debug)
if(unlink(mailbox) < 0)
perror(mailbox);
if(unlink(tname) < 0)
perror(tname);
(void)unlock(mailbox);
continue;
}
if(debug || !num_expired) {
(void)unlink(tname);
(void)fclose(mfp);
resettimes(mailbox);
if(!unlock(mailbox))
(void)fprintf(stderr,
"%s: can't unlock\n",mailbox);
continue;
}
if((mfp = fopen(mailbox,"w")) == NULL) {
perror(mailbox);
(void)unlock(mailbox);
continue;
}
if((ofp = fopen(tname,"r")) == NULL) {
perror(tname);
(void)fclose(mfp);
resettimes(mailbox);
(void)unlock(mailbox);
continue;
}
while((c = fgetc(ofp)) != EOF)
(void)fputc(c,mfp);
(void)fclose(ofp);
(void)fclose(mfp);
resettimes(mailbox);
if(!unlock(mailbox)) {
(void)fprintf(stderr,"%s: can't unlock\n",mailbox);
continue;
}
if(unlink(tname) < 0)
perror(tname);
}
return(0);
}
void
resettimes(mbox)
char *mbox;
{
if(geteuid() == 0 || getuid() == mbox_id ) {
#ifdef UTIME
if(utime(mbox,&tv) < 0) {
perror("utime");
}
#else
tv[0].tv_usec = (time_t)0;
tv[1].tv_usec = (time_t)0;
if(utimes(mbox,tv) < 0) {
perror("utimes");
}
#endif
}
}
do_msgs(mfp,ofp)
FILE *mfp;
FILE *ofp;
{
int writeout = 1;
int msgnum = 0;
char buf[BUFSIZ];
struct msg msg;
int num_expired = 0;
while(fgets(buf,BUFSIZ,mfp)) {
if(!strncmp("From ",buf,5)) {
msgnum++;
get_msg_info(buf,&msg);
if(msg.time < 0) {
(void)fprintf(stderr,"Bad header\n");
continue;
}
if(debug >= 3 || verbose >= 3)
(void)printf("\t\tmessage from %s %d\n",
msg.from, msg.time);
if(currtime - msg.time > sec_aged) {
writeout = 0;
num_expired++;
if(fromwho && strcmp(fromwho,msg.from))
writeout = 1;
if((debug >= 1 || verbose >= 1) && !writeout)
(void)printf(
"\tmessage #%d, expired (%d days)\n",
msgnum,(currtime-msg.time)/86400);
if(debug >= 2 || verbose >= 2)
(void)printf(
"\t\tcurrtime = %d, msg.time = %d\n",
currtime,msg.time);
if(debug >= 2 || verbose >= 2)
(void)printf("\t\tfrom = %s\n", msg.from);
} else {
writeout = 1;
}
}
if(writeout)
(void)fprintf(ofp,"%s",buf);
}
(void)fclose(mfp);
(void)fclose(ofp);
return(num_expired);
}
get_msg_info(fromp,s)
char *fromp;
struct msg *s;
{
static char name[1024];
char *p, *wp;
#ifdef HAVE_STRPTIME
struct tm tm;
#endif
for(p=fromp;*p!=' ';p++)
;
for(;*p==' ';p++)
;
for(wp=name;*p!=' ';p++,wp++)
*wp = *p;
*wp = 0;
s->from = name;
for(;*p==' ';p++)
;
#ifdef HAVE_STRPTIME
strptime(p,"%a %h %e %H:%M:%S %Y",&tm);
s->time = timelocal(&tm);
#else
s->time = mystrptime(p);
#endif /* HAVE_STRPTIME */
if(debug >= 3) {
(void)printf("\t\ttimelocal = %ld\n",s->time);
}
}
#define equal(S1,S2) (!strcmp(S1,S2))
#define MINUTE (60L)
#define HOUR (MINUTE * 60L)
#define DAY (HOUR * 24L)
#define RYEAR (DAY * 365L)
#define LYEAR (DAY * 366L)
struct mons {
int days;
char *month;
} months[] = {
31, "Jan",
28, "Feb",
31, "Mar",
30, "Apr",
31, "May",
30, "Jun",
31, "Jul",
31, "Aug",
30, "Sep",
31, "Oct",
30, "Nov",
31, "Dec",
0, 0
};
time_t
mystrptime(s)
char *s;
{
struct mons *mp;
char mymon[4];
char myyear[5];
char *p;
int dom, tot=0, year, mfound=0;
int hr, min;
int dindex = 70;
long sectot=0;
if(sscanf(s,"%*s %s %d %d:%d",
mymon,&dom,&hr,&min) < 3) {
(void)fprintf(stderr,"Bad date format\n");
return(-1);
}
p = s + strlen(s);
for(;!isdigit(*p);p--)
;
p-=3;
(void)strncpy(myyear,p,4);
myyear[4] = 0;
year = atoi(myyear);
/* handle leap years */
if((year % 4) == 0)
months[1].days++;
/* add to tot until we find the month we're looking for */
for(mp=months;mp->days;mp++) {
if(equal(mp->month,mymon)) {
mfound++;
break;
}
tot += mp->days;
}
if(!mfound) {
(void)fprintf(stderr,"Bad date format\n");
return(-1);
}
sectot = ((tot+dom-1)*DAY) + (hr*HOUR) + (min*MINUTE);
for(dindex=70;dindex<(year-1900);dindex++)
if(dindex % 4 == 0)
sectot += LYEAR;
else
sectot += RYEAR;
return(sectot);
}
locked(file)
char *file;
{
char lfile[BUFSIZ];
struct stat sbuf;
int count = 0;
(void)sprintf(lfile,"%s.lock",file);
for(count = 0; count < 3; count++) {
if(stat(lfile,&sbuf) < 0)
break;
else
sleep(3);
}
return(count==3);
}
lock(file)
char *file;
{
char fname[BUFSIZ];
int fd;
(void)sprintf(fname,"%s.lock",file);
if((fd = open(fname,O_CREAT,0700)) < 0) {
perror(fname);
return(0);
}
(void)close(fd);
return(1);
}
unlock(file)
char *file;
{
char fname[BUFSIZ];
(void)sprintf(fname,"%s.lock",file);
if(unlink(fname) < 0) {
perror(fname);
return(0);
}
return(1);
}
void
usage()
{
(void)fprintf(stderr,
"Usage: %s [-a age] [-d] [-o] [-u username] [-v] [-z] mailbox..\n",
myname);
}