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
This commit is contained in:
Garance A Drosehn 2002-04-23 00:06:10 +00:00
parent 8a57f7e245
commit 98f6cc5401
4 changed files with 70 additions and 11 deletions

View File

@ -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 */

View File

@ -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");

View File

@ -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 @@ print(struct printer *pp, int format, char *file)
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:

View File

@ -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