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]> |
lpd has a '-r' option to run 'of' for remote printers, but it doesn't actually pass the contents of any files through it. We have another application here that means we want to run 'if' in that same situation (-r passed). Complications: - lpd has to send the size of the file across before its contents, so to work the filter has to store the results to a temporary file. - Each file is sent separately so 'of' has to be run for each entry, rather than once for everything sent (assuming I've followed the logic correctly). I've come up with a set of patches that handles this - does anyone have any thought/objections/comments? -- David Brownlee/absolute [email protected]
diff
(text/plain, 4.6 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/28 14:38:07
@@ -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 (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);
/*
@@ -1188,6 +1211,7 @@
abortpr(int signo)
{
(void)unlink(tempfile);
+ (void)unlink(tempremote);
kill(0, SIGINT);
if (ofilter > 0)
kill(ofilter, SIGCONT);
@@ -1276,34 +1300,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 +1336,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);
}
/*