diff options
-rw-r--r-- | usr.sbin/lpr/common_source/common.c | 55 | ||||
-rw-r--r-- | usr.sbin/lpr/common_source/displayq.c | 15 | ||||
-rw-r--r-- | usr.sbin/lpr/common_source/lp.h | 2 | ||||
-rw-r--r-- | usr.sbin/lpr/common_source/matchjobs.c | 19 | ||||
-rw-r--r-- | usr.sbin/lpr/common_source/rmjob.c | 25 |
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); |