home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
rtsi.com
/
2014.01.www.rtsi.com.tar
/
www.rtsi.com
/
OS9
/
OSK
/
TELECOM
/
UUCP_Blars.lzh
/
uumailclean.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-03-10
|
17KB
|
759 lines
/*
* uumailclean - this program searches through the uucp spool directory
* looking for mail files. Files which have been around for longer than
* "failtime" hours will be returned to the sender. If a file has been
* around longer than "warntime" hours, then a warning message is sent (once)
* to the sender.
*
* Originally Written by Jim Crammond <jim@cs.hw.ac.uk> 3/86
* Hacked to death by Rick Adams <rick@seismo.css.gov> 5/87
* Released to comp.sources.unix 6/88
* Ported to OS-9/68000 by Wolfgang Ocker <weo@recco> 9/88
* Released to sub.os9 9/88
*
* This program contains no ATT code and may be freely used on sites without a
* source license.
*/
/*
* OS-9/68000 BETA RELEASE!!!
*
* Pls send comments, suggestions or bug reports (including diffs) to
* weo@recco.chi.sub.org
*/
#include <stdio.h>
#include <types.h>
#include <sys/stat.h>
#include <ctype.h>
#include <direct.h>
#include <dir.h>
#include <modes.h>
#define TRUE 1
#define FALSE 0
extern int errno;
#define STRCMP(a,b) ((*(a) != *(b)) ? (*(a)-*(b)) : strcmp((a)+1, (b)+1))
#define STRNCMP(a,b,n) ((*(a) != *(b)) ? (*(a)-*(b)) : strncmp(a, b, n))
long Now;
/* Various UUCP specific defines */
#define CMDPRE 'C'
#define MAXBASENAME 15
#define SYSNSIZE (6) /* system name length */
#define FILENAMELEN (MAXBASENAME + 1 + 2) /* uucp filename length */
#define DEBUG(level, format, param) if (Debug >= level) fprintf(stderr, format, param); else
#define SENDMAIL "smail"
#define BLKSIZE ((BUFSIZ/(FILENAMELEN)) - 1)
# define Csubfile(x) x
# define Dsubfile(x) x
# define Xsubfile(x) x
#include <strings.h>
void checkfiles();
void fail();
void warn();
void print_message();
void usage();
extern char *info_str();
struct flist {
char fname[BLKSIZE][FILENAMELEN];
int nused;
struct flist *next;
};
struct flist warnlist;
FILE *warnfp;
char *Spool = "/h0/SPOOL/UUCP";
char _Spool[120];
char myuucpname[FILENAMELEN];
#define WARNFILE ".LOG/warnlist.mail"
int warntime = 24 * 3; /* default hours before sending a warning */
int failtime = 24 * 14; /* default hours before returning the mail */
int Debug = 0;
int nflag = 0;
void usage();
/*
* m a i n
*/
main(argc, argv)
char **argv;
{
int c;
int i, j;
char *cp;
if ((cp = info_str("UUCP.SPOOL", _Spool, sizeof(_Spool))) != NULL)
Spool = cp;
for (i = 1; i < argc; i++)
if (argv[i][0] == '-')
for (j = 1; j < strlen(argv[i]); j++)
switch (tolower(argv[i][j])) {
case '?':
usage();
exit(1);
case 's':
Spool = argv[i] + j + (argv[i][j+1] == '=' ? 2 : 1);
j = strlen(argv[i]);
break;
case 'f':
failtime = atoi(argv[i] + j +
(argv[i][j+1] == '=' ? 2 : 1));
j = strlen(argv[i]);
break;
case 'w':
warntime = atoi(argv[i] + j +
(argv[i][j+1] == '=' ? 2 : 1));
j = strlen(argv[i]);
break;
case 'x':
Debug = atoi(argv[i] + j +
(argv[i][j+1] == '=' ? 2 : 1));
j = strlen(argv[i]);
break;
case 'h':
strncpy(myuucpname,
argv[i] + j + (argv[i][j+1] == '=' ? 2 : 1),
FILENAMELEN);
j = strlen(argv[i]);
break;
case 'n':
nflag = TRUE;
break;
}
if (myuucpname[0] == '\0') {
register char *p;
if (gethostname(myuucpname, FILENAMELEN) == NULL)
exit(_errmsg(1, "Can't determine hostname"));
p = index(myuucpname, '.');
if (p)
*p = '\0';
}
setuid(getmuid());
if (chdir(Spool) < 0)
exit(_errmsg(errno, "Can't change to spooldirectory"));
init_warnedlist(WARNFILE);
checkfiles(".");
exit(0);
}
/*
* c h e c k f i l e s
*
* scan a directory looking for "old" control files. For each
* one found, call fail or warn as appropriate.
*/
void checkfiles(dir)
char *dir;
{
register DIR *dirp;
register struct direct *dentp;
struct stat stbuf;
int hours;
int clen;
(void) time(&Now);
DEBUG(5, "checkfiles(%s)\n", dir);
if ((dirp = opendir(dir)) == NULL) {
_errmsg(errno, "directory unreadable");
return;
}
while ((dentp = readdir(dirp)) != NULL) {
if (dentp->d_name[0] != CMDPRE)
continue;
clen = strlen(dentp->d_name) - 4;
if ((clen > 0) && (STRCMP("POLL", &dentp->d_name[clen]) == 0))
continue;
DEBUG(9, "stat %s\n", dentp->d_name);
if (stat(Csubfile(dentp->d_name), &stbuf) == -1) {
if (Debug >= 4)
_errmsg(errno, "stat failed: %s\n", Csubfile(dentp->d_name));
continue;
}
if ((stbuf.st_mode & S_IFMT) == S_IFDIR)
continue;
hours = (int) (Now - stbuf.st_mtime) / 3600;
DEBUG(9, "%d hours old\n", hours);
if (hours >= failtime)
fail(dentp->d_name, hours);
else
if (hours >= warntime)
warn(dentp->d_name, hours);
}
}
/*
* f a i l
*
* send a failure message to the sender and delete the mail.
*/
void fail(cmdfile, hours)
char *cmdfile;
int hours;
{
char dfile[FILENAMELEN], xfile[FILENAMELEN];
char host[FILENAMELEN];
register char *from, **to;
char *sender(), **recipients();
FILE *out, *popen();
char cmd[BUFSIZ];
DEBUG(4, "fail called on %s\n", cmdfile);
if (getfnames(cmdfile, dfile, xfile) < 0)
return;
if (xfile[0] == '\0' || (to = recipients(xfile)) == NULL)
return;
if (dfile[0] == '\0' || (from = sender(dfile)) == NULL)
return;
strcpy(host, &cmdfile[2]);
host[strlen(cmdfile) - SYSNSIZE] = '\0';
/* sprintf(cmd, "%s -t", SENDMAIL);*/
sprintf(cmd, "%s -R %s", SENDMAIL, from);
DEBUG(1, "Failed: From: %s\n\tTo:", from);
if (nflag) {
out = stdout;
fflush(stderr);
printf("\nFile: %s\n", cmdfile);
}
else
out = popen(cmd, "w");
fprintf(out, "From: MAILER-DAEMON\nSubject: Failed Mail\nTo: %s\n\n",
from);
fprintf(out, "After %d days (%d hours), your message to the following people:\n\n",
hours / 24, hours);
/* put out recipents */
while (*to) {
DEBUG(1, " %s!", host);
DEBUG(1, "%s", *to);
fprintf(out, "\t%s (host=%s)\n", *to, host);
to++;
}
DEBUG(1, "\n", 0);
fprintf(out, "\ncould not be delivered.\n\n");
fprintf(out, " ----- Unsent message follows ----- \n");
/* print all of the message */
print_message(dfile, out, 0);
if (nflag)
return;
pclose(out);
(void) unlink(Csubfile(cmdfile));
(void) unlink(Dsubfile(dfile));
(void) unlink(Dsubfile(xfile));
}
/*
* w a r n
*
* send a warning message to the sender and add the control file to
* the list of files for which warnings have been sent.
*/
void warn(cmdfile, hours)
char *cmdfile;
int hours;
{
char dfile[FILENAMELEN], xfile[FILENAMELEN];
char host[FILENAMELEN];
char *from, **to;
char *sender(), **recipients();
FILE *out, *popen();
char cmd[BUFSIZ];
if (in_warnedlist(cmdfile))
return;
DEBUG(4, "warn called on %s\n", cmdfile);
if (getfnames(cmdfile, dfile, xfile) < 0) {
DEBUG(5, "getfnames(%s) failed\n", cmdfile);
return;
}
if ((to = recipients(xfile)) == NULL || (from = sender(dfile)) == NULL)
return;
strcpy(host, &cmdfile[2]);
host[strlen(cmdfile) - SYSNSIZE] = '\0';
sprintf(cmd, "%s -R %s", SENDMAIL, from);
DEBUG(1, "Warning: From: %s\n\tTo:", from);
if (nflag) {
out = stdout;
fflush(stderr);
printf("\nFile: %s\n", cmdfile);
}
else
out = popen(cmd, "w");
fprintf(out, "From: MAILER-DAEMON\nSubject: Waiting Mail\nTo: %s\n\n",
from);
fprintf(out, "After %d days (%d hours), your message to the following people:\n\n",
hours / 24, hours);
/* put out recipents */
while (*to) {
DEBUG(1, " %s!", host);
DEBUG(1, "%s", *to);
fprintf(out, "\t%s (host=%s)\n", *to, host);
to++;
}
DEBUG(1, "\n", 0);
fprintf(out, "\nhas not yet been delivered. Attempts to deliver the message will\n");
fprintf(out, "continue for %d more days. No further action is required by you.\n\n", (failtime - hours) / 24);
fprintf(out, " ----- Queued message begins ----- \n");
/* print a summary of the message */
print_message(dfile, out, 1);
if (nflag)
return;
pclose(out);
fprintf(warnfp, "%s\n", cmdfile);
}
/*
* g e t f n a m e s
*
* read the control file to find the data and execute files
* which contain the message and list of recipients. dfile is set to the
* datafile, xfile to the execute file.
*/
getfnames(cmdfile, dfile, xfile)
char *cmdfile;
char *dfile;
char *xfile;
{
register FILE *fp;
register char *s, *d;
register int n;
char buf[BUFSIZ];
DEBUG(5, "getfnames(%s) called\n", cmdfile);
if ((fp = fopen(Csubfile(cmdfile), "r")) == NULL) {
_errmsg(errno, "Can't open %s\n", Csubfile(cmdfile));
return(-1);
}
if (fgets(buf, BUFSIZ, fp) == NULL) {
DEBUG(7, "fgets dfile %s failed\n", cmdfile);
fclose(fp);
return(-1);
}
s = buf;
d = dfile;
while (*s != '\0' && *s++ != ' ') ; /* skip first argument */
n = FILENAMELEN - 1;
do {
*d++ = *s;
} while (*s != '\0' && *s != ' ' && *s++ != '\n' && --n);
d[-1] = '\0';
DEBUG(5, "dfile set to %s\n", dfile);
if (fgets(buf, BUFSIZ, fp) == NULL) {
DEBUG(7, "fgets xfile %s failed\n", cmdfile);
fclose(fp);
return(-1);
}
s = buf;
d = xfile;
while (*s != '\0' && *s++ != ' ') ; /* skip first argument */
n = FILENAMELEN - 1;
do {
*d++ = *s;
} while (*s != '\0' && *s != ' ' && *s++ != '\n' && --n);
d[-1] = '\0';
DEBUG(5, "xfile set to %s\n", xfile);
fclose(fp);
return(0);
}
/*
* r e c i p i e n t s
*
* returns a list of recipients that the mail was intended for,
* or NULL if the execute file is not a mail file.
*/
char **recipients(xfile)
char *xfile;
{
static char rbuf[BUFSIZ];
static char *tobuf[BUFSIZ*2]; /* see uuxqt */
register FILE *fp;
register char *p, **t;
DEBUG(7, "recipients(%s)\n", xfile);
if ((fp = fopen(Dsubfile(xfile), "r")) == NULL) {
_errmsg(errno, "can't open %s\n", Dsubfile(xfile));
return(NULL);
}
while (fgets(rbuf, BUFSIZ, fp) != NULL) {
if (rbuf[0] == 'C' && STRNCMP(rbuf, "C rmail ", 8) == 0) {
/* turn into an array of addresses */
for (p = &rbuf[8], t = tobuf; *p;) {
while (*p == ' ' || *p == '\n')
*p++ = '\0';
*t = p;
while (*p && *p != ' ' && *p != '\n')
p++;
if (*t != p)
t++;
}
*t = NULL;
fclose(fp);
return(tobuf);
}
}
fclose(fp);
return(NULL);
}
char *badnames[] = {
"daemon",
"/dev/null",
"mailer",
"postmaster",
"netlib",
"netlibd",
"listserv",
"uucp",
"news",
"usenet",
0
};
char *badsuffix[] = {
"archive",
"daemon",
"sender",
"mailer",
"relay",
"request",
"reply",
"server",
0
};
/*
* s e n d e r
*
* returns the sender address from the uucp from line, or NULL if
* not found.
*/
char *sender(dfile)
char *dfile;
{
static char buf[BUFSIZ];
char username[BUFSIZ];
register char *senderof, *cp, **bname;
register FILE *fp;
DEBUG(7, "sender(%s)\n", dfile);
if ((fp = fopen(Dsubfile(dfile), "r")) == NULL) {
_errmsg(errno, "Can't open %s\n", Dsubfile(dfile));
return(NULL);
}
if (fgets(buf, BUFSIZ, fp) == NULL)
return(NULL);
fclose(fp);
senderof = index(buf, ' ');
if (senderof++ == '\0')
return(NULL);
cp = index(senderof, ' ');
if(cp != NULL)
*cp = '\0';
/* pick of the username */
cp = rindex(senderof, '!'); /* try uucp style */
if (cp != NULL)
strcpy(username, cp+1);
else { /* try arpa style */
cp = index(senderof, '@');
if (cp == NULL)
return(senderof);
strcpy(username, senderof);
cp = index(username, '@');
*cp = '\0';
}
/* lower case username so get case independent strcmp */
cp = username;
do {
if (isupper(*cp))
*cp = tolower(*cp);
} while (*cp++ != '\0');
DEBUG(7,"checking username \"%s\"\n", username);
/* some lists begin with info- */
if (STRNCMP(username, "info-", 5) == 0) {
DEBUG(7, "Not warning %s\n", senderof);
return(NULL);
}
cp = rindex(username, '-');
if (cp++ == NULL) {
bname = badnames;
cp = username;
}
else
bname = badsuffix;
while (*bname != NULL) {
DEBUG(9, "\tcomparing against %s\n", *bname);
if (STRCMP(*bname, cp) == 0) {
DEBUG(7, "Not warning %s\n", senderof);
return(NULL);
}
bname++;
}
return(senderof);
}
/*
* p r i n t _ m e s s a g e
*
* print the message in "dfile" on the stream "outp". If
* the edited flag is set, then only print some interesting headers and the
* first few lines of the body.
*/
void print_message(dfile, outp, edited)
char *dfile;
register FILE *outp;
int edited;
{
register FILE *dfp;
char buf[BUFSIZ];
int iflg, linecount;
if ((dfp = fopen(Dsubfile(dfile), "r")) == NULL)
return;
/* skip unix from line */
fgets(buf, BUFSIZ, dfp);
/* print header */
iflg = 0;
while (fgets(buf, BUFSIZ, dfp) != NULL && buf[0] != '\n') {
if (edited) {
if (buf[0] == '\t' || buf[0] == ' ') {
if (iflg)
fputs(buf, outp);
continue;
}
if (!interested(buf)) {
iflg = 0;
continue;
}
iflg = 1;
}
fputs(buf, outp);
}
putc('\n', outp);
/* print body */
linecount = 0;
while (fgets(buf, BUFSIZ, dfp) != NULL) {
if (edited && ++linecount > 5) {
fprintf(outp, ".....\n");
break;
}
fputs(buf, outp);
}
fclose(dfp);
}
static char *headers[] = {
"From:",
"Date:",
"To:",
"Cc:",
"Subject:",
0
};
/*
* i n t e r e s t e d
*
* determine whether "hdr" is considered interesting and thus
* should be printed in edited mode.
*/
interested(hdr)
char *hdr;
{
register char **hp = headers;
while (*hp) {
if (STRNCMP(hdr, *hp, strlen(*hp)) == 0)
return(1);
hp++;
}
return(0);
}
/*
* i n i t _ w a r n e d l i s t
*
* Initialise list of files for which warning messages have already been
* sent. This involves reading the warnfile into a table, removing files
* which no longer exist (i.e. been sent or deleted), and writing this out
* again.
*/
init_warnedlist(warnfile)
char *warnfile;
{
register struct flist *wp;
register char *p;
register int i;
char warned[FILENAMELEN];
wp = &warnlist;
wp->next = NULL;
wp->nused = 0;
if ((warnfp = fopen(warnfile, "r")) != NULL) {
while (fgets(warned, FILENAMELEN, warnfp) != NULL) {
if(warned[0] == '\n')
continue;
if ((p = index(warned, '\n')) != NULL)
*p = '\0';
if (access(Csubfile(warned), S_IREAD) == 0) {
if (wp->nused >= BLKSIZE) {
wp->next = (struct flist *) malloc(sizeof(warnlist));
wp = wp->next;
wp->next = (struct flist *) NULL;
wp->nused = 0;
}
strcpy(wp->fname[wp->nused], warned);
wp->nused++;
}
}
fclose(warnfp);
}
/*
* Rewrite warnedlist removing files that no longer exist. Could be
* really paranoid here and create a temporary file first, rather
* than overwrite; in case of crashed
*/
if ((warnfp = fopen(warnfile, "w")) != NULL) {
wp = &warnlist;
while (wp) {
for (i = 0; i < wp->nused; i++)
fprintf(warnfp, "%s\n", wp->fname[i]);
wp = wp->next;
}
fflush(warnfp);
}
}
/*
* i n _ w a r n e d l i s t
*
* Determine whether the given filename is in the warn list. Returns 1 if
* found, 0 otherwise.
*
* This should really use some clever hashing scheme, but the cpu
* time spent traversing this list is only 1% of total.
*/
in_warnedlist(file)
register char *file;
{
register struct flist *wp = &warnlist;
register int i;
while (wp) {
for (i = 0; i < wp->nused; i++) {
if (STRCMP(file, wp->fname[i]) == 0)
return(1);
}
wp = wp->next;
}
return(0);
}
char DLocalX[FILENAMELEN], DLocal[FILENAMELEN];
static char *dprefix[] = {
DLocalX, /* Outbound 'xqt' request files */
DLocal, /* Outbound data files */
"D.", /* Other "D." files (remember the "."!) */
"C.", /* "C." subdirectory */
"X.", /* "X." subdirectory */
"TM.", /* Temporaries for inbound files */
0
};
/*
* u s a g e
*/
void usage()
{
fputs("Syntax: uumailclean [<opts>]\n", stderr);
fputs("Function: warn/delete very old mails\n", stderr);
fputs("Options:\n", stderr);
fputs(" -s=<path> spool directory\n", stderr);
fputs(" -f=<time> fail time [hours]\n", stderr);
fputs(" -w=<time> warn time [hours]\n", stderr);
fputs(" -x=<level> debug level\n", stderr);
fputs(" -h=<hostname> host name\n", stderr);
fputs(" -n only display, no actions\n", stderr);
}