root/usr/src/cmd/lp/cmd/lpsched/rstatus.c
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License (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 2006 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

/*      Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
/*        All Rights Reserved   */

#include "lpsched.h"


/**
 ** insertr()
 **/

void
insertr(RSTATUS *r)
{
        RSTATUS                 *prs;


        if (!Request_List) {
                Request_List = r;
                return;
        }

        for (prs = Request_List; prs; prs = prs->next) {
                if (rsort(&r, &prs) < 0) {
                        r->prev = prs->prev;
                        if (r->prev)
                                r->prev->next = r;
                        r->next = prs;
                        prs->prev = r;
                        if (prs == Request_List)
                                Request_List = r;
                        return;
                }

                if (prs->next)
                        continue;

                r->prev = prs;
                prs->next = r;
                return;
        }
}

/**
 ** remover()
 **/

void
remover(RSTATUS *r)
{
        if (r == Request_List)          /* on the request chain */
                Request_List = r->next;

        if (r->next)
                r->next->prev = r->prev;

        if (r->prev)
                r->prev->next = r->next;

        r->next = 0;
        r->prev = 0;
        return;
}

/**
 ** request_by_id()
 **/

RSTATUS *
request_by_id(char *id)
{
        register RSTATUS        *prs;

        for (prs = Request_List; prs; prs = prs->next)
                if (STREQU(id, prs->secure->req_id))
                        return (prs);
        return (0);
}

RSTATUS *
request_by_id_num( long num )
{
        register RSTATUS        *prs;

        for (prs = Request_List; prs; prs = prs->next) {
                char *tmp = strrchr(prs->secure->req_id, '-');

                if (tmp && (num == atol(++tmp)))
                        return (prs);
        }
        return(0);
}


/**
 ** rsort()
 **/

static int              later ( RSTATUS * , RSTATUS * );

int
rsort (RSTATUS **p1, RSTATUS **p2)
{
        /*
         * Of two requests needing immediate handling, the first
         * will be the request with the LATER date. In case of a tie,
         * the first is the one with the larger request ID (i.e. the
         * one that came in last).
         */
        if ((*p1)->request->outcome & RS_IMMEDIATE)
                if ((*p2)->request->outcome & RS_IMMEDIATE)
                        if (later(*p1, *p2))
                                return (-1);
                        else
                                return (1);
                else
                        return (-1);

        else if ((*p2)->request->outcome & RS_IMMEDIATE)
                return (1);

        /*
         * Of two requests not needing immediate handling, the first
         * will be the request with the highest priority. If both have
         * the same priority, the first is the one with the EARLIER date.
         * In case of a tie, the first is the one with the smaller ID
         * (i.e. the one that came in first).
         */
        else if ((*p1)->request->priority == (*p2)->request->priority)
                if (!later(*p1, *p2))
                        return (-1);
                else
                        return (1);

        else
                return ((*p1)->request->priority - (*p2)->request->priority);
        /*NOTREACHED*/
}

static int
later(RSTATUS *prs1, RSTATUS *prs2)
{
        if (prs1->secure->date > prs2->secure->date)
                return (1);

        else if (prs1->secure->date < prs2->secure->date)
                return (0);

        /*
         * The dates are the same, so compare the request IDs.
         * One problem with comparing request IDs is that the order
         * of two IDs may be reversed if the IDs wrapped around. This
         * is a very unlikely problem, because the cycle should take
         * more than one second to wrap!
         */
        else {
                register int            len1 = strlen(prs1->req_file),
                                        len2 = strlen(prs2->req_file);

                /*
                 * Use the request file name (ID-0) for comparison,
                 * because the real request ID (DEST-ID) won't compare
                 * properly because of the destination prefix.
                 * The strlen() comparison is necessary, otherwise
                 * IDs like "99-0" and "100-0" will compare wrong.
                 */
                if (len1 > len2)
                        return (1);
                else if (len1 < len2)
                        return (0);
                else
                        return (strcmp(prs1->req_file, prs2->req_file) > 0);
        }
        /*NOTREACHED*/
}