Re: Changes to lpd to run if and of on remote printers

David Brownlee <[email protected]>
Newsgroups gmane.os.netbsd.devel.general
Message-ID <[email protected]>
On Thu, 29 Aug 2002, Greg A. Woods wrote:

> [ On Wednesday, August 28, 2002 at 15:38:44 (+0100), David Brownlee wrote: ]
> > Subject: Changes to lpd to run if and of on remote printers
> >
> > 	lpd has a '-r' option to run 'of' for remote printers, but it
> > 	doesn't actually pass the contents of any files through it.
> >
> > 	I've come up with a set of patches that handles this - does
> > 	anyone have any thought/objections/comments?
>
> It sounds like a good idea -- I've wanted to do something like this in
> the past myself, though in that case I ened up using a different host
> with a different print spooling implementation.

	This is an updated version that doesn't pass the control file
	through the filter (awarded myself 73 dork points and a clue by
	four to the head for that)...

-- 
		David/absolute          -- www.netbsd.org: No hype required --
diff (text/plain, 4.8 KB)
Index: lpd/printjob.c
===================================================================
RCS file: /cvsroot/basesrc/usr.sbin/lpr/lpd/printjob.c,v
retrieving revision 1.34
diff -u -B -r1.34 printjob.c
--- lpd/printjob.c	2002/07/14 15:28:00	1.34
+++ lpd/printjob.c	2002/08/29 14:47:22
@@ -117,6 +117,7 @@
 static char	pxlength[10] = "-y";	/* page length in pixels */
 static char	pxwidth[10] = "-x";	/* page width in pixels */
 static char	tempfile[] = "errsXXXXXX"; /* file name for filter output */
+static char	tempremote[] = "remoteXXXXXX"; /* file name for remote filter */
 static char	width[10] = "-w";	/* page width in static characters */
 
 static void	abortpr(int);
@@ -124,14 +125,15 @@
 static int	dofork(int);
 static int	dropit(int);
 static void	init(void);
+static void	setup_ofilter(int);
+static void	close_ofilter(void);
 static void	openpr(void);
 static void	opennet(char *);
 static void	opentty(void);
 static void	openrem(void);
 static int	print(int, char *);
 static int	printit(char *);
-static void	pstatus(const char *, ...)
-	__attribute__((__format__(__printf__, 1, 2)));
+static void	pstatus(const char *, ...);
 static char	response(void);
 static void	scan_out(int, char *, int);
 static char	*scnline(int, char *, int);
@@ -167,6 +169,7 @@
 	signal(SIGTERM, abortpr);
 
 	(void)mktemp(tempfile);		/* OK */
+	(void)mktemp(tempremote);	/* OK */
 
 	/*
 	 * uses short form file names
@@ -256,13 +259,8 @@
 		else if (i == REPRINT && ++errcnt < 5) {
 			/* try reprinting the job */
 			syslog(LOG_INFO, "restarting %s", printer);
-			if (ofilter > 0) {
-				kill(ofilter, SIGCONT);	/* to be sure */
-				(void)close(ofd);
-				while ((i = wait(NULL)) > 0 && i != ofilter)
-					;
-				ofilter = 0;
-			}
+			if (ofilter > 0)
+				close_ofilter();
 			(void)close(pfd);	/* close printer */
 			if (ftruncate(lfd, pidoff) < 0)
 				syslog(LOG_WARNING, "%s: %s: %m", printer, LO);
@@ -298,6 +296,7 @@
 				(void)write(ofd, TR, strlen(TR));
 		}
 		(void)unlink(tempfile);
+		(void)unlink(tempremote);
 		exit(0);
 	}
 	goto again;
@@ -854,7 +853,30 @@
 	struct stat stb;
 	char buf[BUFSIZ];
 	int sizerr, resp;
+	extern int rflag;
+
+	if (type == '\2' && rflag && (OF || IF)) {
+		int	save_pfd = pfd;
 
+		(void)unlink(tempremote);
+		pfd = open(tempremote, O_WRONLY|O_CREAT|O_TRUNC|O_EXCL, 0664);
+		if (pfd == -1) {
+			pfd = save_pfd;
+			return ERROR;
+		}
+		setup_ofilter(1);
+		switch (i = print('f', file)) {
+		case ERROR:
+		case REPRINT:
+		case FILTERERR:
+		case ACCESS:
+			return(i);
+		}
+		close_ofilter();
+		pfd = save_pfd;
+		file = tempremote;
+	}
+
 	if (lstat(file, &stb) < 0 || (f = open(file, O_RDONLY)) < 0)
 		return(ERROR);
 	/*
@@ -1164,6 +1187,7 @@
 			initgroups(pw->pw_name, pw->pw_gid);
 			setgid(pw->pw_gid);
 			setuid(DU);
+			signal(SIGCHLD, SIG_DFL);
 		}
 		return (pid);
 	}
@@ -1188,6 +1212,7 @@
 abortpr(int signo)
 {
 	(void)unlink(tempfile);
+	(void)unlink(tempremote);
 	kill(0, SIGINT);
 	if (ofilter > 0)
 		kill(ofilter, SIGCONT);
@@ -1276,34 +1301,19 @@
 	tof = (cgetcap(bp, "fo", ':') == NULL);
 }
 
-/*
- * Acquire line printer or remote connection.
- */
+/*      
+ * Setup output filter - called once for local printer, or (if -r given to lpd)
+ * once per file for remote printers
+ */     
 static void
-openpr(void)
+setup_ofilter(int check_rflag)
 {
-	int i, nofile;
-	char *cp;
 	extern int rflag;
-
-	if (!remote && *LP) {
-		if ((cp = strchr(LP, '@')))
-			opennet(cp);
-		else
-			opentty();
-	} else if (remote) {
-		openrem();
-	} else {
-		syslog(LOG_ERR, "%s: no line printer device or host name",
-			printer);
-		exit(1);
-	}
 
-	/*
-	 * Start up an output filter, if needed.
-	 */
-	if ((!remote || rflag) && OF) {
+	if (OF && (!remote || (check_rflag && rflag))) {
 		int p[2];
+		int i, nofile;
+		char *cp;
 
 		pipe(p);
 		if ((ofilter = dofork(DOABORT)) == 0) {	/* child */
@@ -1327,6 +1337,51 @@
 		ofd = pfd;
 		ofilter = 0;
 	}
+}
+
+/*
+ * Close the output filter and reset ofd back to the main pfd descriptor
+ */
+static void
+close_ofilter(void)
+{
+	int i;
+
+	if (ofilter) {
+		kill(ofilter, SIGCONT);	/* to be sure */
+		(void)close(ofd);
+		ofd = pfd;
+		while ((i = wait(NULL)) > 0 && i != ofilter)
+			;
+		ofilter = 0;
+	}
+}
+
+/*
+ * Acquire line printer or remote connection.
+ */
+static void
+openpr(void)
+{
+	char *cp;
+
+	if (!remote && *LP) {
+		if ((cp = strchr(LP, '@')))
+			opennet(cp);
+		else
+			opentty();
+	} else if (remote) {
+		openrem();
+	} else {
+		syslog(LOG_ERR, "%s: no line printer device or host name",
+			printer);
+		exit(1);
+	}
+
+	/*
+	 * Start up an output filter, if needed.
+	 */
+	setup_ofilter(0);
 }
 
 /*
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.