Subject: bin/37346: lpd prints out of order
To: None <gnats-admin@netbsd.org, netbsd-bugs@netbsd.org>
From: None <mlelstv@serpens.de>
List: netbsd-bugs
Date: 11/08/2007 23:00:01
	Note: There was a bad value `non-critcal' for the field `Severity'.
	It was set to the default value of `serious'.

>Number:         37346
>Category:       bin
>Synopsis:       lpd prints out of order
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    bin-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Thu Nov 08 23:00:00 +0000 2007
>Originator:     Michael van Elst
>Release:        NetBSD 4.0_RC2
>Organization:
-- 
                                Michael van Elst
Internet: mlelstv@serpens.de
                                "A potential Snark may lurk in every tree."
>Environment:
	
	
System: NetBSD henery 4.0_RC2 NetBSD 4.0_RC2 (HENERY) #38: Thu Oct 4 20:13:01 CEST 2007 mlelstv@henery:/home/netbsd4/obj.i386/home/netbsd4/src/sys/arch/i386/compile/HENERY i386
Architecture: i386
Machine: i386
>Description:
When you print several files in a row using lpr it is possible
that lpd prints them out in a different order.

The reason is that lpd sorts the queue by mtime which has second
granularity. Files spooled within the same second appear in arbitrary
order in the output.

The corresponding sort function is in common_source/common.c:316
/*
 * Compare modification times.
 */
static int
compar(const void *p1, const void *p2)
{
        const struct queue *const *q1 = p1;
        const struct queue *const *q2 = p2;

        if ((*q1)->q_time < (*q2)->q_time)
                return -1;
        if ((*q1)->q_time > (*q2)->q_time)
                return 1;
        return 0;
}


>How-To-Repeat:
Just lpr a couple of files. Watch with lpq that jobids and queue rank
don't agree.
>Fix:

Make the sorting stable regarding jobids.

The matter is complicated by jobids being relative to submitting
hosts and jobids being modulo 1000. The information is also only
present in the names of the spool files.

/*
 * Compare modification times.
 */
static int
compar(const void *p1, const void *p2)
{
        const struct queue *const *q1 = p1;
        const struct queue *const *q2 = p2;
	int j1, j2;

        if ((*q1)->q_time < (*q2)->q_time)
                return -1;
        if ((*q1)->q_time > (*q2)->q_time)
                return 1;

	j1 = atoi((*q1)->q_name+3);
	j2 = atoi((*q2)->q_name+3);

        if (j1 == j2)
                return 0;
        if ((j1 < j2 && j2-j1 < 500) || (j1 > j2 && j1-j2 > 500))
                return -1;
        if ((j1 < j2 && j2-j1 > 500) || (j1 > j2 && j1-j2 < 500))
                return 1;

	return 0;
}

For remote printing the change needs to be done on both sides.
Otherwise the local lpd will already send the files in wrong order
to the remote side.

>Unformatted: