#include "uucp.h"
#ifdef V7
#define O_RDONLY 0
#endif
#define USAGE "[-oDAYS] [-mSTRING] [-Cdays] [-Ddays] [-Wdays] [-Xdays] [-xLEVEL] [-sSYSTEM]"
extern int _age();
extern void procdtype(), oprocess(), xprocess(), cprocess();
extern void dXprocess(), dNprocess(), dMprocess(), dDprocess(), wprocess();
extern int toWho(), sendMail(), execRnews();
extern void logit();
void cleanup(){}
void systat(){}
void logent(){}
static void cleanworkspace(void);
#define D_MAIL 1
#define D_NEWS 2
#define D_XFILE 3
#define D_DATA 4
#define FULLNAME(full,dir,file) (void) sprintf(full, "%s/%s", dir, file);
int _Ddays = 7;
int _Cdays = 7;
int _Xdays = 2;
int _Odays = 2;
int _Wdays = 1;
char _ShortLocal[6];
char *_Undeliverable[] = {
"Subject: Undeliverable Mail\n",
"This mail message is undeliverable.\n",
"(Probably to or from system '%s')\n",
"It was sent to you or by you.\n",
"Sorry for the inconvenience.\n",
"",
};
#define CANT1 2
#define CANT2 3
char *_CantContact[] = {
"Subject: Job Killed By uucp\n",
"We can't contact machine '%s'.\n",
" ",
" ",
"",
};
#define WARN1 2
#define WARN2 5
#define WARN3 6
char *_Warning[] = {
"Subject: Warning From uucp\n",
"We have been unable to contact machine '%s' since you queued your job.\n",
" ",
"Attempts will continue for a few more days.\n",
"",
" ",
" ",
"",
};
int
main(argc, argv, envp)
int argc;
char *argv[];
char **envp;
{
DIR *jcdir, *machdir, *spooldir;
char fullname[MAXFULLNAME], statfile[MAXFULLNAME], machname[MAXFULLNAME];
char file1[NAMESIZE+1], file2[NAMESIZE+1], file3[NAMESIZE+1];
char soptName[MAXFULLNAME], lockname[MAXFULLNAME];
int i, value;
soptName[0] = NULLCHAR;
(void) strcpy(Logfile, CLEANUPLOGFILE);
uucpname(Myname);
(void) strncpy(_ShortLocal, Myname, 5);
_ShortLocal[5] = NULLCHAR;
(void) strcpy(Progname, "uucleanup");
while ((i = getopt(argc, argv, "C:D:W:X:m:o:s:x:")) != EOF) {
switch(i){
case 's':
(void) strcpy(soptName, optarg);
break;
case 'x':
Debug = atoi(optarg);
if (Debug <= 0 || Debug >= 10) {
fprintf(stderr,
"WARNING: %s: invalid debug level %s ignored, using level 1\n",
Progname, optarg);
Debug = 1;
}
#ifdef SMALL
fprintf(stderr,
"WARNING: uucleanup built with SMALL flag defined -- no debug info available\n");
#endif
break;
case 'm':
_Warning[WARN3] = optarg;
break;
default:
(void) fprintf(stderr, "\tusage: %s %s\n",
Progname, USAGE);
exit(1);
case 'C':
case 'D':
case 'W':
case 'X':
case 'o':
value = atoi(optarg);
if (value < 1) {
fprintf(stderr," Options: CDWXo require value > 0\n");
exit(1);
}
switch(i) {
case 'C':
_Cdays = value;
break;
case 'D':
_Ddays = value;
break;
case 'W':
_Wdays = value;
break;
case 'X':
_Xdays = value;
break;
case 'o':
_Odays = value;
break;
}
break;
}
}
if (argc != optind) {
(void) fprintf(stderr, "\tusage: %s %s\n", Progname, USAGE);
exit(1);
}
DEBUG(5, "Progname (%s): STARTED\n", Progname);
DEBUG(5, "Myname (%s), ", Myname);
DEBUG(5, "_ShortLocal (%s)\n", _ShortLocal);
DEBUG(5, "Days C.(%d), ", _Cdays);
DEBUG(5, "D.(%d), ", _Ddays);
DEBUG(5, "W.(%d), ", _Wdays);
DEBUG(5, "X.(%d), ", _Xdays);
DEBUG(5, "other (%d)\n", _Odays);
cleanworkspace();
if (chdir(SPOOL) != 0) {
(void) fprintf(stderr, "CAN'T CHDIR (%s): errno (%d)\n",
SPOOL, errno);
exit(1);
}
if ((spooldir = opendir(SPOOL)) == NULL) {
(void) fprintf(stderr, "CAN'T OPEN (%s): errno (%d)\n",
SPOOL, errno);
exit(1);
}
while (gdirf(spooldir, file1, SPOOL) == TRUE) {
if (*soptName && !EQUALS(soptName, file1))
continue;
(void) strcpy(Rmtname, file1);
(void) sprintf(machname, "%s/%s", SPOOL, file1);
if ((machdir = opendir(machname)) == NULL) {
(void) fprintf(stderr, "CAN'T OPEN (%s): errno (%d)\n",
machname, errno);
if (*soptName)
break;
else
continue;
}
DEBUG(7, "Directory: (%s) is open\n", file1);
while (gnamef(machdir, file2) == TRUE) {
(void) sprintf(statfile, "%s/%s", machname, file2);
if (DIRECTORY(statfile)) {
(void) sprintf(lockname, "%s.%.*s.%s",
LOCKPRE, SYSNSIZE, file1, file2);
if (cklock(lockname))
continue;
if ((jcdir = opendir(statfile)) == NULL) {
(void) fprintf(stderr,
"CAN'T OPEN (%s): errno (%d)\n",
statfile, errno);
continue;
}
DEBUG(7, "Directory: (%s) is open\n", file2);
while (gnamef(jcdir, file3)) {
DEBUG(9, "file: %s\n", file3);
FULLNAME(fullname, statfile, file3);
DEBUG(9,"Fullname is (%s)\n", fullname);
if (EQUALSN(file3, "C.", 2)) {
if (_age(fullname) >= _Cdays)
cprocess(fullname);
else if(_age(fullname) >= _Wdays)
wprocess(statfile, file3);
}
else if (EQUALSN(file3, "D.", 2)) {
if (_age(fullname) >= _Ddays)
procdtype(statfile, file3);
}
else if (_age(fullname) >= _Odays)
oprocess(fullname);
}
closedir(jcdir);
continue;
}
DEBUG(9, "file: %s\n", file2);
DEBUG(9, "Fullname is (%s)\n", statfile);
if (EQUALSN(file2, "X.", 2)) {
if (_age(statfile) >= _Xdays)
xprocess(statfile);
}
else if (EQUALSN(file2, "D.", 2)) {
if (_age(statfile) >= _Ddays)
procdtype(machname, file2);
}
else if (_age(statfile) >= _Odays)
oprocess(statfile);
}
closedir(machdir);
}
closedir(spooldir);
return (0);
}
void
procdtype(dir, file)
char *dir, *file;
{
char fullname[MAXFULLNAME];
FULLNAME(fullname, dir, file);
switch(dType(fullname)) {
case D_DATA:
dDprocess(fullname);
break;
case D_MAIL:
dMprocess(dir, file);
break;
case D_NEWS:
dNprocess(dir, file);
break;
case D_XFILE:
dXprocess(fullname);
break;
default:
break;
}
return;
}
void
xprocess(fullname)
char *fullname;
{
char text[BUFSIZ];
DEBUG(5, "xprocess(%s), ", fullname);
DEBUG(5, "unlink(%s)\n", fullname);
(void) sprintf(text, "xprocess: unlink(%s)", fullname);
errno = 0;
(void) unlink(fullname);
logit(text, errno);
return;
}
#define CMFMT "\n\t%s!%s -> %s!%s (Date %2.2d/%2.2d)\n\nCan't be executed."
#define XFMT "\n\t%s!%s (Date %2.2d/%2.2d)\n"
#define XMFMT "\n\tmail %s!%s (Date %2.2d/%2.2d)\n"
#define WFMT "\n\t%s!%s -> %s!%s (Date %2.2d/%2.2d)\n"
void
cprocess(fullname)
char *fullname;
{
struct stat s;
struct tm *tp;
char buf[BUFSIZ], user[9];
char file1[BUFSIZ], file2[BUFSIZ], file3[BUFSIZ], type[2], opt[256];
char text[BUFSIZ], text1[BUFSIZ], text2[BUFSIZ];
FILE *fp;
int ret;
DEBUG(5, "cprocess(%s)\n", fullname);
fp = fopen(fullname, "r");
if (fp == NULL) {
DEBUG(5, "Can't open file (%s), ", fullname);
DEBUG(5, "errno=%d -- skip it!\n", errno);
return;
}
if (fstat(fileno(fp), &s) != 0) {
(void) fclose(fp);
return;
}
tp = localtime(&s.st_mtime);
if (s.st_size == 0) {
DEBUG(5, "dummy C. -- unlink(%s)\n", fullname);
(void) sprintf(text, "dDprocess: dummy C. unlinked(%s)",
fullname);
errno = 0;
(void) unlink(fullname);
logit(text, errno);
(void) fclose(fp);
return;
}
while (fgets(buf, BUFSIZ, fp) != NULL) {
buf[strlen(buf)-1] = NULLCHAR;
if (sscanf(buf,"%s%s%s%s%s%s", type, file1, file2,
user, opt, file3) <5) {
(void) sprintf(text, "cprocess: Bad C. %s, unlink(%s)",
buf, fullname);
break;
}
*text = NULLCHAR;
ret = 0;
(void) sprintf(text2, "Job (%s) killed!\n",
BASENAME(fullname, '/')+2);
_CantContact[CANT2] = text2;
if (*type == 'S') {
if (EQUALSN(file1, "D.", 2))
continue;
(void) sprintf(text1, CMFMT, Myname, file1, Rmtname, file2,
tp->tm_mon + 1, tp->tm_mday);
_CantContact[CANT1] = text1;
ret = sendMail((char *) NULL, user, "", _CantContact);
}
else if (*type == 'R') {
(void) sprintf(text1, CMFMT, Rmtname, file1, Myname, file2,
tp->tm_mon + 1, tp->tm_mday);
_CantContact[CANT1] = text1;
ret = sendMail((char *) NULL, user, "", _CantContact);
}
}
if (!*text) {
(void) sprintf(text,
"cprocess: C. %s, mail returned (%d), unlink(%s)",
buf, ret, fullname);
}
DEBUG(3, "text (%s)\n", text);
errno = 0;
(void) unlink(fullname);
logit(text, errno);
(void) fclose(fp);
return;
}
void
wprocess(dir, file)
char *dir, *file;
{
struct stat s;
struct tm *tp;
char fullname[BUFSIZ], xfile[BUFSIZ], xF_file[BUFSIZ];
char buf[BUFSIZ], user[BUFSIZ];
char file1[BUFSIZ], file2[BUFSIZ], file3[BUFSIZ], type[2], opt[256];
char text[BUFSIZ], text1[BUFSIZ], text2[BUFSIZ];
char *realuser, uline_m[NAMESIZE], uline_u[BUFSIZ], retaddr[BUFSIZ];
FILE *fp, *xfp;
int ret;
FULLNAME(fullname, dir, file);
DEBUG(5, "wprocess(%s)\n", fullname);
fp = fopen(fullname, "r");
if (fp == NULL) {
DEBUG(4, "Can't open file (%s), ", fullname);
DEBUG(4, "errno=%d -- skip it!\n", errno);
return;
}
if (fstat(fileno(fp), &s) != 0) {
(void) fclose(fp);
return;
}
tp = localtime(&s.st_mtime);
if (s.st_size == 0) {
DEBUG(5, "dummy C. -- skip(%s)\n", fullname);
(void) fclose(fp);
return;
}
while (fgets(buf, BUFSIZ, fp) != NULL) {
buf[strlen(buf)-1] = NULLCHAR;
if (sscanf(buf,"%s%s%s%s%s%s", type, file1, file2,
user, opt, file3) <5) {
DEBUG(5, "short line (%s): ", buf);
DEBUG(5, "bad D. -- skip(%s)\n", fullname);
(void) fclose(fp);
return;
}
(void) sprintf(text2,
"\nuucp job id is %s.\n", BASENAME(fullname, '/')+2);
_Warning[WARN2] = text2;
if (*type == 'S') {
if (EQUALSN(file2, "X.", 2)) {
FULLNAME(xfile, dir, file1);
if ((xfp = fopen(xfile, "r")) == NULL) {
DEBUG(3, "Can't read %s\n", xfile);
break;
}
*retaddr = *uline_u = *uline_m = *text = NULLCHAR;
while (fgets(buf, BUFSIZ, xfp) != NULL) {
buf[strlen(buf)-1] = NULLCHAR;
switch(*buf) {
case 'F':
FULLNAME(xF_file, dir, &buf[2]);
break;
case 'R':
sscanf(buf+2, "%s", retaddr);
DEBUG(7, "retaddr (%s)\n", retaddr);
break;
case 'U':
sscanf(buf+2, "%s%s",
uline_u, uline_m);
break;
}
if (buf[0] != 'C')
continue;
realuser = uline_u;
if (*retaddr != NULLCHAR)
realuser = retaddr;
if (*realuser == NULLCHAR)
strcpy(realuser, user);
if (!EQUALS(uline_m, Myname))
sprintf(user, "%s!%s",
uline_m, realuser);
else
strcpy(user, realuser);
if (EQUALSN(buf+2, "rmail ", 6))
(void) sprintf(text1, XMFMT,
Rmtname, buf+8,
tp->tm_mon+1, tp->tm_mday);
else
(void) sprintf(text1, XFMT,
Rmtname, buf+2,
tp->tm_mon+1, tp->tm_mday);
_Warning[WARN1] = text1;
if (EQUALSN(&buf[2], "rmail", 5))
ret = sendMail((char *) NULL,
user, xF_file, _Warning);
else
ret = sendMail((char *) NULL,
user, "", _Warning);
break;
}
(void) fclose(xfp);
break;
}
if (EQUALSN(file1, "D.", 2))
continue;
(void) sprintf(text1, WFMT, Myname, file1, Rmtname, file2,
tp->tm_mon + 1, tp->tm_mday);
_Warning[WARN1] = text1;
ret = sendMail((char *) NULL, user, "", _Warning);
}
else if (*type == 'R') {
if (EQUALSN(file1, "D.", 2) && EQUALSN(file2, "D.", 2))
continue;
(void) sprintf(text1, WFMT, Rmtname, file1, Myname, file2,
tp->tm_mon + 1, tp->tm_mday);
_Warning[WARN1] = text1;
ret = sendMail((char *) NULL, user, "", _Warning);
}
}
(void) sprintf(text,
"wprocess: %s: %s, warning message sent to %s, returned (%d)",
fullname, buf, user, ret);
DEBUG(3, "text (%s)\n", text);
logit(text, errno);
(void) fclose(fp);
return;
}
void
oprocess(fullname)
char *fullname;
{
char *p, text[BUFSIZ];
p = BASENAME(fullname, '/');
if (EQUALSN(p, "P.", 2) == 0)
if (_age(fullname) <= _Cdays)
return;
DEBUG(5, "oprocess(%s), ", fullname);
DEBUG(5, "unlink(%s)\n", fullname);
(void) sprintf(text, "oprocess: unlink(%s)", fullname);
errno = 0;
(void) unlink(fullname);
logit(text, errno);
return;
}
void
dDprocess(fullname)
char *fullname;
{
char text[BUFSIZ];
DEBUG(5, "dDprocess(%s), ", fullname);
DEBUG(5, "unlink(%s)\n", fullname);
(void) sprintf(text, "dDprocess: unlink(%s)", fullname);
errno = 0;
(void) unlink(fullname);
logit(text, errno);
return;
}
void
dXprocess(fullname)
char *fullname;
{
char text[BUFSIZ];
DEBUG(5, "dXprocess(%s), ", fullname);
DEBUG(5, " unlink(%s)\n", fullname);
(void) sprintf(text, "dXprocess: unlink(%s)", fullname);
errno = 0;
(void) unlink(fullname);
logit(text, errno);
return;
}
void
dMprocess(dir, file)
char *dir, *file;
{
int ret;
char fullname[MAXFULLNAME];
char *toUser, *toSystem;
char text[BUFSIZ];
(void) sprintf(fullname, "%s/%s", dir, file);
DEBUG(5, "dMprocess(%s)\n", fullname);
if (PREFIX(_ShortLocal, &file[2])) {
DEBUG(5, " Local file %s: ", file);
}
else {
DEBUG(5, " Remote file %s: ", file);
}
if (toWho(fullname, &toUser, &toSystem)) {
DEBUG(5, "toUser %s, ", toUser);
DEBUG(5, "toSystem %s ", toSystem);
ret = sendMail(toSystem, toUser, fullname, _Undeliverable);
DEBUG(5, "Mail sent, unlink(%s)\n", fullname);
(void) sprintf(text,
"dMprocess: mail %s to %s!%s, returned (%d), unlink(%s)",
fullname, toSystem, toUser, ret, fullname);
errno = 0;
(void) unlink(fullname);
logit(text, errno);
}
return;
}
void
dNprocess(dir, file)
char *dir, *file;
{
char fullname[MAXFULLNAME];
char text[BUFSIZ];
int ret;
(void) sprintf(fullname, "%s/%s", dir, file);
DEBUG(5, "dNprocess(%s)\n", fullname);
if (PREFIX(_ShortLocal, &file[2])) {
DEBUG(5, " Local file %s, ", file);
DEBUG(5, "unlink(%s)\n", fullname);
(void) unlink(fullname);
(void) sprintf(text, "dNprocess: Local news item unlink(%s)",
fullname);
errno = 0;
(void) unlink(fullname);
logit(text, errno);
}
else {
DEBUG(5, " Remote file %s, ", file);
DEBUG(5, "exec rnews(%s), ", fullname);
ret = execRnews(fullname);
DEBUG(5, "unlink(%s)\n", fullname);
(void) sprintf(text,
"dNprocess: Remote - exec rnews %s: returned (%d), unlink(%s)",
fullname, ret, fullname);
errno = 0;
(void) unlink(fullname);
logit(text, errno);
}
return;
}
static long _sec_per_day = 86400L;
int
_age(fullname)
char *fullname;
{
static time_t ptime = 0;
time_t time();
struct stat stbuf;
int e;
if (!ptime)
(void) time(&ptime);
if (stat(fullname, &stbuf) != -1) {
return ((int)((ptime - stbuf.st_mtime)/_sec_per_day));
}
e = errno;
DEBUG(9, "_age: stat (%s) failed", fullname);
DEBUG(9, ", errno %d\n", e);
return(0);
}
#define NLINES 10
int
dType(fullname)
char *fullname;
{
char buf[BUFSIZ];
FILE *fp;
int i, type;
fp = fopen(fullname, "r");
if (fp == NULL) {
DEBUG(4, "Can't open file (%s), ", fullname);
DEBUG(4, "errno=%d -- skip it!\n", errno);
return(FAIL);
}
type = D_DATA;
for (i=0; i<NLINES; i++) {
if (fgets(buf, BUFSIZ, fp) == NULL)
break;
DEBUG(9, "buf: %s\n", buf);
if (EQUALSN(buf, "From ", 5)) {
type = D_MAIL;
break;
}
if (EQUALSN(buf, "U ", 2)) {
type = D_XFILE;
break;
}
if (EQUALSN(buf, "Newsgroups: ", 12)) {
type = D_NEWS;
break;
}
}
(void) fclose(fp);
return(type);
}
int
sendMail(system, user, file, mtext)
char *system, *user, *file;
char *mtext[];
{
FILE *fp, *fi;
char cmd[BUFSIZ];
char *p;
DEBUG(5, "Mail %s to ", file);
DEBUG(5, "%s\n", user);
if (system != NULL && (p = strpbrk(system, Shchar)) != NULL) {
*p = NULLCHAR;
}
if (user != NULL && (p = strpbrk(user, Shchar)) != NULL) {
*p = NULLCHAR;
}
if (system != NULL && *system != '\0')
(void) sprintf(cmd, "%s %s '%s!%s'", PATH, MAIL, system, user);
else
(void) sprintf(cmd, "%s %s '%s'", PATH, MAIL, user);
DEBUG(7, "sendMail: %s\n", cmd);
if ((fp = popen(cmd, "w")) == NULL)
return(-errno);
while (*mtext[0] )
(void) fprintf(fp, *mtext++, Rmtname);
(void) fprintf(fp, "\n\tSincerely,\n\t%s!uucp\n", Myname);
(void) fprintf(fp,
"\n#############################################\n");
if (*file) {
if ((fi= fopen(file, "r")) == NULL)
return(pclose(fp));
(void) fprintf(fp,
"##### Data File: ############################\n");
xfappend(fi, fp);
(void) fclose(fi);
}
return(pclose(fp));
}
int
execRnews(file)
char *file;
{
FILE *fp, *fi;
char cmd[BUFSIZ];
DEBUG(5, "Rnews %s\n", file);
(void) sprintf(cmd, "%s rnews ", PATH);
if ((fp = popen(cmd, "w")) == NULL)
return(-errno);
if ( (fi = fopen(file, "r")) == NULL)
return(pclose(fp));
xfappend(fi, fp);
(void) fclose(fi);
return(pclose(fp));
}
int
toWho(file, user, system)
char *file;
char **system;
char **user;
{
char buf[BUFSIZ];
FILE *fp;
int i;
static char fuser[BUFSIZ], fsystem[MAXBASENAME+1];
static char luser[BUFSIZ], lsystem[MAXBASENAME+1];
*fuser = NULLCHAR;
DEBUG(5, "toWho(%s)\n", file);
fp = fopen(file, "r");
for (i=0; i<NLINES; i++) {
if (fgets(buf, BUFSIZ, fp) == NULL)
break;
DEBUG(9, "buf: %s\n", buf);
if (!analFrom(buf, luser, lsystem))
continue;
if ( !*fuser) {
(void) strcpy(fuser, luser);
(void) strcpy(fsystem, lsystem);
}
if (EQUALS(Myname, lsystem)) {
*user = luser;
*system = lsystem;
(void) fclose(fp);
return(1);
}
}
(void) fclose(fp);
if (!*fuser)
return(0);
*user = fuser;
*system = fsystem;
return(1);
}
int
analFrom(line, user, system)
char *line, *user, *system;
{
char *s;
int i;
if (!PREFIX("From ", line) && !PREFIX(">From ", line))
return(0);
s = strchr(line, ' ') + 1;
for (i = 0; *s && *s != ' ' && *s != '\n'; i++)
user[i] = *s++;
user[i] = NULLCHAR;
while (*s && ((s = strchr(s, ' ')) != NULL)) {
s++;
if (PREFIX("remote from ", s)) {
s = s + strlen("remote from ");
for (i = 0; (i<MAXBASENAME) && *s && *s != ' ' && *s != '\n'; i++)
system[i] = *s++;
system[i] = NULLCHAR;
return(1);
}
}
return(0);
}
static FILE *_Lf = NULL;
void
logit(text, status)
char *text;
int status;
{
if (Nstat.t_pid == 0)
Nstat.t_pid = getpid();
if (_Lf == NULL) {
_Lf = fopen(Logfile, "a");
(void) chmod(Logfile, LOGFILEMODE);
if (_Lf == NULL)
return;
setbuf(_Lf, CNULL);
}
(void) fseek(_Lf, 0L, 2);
(void) fprintf(_Lf, "%s ", Rmtname);
(void) fprintf(_Lf, "(%s,%ld,%d) ", timeStamp(), (long) Nstat.t_pid, Seqn);
(void) fprintf(_Lf, "%s (%d)\n", text, status);
return;
}
static void
cleanworkspace(void)
{
DIR *spooldir;
char f[MAXFULLNAME];
if (chdir(WORKSPACE) != 0) {
(void) fprintf(stderr, "CAN'T CHDIR (%s): errno (%d)\n", WORKSPACE, errno);
return;
}
if ((spooldir = opendir(WORKSPACE)) == NULL) {
(void) fprintf(stderr, "CAN'T OPEN (%s): errno (%d)\n", WORKSPACE, errno);
return;
}
while (gnamef(spooldir, f) == TRUE)
if (_age(f) >= 1)
if (unlink(f) != 0)
(void) fprintf(stderr, "CAN'T UNLINK (%s): errno (%d)\n", f, errno);
}