summaryrefslogtreecommitdiffstats
path: root/usr.sbin/lpr
diff options
context:
space:
mode:
authorgad <gad@FreeBSD.org>2002-04-23 00:06:10 +0000
committergad <gad@FreeBSD.org>2002-04-23 00:06:10 +0000
commit45f3bdde744be43fd191ee929a8c5a7cec0b0856 (patch)
tree82ccb92a46cd5cb4524779c4ff8a1c2dd3cfaa9f /usr.sbin/lpr
parentc141c42f1c29ac0cccbf419c008c2829aaed2bdf (diff)
downloadFreeBSD-src-45f3bdde744be43fd191ee929a8c5a7cec0b0856.zip
FreeBSD-src-45f3bdde744be43fd191ee929a8c5a7cec0b0856.tar.gz
Implement new printcap option of "rc" aka "remote.resend_copies".
This is a boolean option, and if it is specified in a print queue for a remote host, it causes lpd to resend the data file for each copy the user requested on 'lpr -#n'. This is useful for network printers which accept lpd-style jobs, but which ignore the control file (and thus they ignore any request for multiple copies). PR: 25635 Reviewed by: short review on freebsd-audit MFC after: 6 days
Diffstat (limited to 'usr.sbin/lpr')
-rw-r--r--usr.sbin/lpr/common_source/lp.h1
-rw-r--r--usr.sbin/lpr/common_source/printcap.c1
-rw-r--r--usr.sbin/lpr/lpd/printjob.c59
-rw-r--r--usr.sbin/lpr/lpr/printcap.520
4 files changed, 70 insertions, 11 deletions
diff --git a/usr.sbin/lpr/common_source/lp.h b/usr.sbin/lpr/common_source/lp.h
index a2e0bff..6faaf4d 100644
--- a/usr.sbin/lpr/common_source/lp.h
+++ b/usr.sbin/lpr/common_source/lp.h
@@ -72,6 +72,7 @@ struct printer {
long page_width; /* PW: page width */
long page_pwidth; /* PX: page width in pixels */
long page_plength; /* PY: page length in pixels */
+ long resend_copies; /* RC: resend copies to remote host */
char *restrict_grp; /* RG: restricted group */
char *remote_host; /* RM: remote machine name */
char *remote_queue; /* RP: remote printer name */
diff --git a/usr.sbin/lpr/common_source/printcap.c b/usr.sbin/lpr/common_source/printcap.c
index d70c5b1..d949893 100644
--- a/usr.sbin/lpr/common_source/printcap.c
+++ b/usr.sbin/lpr/common_source/printcap.c
@@ -257,6 +257,7 @@ getprintcap_int(char *bp, struct printer *pp)
&pp->status_file));
CHK(capdb_getaltstr(bp, "tr", "job.trailer", 0, &pp->trailer));
+ pp->resend_copies = capdb_getaltlog(bp, "rc", "remote.resend_copies");
pp->restricted = capdb_getaltlog(bp, "rs", "daemon.restricted");
pp->short_banner = capdb_getaltlog(bp, "sb", "banner.short");
pp->no_copies = capdb_getaltlog(bp, "sc", "job.no_copies");
diff --git a/usr.sbin/lpr/lpd/printjob.c b/usr.sbin/lpr/lpd/printjob.c
index 3ac859e..59ccccb 100644
--- a/usr.sbin/lpr/lpd/printjob.c
+++ b/usr.sbin/lpr/lpd/printjob.c
@@ -146,7 +146,7 @@ static void scan_out(struct printer *_pp, int _scfd, char *_scsp,
int _dlm);
static char *scnline(int _key, char *_p, int _c);
static int sendfile(struct printer *_pp, int _type, char *_file,
- char _format);
+ char _format, int _copyreq);
static int sendit(struct printer *_pp, char *_file);
static void sendmail(struct printer *_pp, char *_userid, int _bombed);
static void setty(const struct printer *_pp);
@@ -868,7 +868,7 @@ start:
static int
sendit(struct printer *pp, char *file)
{
- register int i, err = OK;
+ int dfcopies, err, i;
char *cp, last[BUFSIZ];
/*
@@ -895,6 +895,7 @@ sendit(struct printer *pp, char *file)
/*
* pass 1
*/
+ err = OK;
while (getline(cfp)) {
again:
if (line[0] == 'S') {
@@ -925,11 +926,14 @@ sendit(struct printer *pp, char *file)
} else if (line[0] == 'I') {
strlcpy(indent+2, line + 1, sizeof(indent) - 2);
} else if (line[0] >= 'a' && line[0] <= 'z') {
+ dfcopies = 1;
strcpy(last, line);
- while ((i = getline(cfp)) != 0)
- if (strcmp(last, line))
+ while ((i = getline(cfp)) != 0) {
+ if (strcmp(last, line) != 0)
break;
- switch (sendfile(pp, '\3', last+1, *last)) {
+ dfcopies++;
+ }
+ switch (sendfile(pp, '\3', last+1, *last, dfcopies)) {
case OK:
if (i)
goto again;
@@ -945,7 +949,7 @@ sendit(struct printer *pp, char *file)
break;
}
}
- if (err == OK && sendfile(pp, '\2', file, '\0') > 0) {
+ if (err == OK && sendfile(pp, '\2', file, '\0', 1) > 0) {
(void) fclose(cfp);
return(REPRINT);
}
@@ -969,13 +973,13 @@ sendit(struct printer *pp, char *file)
* Return positive if we should try resending.
*/
static int
-sendfile(struct printer *pp, int type, char *file, char format)
+sendfile(struct printer *pp, int type, char *file, char format, int copyreq)
{
int i, amt;
struct stat stb;
char *av[15], *filtcmd;
char buf[BUFSIZ], opt_c[4], opt_h[4], opt_n[4];
- int filtstat, narg, resp, sfd, sfres, sizerr, statrc;
+ int copycnt, filtstat, narg, resp, sfd, sfres, sizerr, statrc;
statrc = lstat(file, &stb);
if (statrc < 0) {
@@ -1102,7 +1106,15 @@ sendfile(struct printer *pp, int type, char *file, char format)
lseek(sfd, 0, SEEK_SET);
}
- (void) sprintf(buf, "%c%qd %s\n", type, stb.st_size, file);
+ copycnt = 0;
+sendagain:
+ copycnt++;
+
+ if (copycnt < 2)
+ (void) sprintf(buf, "%c%qd %s\n", type, stb.st_size, file);
+ else
+ (void) sprintf(buf, "%c%qd %s_c%d\n", type, stb.st_size,
+ file, copycnt);
amt = strlen(buf);
for (i = 0; ; i++) {
if (write(pfd, buf, amt) != amt ||
@@ -1121,6 +1133,10 @@ sendfile(struct printer *pp, int type, char *file, char format)
}
if (i)
pstatus(pp, "sending to %s", pp->remote_host);
+ /*
+ * XXX - we should change trstat_init()/trstat_write() to include
+ * the copycnt in the statistics record it may write.
+ */
if (type == '\3')
trstat_init(pp, file, job_dfcnt);
for (i = 0; i < stb.st_size; i += BUFSIZ) {
@@ -1146,9 +1162,30 @@ sendfile(struct printer *pp, int type, char *file, char format)
sfres = REPRINT;
goto return_sfres;
}
- if (type == '\3')
+ if (type == '\3') {
trstat_write(pp, TR_SENDING, stb.st_size, logname,
- pp->remote_host, origin_host);
+ pp->remote_host, origin_host);
+ /*
+ * Usually we only need to send one copy of a datafile,
+ * because the control-file will simply print the same
+ * file multiple times. However, some printers ignore
+ * the control file, and simply print each data file as
+ * it arrives. For such "remote hosts", we need to
+ * transfer the same data file multiple times. Such a
+ * a host is indicated by adding 'rc' to the printcap
+ * entry.
+ * XXX - Right now this ONLY works for remote hosts which
+ * do ignore the name of the data file, because
+ * this sends the file multiple times with slight
+ * changes to the filename. To do this right would
+ * require that we also rewrite the control file
+ * to match those filenames.
+ */
+ if (pp->resend_copies && (copycnt < copyreq)) {
+ lseek(sfd, 0, SEEK_SET);
+ goto sendagain;
+ }
+ }
sfres = OK;
return_sfres:
diff --git a/usr.sbin/lpr/lpr/printcap.5 b/usr.sbin/lpr/lpr/printcap.5
index 0f42f67..eef7f3b 100644
--- a/usr.sbin/lpr/lpr/printcap.5
+++ b/usr.sbin/lpr/lpr/printcap.5
@@ -109,6 +109,7 @@ blocks), zero = unlimited
.It "pw num 132 page width (in characters)"
.It "px num 0 page width in pixels (horizontal)"
.It "py num 0 page length in pixels (vertical)"
+.It "rc bool false when sending to a remote host, resend copies (see below)"
.It "rf str" Ta Dv NULL Ta No "filter for printing"
.Tn FORTRAN
style text files
@@ -157,6 +158,7 @@ Each two-letter capability has a human-readable alternate name.
.It "pw page.width"
.It "px page.pwidth"
.It "py page.plength"
+.It "rc remote.resend_copies"
.It "rf filt.fortran"
.It "rg daemon.restrictgrp"
.It "rm remote.host"
@@ -325,6 +327,24 @@ will therefore happen before
.Xr pr 1
is executed rather than afterwards.
.Pp
+There are some models of network printers which accept jobs from
+.Xr lpd 8 , but they ignore the control file for a job and simply print
+each data file as it arrives at the printer.
+One side-effect of this behavior is that the printer will ignore any request
+for multiple copies as given with the
+.Fl #
+flag on the
+.Xr lpr 1 command.
+The
+.Cm rc
+entry will cause
+.Xr lpd 8 to resend each data file for each copy that the user
+originally requested.
+Note that the
+.Cm rc
+entry should only be specified on hosts which send jobs directly to
+the printer.
+.Pp
If
.Cm lp
is specified as
OpenPOWER on IntegriCloud