Add small section to PRINTJOB.C in /usr/src/usr.sbin/lpr/lpd to extract the source file name from the (LPD) control file and pass it to the input filter, along with another "identifying" parameter, at the end of the current/normal parameter string. The last two parameters below are what get added to the input filter parameter list: -w132 -l66 -i0 -n xxxx -h xxxx /var/account/lp.printacct -fn .cshrc This will allow remote LPD's to do special actions on print files based on their original source file name, and is really intended for use in an input filter so it can achieve specialization without having to use other, external, methods to derive meaningful identifying information about the file waiting for it on STDIN.
Slightly modifed PRINTJOB.C.DIFFS to insert new parameters in input filter list only when original filename is found in the control file.
Responsible Changed From-To: freebsd-bugs->gad One for the lpd maintainer.
*************** *** 780,785 **** --- 803,813 ---- av[n++] = "-h"; av[n++] = origin_host; av[n++] = pp->acct_file; + /* added 20 Feb, 21 Apr 2003 - JD */ + if ((strcmp(ofilename, " ") != 0)&&(strcmp(ofilename, "") != 0)) { + av[n++] = "-fn"; + av[n++] = ofilename; + } /* JD */ av[n] = 0; fo = pfd; if (of_pid > 0) { /* stop output filter */
Oops. I thought I had already replied to this PR. It is not a good idea to add one more parameter to the parameters given to the filters run by lpd. The problem is that "you" (the generic you) have no control over all the different filters that everyone else will write and use. Some filters will break if you add any new parameter to them. I know this, as I added one simple parameter at RPI only to find out that it broke the print queue for someone like the dean of engineering. We (RPI) have only three or four different filters that we run, and my simple change managed to break at least one of them. I was in a bit of hot water over that (well, for about 24 hours...), and I am not eager to repeat that by inflicting the same mistake on everyone who runs freebsd. A better way to do this kind of thing is with environment variables. That way it is very very unlikely that you'll break any existing script. I have some other ideas which pertain to what you're trying to do, but I haven't had the time to implement them all yet. -- Garance Alistair Drosehn = gad@gilead.netel.rpi.edu Senior Systems Programmer or gad@FreeBSD.org Rensselaer Polytechnic Institute; Troy, NY; USA
Patch to use environment variables instead of modifying the filter parameter list: *** printjob.c.orig Wed Apr 30 11:41:47 2003 --- printjob.c Wed Apr 30 11:41:52 2003 *************** *** 114,119 **** --- 114,122 ---- /* indentation size in static characters */ static char indent[10] = "-i0"; static char jobname[100]; /* job or file name */ + static char LPD_FILENAME[100]; /* name of (source) file to print - JD*/+ static char LPD_FILENAME_VAR[12] = "LPD_FILENAME"; /* new env var - JD */ + static long origfpos = 0L; /* original cfp file position - JD */ static char length[10] = "-l"; /* page length in lines */ static char logname[32]; /* user's login name */ static char pxlength[10] = "-y"; /* page length in pixels */ *************** *** 645,650 **** --- 648,678 ---- (void) close(fi); return (OK); } + + /* + * reset pointer to config file, parse cf for filename, + * reset pointer again to where it was before we got here + * + * JD 06 March 2003, 30 April 2003 + * + */ + origfpos = ftell(cfp); /* get previous file position */ + fseek(cfp, 0L, 0); /* set file position to beginning of file */ + strlcpy(LPD_FILENAME, "undefined", sizeof(LPD_FILENAME)); /* initialize variable */ + while (getline(cfp)) + switch (line[0]){ + case 'N': + if (line[1] != '\0') { + strlcpy(LPD_FILENAME, line + 1, sizeof(LPD_FILENAME)); + if (strncmp(LPD_FILENAME, " ", sizeof(LPD_FILENAME)) == 0) + strlcpy(LPD_FILENAME, "undefined", sizeof(LPD_FILENAME)); + } + continue; + default: continue; + } + fseek(cfp, origfpos, 0); /* reset file pointer */ + /*-------------------- JD */ + switch (format) { case 'p': /* print file using 'pr' */ if (pp->filters[LPF_INPUT] == NULL) { /* use output filter */ *************** *** 780,785 **** --- 808,822 ---- av[n++] = "-h"; av[n++] = origin_host; av[n++] = pp->acct_file; + /* added 20 Feb, 21 Apr 2003 - JD */ + unsetenv(LPD_FILENAME); errno = 0; + if (setenv(LPD_FILENAME_VAR, LPD_FILENAME, 1) < 0) { + if (errno == ENOMEM) + syslog(LOG_ERR, "Not enough memory to set LPD_FILENAME environment variable"); + else + syslog(LOG_ERR, "Unknown setenv error attempting to set LPD_FILENAME environment variable"); + } + /* JD */ av[n] = 0; fo = pfd; if (of_pid > 0) { /* stop output filter */
Attached is an updated patch for "printjob.c" which includes the same environment variable setting for a file to be sent to a remote printer, but processed by an input filter first using a printcap entry such as the following where "ps49...." is a print server similar to an HP Deskjet. djpsbw_duplex:\ :lf=/var/log/lpd-errs:mx#0:sh:\ :af=/var/account/lp.printacct:\ :if=/usr/libexec/lpr/a2psBWdupprt.sh:\ :rm=ps49cef5.localnet10:\ :rp=lpt1:sd=/var/spool/lpd/djpsbw_duplex:
Slight correction to setenv/unsetenv code and variables to 1) better follow example of setenv/unsetenv calls (with pointer variables) and 2) to fix a strange setenv/unsetenv call that produced a "LPD_FILENAME-s63" variable name. The code has been tested and verified in both FreeBSD-5.2.1 and FreeBSD-4.8. *** printjob.c.orig Wed Aug 20 22:43:48 2003 --- printjob.c Fri May 14 03:18:43 2004 *************** *** 119,124 **** --- 119,129 ---- /* indentation size in static characters */ static char indent[10] = "-i0"; static char jobname[100]; /* job or file name */ + static char LPD_FILENAME[100]; /* name of (source) file to print - JD*/ + static char *LPD_FILENAME_VALUE = LPD_FILENAME; + static char LPD_FILENAME_VARNAME[13] = "LPD_FILENAME\0";/* new env var - JD */ + static char *LPD_FILENAME_VAR = LPD_FILENAME_VARNAME; + static long origfpos = 0L; /* original cfp file position - JD */ static char length[10] = "-l"; /* page length in lines */ static char logname[32]; /* user's login name */ static char pxlength[10] = "-y"; /* page length in pixels */ *************** *** 385,390 **** --- 390,396 ---- bombed = OK; didignorehdr = 0; + /* * open control file; ignore if no longer there. */ *************** *** 444,450 **** */ /* pass 1 */ - while (getline(cfp)) switch (line[0]) { case 'H': --- 450,455 ---- *************** *** 650,655 **** --- 655,685 ---- (void) close(fi); return (OK); } + + /* + * reset pointer to config file, parse cf for filename, + * reset pointer again to where it was before we got here + * + * JD 06 March 2003, 30 April 2003 + * + */ + origfpos = ftell(cfp); /* get previous file position */ + fseek(cfp, 0L, 0); /* set file position to beginning of file */ + strlcpy(LPD_FILENAME, "undefined", sizeof(LPD_FILENAME)); /* init var */ + while (getline(cfp)){ + switch (line[0]){ + case 'N': + if (line[1] != '\0') { + strlcpy(LPD_FILENAME, line + 1, sizeof(LPD_FILENAME)); + if (strncmp(LPD_FILENAME, " ", sizeof(LPD_FILENAME)) == 0) + strlcpy(LPD_FILENAME, "undefined", sizeof(LPD_FILENAME)); + } + continue; + default: continue; + }} + fseek(cfp, origfpos, 0); /* reset file pointer */ + /*-------------------- JD */ + switch (format) { case 'p': /* print file using 'pr' */ if (pp->filters[LPF_INPUT] == NULL) { /* use output filter */ *************** *** 785,790 **** --- 815,829 ---- av[n++] = "-h"; av[n++] = origin_host; av[n++] = pp->acct_file; + /* added 20 Feb 2003, 21 Apr 2003, May 13 2004 - JD */ + unsetenv(LPD_FILENAME_VAR); errno = 0; + if (setenv(LPD_FILENAME_VAR, LPD_FILENAME_VALUE, 1) != 0) { + if (errno == ENOMEM) + syslog(LOG_ERR, "Not enough memory to set LPD_FILENAME environment variable"); + else + syslog(LOG_ERR, "Unknown setenv error attempting to set LPD_FILENAME environment variable"); + } + /* JD */ av[n] = 0; fo = pfd; if (of_pid > 0) { /* stop output filter */ *************** *** 949,954 **** --- 988,1013 ---- break; dfcopies++; } + /* + JD - 22 Feb 2004: extract spool file name and + assign it to environment variable for later use + by (local) input filter + */ + origfpos = ftell(cfp); /* get previous file position */ + fseek(cfp, 0L, 0); /* set file position to beginning of file */ + strlcpy(LPD_FILENAME, "undefined", sizeof(LPD_FILENAME)); /* initialize variable */ + while (getline(cfp)){ + switch (line[0]){ + case 'N': + if (line[1] != '\0') { + strlcpy(LPD_FILENAME, line + 1, sizeof(LPD_FILENAME)); + if (strncmp(LPD_FILENAME, " ", sizeof(LPD_FILENAME)) == 0) + strlcpy(LPD_FILENAME, "undefined", sizeof(LPD_FILENAME)); + } + continue; + default: continue; + }} + /* JD */ switch (sendfile(pp, '\3', last+1, *last, dfcopies)) { case OK: if (i) *************** *** 1065,1070 **** --- 1124,1138 ---- av[++narg] = origin_host; av[++narg] = pp->acct_file; av[++narg] = NULL; + /* added 21 Feb 2004, May 14 2004 - JD */ + unsetenv(LPD_FILENAME_VAR); errno = 0; + if (setenv(LPD_FILENAME_VAR, LPD_FILENAME_VALUE, 1) != 0) { + if (errno == ENOMEM) + syslog(LOG_ERR, "Not enough memory to set LPD_FILENAME environment variable"); + else + syslog(LOG_ERR, "Unknown setenv error attempting to set LPD_FILENAME environment variable"); + } + /* JD */ } else if (pp->filters[LPF_OUTPUT]) { filtcmd = pp->filters[LPF_OUTPUT]; av[0] = filtcmd;
Last, hopefully, change to LPD (printjob.c) to allow a user to use the lpr '-p -T ...' parameter sequence to "pass" a filename to LPD when printing a file which is being piped to LPD. For example, man strlcpy | lpr -p -T 'strlcpy.man' -P djpsbw_duplex will set the TITLE variable and the modified code will use that value when it determines that the FILENAME variable is empty/null, thus allowing remote LPD and/or input filter scripts to obtain either a real filename, or a pseudo filename for their use. Also - reduced size of extra variables as 100 characters would obviously not fit on one (8.5 x 11, portrait) print line. Where the output is printed in landscape, there may be more room for a longer filename, but 50 characters should be sufficient to properly identify the "source" file. Otherwise, more code would be needed to determine the best-fit-substring for printing orientation which might be difficult and/or clumsy to achieve. 50 characters should be good enough. *** printjob.c.orig Wed Aug 20 22:43:48 2003 --- printjob.c Sat May 22 03:22:59 2004 *************** *** 119,124 **** --- 119,130 ---- /* indentation size in static characters */ static char indent[10] = "-i0"; static char jobname[100]; /* job or file name */ + static char LPD_FILENAME[50] = "\0"; /* name of (source) file to print - JD*/ + static char *LPD_FILENAME_VALUE = LPD_FILENAME; + static char LPD_FILENAME_VARNAME[13] = "LPD_FILENAME\0";/* new env var - JD */ + static char *LPD_FILENAME_VAR = LPD_FILENAME_VARNAME; + static char LPD_PRTITLE[50] = "\0"; /* additional copy of pr TITLE - JD */ + static long origfpos = 0L; /* original cfp file position - JD */ static char length[10] = "-l"; /* page length in lines */ static char logname[32]; /* user's login name */ static char pxlength[10] = "-y"; /* page length in pixels */ *************** *** 650,655 **** --- 656,709 ---- (void) close(fi); return (OK); } + + /* + * Reset pointer to config file, parse cf for filename + * + * Also keep a secondary copy of Jobname and/or Title + * in case fileName is missing, in which case LPD_FILENAME + * will be set to (non-null) pr TITLE, if "-p -T ..." is + * included with lpr command when printing, say, + * a MANual page piped to LPR + * + * Reset pointer again to where it was before we got here + * + * JD 06 March 2003, 30 April 2003, 22 May 2004 + * + */ + origfpos = ftell(cfp); /* get previous file position */ + fseek(cfp, 0L, 0); /* set file position to beginning of file */ + strlcpy(LPD_FILENAME, "undefined\0", sizeof(LPD_FILENAME)); /* init var */ + strlcpy(LPD_PRTITLE, "\0", sizeof(LPD_PRTITLE)); + while (getline(cfp)){ + switch (line[0]){ + case 'N': + if (line[1] != '\0') { + strlcpy(LPD_FILENAME, line + 1, sizeof(LPD_FILENAME)); + if (strncmp(LPD_FILENAME, " ", sizeof(LPD_FILENAME)) == 0) + strlcpy(LPD_FILENAME, "undefined\0", sizeof(LPD_FILENAME)); + } + continue; + case 'T': + if (line[1] != '\0') { + strlcpy(LPD_PRTITLE, line + 1, sizeof(LPD_PRTITLE)); + } + continue; + default: continue; + }} + fseek(cfp, origfpos, 0); /* reset file pointer */ + /* + if no filename in cfg file, "steal" filename from pr TITLE + if it is non-null/empty + */ + if (strncmp(LPD_FILENAME, "undefined", sizeof(LPD_FILENAME)) == 0) { + if (LPD_PRTITLE[1] != '\0') { + strlcpy(LPD_FILENAME, LPD_PRTITLE, sizeof(LPD_FILENAME)); + strlcpy(LPD_PRTITLE, "\0", sizeof(LPD_PRTITLE)); + } + } + /*-------------------- JD */ + switch (format) { case 'p': /* print file using 'pr' */ if (pp->filters[LPF_INPUT] == NULL) { /* use output filter */ *************** *** 785,790 **** --- 839,853 ---- av[n++] = "-h"; av[n++] = origin_host; av[n++] = pp->acct_file; + /* added 20 Feb 2003, 21 Apr 2003, May 13 2004 - JD */ + unsetenv(LPD_FILENAME_VAR); errno = 0; + if (setenv(LPD_FILENAME_VAR, LPD_FILENAME_VALUE, 1) != 0) { + if (errno == ENOMEM) + syslog(LOG_ERR, "Not enough memory to set LPD_FILENAME environment variable"); + else + syslog(LOG_ERR, "Unknown setenv error attempting to set LPD_FILENAME environment variable"); + } + /* JD */ av[n] = 0; fo = pfd; if (of_pid > 0) { /* stop output filter */ *************** *** 949,954 **** --- 1012,1065 ---- break; dfcopies++; } + + /* + * Reset pointer to config file, parse cf for filename + * + * Also keep a secondary copy of Jobname and/or Title + * in case fileName is missing, in which case LPD_FILENAME + * will be set to (non-null) pr TITLE, if "-p -T ..." is + * included with lpr command when printing, say, + * a MANual page piped to LPR + * + * Reset pointer again to where it was before we got here + * + * JD 06 March 2003, 30 April 2003, 22 May 2004 + * + */ + origfpos = ftell(cfp); /* get previous file position */ + fseek(cfp, 0L, 0); /* set file position to beginning of file */ + strlcpy(LPD_FILENAME, "undefined\0", sizeof(LPD_FILENAME)); /* init var */ + strlcpy(LPD_PRTITLE, "\0", sizeof(LPD_PRTITLE)); + while (getline(cfp)){ + switch (line[0]){ + case 'N': + if (line[1] != '\0') { + strlcpy(LPD_FILENAME, line + 1, sizeof(LPD_FILENAME)); + if (strncmp(LPD_FILENAME, " ", sizeof(LPD_FILENAME)) == 0) + strlcpy(LPD_FILENAME, "undefined\0", sizeof(LPD_FILENAME)); + } + continue; + case 'T': + if (line[1] != '\0') { + strlcpy(LPD_PRTITLE, line + 1, sizeof(LPD_PRTITLE)); + } + continue; + default: continue; + }} + fseek(cfp, origfpos, 0); /* reset file pointer */ + /* + if no filename in cfg file, "steal" filename from 'pr' TITLE + if it is non-null/empty + */ + if (strncmp(LPD_FILENAME, "undefined", sizeof(LPD_FILENAME)) == 0) { + if (LPD_PRTITLE[1] != '\0') { + strlcpy(LPD_FILENAME, LPD_PRTITLE, sizeof(LPD_FILENAME)); + strlcpy(LPD_PRTITLE, "\0", sizeof(LPD_PRTITLE)); + } + } + /*-------------------- JD */ + switch (sendfile(pp, '\3', last+1, *last, dfcopies)) { case OK: if (i) *************** *** 1065,1070 **** --- 1176,1190 ---- av[++narg] = origin_host; av[++narg] = pp->acct_file; av[++narg] = NULL; + /* added 21 Feb 2004, May 14 2004 - JD */ + unsetenv(LPD_FILENAME_VAR); errno = 0; + if (setenv(LPD_FILENAME_VAR, LPD_FILENAME_VALUE, 1) != 0) { + if (errno == ENOMEM) + syslog(LOG_ERR, "Not enough memory to set LPD_FILENAME environment variable"); + else + syslog(LOG_ERR, "Unknown setenv error attempting to set LPD_FILENAME environment variable"); + } + /* JD */ } else if (pp->filters[LPF_OUTPUT]) { filtcmd = pp->filters[LPF_OUTPUT]; av[0] = filtcmd;
I just thought I would note that I do plan to get back to this PR, as soon as I catch up with a few other side-projects that I am in the middle of... Sorry for the delays! -- Garance Alistair Drosehn = gad@gilead.netel.rpi.edu Senior Systems Programmer or gad@FreeBSD.org Rensselaer Polytechnic Institute; Troy, NY; USA
State Changed From-To: open->analyzed Mark as 'analyzed' because it has been at least looked at.
batch change: For bugs that match the following - Status Is In progress AND - Untouched since 2018-01-01. AND - Affects Base System OR Documentation DO: Reset to open status. Note: I did a quick pass but if you are getting this email it might be worthwhile to double check to see if this bug ought to be closed.
Keyword: patch or patch-ready – in lieu of summary line prefix: [patch] * bulk change for the keyword * summary lines may be edited manually (not in bulk). Keyword descriptions and search interface: <https://bugs.freebsd.org/bugzilla/describekeywords.cgi>