root/usr/src/cmd/mail/ckdlivopts.c
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License, Version 1.0 only
 * (the "License").  You may not use this file except in compliance
 * with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */
/*      Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
/*        All Rights Reserved   */

/*
    NAME
        ckdlivopts - check delivery notification options

    SYNOPSIS
        int ckdlivopts(int tcopy_hdr, int *svopts)

    DESCRIPTION
        Check if delivery notification requested for message being
        processed. Returns specified options as combined from H_DEFOPTS,
        H_TROPTS, & H_TCOPY lines.

        (Positive notification options)
                001 ==> /delivery requested
                002 ==> /nodelivery requested
        (Negative notification options)
                010 ==> /report requested
                020 ==> /return requested
                040 ==> /ignore requested

        Combinations are expected, i.e. - 011 ==> /delivery/report
        If not specified, the assumed defaults are /nodelivery/return (rc=022)

        The options discovered in the header are stored into svopts.
 */
#include "mail.h"

static void getopts();
static void mergeopts();

struct dlvopts {
        int     deliv;
        int     nodeliv;
        int     rept;
        int     rtrn;
        int     ign;
};

int ckdlivopts(tcopy_hdr, svopts)
int     tcopy_hdr;
int     *svopts;
{
        static char     pn[] = "ckdlivopts";
        struct  hdrs    *hp;
        struct dlvopts  toopts, tropts, defopts;
        int             rc;

        /* already done this once. no need to repeat..... */
        if (svopts && *svopts != 0) {
                Dout(pn, 0, "*svopts = o%o\n", *svopts);
                return (*svopts);
        }
        memset((char *)&defopts, 0, sizeof(struct dlvopts));
        if ((hp = hdrlines[H_DEFOPTS].head) != (struct hdrs *)NULL) {
                Dout(pn, 3, "H_DEFOPTS line = '%s'\n", hp->value);
                getopts(hp->value, &defopts);
        }
        memset((char *)&tropts, 0, sizeof(struct dlvopts));
        if ((hp = hdrlines[H_TROPTS].head) != (struct hdrs *)NULL) {
                Dout(pn, 3, "H_TROPTS line = '%s'\n", hp->value);
                getopts(hp->value, &tropts);
        }
        memset((char *)&toopts, 0, sizeof(struct dlvopts));
        if ((hp = hdrlines[tcopy_hdr].head) != (struct hdrs *)NULL) {
                Dout(pn, 3,"H_TCOPY line = '%s'\n", hp->value);
                getopts(hp->value, &toopts);
        }
        /* Combine options from different header lines. Precedence is */
        /* toopts --> tropts --> defopts. Results left in defopts */
        mergeopts(&tropts,&defopts);
        mergeopts(&toopts,&defopts);

        if (defopts.deliv)      rc = DELIVERY;
        else                    rc = NODELIVERY;

        if (defopts.rtrn)       rc += RETURN;
        else if (defopts.rept)  rc += REPORT;
        else if (defopts.ign)   rc += IGNORE;
        else                    rc += RETURN;

        Dout(pn, 0,"returning = o%o\n", rc);
        if (svopts)
                *svopts = rc;
        return (rc);
}

/*
 * Pick transport options off of header line.
 * If conflicting options found, use MOST demanding; i.e. - /delivery/return.
 */
static void getopts(s, optr)
register char   *s;
register struct dlvopts *optr;
{
        register char   *op;

        for (op = strchr (s, '/'); op++; op = strchr(op, '/')) {
                if (casncmp(op, "delivery", 7) == 0) {
                        optr->deliv = 1;
                        optr->nodeliv = 0;
                } else if (casncmp(op, "nodelivery", 10) == 0) {
                        if (optr->deliv == 0) {
                                optr->nodeliv = 1;
                        }
                } else if (casncmp(op, "report", 6) == 0) {
                        optr->ign = 0;
                        if (optr->rtrn == 0) {
                                optr->rept = 1;
                        }
                } else if (casncmp(op, "return", 6) == 0) {
                        optr->rtrn = 1;
                        optr->rept = optr->ign = 0;
                } else if (casncmp(op, "ignore", 6) == 0) {
                        optr->rept = 0;
                        if (optr->rtrn == 0) {
                                optr->ign = 1;
                        }
                }
        }
}

/*
 * Merge options between 2 sets. Higher set has precedence.
 * Results left in lower set.
 */
static void mergeopts(higher, lower)
register struct dlvopts *higher, *lower;
{
        if (higher->deliv == 1) {
                lower->deliv = 1;
                lower->nodeliv = 0;
        }
        if (higher->nodeliv == 1) {
                lower->nodeliv = 1;
                lower->deliv = 0;
        }
        if (higher->rept == 1) {
                lower->rept = 1;
                lower->rtrn = lower->ign = 0;
        }
        if (higher->rtrn == 1) {
                lower->rtrn = 1;
                lower->rept = lower->ign = 0;
        }
        if (higher->ign == 1) {
                lower->ign = 1;
                lower->rept = lower->rtrn = 0;
        }
}