Subject: bin/28593: lpd problem/bug with 'port@host' entries and jetdirect/direct tcp printers
To: None <gnats-admin@netbsd.org, netbsd-bugs@netbsd.org>
From: Markus W Kilbinger <kilbi@rad.rwth-aachen.de>
List: netbsd-bugs
Date: 12/09/2004 14:27:01
>Number:         28593
>Category:       bin
>Synopsis:       lpd is handling jetdirect/direct tcp printers not properly
>Confidential:   no
>Severity:       non-critical
>Priority:       high
>Responsible:    bin-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Thu Dec 09 14:27:00 +0000 2004
>Originator:     kilbi@rad.rwth-aachen.de
>Release:        NetBSD 2.0 and -current
>Organization:
>Environment:
	
	
System: NetBSD basis 2.0 NetBSD 2.0 (BASIS) #6: Mon Nov 29 10:14:17 MET 2004 root@basis:/usr/src/sys/arch/i386/compile/BASIS i386
Architecture: i386
Machine: i386
All machines/platforms
>Description:
	For several months I was investigating the reason, why several
	printjobs for jetdirect or other direct tcp (normally port
	9100) printers (as kyocera's) failed (with '40 eio error's on
	jetdirect, mostly showing some postscript errors on the
	'final' paper sheet).

	After looking at cups sources of their socket backend the
	reason seems to be that these jetdirect printers require the
	sending host to read back some message over the network
	connection (where lpd at the moment simply ends with an
	exit(0)).
>How-To-Repeat:
	E. g. take a postscript print job which produces a stderr
	meassage like '%%[ ProductName: HP LaserJet 4050 Series ]%%'
	(Adobe's Postscript driver does this), send it via direct tcp
	(lpd and port@host) to a jetdirect (postscript capable! :-))
	printer and see how it fails.
>Fix:
	The appended patch solves the problem completely for me (and
	about 40 tcp capable print spoolers of our dept.). The
	important part is the 'select' call itself (waiting for a sent
	back message and timeout), which does not end with the
	'timeout' normally. The (optional) read back of the sent back
	message yields the above mentioned postscript stderr message.

	This patch is only worth for template purposes... ;-)

	I've chosen 'sw-bug' as category because so many jetdirect
	devices are involved.

Index: lpd/printjob.c
===================================================================
RCS file: /cvsroot/src/usr.sbin/lpr/lpd/printjob.c,v
retrieving revision 1.39
diff -u -b -r1.39 printjob.c
--- lpd/printjob.c	7 Aug 2003 11:25:28 -0000	1.39
+++ lpd/printjob.c	9 Dec 2004 13:02:45 -0000
@@ -59,6 +59,8 @@
 #include <sys/types.h>
 #include <sys/file.h>
 
+#include<sys/socket.h>
+
 #include <pwd.h>
 #include <unistd.h>
 #include <signal.h>
@@ -299,8 +301,37 @@
 			if (TR != NULL)		/* output trailer */
 				(void)write(ofd, TR, strlen(TR));
 		}
+
+		/* That's what {Free,Open}BSD does */
+		/* , but it's not enough (still 40 eio errors) */
+		/* (void)close(ofd);
+		   (void)wait(NULL); */
+
 		(void)unlink(tempfile);
 		(void)unlink(tempremote);
+
+		/* Stuff that is done in cups socket backend */
+		shutdown(pfd, SHUT_WR);
+
+		fd_set input;
+		struct timeval timeout;
+
+		timeout.tv_sec  = 90;
+		timeout.tv_usec = 0;
+		FD_ZERO(&input);
+		FD_SET(pfd, &input);
+		if (select(pfd + 1, &input, NULL, NULL, &timeout) > 0) {
+		  char buf[BUFSIZ];
+		  int rlen;
+
+		  if ((rlen = recv(pfd, buf, sizeof(buf), 0)) > 0) {
+		    if (rlen >= sizeof(buf)) rlen = sizeof(buf) - 1;
+		    buf[rlen] = '\0';
+		    syslog(LOG_ERR, "Printer reply: >%s<\n", buf);
+		  }
+		}
+		(void)close(pfd);
+
 		exit(0);
 	}
 	goto again;

>Unformatted: