From dwmalone@maths.tcd.ie  Fri Jun 26 11:35:09 1998
Received: from salmon.maths.tcd.ie (mmdf@salmon.maths.tcd.ie [134.226.81.11])
          by hub.freebsd.org (8.8.8/8.8.8) with SMTP id LAA04120
          for <FreeBSD-gnats-submit@freebsd.org>; Fri, 26 Jun 1998 11:35:03 -0700 (PDT)
          (envelope-from dwmalone@maths.tcd.ie)
Received: from boole.maths.tcd.ie by salmon.maths.tcd.ie with SMTP
          id <aa25686@salmon.maths.tcd.ie>; 26 Jun 98 19:34:50 +0100 (BST)
Message-Id: <9806261934.aa02238@boole.maths.tcd.ie>
Date: Fri, 26 Jun 98 19:34:50 +0100 (BST)
From: dwmalone@maths.tcd.ie
Sender: dwmalone@maths.tcd.ie
Reply-To: dwmalone@maths.tcd.ie
To: FreeBSD-gnats-submit@freebsd.org
Subject: lpd remote printer on local host broken.
X-Send-Pr-Version: 3.2

>Number:         7081
>Category:       bin
>Synopsis:       [patch] lpr stuff doesn't deal with RM and RP well if RM = hostname
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Fri Jun 26 11:40:00 PDT 1998
>Closed-Date:    Tue Apr 27 00:08:44 PDT 1999
>Last-Modified:  Tue Apr 27 00:10:58 PDT 1999
>Originator:     David Malone
>Release:        FreeBSD 2.2.6-STABLE i386
>Organization:
School of Mathematics, Trinity College, Dublin.
>Environment:

	We're tring to use one printcap on all our machines. 
	To do this we set up a printcap entry for "laser"
	which says "rm=printserver rp=laser-real". We then also
	have an entry for "laser-real" which has the actual
	printer details.

	The idea is that users use the "laser" name for the printer
	all the time. This solution is documented in "Unix System
	Administration Handbook" p. 588, so I presume it should work.

	I've included the actual printcap entries below.

>Description:

	lpd tries to be clever and checks if RM == my_hostname.
	However, it doesn't check if the remote printer name it
	is sending it to is the same as the local printer name,
	and so chokes 'cos "laser" is not a real printer.

>How-To-Repeat:

	Try the following printcap on a machine called printserver.

laser:\
	:rm=printserver:rp=laser-real:mx#0:sf:sh:rw:sb:\
	:sd=/var/spool/lpd/laser:

laser-real:\
	:mx#0:lp=/dev/null:\
	:sd=/var/spool/lpd/laser-real:\
	:lf=/var/log/lpd-errs:\
	:af=/var/log/laser-real.acct:\
	:if=/local/etc/laser-psif:

	You'll get the cryptic syslog message when you try to print:

Jun 26 19:00:59 printserver lpd[1249]: /dev/lp: No such file or directory

>Fix:
	
	I've included a patch to the stable source, which treats
	the printer as a remote printer iff you set RP and RP doesn't
	match the current printer. This means there won't be any
	unexpected printer loops. It's all done with cap library
	functions, so there shouldn't be many problems.

	With a little modification this could also be applied to
	the current source, only to the checkremote function in
	net.c, just after the line "pp->remote = 1;". However the
	current source looks more clever - so there might be a
	better solution.


*** /usr/src/usr.sbin/lpr/common_source/common.c	Fri Oct 31 21:19:24 1997
--- common.c	Fri Jun 26 19:06:14 1998
***************
*** 304,309 ****
--- 304,310 ----
  	char name[MAXHOSTNAMELEN];
  	register struct hostent *hp;
  	static char errbuf[128];
+ 	char *rp,*rp_b;
  
  	remote = 0;	/* assume printer is local */
  	if (RM != NULL) {
***************
*** 330,338 ****
--- 331,355 ----
  		/*
  		 * if the two hosts are not the same,
  		 * then the printer must be remote.
+ 		 * otherwise check if the remote printer name
+ 		 * and the current printer name match.
+ 		 * (Can't trust RP, it may have been set to default).
  		 */
  		if (strcasecmp(name, hp->h_name) != 0)
  			remote = 1;
+ 		else if (cgetstr(bp, "rp", &rp) > 0) {
+ 			if (cgetent(&rp_b, printcapdb, rp) == 0) {
+ 				if (cgetmatch(rp_b, printer) != 0)
+ 					remote = 1;
+ 				free(rp_b);
+ 			} else {
+ 			    	(void) snprintf(errbuf, sizeof(errbuf),
+ 				    "can't find (local) remote printer %s",
+ 				    rp);
+ 		    		return errbuf;
+ 			}
+ 			free(rp);
+ 		}
  	}
  	return NULL;
  }
>Release-Note:
>Audit-Trail:
State-Changed-From-To: open->suspended 
State-Changed-By: phk 
State-Changed-When: Sat Jun 27 02:27:18 PDT 1998 
State-Changed-Why:  
awaiting committer 

From: David Malone <dwmalone@maths.tcd.ie>
To: freebsd-gnats-submit@freebsd.org
Cc:  
Subject: Re: bin/7081: [patch] lpr stuff doesn't deal with RM and RP well if RM = hostname
Date: Thu, 04 Feb 1999 18:15:04 +0000

 This PR has been fixed in 2.2-STABLE (as of version 1.4.2.3 of common.c).
 Lpr is quite different in 3.0 so the same patch won't work. However I've
 written what I think is an equivelent patch for 3.0 and current - it should
 have the same effect as the 2.2 fix. If this was committed the PR could
 be closed.
 
 	David.
 
 
 diff -cwr common_source/lp.h /usr/src/usr.sbin/lpr/common_source/lp.h
 *** common_source/lp.h	Thu Feb  4 17:04:06 1999
 --- /usr/src/usr.sbin/lpr/common_source/lp.h	Tue Dec  2 20:45:21 1997
 ***************
 *** 50,56 ****
   struct	printer {
   	char	*printer;	/* printer name */
   	int	 remote;	/* true if RM points to a remote host */
 - 	int	 rp_matches_local; /* true if rp has same name as us */
   	int	 tof;		/* true if we are at top-of-form */
   	/* ------------------------------------------------------ */
   	char	*acct_file;	/* AF: accounting file */
 --- 50,55 ----
 diff -cwr common_source/net.c /usr/src/usr.sbin/lpr/common_source/net.c
 *** common_source/net.c	Thu Feb  4 17:19:21 1999
 --- /usr/src/usr.sbin/lpr/common_source/net.c	Tue Dec  2 20:45:22 1997
 ***************
 *** 160,170 ****
   	struct in_addr *localaddrs;
   	int i, j, nlocaladdrs, ncommonaddrs;
   
 - 	if (!pp->rp_matches_local) { /* Remote printer doesn't match local */
 - 		pp->remote = 1;
 - 		return NULL;
 - 	}
 - 
   	pp->remote = 0;	/* assume printer is local */
   	if (pp->remote_host != NULL) {
   		/* get the addresses of the local host */
 --- 160,165 ----
 diff -cwr common_source/printcap.c /usr/src/usr.sbin/lpr/common_source/printcap.c
 *** common_source/printcap.c	Thu Feb  4 17:57:21 1999
 --- /usr/src/usr.sbin/lpr/common_source/printcap.c	Sat Dec 27 20:49:39 1997
 ***************
 *** 215,222 ****
   	struct printer *pp;
   {
   	enum lpd_filters filt;
 - 	char *rp_name;
 - 	int error;
   
   	if ((pp->printer = capdb_canonical_name(bp)) == 0)
   		return PCAPERR_OSERR;
 --- 215,220 ----
 ***************
 *** 264,283 ****
   	pp->rw = capdb_getaltlog(bp, "rw", "tty.rw");
   	pp->tof = !capdb_getaltlog(bp, "fo", "job.topofform");
   	
 - 	/*
 - 	 * Decide if the remote printer name matches the local printer name.
 - 	 * If no name is given then we assume they mean them to match.
 - 	 * If a name is given see if the rp_name is one of the names for
 - 	 * this printer.
 - 	 */
 - 	pp->rp_matches_local = 1;
 - 	CHK((error = capdb_getaltstr(bp, "rp", "remote.queue", 0, &rp_name)));
 - 	if (error != PCAPERR_NOTFOUND && rp_name != NULL) {
 - 		if (cgetmatch(bp,rp_name) != 0)
 - 			pp->rp_matches_local = 0;
 - 		free(rp_name);
 - 	}
 - 
   	/*
   	 * Filters:
   	 */
 --- 262,267 ----
State-Changed-From-To: suspended->closed 
State-Changed-By: jkh 
State-Changed-When: Tue Apr 27 00:08:44 PDT 1999 
State-Changed-Why:  
Committed to both branches 
>Unformatted:
