home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
unix
/
volume18
/
mq
/
mq.c
< prev
next >
Wrap
C/C++ Source or Header
|
1989-03-05
|
10KB
|
437 lines
/* program for selectively displaying the mail queue.
*
* usage:
* mq [-w] [-n] [-v] [-f [name]] [-t [name]] [-d name]
*
* caveats/comments:
* -> 1) no checking is done w.r.t. what other programs are doing
* to the mail queue files.
* 2) items in the queue without a control file are ignored and
* not counted.
* 3) one might also want to sort by priority.
*
* author:
* Kevin Sweet ---------------------------------- sweet@scubed.arpa
* S-CUBED, 3398 Carmel Mountain, San Diego, CA 92121-1095
* (home) 12205 Carmel Vista 242, San Diego, CA 92130-2237
* ------- [ames,att,harvard,rutgers,ucsd,uunet]scubed!sweet ------
*
* This work is copyright 1988 by Kevin Sweet. Permission is granted
* to modify and distribute this work under the provision that the
* author is informed of any non-cosmetic changes to the code and that
* the author's name remain part of the documentaion.
*/
#ifndef VOID
# define VOID
#endif
#include <sys/types.h>
#include <sys/stat.h>
#ifdef SYSV
# include <string.h>
# define index strchr
# define rindex strrchr
# include <ndir.h> /* see Makefile... */
#else /* SYSV */
# include <strings.h>
# include <sys/dir.h>
#endif
#include <stdio.h>
#include <ctype.h>
int order();
extern int free(), qsort();
extern long atol();
extern char *ctime(), *getenv(), *malloc();
static int gethelp();
#define FALSE 0
#define LSIZE 256
#define MALLOC(a) (char *) malloc( (unsigned) sizeof(char) * \
((a) + 1) )
#define NUMQ 128
/* #define SORT_BY_ID /**/
#define SORT_BY_TIME /**/
#define SWITCHAR '-'
#define TRUE 1
struct mqueue {
long l; /* location in directory stream */
long t; /* time entered queue */
char q[8]; /* queue id */
};
typedef unsigned short int BOOLEAN;
main(argc, argv)
int argc;
char *argv[];
{
BOOLEAN DONT, FROM, NUMBER, TO, VERBOSE, WIDE;
DIR *dp;
FILE *fp;
char dont[80], from[80], line[LSIZE], to[80];
register char *cp, *fg, *message, *qdir, *user;
register int i, icnt, ldont, lfrom, lto, mcnt, qcnt, qdlen;
register long size;
struct direct *dirp;
struct mqueue qinfo[NUMQ];
struct stat sbuf;
/* find the print options
*/
#ifdef SYSV
user = getenv("LOGNAME");
#else
user = getenv("USER");
#endif
DONT = FROM = NUMBER = TO = VERBOSE = WIDE = FALSE;
for (i = 1, cp = argv[1]; i < argc; i++, cp = argv[i])
if (cp[0] == SWITCHAR)
switch (cp[1]) {
case 'h': case 'H':
gethelp(argv[0], 0);
case 'n': case 'N':
NUMBER = TRUE;
break;
case 'w': case 'W':
WIDE = TRUE;
break;
case 'v': case 'V':
VERBOSE = TRUE;
break;
case 'f': case 'F':
FROM = TRUE;
if (cp[2])
sprintf(from, "%.79s", &argv[i][2]);
else
if (i != argc-1 && argv[i+1][0] != SWITCHAR) {
sprintf(from, "%.79s", argv[i+1]);
i++;
}
else
sprintf(from, "%.79s", user);
lfrom = strlen(from);
break;
case 't': case 'T':
TO = TRUE;
if (cp[2])
sprintf(to, "%.79s", &argv[i][2]);
else
if (i != argc-1 && argv[i+1][0] != SWITCHAR) {
sprintf(to, "%.79s", argv[i+1]);
i++;
}
else
sprintf(to, "%.79s", user);
lto = strlen(to);
break;
case 'd': case 'D':
DONT = TRUE;
if (cp[2])
sprintf(dont, "%.79s", &argv[i][2]);
else
if (i != argc-1 && argv[i+1][0] != SWITCHAR) {
sprintf(dont, "%.79s", argv[i+1]);
i++;
}
else
sprintf(dont, "%c", '\0');
ldont = strlen(dont);
if (!ldont) DONT = FALSE;
break;
default:
printf("invalid option '%c': ", cp[1]);
gethelp(argv[0], -1);
} /* end switch */
else
{
gethelp(argv[0], 0);
} /* end for/if */
/* find the mqueue directory.
*/
qcnt = 0;
#ifndef DEBUG
if ( !(fp = fopen("/usr/lib/sendmail.cf", "r")) ) {
printf("fatal error: ");
printf("unable to read /usr/lib/sendmail.cf\n");
gethelp(argv[0], 1);
}
while ((fg = fgets(line, LSIZE, fp)) != (char *) NULL) {
if (strncmp(fg, "OQ", 2)) continue;
fg[strlen(line)-1] = '\0';
fg += 2;
qcnt++;
qdlen = strlen(fg) + 1;
qdir = MALLOC(qdlen);
strncpy(qdir, fg, qdlen - 1);
break;
}
fclose(fp);
#endif /* DEBUG */
if (!qcnt) {
qdlen = strlen(MQUEUE) + 1;
qdir = MALLOC(qdlen);
strncpy(qdir, MQUEUE, qdlen - 1);
}
/* find queue files in the mqueue directory:
* save the location in the directory stream, the queue id and
* the time for each vaild (non-zero length) queue control file.
*/
if ( !(dp = opendir(qdir)) ) {
printf("fatal error: ");
printf("unable to open directory %s\n", qdir);
gethelp(argv[0], 2);
}
mcnt = qcnt = 0;
for (dirp = readdir(dp); dirp != (struct direct *) NULL;
dirp = readdir(dp))
if (!strncmp(dirp->d_name, "qf", 2)) {
/*
* open the file and test it for validity
*/
cp = MALLOC(qdlen + 1 + strlen(dirp->d_name));
sprintf(cp, "%s/%s", qdir, dirp->d_name);
fp = fopen(cp, "r");
VOID stat(cp, &sbuf);
VOID free(cp);
if (!fp) continue;
if (!sbuf.st_size) {
fclose(fp);
continue;
}
/*
* do book-keeping
*/
icnt = 0;
mcnt++;
if (qcnt < NUMQ)
/*
* check to see if we are supposed to print the entry
*/
while ( fg = fgets(line, LSIZE, fp) ) {
fg[strlen(line)-1] = '\0';
if (*fg == 'S') {
if (FROM) {
for (; *fg; *fg++)
if (!strncmp(fg, from, lfrom))
icnt |= 0x001;
} else
icnt |= 0x001;
} else
if (*fg == 'R') {
if (TO) {
for (; *fg; *fg++)
if (!strncmp(fg, to, lto))
icnt |= 0x002;
} else
icnt |= 0x002;
if (DONT) {
for (; *fg; *fg++)
if (!strncmp(fg, dont, ldont))
icnt |= 0x004;
}
}
} /* end while loop */
if ( (icnt & 0x004) ||
!(icnt & 0x002) ||
!(icnt & 0x001) ) {
/*
* either DONT was specified _and_ we found
* the dont field in the Receiver field,
* or TO was specified _and_ we did not find
* the to field in the Receiver field,
* or FROM was specified _and_ we did not find
* the from field in the Sender field;
* or we have exceeded the array dimension for
* holding queue information.
*/
fclose(fp);
continue;
}
/*
* save the location in the directory stream
*/
qinfo[qcnt].l = telldir(dp);
/*
* save the queue id
*/
sprintf(qinfo[qcnt].q, "%.7s",
index(dirp->d_name, 'f')+1);
/*
* save the queue time
*/
VOID fseek(fp, 0L, 0);
while ((fg = fgets(line, LSIZE, fp)) && *fg != 'D')
if (*fg == 'T') qinfo[qcnt].t = atol(&line[1]);
/*
* increment the valid queue file counter
*/
qcnt++;
fclose(fp);
}
closedir(dp);
/* print the requisite header
*/
if (!qcnt) {
if (!mcnt) printf("Mail queue is empty\n");
else {
printf("Mail Queue (%d request%c",
mcnt, mcnt > 1 ? 's' : '\0');
printf(", none %s)\n",
NUMBER == TRUE ? "applied" : "printed");
}
exit(0);
}
printf("%sMail Queue (%d request%c", NUMBER == TRUE ? "" :
( VERBOSE == TRUE ? " " : "\t\t" ),
mcnt, mcnt > 1 ? 's' : '\0');
if (qcnt != mcnt)
printf(", only %d %s", qcnt,
NUMBER == TRUE ? "applied" : "printed");
printf(")\n");
if (NUMBER) exit(0);
if (VERBOSE == FALSE)
printf("%s%s\n", "--QID-- --Size-- -----Q-Time----- ",
"------------Sender/Recipient-----------------");
/* sort the queue files
*/
VOID qsort(qinfo, qcnt, sizeof(struct mqueue), order);
/* loop through the valid queue files:
*/
for (icnt = 0; icnt < qcnt; icnt++) {
cp = MALLOC(qdlen + 2 + strlen(qinfo[icnt].q));
sprintf(cp, "%s/qf%s", qdir, qinfo[icnt].q);
fp = fopen(cp, "r");
VOID free(cp);
/* read in everything up to the first header line
*/
mcnt = 0;
while ( fg = fgets(line, LSIZE, fp) ) {
/* get rid of the trailing newline
*/
fg[strlen(line)-1] = '\0';
/* get the size of the data file (long)
*/
if (*fg == 'D') {
cp = MALLOC(qdlen + strlen(fg));
sprintf(cp, "%s/%s", qdir, &line[1]);
VOID stat(cp, &sbuf);
size = (long) sbuf.st_size;
VOID free(cp);
} else
/*
* get the error message (char *)
*/
if (*fg == 'M') {
message = MALLOC(strlen(fg));
sprintf(message, "%s", &line[1]);
mcnt++;
} else
/*
* get the sender (char *)
*/
if (*fg == 'S') {
/*
* print out what we have so far
*/
if (VERBOSE) {
if (WIDE) printf("from: %s\n", &line[1]);
else printf("from: %.73s\n", &line[1]);
} else {
printf("%-7.7s %8ld %.16s ",
qinfo[icnt].q, size, ctime(&qinfo[icnt].t));
if (WIDE) {
printf("%s\n", &line[1]);
if (mcnt) printf("\t\t\t\t (%s)\n", message);
} else {
printf("%.45s\n", &line[1]);
if (mcnt) printf("\t\t\t\t (%.43s)\n", message);
}
}
size = 0L;
if (mcnt) VOID free(message);
} else
/*
* get the recipients (char *)
*/
if (*fg == 'R') {
/*
* print out the rest
*/
if (VERBOSE) {
printf(" to: ");
if (WIDE)
printf("%s\n", &line[1]);
else
printf("%.69s\n", &line[1]);
} else {
printf("\t\t\t\t ");
if (WIDE)
printf("%s\n", &line[1]);
else
printf("%.45s\n", &line[1]);
}
}
} /* end fp loop */
fclose(fp);
if (VERBOSE) printf(" in queue since: %.16s\n",
ctime(&qinfo[icnt].t));
} /* end valid queue file loop */
exit(0);
}
/* qsort comparison function.
*/
int
order(e1, e2)
struct mqueue *e1;
struct mqueue *e2;
{
#ifdef SORT_BY_TIME
if (e1->t < e2->t) return(-1);
else if (e1->t > e2->t) return(1);
else return(0);
#endif
#ifdef SORT_BY_ID
return(strcmp(e1->q, e2->q));
#endif
}
/* the help/usage message
*/
static
int
gethelp(program, exit_status)
char *program;
int exit_status;
{
register char *name;
name = rindex(program, '/');
if (name) *name++;
else {
name = rindex(program, '\\');
if (name) *name++;
else name = program;
}
printf("usage: %s [-w] [-n] [-v]", name);
printf(" [-f [name]] [-t [name]] [-d name]\n");
exit(exit_status);
}