home *** CD-ROM | disk | FTP | other *** search
- /* 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);
- }
-
-