diff options
author | Todd C. Miller <millert@cvs.openbsd.org> | 2002-05-20 23:13:51 +0000 |
---|---|---|
committer | Todd C. Miller <millert@cvs.openbsd.org> | 2002-05-20 23:13:51 +0000 |
commit | b2a7fd194eceff2b87de78d7cec611dbe9852f58 (patch) | |
tree | 964c1ee0a29425901306badd36cf127d4a351291 /usr.sbin/lpr/pac/pac.c | |
parent | 1c6d6f81973745cbc85a424ec5f1931f07e8ebf7 (diff) |
Pull in useful bits from NetBSD and make our lp* easier to diff and
do some minor cleanup of my own:
o IPv6 support
o ANSI function headers
o use getopt()
o synce usage() with man pages
o passes -Wall on both 32bit and 64bit platforms
o add an option to set the max number of children lpd will fork off
o add an lpd option to bind to specific addresses instead of INADDR_ANY.
o allow user to specify how long to wait for a connection to remote servers
o more strlcpy() and snprintf() usage
o Use FOO_FILENO constants instead of hard-coding 0-2
o Add some keeps to man the page SYNOPSIS to avoid options being split
Diffstat (limited to 'usr.sbin/lpr/pac/pac.c')
-rw-r--r-- | usr.sbin/lpr/pac/pac.c | 285 |
1 files changed, 148 insertions, 137 deletions
diff --git a/usr.sbin/lpr/pac/pac.c b/usr.sbin/lpr/pac/pac.c index f355056a4e8..3da340f36cd 100644 --- a/usr.sbin/lpr/pac/pac.c +++ b/usr.sbin/lpr/pac/pac.c @@ -1,5 +1,5 @@ -/* $OpenBSD: pac.c,v 1.12 2002/02/16 21:28:04 millert Exp $ */ -/* $NetBSD: pac.c,v 1.7 1996/03/21 18:21:20 jtc Exp $ */ +/* $OpenBSD: pac.c,v 1.13 2002/05/20 23:13:50 millert Exp $ */ +/* $NetBSD: pac.c,v 1.14 2000/04/27 13:40:18 msaitoh Exp $ */ /* * Copyright (c) 1983, 1993 @@ -45,7 +45,7 @@ static const char copyright[] = #if 0 static const char sccsid[] = "@(#)pac.c 8.1 (Berkeley) 6/6/93"; #else -static const char rcsid[] = "$OpenBSD: pac.c,v 1.12 2002/02/16 21:28:04 millert Exp $"; +static const char rcsid[] = "$OpenBSD: pac.c,v 1.13 2002/05/20 23:13:50 millert Exp $"; #endif #endif /* not lint */ @@ -58,11 +58,16 @@ static const char rcsid[] = "$OpenBSD: pac.c,v 1.12 2002/02/16 21:28:04 millert #include <sys/param.h> +#include <ctype.h> #include <dirent.h> +#include <err.h> +#include <errno.h> #include <stdlib.h> #include <unistd.h> #include <stdio.h> +#include <stdlib.h> #include <string.h> + #include "lp.h" #include "lp.local.h" @@ -79,8 +84,6 @@ static int sort; /* Sort by cost */ static char *sumfile; /* summary file */ static int summarize; /* Compress accounting file */ -uid_t uid, euid; - volatile sig_atomic_t gotintr; /* @@ -101,97 +104,93 @@ struct hent { static struct hent *hashtab[HSHSIZE]; /* Hash table proper */ static void account(FILE *); -static int any(int, char []); -static int chkprinter(char *); +static int chkprinter(const char *); static void dumpit(void); -static int hash(char []); -static struct hent *enter(char []); -static struct hent *lookup(char []); +static int hash(const char *); +static struct hent *enter(const char *); +static struct hent *lookup(const char *); static int qucmp(const void *, const void *); static void rewrite(void); +__dead void usage(void); int -main(argc, argv) - int argc; - char **argv; +main(int argc, char **argv) { FILE *acct; - char *cp; + int ch; euid = geteuid(); /* these aren't used in pac(1) */ uid = getuid(); - while (--argc) { - cp = *++argv; - if (*cp++ == '-') { - switch(*cp++) { - case 'P': - /* - * Printer name. - */ - printer = cp; - continue; - - case 'p': - /* - * get the price. - */ - price = atof(cp); - pflag = 1; - continue; - - case 's': - /* - * Summarize and compress accounting file. - */ - summarize++; - continue; - - case 'c': - /* - * Sort by cost. - */ - sort++; - continue; - - case 'm': - /* - * disregard machine names for each user - */ - mflag = 1; - continue; - - case 'r': - /* - * Reverse sorting order. - */ - reverse++; - continue; - - default: -fprintf(stderr, - "usage: pac [-Pprinter] [-pprice] [-s] [-c] [-r] [-m] [user ...]\n"); - exit(1); - } + while ((ch = getopt(argc, argv, "P:p:scmr")) != -1) { + switch (ch) { + case 'P': + /* + * Printer name. + */ + printer = optarg; + continue; + + case 'p': + /* + * get the price. + */ + price = atof(optarg); + pflag = 1; + continue; + + case 's': + /* + * Summarize and compress accounting file. + */ + summarize++; + continue; + + case 'c': + /* + * Sort by cost. + */ + sort++; + continue; + + case 'm': + /* + * disregard machine names for each user + */ + mflag = 1; + continue; + + case 'r': + /* + * Reverse sorting order. + */ + reverse++; + continue; + + default: + usage(); + /* NOTREACHED */ } - (void) enter(--cp); + } + argc -= optind; + argv += optind; + + /* + * If there are any arguments left, they're names of users + * we want to print info for. In that case, put them in the hash + * table and unset allflag. + */ + for( ; argc > 0; argc--, argv++) { + (void)enter(*argv); allflag = 0; } - if (printer == NULL) { - char *p; + if (printer == NULL && (printer = getenv("PRINTER")) == NULL) printer = DEFLP; - if ((p = getenv("PRINTER")) != NULL) - printer = p; - } - if (!chkprinter(printer)) { - printf("pac: unknown printer %s\n", printer); - exit(2); - } + if (!chkprinter(printer)) + errx(2, "unknown printer: %s", printer); - if ((acct = fopen(acctfile, "r")) == NULL) { - perror(acctfile); - exit(1); - } + if ((acct = fopen(acctfile, "r")) == NULL) + err(1, "%s", acctfile); account(acct); fclose(acct); if ((acct = fopen(sumfile, "r")) != NULL) { @@ -211,33 +210,54 @@ fprintf(stderr, * is set, then just gather the facts on everyone. * Note that we must accomodate both the active and summary file * formats here. + * The Format of the accounting file is: + * feet_per_page [runs_count] [hostname:]username + * Some software relies on whitespace between runs_count and hostname:username + * being optional (such as Ghostscript's unix-lpr.sh). + * * Host names are ignored if the -m flag is present. */ static void -account(acct) - FILE *acct; +account(FILE *acct) { char linebuf[BUFSIZ]; double t; - char *cp, *cp2; + long l; + char *cp, *cp2, *ep; struct hent *hp; int ic; - while (fgets(linebuf, BUFSIZ, acct) != NULL) { + while (fgets(linebuf, sizeof(linebuf), acct) != NULL) { cp = linebuf; - while (any(*cp, " \t")) - cp++; - t = atof(cp); - while (any(*cp, ".0123456789")) + while (isspace(*cp)) cp++; - while (any(*cp, " \t")) + + /* get t, feet_per_page */ + errno = 0; + t = strtod(cp, &ep); + if (!isspace(*ep) || errno == ERANGE) + continue; + + /* get ic, runs_count (optional) */ + for (cp = ep + 1; isspace(*cp); ) cp++; - for (cp2 = cp; !any(*cp2, " \t\n"); cp2++) + l = strtol(cp, &ep, 10); + if (cp == ep) + l = 0; /* runs_count not specified */ + else if (l < 0 || l >= INT_MAX) + continue; + ic = (int)l; + + /* get [hostname:]username */ + for (cp = ep; isspace(*cp); cp++) + ; + for (cp2 = cp; *cp2 && !isspace(*cp2); cp2++) ; - ic = atoi(cp2); *cp2 = '\0'; - if (mflag && strchr(cp, ':')) - cp = strchr(cp, ':') + 1; + /* if -m was specified, don't use the hostname part */ + if (mflag && (cp2 = strchr(cp, ':')) != NULL) + cp = cp2 + 1; + hp = lookup(cp); if (hp == NULL) { if (!allflag) @@ -257,7 +277,7 @@ account(acct) * and print it all out. */ static void -dumpit() +dumpit(void) { struct hent **base; struct hent *hp, **ap; @@ -266,7 +286,9 @@ dumpit() hp = hashtab[0]; hno = 1; - base = (struct hent **) calloc(sizeof hp, hcount); + base = (struct hent **) malloc(hcount * sizeof(hp)); + if (base == NULL) + err(1, NULL); for (ap = base, c = hcount; c--; ap++) { while (hp == NULL) hp = hashtab[hno++]; @@ -295,14 +317,14 @@ dumpit() * Rewrite the summary file with the summary information we have accumulated. */ static void -rewrite() +rewrite(void) { struct hent *hp; int i; FILE *acctf; if ((acctf = fopen(sumfile, "w")) == NULL) { - perror(sumfile); + warn("%s", sumfile); errs++; return; } @@ -316,12 +338,12 @@ rewrite() } fflush(acctf); if (ferror(acctf)) { - perror(sumfile); + warn("%s", sumfile); errs++; } fclose(acctf); if ((acctf = fopen(acctfile, "w")) == NULL) - perror(acctfile); + warn("%s", acctfile); else fclose(acctf); } @@ -335,8 +357,7 @@ rewrite() */ static struct hent * -enter(name) - char name[]; +enter(const char *name) { struct hent *hp; int h; @@ -345,9 +366,12 @@ enter(name) return(hp); h = hash(name); hcount++; - hp = (struct hent *) calloc(sizeof *hp, 1); - hp->h_name = (char *) calloc(sizeof(char), strlen(name)+1); - strcpy(hp->h_name, name); + hp = (struct hent *) malloc(sizeof *hp); + if (hp == NULL) + err(1, NULL); + hp->h_name = strdup(name); + if (hp->h_name == NULL) + err(1, NULL); hp->h_feetpages = 0.0; hp->h_count = 0; hp->h_link = hashtab[h]; @@ -361,8 +385,7 @@ enter(name) */ static struct hent * -lookup(name) - char name[]; +lookup(const char *name) { int h; struct hent *hp; @@ -379,11 +402,10 @@ lookup(name) * the hash table to begin the search. */ static int -hash(name) - char name[]; +hash(const char *name) { int h; - char *cp; + const char *cp; for (cp = name, h = 0; *cp; h = (h << 2) + *cp++) ; @@ -391,30 +413,12 @@ hash(name) } /* - * Other stuff - */ -static int -any(ch, str) - int ch; - char str[]; -{ - int c = ch; - char *cp = str; - - while (*cp) - if (*cp++ == c) - return(1); - return(0); -} - -/* * The qsort comparison routine. * The comparison is ascii collating order * or by feet of typesetter film, according to sort. */ static int -qucmp(a, b) - const void *a, *b; +qucmp(const void *a, const void *b) { struct hent *h1, *h2; int r; @@ -433,8 +437,7 @@ qucmp(a, b) * Perform lookup for printer name or abbreviation -- */ static int -chkprinter(s) - char *s; +chkprinter(const char *s) { int stat; @@ -452,12 +455,20 @@ chkprinter(s) } if (!pflag && (cgetnum(bp, "pc", &price100) == 0)) price = price100/10000.0; - sumfile = (char *) calloc(sizeof(char), strlen(acctfile)+5); - if (sumfile == NULL) { - perror("pac"); - exit(1); - } - strcpy(sumfile, acctfile); - strcat(sumfile, "_sum"); + sumfile = (char *) malloc(strlen(acctfile) + 5); + if (sumfile == NULL) + err(1, "pac"); + strcpy(sumfile, acctfile); /* safe */ + strcat(sumfile, "_sum"); /* safe */ return(1); } + +__dead void +usage(void) +{ + extern char *__progname; + + fprintf(stderr, "usage: %s [-cmrs] [-Pprinter] [-pprice] [user ...]\n", + __progname); + exit(1); +} |