summaryrefslogtreecommitdiffstats
path: root/usr.sbin/lpr
diff options
context:
space:
mode:
Diffstat (limited to 'usr.sbin/lpr')
-rw-r--r--usr.sbin/lpr/common_source/common.c55
-rw-r--r--usr.sbin/lpr/common_source/displayq.c15
-rw-r--r--usr.sbin/lpr/common_source/lp.h2
-rw-r--r--usr.sbin/lpr/common_source/matchjobs.c19
-rw-r--r--usr.sbin/lpr/common_source/rmjob.c25
5 files changed, 79 insertions, 37 deletions
diff --git a/usr.sbin/lpr/common_source/common.c b/usr.sbin/lpr/common_source/common.c
index d2ffb6a..d28ac1f 100644
--- a/usr.sbin/lpr/common_source/common.c
+++ b/usr.sbin/lpr/common_source/common.c
@@ -50,6 +50,7 @@ __FBSDID("$FreeBSD$");
#include <sys/time.h>
#include <sys/types.h>
+#include <ctype.h>
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
@@ -73,6 +74,13 @@ extern uid_t uid, euid;
static int compar(const void *_p1, const void *_p2);
/*
+ * isdigit() takes a parameter of 'int', but expect values in the range
+ * of unsigned char. Define a wrapper which takes a value of type 'char',
+ * whether signed or unsigned, and ensure it ends up in the right range.
+ */
+#define isdigitch(Anychar) isdigit((u_char)(Anychar))
+
+/*
* Getline reads a line from the control file cfp, removes tabs, converts
* new-line to null and leaves it in line.
* Returns 0 at EOF or the number of characters read.
@@ -207,6 +215,53 @@ compar(const void *p1, const void *p2)
return (strcmp(qe1->job_cfname, qe2->job_cfname));
}
+/*
+ * A simple routine to determine the job number for a print job based on
+ * the name of its control file. The algorithm used here may look odd, but
+ * the main issue is that all parts of `lpd', `lpc', `lpq' & `lprm' must be
+ * using the same algorithm, whatever that algorithm may be. If the caller
+ * provides a non-null value for ''hostpp', then this returns a pointer to
+ * the start of the hostname (or IP address?) as found in the filename.
+ *
+ * Algorithm: The standard `cf' file has the job number start in position 4,
+ * but some implementations have that as an extra file-sequence letter, and
+ * start the job number in position 5. The job number is usually three bytes,
+ * but may be as many as five. Confusing matters still more, some Windows
+ * print servers will append an IP address to the job number, instead of
+ * the expected hostname. So, if the job number ends with a '.', then
+ * assume the correct jobnum value is the first three digits.
+ */
+int
+calc_jobnum(const char *cfname, const char **hostpp)
+{
+ int jnum;
+ const char *cp, *numstr, *hoststr;
+
+ numstr = cfname + 3;
+ if (!isdigitch(*numstr))
+ numstr++;
+ jnum = 0;
+ for (cp = numstr; (cp < numstr + 5) && isdigitch(*cp); cp++)
+ jnum = jnum * 10 + (*cp - '0');
+ hoststr = cp;
+
+ /*
+ * If the filename was built with an IP number instead of a hostname,
+ * then recalculate using only the first three digits found.
+ */
+ while(isdigitch(*cp))
+ cp++;
+ if (*cp == '.') {
+ jnum = 0;
+ for (cp = numstr; (cp < numstr + 3) && isdigitch(*cp); cp++)
+ jnum = jnum * 10 + (*cp - '0');
+ hoststr = cp;
+ }
+ if (hostpp != NULL)
+ *hostpp = hoststr;
+ return (jnum);
+}
+
/* sleep n milliseconds */
void
delay(int millisec)
diff --git a/usr.sbin/lpr/common_source/displayq.c b/usr.sbin/lpr/common_source/displayq.c
index cdac70c..6c03621 100644
--- a/usr.sbin/lpr/common_source/displayq.c
+++ b/usr.sbin/lpr/common_source/displayq.c
@@ -286,7 +286,7 @@ header(void)
void
inform(const struct printer *pp, char *cf)
{
- register int copycnt;
+ int copycnt, jnum;
char savedname[MAXPATHLEN+1];
FILE *cfp;
@@ -318,6 +318,7 @@ inform(const struct printer *pp, char *cf)
copycnt = 0;
file[0] = '\0';
savedname[0] = '\0';
+ jnum = calc_jobnum(cf, NULL);
while (getline(cfp)) {
switch (line[0]) {
case 'P': /* Was this file specified in the user's list? */
@@ -335,7 +336,7 @@ inform(const struct printer *pp, char *cf)
col = 0;
prank(rank);
blankfill(OWNCOL);
- printf("%-10s %-3d ", line+1, atoi(cf+3));
+ printf("%-10s %-3d ", line+1, jnum);
col += 16;
first = 1;
}
@@ -383,8 +384,9 @@ inform(const struct printer *pp, char *cf)
int
inlist(char *uname, char *cfile)
{
- register int *r, n;
- register char **u, *cp;
+ int *r, jnum;
+ char **u;
+ const char *cfhost;
if (users == 0 && requests == 0)
return(1);
@@ -397,10 +399,9 @@ inlist(char *uname, char *cfile)
/*
* Check the request list
*/
- for (n = 0, cp = cfile+3; isdigit(*cp); )
- n = n * 10 + (*cp++ - '0');
+ jnum = calc_jobnum(cfile, &cfhost);
for (r = requ; r < &requ[requests]; r++)
- if (*r == n && !strcmp(cp, from_host))
+ if (*r == jnum && !strcmp(cfhost, from_host))
return(1);
return(0);
}
diff --git a/usr.sbin/lpr/common_source/lp.h b/usr.sbin/lpr/common_source/lp.h
index fea03b9..891ed2f 100644
--- a/usr.sbin/lpr/common_source/lp.h
+++ b/usr.sbin/lpr/common_source/lp.h
@@ -259,6 +259,7 @@ __BEGIN_DECLS
struct dirent;
void blankfill(int _tocol);
+int calc_jobnum(const char *_cfname, const char **_hostpp);
char *checkremote(struct printer *_pp);
int chk(char *_file);
void closeallfds(int _start);
@@ -280,7 +281,6 @@ void init_printer(struct printer *_pp);
void init_request(struct request *_rp);
int inlist(char *_uname, char *_cfile);
int iscf(struct dirent *_d);
-int isowner(char *_owner, char *_file);
void ldump(const char *_nfile, const char *_datafile, int _copies);
void lastprinter(void);
int lockchk(struct printer *_pp, char *_slockf);
diff --git a/usr.sbin/lpr/common_source/matchjobs.c b/usr.sbin/lpr/common_source/matchjobs.c
index eeeb0d4..de572f8 100644
--- a/usr.sbin/lpr/common_source/matchjobs.c
+++ b/usr.sbin/lpr/common_source/matchjobs.c
@@ -401,7 +401,7 @@ static int
match_jobspec(struct jobqueue *jq, struct jobspec *jspec)
{
struct cjobinfo *cfinf;
- char *cp, *cf_numstr, *cf_hoststr;
+ const char *cf_hoststr;
int jnum, match;
#if DEBUG_SCANJS
@@ -418,22 +418,7 @@ match_jobspec(struct jobqueue *jq, struct jobspec *jspec)
if (jq->job_matched)
return (0);
- /*
- * The standard `cf' file has the job number start in position 4,
- * but some implementations have that as an extra file-sequence
- * letter, and start the job number in position 5. The job
- * number is usually three bytes, but may be as many as five.
- *
- * XXX - All this nonsense should really be handled in a single
- * place, like getq()...
- */
- cf_numstr = jq->job_cfname + 3;
- if (!isdigitch(*cf_numstr))
- cf_numstr++;
- jnum = 0;
- for (cp = cf_numstr; (cp < cf_numstr + 5) && isdigitch(*cp); cp++)
- jnum = jnum * 10 + (*cp - '0');
- cf_hoststr = cp;
+ jnum = calc_jobnum(jq->job_cfname, &cf_hoststr);
cfinf = NULL;
match = 0; /* assume the job will not match */
jspec->matcheduser = NULL;
diff --git a/usr.sbin/lpr/common_source/rmjob.c b/usr.sbin/lpr/common_source/rmjob.c
index 589117a..d6fd614 100644
--- a/usr.sbin/lpr/common_source/rmjob.c
+++ b/usr.sbin/lpr/common_source/rmjob.c
@@ -76,6 +76,7 @@ extern uid_t uid, euid; /* real and effective user id's */
static void alarmhandler(int _signo);
static void do_unlink(char *_file);
+static int isowner(char *_owner, char *_file, const char *_cfhost);
void
rmjob(const char *printer)
@@ -233,8 +234,9 @@ do_unlink(char *file)
int
chk(char *file)
{
- register int *r, n;
- register char **u, *cp;
+ int *r, jnum;
+ char **u;
+ const char *cfhost;
FILE *cfp;
/*
@@ -243,7 +245,8 @@ chk(char *file)
if (strlen(file) < 7 || file[0] != 'c' || file[1] != 'f')
return(0);
- if (all && (from_host == local_host || !strcmp(from_host, file+6)))
+ jnum = calc_jobnum(file, &cfhost);
+ if (all && (from_host == local_host || !strcmp(from_host, cfhost)))
return(1);
/*
@@ -262,20 +265,18 @@ chk(char *file)
return(0);
if (users == 0 && requests == 0)
- return(!strcmp(file, current) && isowner(line+1, file));
+ return(!strcmp(file, current) && isowner(line+1, file, cfhost));
/*
* Check the request list
*/
- for (n = 0, cp = file+3; isdigit(*cp); )
- n = n * 10 + (*cp++ - '0');
for (r = requ; r < &requ[requests]; r++)
- if (*r == n && isowner(line+1, file))
+ if (*r == jnum && isowner(line+1, file, cfhost))
return(1);
/*
* Check to see if it's in the user list
*/
for (u = user; u < &user[users]; u++)
- if (!strcmp(*u, line+1) && isowner(line+1, file))
+ if (!strcmp(*u, line+1) && isowner(line+1, file, cfhost))
return(1);
return(0);
}
@@ -286,13 +287,13 @@ chk(char *file)
* files sent from the remote machine to be removed.
* Normal users can only remove the file from where it was sent.
*/
-int
-isowner(char *owner, char *file)
+static int
+isowner(char *owner, char *file, const char *cfhost)
{
if (!strcmp(person, root) && (from_host == local_host ||
- !strcmp(from_host, file+6)))
+ !strcmp(from_host, cfhost)))
return (1);
- if (!strcmp(person, owner) && !strcmp(from_host, file+6))
+ if (!strcmp(person, owner) && !strcmp(from_host, cfhost))
return (1);
if (from_host != local_host)
printf("%s: ", local_host);
OpenPOWER on IntegriCloud