home *** CD-ROM | disk | FTP | other *** search
- /* $Header: dest.c,v 2.5 90/03/06 12:21:10 chip Exp $
- *
- * Operations on the list of mail destinations.
- *
- * $Log: dest.c,v $
- * Revision 2.5 90/03/06 12:21:10 chip
- * Move logging into log.c and address parsing into addr.c.
- * New: error delivery file for messages that fail.
- * Major rearrangement of delivery file code.
- *
- * Revision 2.4 90/02/23 16:35:53 chip
- * \Fix problems determining legality of user references.
- *
- * Revision 2.3 90/02/23 14:16:42 chip
- * Support "#!" in delivery files.
- * Support "user|program" and "user?error" from delivery files.
- * Improve debugging and error message formatting.
- * Rearrange code for clarity.
- *
- * Revision 2.2 89/09/29 18:17:57 network
- * Save message when delivery file produces no output,
- * unless delivery file output the "DROP" string.
- * Don't recopy temp files for sys and post-user delfiles.
- *
- * Revision 2.1 89/06/09 12:25:22 network
- * Update RCS revisions.
- *
- * Revision 1.5 89/06/09 12:23:45 network
- * Baseline for 2.0 release.
- *
- */
-
- #include "deliver.h"
-
- /*
- * Local data.
- */
-
- static DEST deadhead = { &deadhead, &deadhead };
- #define HEADPTR (&deadhead)
-
- /*
- * Local functions.
- */
-
- static int destcmp();
- static int ptrcmp();
-
- /*----------------------------------------------------------------------
- * Consider mail to the given user as undeliverable.
- */
-
- dest_undel(name)
- char *name;
- {
- (void) dest(name, CL_MBOX, MBX_UNDEL);
- }
-
- /*----------------------------------------------------------------------
- * Add a new destination to the list (unless it already exists).
- * Return pointer to DEST.
- */
-
- DEST *
- dest(name, class, s)
- char *name;
- DCLASS class;
- char *s;
- {
- DEST *d;
-
- /* Make sure that parameter is provided when it's needed. */
-
- if ((class == CL_MBOX || class == CL_PROG) != (s != NULL))
- return NULL;
-
- /* Look for an already-existing copy of the given destination. */
-
- for (d = HEADPTR->d_next; d != HEADPTR; d = d->d_next)
- {
- if (d->d_class != class)
- continue;
-
- if (strcmp(d->d_name, name) != 0)
- continue;
-
- if (s && strcmp(d->d_param, s) != 0)
- continue;
-
- /*
- * Like, gnarly, dude! It's already in the chain!
- */
-
- return d;
- }
-
- /*
- * The given dest isn't in the list, so we have to add it.
- */
-
- d = (DEST *) zalloc(sizeof(DEST));
- d->d_class = class;
- d->d_state = ST_WORKING;
- d->d_name = copystr(name);
- d->d_param = s ? copystr(s) : NULL;
-
- /*
- * Check address for validity.
- */
-
- if (!addr_clean(name))
- dest_err(d, E_IVADDR);
- else if (class != CL_UUCP && name_context(name) == NULL)
- dest_err(d, E_NSUSER);
-
- /*
- * Put new address at the end of of the chain.
- * (This is important! Other code depends on it.)
- */
-
- d->d_prev = HEADPTR->d_prev;
- d->d_next = HEADPTR;
- d->d_prev->d_next = d;
- d->d_next->d_prev = d;
-
- return d;
- }
-
- /*----------------------------------------------------------------------
- * Return pointer to first DEST in the list.
- */
-
- DEST *
- first_dest()
- {
- if (HEADPTR->d_next != HEADPTR)
- return HEADPTR->d_next;
-
- return NULL;
- }
-
- /*----------------------------------------------------------------------
- * Return pointer to next DEST in the list, or NULL.
- */
-
- DEST *
- next_dest(d)
- DEST *d;
- {
- if (d && (d = d->d_next) != HEADPTR)
- return d;
-
- return NULL;
- }
-
- /*----------------------------------------------------------------------
- * Return the number of destinations in the list.
- */
-
- int
- dest_count()
- {
- DEST *d;
- int count;
-
- count = 0;
- for (d = HEADPTR->d_next; d && d != HEADPTR; d = d->d_next)
- ++count;
-
- return count;
- }
-
- /*----------------------------------------------------------------------
- * Return an allocated array of DEST pointers, or NULL if none.
- * The given integer is set to the array size.
- * Note that the caller must FREE this array when he's done.
- */
-
- DEST **
- dest_array(countp)
- int *countp;
- {
- DEST **dv, *d;
- int i, count;
-
- if ((count = dest_count()) <= 0)
- {
- *countp = 0;
- return NULL;
- }
-
- dv = (DEST **) zalloc(count * sizeof(DEST *));
-
- i = 0;
- for (d = HEADPTR->d_next; d && d != HEADPTR; d = d->d_next)
- {
- if (i < count)
- dv[i++] = d;
- }
-
- qsort((char *)dv, count, sizeof(dv[0]), destcmp);
-
- *countp = count;
- return dv;
- }
-
- /*----------------------------------------------------------------------
- * Compare two DEST pointers, for output sorting.
- */
-
- static int
- destcmp(p1, p2)
- char *p1, *p2;
- {
- DEST *d1, *d2;
- int cmp;
-
- d1 = *(DEST **)p1;
- d2 = *(DEST **)p2;
-
- #if 0
- /* Errors go last. */
- if ((d1->d_state == ST_ERROR) != (d2->d_state == ST_ERROR))
- return (d1->d_state == ST_ERROR) ? 1 : -1;
- #endif
-
- #if 0
- /* By class. */
- if ((cmp = (int)d1->d_class - (int)d2->d_class) != 0)
- return (cmp < 0) ? -1 : 1;
- #endif
-
- /* By user name. */
- if ((cmp = ptrcmp(d1->d_name, d2->d_name)) != 0)
- return cmp;
-
- /* By mailbox/program. */
- if ((cmp = ptrcmp(d1->d_param, d2->d_param)) != 0)
- return cmp;
-
- return 0;
- }
-
- /*----------------------------------------------------------------------
- * Compare two pointers, either of which may be NULL.
- */
-
- static int
- ptrcmp(p, q)
- char *p, *q;
- {
- if (p == q)
- return 0;
- if (p == NULL)
- return -1;
- if (q == NULL)
- return 1;
- return strcmp(p, q);
- }
-
- /*----------------------------------------------------------------------
- * Return a destination's error message.
- */
-
- char *
- derrmsg(d)
- DEST *d;
- {
- static char unknown_buf[40];
- static char no_error[] = "no error?!";
-
- if (!d || d->d_state != ST_ERROR)
- return no_error;
-
- switch (d->d_error)
- {
- case E_IVADDR:
- return "Invalid address string";
- case E_NSUSER:
- return "No such user";
- case E_NSHOST:
- return "No such UUCP host";
- case E_CTPERM:
- return "No permissions for that context";
- case E_CTLOST:
- return "Context lost (should never happen)";
- case E_MBOX:
- return "Can't write to mailbox";
- case E_PROG:
- return "Subprocess reported failure when exiting";
- case E_PIPE:
- return "Subprocess died while reading its standard input";
- case E_DFONLY:
- return "Address not valid from command line";
- case E_ERRMSG:
- return d->d_errmsg ? d->d_errmsg : no_error;
- }
-
- (void) sprintf(unknown_buf, "Unknown error %d", d->d_error);
- return unknown_buf;
- }
-