int main(int argc, char **argv) { FILE *acctf; const char *cp, *printer; printer = NULL; 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: usage(); } } (void) enter(--cp); allflag = 0; } if (printer == NULL && (printer = getenv("PRINTER")) == NULL) printer = DEFLP; if (!chkprinter(printer)) { printf("pac: unknown printer %s\n", printer); exit(2); } if ((acctf = fopen(acctfile, "r")) == NULL) { perror(acctfile); exit(1); } account(acctf); fclose(acctf); if ((acctf = fopen(sumfile, "r")) != NULL) { account(acctf); fclose(acctf); } if (summarize) rewrite(); else dumpit(); exit(errs); }
int main(int argc, char *argv[]) { struct passwd *pw; struct group *gptr; const char *arg, *cp, *printer; char *p; char buf[BUFSIZ]; int c, i, f, errs; int ret, didlink; struct stat stb; struct stat statb1, statb2; struct printer myprinter, *pp = &myprinter; printer = NULL; euid = geteuid(); uid = getuid(); PRIV_END if (signal(SIGHUP, SIG_IGN) != SIG_IGN) signal(SIGHUP, cleanup); if (signal(SIGINT, SIG_IGN) != SIG_IGN) signal(SIGINT, cleanup); if (signal(SIGQUIT, SIG_IGN) != SIG_IGN) signal(SIGQUIT, cleanup); if (signal(SIGTERM, SIG_IGN) != SIG_IGN) signal(SIGTERM, cleanup); progname = argv[0]; gethostname(local_host, sizeof(local_host)); openlog("lpd", 0, LOG_LPR); errs = 0; while ((c = getopt(argc, argv, ":#:1:2:3:4:C:J:L:P:T:U:Z:cdfghi:lnmprstvw:")) != -1) switch (c) { case '#': /* n copies */ i = strtol(optarg, &p, 10); if (*p) errx(1, "Bad argument to -#, number expected"); if (i > 0) ncopies = i; break; case '1': /* troff fonts */ case '2': case '3': case '4': fonts[optopt - '1'] = optarg; break; case 'C': /* classification spec */ hdr++; class = optarg; break; case 'J': /* job name */ hdr++; jobname = optarg; break; case 'P': /* specifiy printer name */ printer = optarg; break; case 'L': /* pr's locale */ locale = optarg; break; case 'T': /* pr's title line */ title = optarg; break; case 'U': /* user name */ hdr++; Uflag = optarg; break; case 'Z': Zflag = optarg; break; case 'c': /* print cifplot output */ case 'd': /* print tex output (dvi files) */ case 'g': /* print graph(1G) output */ case 'l': /* literal output */ case 'n': /* print ditroff output */ case 't': /* print troff output (cat files) */ case 'p': /* print using ``pr'' */ case 'v': /* print vplot output */ format = optopt; break; case 'f': /* print fortran output */ format = 'r'; break; case 'h': /* nulifiy header page */ hdr = 0; break; case 'i': /* indent output */ iflag++; indent = strtol(optarg, &p, 10); if (*p) errx(1, "Bad argument to -i, number expected"); break; case 'm': /* send mail when done */ mailflg++; break; case 'q': /* just queue job */ qflag++; break; case 'r': /* remove file when done */ rflag++; break; case 's': /* try to link files */ sflag++; break; case 'w': /* versatec page width */ width = optarg; break; case ':': /* catch "missing argument" error */ if (optopt == 'i') { iflag++; /* -i without args is valid */ indent = 8; } else errs++; break; default: errs++; } argc -= optind; argv += optind; if (errs) usage(); if (printer == NULL && (printer = getenv("PRINTER")) == NULL) printer = DEFLP; chkprinter(printer, pp); if (pp->no_copies && ncopies > 1) errx(1, "multiple copies are not allowed"); if (pp->max_copies > 0 && ncopies > pp->max_copies) errx(1, "only %ld copies are allowed", pp->max_copies); /* * Get the identity of the person doing the lpr using the same * algorithm as lprm. Actually, not quite -- lprm will override * the login name with "root" if the user is running as root; * the daemon actually checks for the string "root" in its * permission checking. Sigh. */ userid = getuid(); if (Uflag) { if (userid != 0 && userid != pp->daemon_user) errx(1, "only privileged users may use the `-U' flag"); lpr_username = Uflag; /* -U person doing 'lpr' */ } else { lpr_username = getlogin(); /* person doing 'lpr' */ if (userid != pp->daemon_user || lpr_username == 0) { if ((pw = getpwuid(userid)) == NULL) errx(1, "Who are you?"); lpr_username = pw->pw_name; } } /* * Check for restricted group access. */ if (pp->restrict_grp != NULL && userid != pp->daemon_user) { if ((gptr = getgrnam(pp->restrict_grp)) == NULL) errx(1, "Restricted group specified incorrectly"); if (gptr->gr_gid != getgid()) { while (*gptr->gr_mem != NULL) { if ((strcmp(lpr_username, *gptr->gr_mem)) == 0) break; gptr->gr_mem++; } if (*gptr->gr_mem == NULL) errx(1, "Not a member of the restricted group"); } } /* * Check to make sure queuing is enabled if userid is not root. */ lock_file_name(pp, buf, sizeof buf); if (userid && stat(buf, &stb) == 0 && (stb.st_mode & LFM_QUEUE_DIS)) errx(1, "Printer queue is disabled"); /* * Initialize the control file. */ mktemps(pp); tfd = nfile(tfname); PRIV_START (void) fchown(tfd, pp->daemon_user, -1); /* owned by daemon for protection */ PRIV_END card('H', local_host); card('P', lpr_username); card('C', class); if (hdr && !pp->no_header) { if (jobname == NULL) { if (argc == 0) jobname = "stdin"; else jobname = ((arg = strrchr(argv[0], '/')) ? arg + 1 : argv[0]); } card('J', jobname); card('L', lpr_username); } if (format != 'p' && Zflag != 0) card('Z', Zflag); if (iflag) card('I', itoa(indent)); if (mailflg) card('M', lpr_username); if (format == 't' || format == 'n' || format == 'd') for (i = 0; i < 4; i++) if (fonts[i] != NULL) card('1'+i, fonts[i]); if (width != NULL) card('W', width); /* * XXX * Our use of `Z' here is incompatible with LPRng's * use. We assume that the only use of our existing * `Z' card is as shown for `p' format (pr) files. */ if (format == 'p') { char *s; if (locale) card('Z', locale); else if ((s = setlocale(LC_TIME, "")) != NULL) card('Z', s); } /* * Read the files and spool them. */ if (argc == 0) copy(pp, 0, " "); else while (argc--) { if (argv[0][0] == '-' && argv[0][1] == '\0') { /* use stdin */ copy(pp, 0, " "); argv++; continue; } if ((f = test(arg = *argv++)) < 0) continue; /* file unreasonable */ if (sflag && (cp = linked(arg)) != NULL) { (void)snprintf(buf, sizeof(buf), "%ju %ju", (uintmax_t)statb.st_dev, (uintmax_t)statb.st_ino); card('S', buf); if (format == 'p') card('T', title ? title : arg); for (i = 0; i < ncopies; i++) card(format, &dfname[inchar-2]); card('U', &dfname[inchar-2]); if (f) card('U', cp); card('N', arg); dfname[inchar]++; nact++; continue; } if (sflag) printf("%s: %s: not linked, copying instead\n", progname, arg); if (f) { /* * The user wants the file removed after it is copied * to the spool area, so see if the file can be moved * instead of copy/unlink'ed. This is much faster and * uses less spool space than copying the file. This * can be very significant when running services like * samba, pcnfs, CAP, et al. */ PRIV_START didlink = 0; /* * There are several things to check to avoid any * security issues. Some of these are redundant * under BSD's, but are necessary when lpr is built * under some other OS's (which I do do...) */ if (lstat(arg, &statb1) < 0) goto nohardlink; if (S_ISLNK(statb1.st_mode)) goto nohardlink; if (link(arg, dfname) != 0) goto nohardlink; didlink = 1; /* * Make sure the user hasn't tried to trick us via * any race conditions */ if (lstat(dfname, &statb2) < 0) goto nohardlink; if (statb1.st_dev != statb2.st_dev) goto nohardlink; if (statb1.st_ino != statb2.st_ino) goto nohardlink; /* * Skip if the file already had multiple hard links, * because changing the owner and access-bits would * change ALL versions of the file */ if (statb2.st_nlink > 2) goto nohardlink; /* * If we can access and remove the original file * without special setuid-ness then this method is * safe. Otherwise, abandon the move and fall back * to the (usual) copy method. */ PRIV_END ret = access(dfname, R_OK); if (ret == 0) ret = unlink(arg); PRIV_START if (ret != 0) goto nohardlink; /* * Unlink of user file was successful. Change the * owner and permissions, add entries to the control * file, and skip the file copying step. */ chown(dfname, pp->daemon_user, getegid()); chmod(dfname, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); PRIV_END if (format == 'p') card('T', title ? title : arg); for (i = 0; i < ncopies; i++) card(format, &dfname[inchar-2]); card('U', &dfname[inchar-2]); card('N', arg); nact++; continue; nohardlink: if (didlink) unlink(dfname); PRIV_END /* restore old uid */ } /* end: if (f) */ if ((i = open(arg, O_RDONLY)) < 0) { printf("%s: cannot open %s\n", progname, arg); } else { copy(pp, i, arg); (void) close(i); if (f && unlink(arg) < 0) printf("%s: %s: not removed\n", progname, arg); } } if (nact) { (void) close(tfd); tfname[inchar]--; /* * Touch the control file to fix position in the queue. */ PRIV_START if ((tfd = open(tfname, O_RDWR)) >= 0) { char touch_c; if (read(tfd, &touch_c, 1) == 1 && lseek(tfd, (off_t)0, 0) == 0 && write(tfd, &touch_c, 1) != 1) { printf("%s: cannot touch %s\n", progname, tfname); tfname[inchar]++; cleanup(0); } (void) close(tfd); } if (link(tfname, cfname) < 0) { printf("%s: cannot rename %s\n", progname, cfname); tfname[inchar]++; cleanup(0); } unlink(tfname); PRIV_END if (qflag) /* just q things up */ exit(0); if (!startdaemon(pp)) printf("jobs queued, but cannot start daemon.\n"); exit(0); } cleanup(0); return (1); /* NOTREACHED */ }
int main(int argc, char *argv[]) { struct passwd *pw; struct group *gptr; char *arg; const char *cp; char buf[MAXPATHLEN]; int i, f, errs, c; struct stat stb; int oerrno; euid = geteuid(); uid = getuid(); seteuid(uid); if (signal(SIGHUP, SIG_IGN) != SIG_IGN) signal(SIGHUP, cleanup); if (signal(SIGINT, SIG_IGN) != SIG_IGN) signal(SIGINT, cleanup); if (signal(SIGQUIT, SIG_IGN) != SIG_IGN) signal(SIGQUIT, cleanup); if (signal(SIGTERM, SIG_IGN) != SIG_IGN) signal(SIGTERM, cleanup); setprogname(*argv); gethostname(host, sizeof (host)); host[sizeof(host) - 1] = '\0'; openlog("lpd", 0, LOG_LPR); errs = 0; while ((c = getopt(argc, argv, ":#:1:2:3:4:C:J:P:RT:U:cdfghi:lmnopqrstvw:")) != -1) { switch (c) { case '#': /* n copies */ if (isdigit((unsigned char)*optarg)) { i = atoi(optarg); if (i > 0) ncopies = i; } break; case '4': /* troff fonts */ case '3': case '2': case '1': fonts[optopt - '1'] = optarg; break; case 'C': /* classification spec */ hdr++; class = optarg; break; case 'J': /* job name */ hdr++; jobname = optarg; break; case 'P': /* specifiy printer name */ printer = optarg; break; case 'R': /* print request id */ Rflag++; break; case 'T': /* pr's title line */ title = optarg; break; case 'U': /* user name */ hdr++; person = optarg; break; case 'c': /* print cifplot output */ case 'd': /* print tex output (dvi files) */ case 'g': /* print graph(1G) output */ case 'l': /* literal output */ case 'o': /* print postscript output */ case 'n': /* print ditroff output */ case 'p': /* print using ``pr'' */ case 't': /* print troff output (cat files) */ case 'v': /* print vplot output */ format = optopt; break; case 'f': /* print fortran output */ format = 'r'; break; case 'h': /* toggle want of header page */ hdr = !hdr; break; case 'i': /* indent output */ iflag++; indent = atoi(optarg); if (indent < 0) indent = 8; break; case 'm': /* send mail when done */ mailflg++; break; case 'q': /* just q job */ qflag++; break; case 'r': /* remove file when done */ rflag++; break; case 's': /* try to link files */ sflag++; break; case 'w': /* versatec page width */ width = optarg; break; case ':': /* catch "missing argument" error */ if (optopt == 'i') { iflag++; /* -i without args is valid */ indent = 8; } else errs++; break; default: errs++; } } argc -= optind; argv += optind; if (errs) usage(); if (printer == NULL && (printer = getenv("PRINTER")) == NULL) printer = DEFLP; chkprinter(printer); if (SC && ncopies > 1) errx(EXIT_FAILURE, "multiple copies are not allowed"); if (MC > 0 && ncopies > MC) errx(EXIT_FAILURE, "only %ld copies are allowed", MC); /* * Get the identity of the person doing the lpr using the same * algorithm as lprm. */ userid = getuid(); if (userid != DU || person == 0) { if ((pw = getpwuid(userid)) == NULL) errx(EXIT_FAILURE, "Who are you?"); person = pw->pw_name; } /* * Check for restricted group access. */ if (RG != NULL && userid != DU) { if ((gptr = getgrnam(RG)) == NULL) errx(EXIT_FAILURE, "Restricted group specified incorrectly"); if (gptr->gr_gid != getgid()) { while (*gptr->gr_mem != NULL) { if ((strcmp(person, *gptr->gr_mem)) == 0) break; gptr->gr_mem++; } if (*gptr->gr_mem == NULL) errx(EXIT_FAILURE, "Not a member of the restricted group"); } } /* * Check to make sure queuing is enabled if userid is not root. */ (void)snprintf(buf, sizeof buf, "%s/%s", SD, LO); if (userid && stat(buf, &stb) == 0 && (stb.st_mode & S_IXGRP)) errx(EXIT_FAILURE, "Printer queue is disabled"); /* * Initialize the control file. */ mktemps(); tfd = nfile(tfname); seteuid(euid); (void)fchown(tfd, DU, -1); /* owned by daemon for protection */ seteuid(uid); card('H', host); card('P', person); if (hdr && !SH) { if (jobname == NULL) { if (argc == 0) jobname = "stdin"; else jobname = (arg = strrchr(argv[0], '/')) ? arg+1 : argv[0]; } card('J', jobname); card('C', class); card('L', person); } if (iflag) card('I', itoa(indent)); if (mailflg) card('M', person); if (format == 't' || format == 'n' || format == 'd') for (i = 0; i < 4; i++) if (fonts[i] != NULL) card('1'+i, fonts[i]); if (width != NULL) card('W', width); /* * Read the files and spool them. */ if (argc == 0) copy(0, " "); else while (argc--) { if (argv[0][0] == '-' && argv[0][1] == '\0') { /* use stdin */ copy(0, " "); argv++; continue; } if ((f = test(arg = *argv++)) < 0) continue; /* file unreasonable */ if (sflag && (cp = linked(arg)) != NULL) { (void)snprintf(buf, sizeof buf, "%llu %llu", (unsigned long long)statb.st_dev, (unsigned long long)statb.st_ino); card('S', buf); if (format == 'p') card('T', title ? title : arg); for (i = 0; i < ncopies; i++) card(format, &dfname[inchar-2]); card('U', &dfname[inchar-2]); if (f) card('U', cp); card('N', arg); dfname[inchar]++; nact++; continue; } if (sflag) warnx("%s: not linked, copying instead", arg); seteuid(uid); if ((i = open(arg, O_RDONLY)) < 0) { oerrno = errno; seteuid(uid); errno = oerrno; warn("cannot open %s", arg); continue; } else { copy(i, arg); (void)close(i); if (f && unlink(arg) < 0) warn("%s: not removed", arg); } seteuid(uid); } if (nact) { (void)close(tfd); tfname[inchar]--; /* * Touch the control file to fix position in the queue. */ seteuid(euid); if ((tfd = open(tfname, O_RDWR)) >= 0) { char ch; if (read(tfd, &ch, 1) == 1 && lseek(tfd, (off_t)0, 0) == 0 && write(tfd, &ch, 1) != 1) { warn("cannot touch %s", tfname); tfname[inchar]++; cleanup(0); } (void)close(tfd); } if (link(tfname, cfname) < 0) { warn("cannot rename %s", cfname); tfname[inchar]++; cleanup(0); } unlink(tfname); seteuid(uid); if (Rflag) printf("request id is %d\n", reqid); if (qflag) /* just queue things up */ exit(0); if (!startdaemon(printer)) printf("jobs queued, but cannot start daemon.\n"); exit(0); } cleanup(0); #ifdef __GNUC__ return (0); #endif /* NOTREACHED */ }
int main(int argc, char **argv) { struct passwd *pw; struct group *gptr; char *arg, *cp; char buf[MAXPATHLEN]; int i, f, ch; struct stat stb; /* * Simulate setuid daemon w/ PRIV_END called. * We don't want lpr to actually be setuid daemon since that * requires that the lpr binary be owned by user daemon, which * is potentially unsafe. */ if ((pw = getpwuid(DEFUID)) == NULL) errx(1, "daemon uid (%u) not in password file", DEFUID); effective_uid = pw->pw_uid; real_uid = getuid(); effective_gid = pw->pw_gid; real_gid = getgid(); setresgid(real_gid, real_gid, effective_gid); setresuid(real_uid, real_uid, effective_uid); if (signal(SIGHUP, SIG_IGN) != SIG_IGN) signal(SIGHUP, cleanup); if (signal(SIGINT, SIG_IGN) != SIG_IGN) signal(SIGINT, cleanup); if (signal(SIGQUIT, SIG_IGN) != SIG_IGN) signal(SIGQUIT, cleanup); if (signal(SIGTERM, SIG_IGN) != SIG_IGN) signal(SIGTERM, cleanup); gethostname(host, sizeof (host)); openlog("lpr", 0, LOG_LPR); while ((ch = getopt(argc, argv, ":#:1:2:3:4:C:J:P:T:U:cdfghi:lmnpqrstvw:")) != -1) { switch (ch) { case '#': /* n copies */ if (isdigit((unsigned char)*optarg)) { i = atoi(optarg); if (i > 0) ncopies = i; } break; case '4': /* troff fonts */ case '3': case '2': case '1': fonts[ch - '1'] = optarg; break; case 'C': /* classification spec */ hdr++; class = optarg; break; case 'J': /* job name */ hdr++; jobname = optarg; break; case 'P': /* specifiy printer name */ printer = optarg; break; case 'T': /* pr's title line */ title = optarg; break; case 'U': /* user name */ hdr++; person = optarg; break; case 'c': /* print cifplot output */ case 'd': /* print tex output (dvi files) */ case 'g': /* print graph(1G) output */ case 'l': /* literal output */ case 'n': /* print ditroff output */ case 'p': /* print using ``pr'' */ case 't': /* print troff output (cat files) */ case 'v': /* print vplot output */ format = ch; break; case 'f': /* print fortran output */ format = 'r'; break; case 'h': /* toggle want of header page */ hdr = !hdr; break; case 'i': /* indent output */ iflag++; indent = atoi(optarg); if (indent < 0) indent = 8; break; case 'm': /* send mail when done */ mailflg++; break; case 'q': /* just q job */ qflag++; break; case 'r': /* remove file when done */ rflag++; break; case 's': /* try to link files */ sflag++; break; case 'w': /* versatec page width */ width = optarg; break; case ':': /* catch "missing argument" error */ if (optopt == 'i') { iflag++; /* -i without args is valid */ indent = 8; } else usage(); break; default: usage(); } } argc -= optind; argv += optind; if (printer == NULL && (printer = getenv("PRINTER")) == NULL) printer = DEFLP; chkprinter(printer); if (SC && ncopies > 1) errx(1, "multiple copies are not allowed"); if (MC > 0 && ncopies > MC) errx(1, "only %ld copies are allowed", MC); /* * Get the identity of the person doing the lpr using the same * algorithm as lprm. */ if (real_uid != DU || person == NULL) { if ((pw = getpwuid(real_uid)) == NULL) errx(1, "Who are you?"); if ((person = strdup(pw->pw_name)) == NULL) err(1, NULL); } /* * Check for restricted group access. */ if (RG != NULL && real_uid != DU) { if ((gptr = getgrnam(RG)) == NULL) errx(1, "Restricted group specified incorrectly"); if (gptr->gr_gid != getgid()) { while (*gptr->gr_mem != NULL) { if ((strcmp(person, *gptr->gr_mem)) == 0) break; gptr->gr_mem++; } if (*gptr->gr_mem == NULL) errx(1, "Not a member of the restricted group"); } } /* * Check to make sure queuing is enabled if real_uid is not root. */ (void)snprintf(buf, sizeof(buf), "%s/%s", SD, LO); if (real_uid && stat(buf, &stb) == 0 && (stb.st_mode & 010)) errx(1, "Printer queue is disabled"); /* * Initialize the control file. */ mktemps(); tfd = nfile(tfname); card('H', host); card('P', person); if (hdr) { if (jobname == NULL) { if (argc == 0) jobname = "stdin"; else jobname = (arg = strrchr(argv[0], '/')) ? arg + 1 : argv[0]; } card('J', jobname); card('C', class); if (!SH) card('L', person); } if (iflag) card('I', itoa(indent)); if (mailflg) card('M', person); if (format == 't' || format == 'n' || format == 'd') for (i = 0; i < 4; i++) if (fonts[i] != NULL) card('1'+i, fonts[i]); if (width != NULL) card('W', width); /* * Read the files and spool them. */ if (argc == 0) copy(0, " "); else while (argc--) { if (argv[0][0] == '-' && argv[0][1] == '\0') { /* use stdin */ copy(0, " "); argv++; continue; } if ((f = test(arg = *argv++)) < 0) continue; /* file unreasonable */ if (sflag && (cp = linked(arg)) != NULL) { (void)snprintf(buf, sizeof(buf), "%d %llu", statb.st_dev, (unsigned long long)statb.st_ino); card('S', buf); if (format == 'p') card('T', title ? title : arg); for (i = 0; i < ncopies; i++) card(format, &dfname[inchar-2]); card('U', &dfname[inchar-2]); if (f) card('U', cp); card('N', arg); dfname[inchar]++; nact++; continue; } if (sflag) warnx("%s: not linked, copying instead", arg); if ((i = safe_open(arg, O_RDONLY, 0)) < 0) warn("%s", arg); else { copy(i, arg); (void)close(i); if (f && unlink(arg) < 0) warnx("%s: not removed", arg); } } if (nact) { (void)close(tfd); tfname[inchar]--; /* * Touch the control file to fix position in the queue. */ PRIV_START; if ((tfd = safe_open(tfname, O_RDWR|O_NOFOLLOW, 0)) >= 0) { char c; if (read(tfd, &c, 1) == 1 && lseek(tfd, (off_t)0, SEEK_SET) == 0 && write(tfd, &c, 1) != 1) { warn("%s", tfname); tfname[inchar]++; cleanup(0); } (void)close(tfd); } if (link(tfname, cfname) < 0) { warn("cannot rename %s", cfname); tfname[inchar]++; cleanup(0); } unlink(tfname); PRIV_END; if (qflag) /* just q things up */ exit(0); if (!startdaemon(printer)) printf("jobs queued, but cannot start daemon.\n"); exit(0); } cleanup(0); return (1); /* NOTREACHED */ }
int main(int argc, char **argv) { FILE *acct; int ch; /* these aren't actually used in pac(1) */ effective_uid = geteuid(); real_uid = getuid(); effective_gid = getegid(); real_gid = getgid(); 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 */ } } 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 && (printer = getenv("PRINTER")) == NULL) printer = DEFLP; if (!chkprinter(printer)) errx(2, "unknown printer: %s", printer); if ((acct = fopen(acctfile, "r")) == NULL) err(1, "%s", acctfile); account(acct); fclose(acct); if ((acct = fopen(sumfile, "r")) != NULL) { account(acct); fclose(acct); } if (summarize) rewrite(); else dumpit(); exit(errs); }
int pickfilter(RSTATUS *prs, CANDIDATE *pc, FSTATUS *pfs) { register char ** pp; register char ** pl; register PSTATUS * pps = pc->pps; char * pipes[2] = { 0 , 0 }; char * cp; char * output_type; char ** modes = 0; char ** parms = 0; char ** valid_printer_types; char ** p_cpi = 0; char ** p_lpi = 0; char ** p_pwid = 0; char ** p_plen = 0; FILTERTYPE ret = fl_none; int got_cpi = 0; int got_lpi = 0; int got_plen = 0; int got_pwid = 0; int must_have_filter= 0; unsigned long chk; /* fix for bugid 1097387 */ output_type = (char *) NULL; /* * The bulk of the code below is building a parameter list "parms" * to send to "insfilter()". */ if (prs->request->modes) { cp = Strdup(prs->request->modes); transform_WS_to_SEP(cp); modes = getlist(cp, "", LP_SEP); Free (cp); } pp = parms = (char **)Malloc( 2 * (NPARM_SPEC + lenlist(modes) + 1) * sizeof(char *) ); /* * Add to the parameter list the appropriate cpi/lpi/etc. * characteristics (aka ``stuff'') that will be used for * this job. The printer defaults are questionable. * Take this opportunity to also save the ``stuff'' in * the request structure. */ unload_str (&(prs->cpi)); unload_str (&(prs->lpi)); unload_str (&(prs->plen)); unload_str (&(prs->pwid)); /* * If a form is involved, pick up its page size and print * spacing requirements. */ if (pfs) { if (pfs->cpi) { *pp++ = PARM_CPI; *pp++ = prs->cpi = pfs->cpi; got_cpi = 1; } if (pfs->lpi) { *pp++ = PARM_LPI; *pp++ = prs->lpi = pfs->lpi; got_lpi = 1; } if (pfs->plen) { *pp++ = PARM_LENGTH; *pp++ = prs->plen = pfs->plen; got_plen = 1; } if (pfs->pwid) { *pp++ = PARM_WIDTH; *pp++ = prs->pwid = pfs->pwid; got_pwid = 1; } /* * If no form is involved, pick up whatever page size and print * spacing requirements were given by the user. */ } else { if (o_cpi) { *pp++ = PARM_CPI; *pp++ = prs->cpi = o_cpi; got_cpi = 1; } if (o_lpi) { *pp++ = PARM_LPI; *pp++ = prs->lpi = o_lpi; got_lpi = 1; } if (o_length) { *pp++ = PARM_LENGTH; *pp++ = prs->plen = o_length; got_plen = 1; } if (o_width) { *pp++ = PARM_WIDTH; *pp++ = prs->pwid = o_width; got_pwid = 1; } } /* * Pick up whatever page size and print spacing requirements * haven't been specified yet from the printer defaults. * * Note: The following cpi/lpi/etc are guaranteed to work * for at least one type of the printer at hand, but not * necessarily all types. Once we pick a type that works * we'll verify that the cpi/lpi/etc stuff works, too. * The code that does that assumes that we do the following last, * after picking up the form and/or user stuff. If this changes, * then the later code will have to be changed, too. */ if (!got_cpi && pps->cpi) { *pp++ = PARM_CPI; *(p_cpi = pp++) = prs->cpi = pps->cpi; } if (!got_lpi && pps->lpi) { *pp++ = PARM_LPI; *(p_lpi = pp++) = prs->lpi = pps->lpi; } if (!got_plen && pps->plen) { *pp++ = PARM_LENGTH; *(p_plen = pp++) = prs->plen = pps->plen; } if (!got_pwid && pps->pwid) { *pp++ = PARM_WIDTH; *(p_pwid = pp++) = prs->pwid = pps->pwid; } /* * Pick up the number of pages, character set (the form's * or the user's), the form name, the number of copies, * and the modes. */ if (prs->request->pages) { *pp++ = PARM_PAGES; *pp++ = prs->request->pages; must_have_filter = 1; } if (prs->request->charset) { *pp++ = PARM_CHARSET; *pp++ = prs->request->charset; } else if (pfs && pfs->form->chset) { *pp++ = PARM_CHARSET; *pp++ = pfs->form->chset; } if (prs->request->form) { *pp++ = PARM_FORM; *pp++ = prs->request->form; } if (prs->request->copies > 1) { *pp++ = PARM_COPIES; sprintf ((*pp++ = BIGGEST_NUMBER_S), "%d", prs->request->copies); } if (modes) { for (pl = modes; *pl; pl++) { *pp++ = PARM_MODES; *pp++ = *pl; } must_have_filter = 1; } *pp = 0; /* null terminated list! */ /* * If the printer type(s) are not ``unknown'', then include * them as possible ``output'' type(s) to match * with the user's input type (directly, or through a filter). */ if (!STREQU(*(pps->printer->printer_types), NAME_UNKNOWN)) valid_printer_types = pc->printer_types; else { valid_printer_types = 0; must_have_filter = 0; } pc->fast = 0; pc->slow = 0; pc->output_type = 0; pc->flags = 0; ret = fl_none; /* * If we don't really need a filter and the types match, * then that's good enough. Some ``broadly defined'' * filters might match our needs, but if the printer * can do what we need, then why pull in a filter? * Besides, Section 3.40 in the requirements imply * that we don't use a filter if the printer can handle * the file. */ if (!must_have_filter ) { if ( valid_printer_types && searchlist_with_terminfo( prs->request->input_type, valid_printer_types ) ) { ret = fl_both; /* not really, but ok */ pc->printer_type = Strdup(prs->request->input_type); } else if ( pps->printer->input_types && searchlist_with_terminfo( prs->request->input_type, pps->printer->input_types ) ) { ret = fl_both; /* not really, but ok */ /* * (1) There is one printer type, might even * be ``unknown''; * (2) There are several printer types, but that * means only one input type, ``simple'', * which any of the printer types can handle. */ pc->printer_type = Strdup(*(pc->printer_types)); } } /* * Don't try using a filter if the user doesn't want * a filter to be used! He or she would rather see an * error message than (heaven forbid!) a filter being * used. */ if (ret == fl_none && !(prs->request->actions & ACT_RAW)) { /* * For each printer type, and each input type the printer * accepts, see if we have a filter that matches the * request to the printer. Each time we try, save the * output type we use in case of success; we just might * need that value later.... */ for ( pl = valid_printer_types; pl && *pl && ret == fl_none; pl++ ) ret = insfilter( pipes, prs->request->input_type, (output_type = *pl), *pl, pps->printer->name, parms, &(pc->flags) ); if (ret != fl_none) pc->printer_type = Strdup(*pl); for ( pl = pps->printer->input_types; pl && *pl && ret == fl_none; pl++ ) /* * Don't waste time with check we've already made. */ if ((must_have_filter == 1) || !valid_printer_types || !searchlist(*pl, valid_printer_types) ) /* * Either we have one (or less) printer * types and many input types, or we have * one input type, ``simple''; regardless, * using the first printer type is OK. */ ret = insfilter( pipes, prs->request->input_type, (output_type = *pl), *(pc->printer_types), pps->printer->name, parms, &(pc->flags) ); if (ret != fl_none) pc->printer_type = Strdup(*(pc->printer_types)); } /* * If we were successful, check that the printer type * we picked can handle the PRINTER'S cpi/lpi/etc. defaults. * (We know that ALL the printer's types can handle the stuff * the user gave or the stuff in the form.) * Each printer's default that doesn't pass muster gets dropped. * This may mean re-instantiating the filter(s) (if any). */ if (ret != fl_none && (p_cpi || p_lpi || p_pwid || p_plen)) { #define NZ(X) ((X)? *(X) : (char *)0) chk = chkprinter( pc->printer_type, NZ(p_cpi), NZ(p_lpi), NZ(p_plen), NZ(p_pwid), (char *)0 ); if (chk) { register char ** _pp; char * hole = ""; /* * Remove the offending printer defaults from the * request list of cpi/lpi/etc. stuff, and punch * (non-null!) holes in the parameter list. */ #define DROP(P,R) if (P) {P[-1] = P[0] = hole; R = 0;} else/*EMPTY*/ if (chk & PCK_CPI) DROP (p_cpi, prs->cpi); if (chk & PCK_LPI) DROP (p_lpi, prs->lpi); if (chk & PCK_WIDTH) DROP (p_pwid, prs->pwid); if (chk & PCK_LENGTH) DROP (p_plen, prs->plen); /* * If there are filters, we have to re-instantiate * them. (Can't check "ret" here, because it may * be misleading.) */ if (pipes[0] || pipes[1]) { /* * First, close up the gaps we punched in * the parameter list. */ for (pp = _pp = parms; *pp; pp++) if (*pp != hole) *_pp++ = *pp; *_pp = 0; /* * Re-instantiate the filter(s). This * CAN'T fail, because it is not mandatory * that filters handle cpi/lpi/etc. stuff. */ ret = insfilter( pipes, prs->request->input_type, output_type, pc->printer_type, pps->printer->name, parms, &(pc->flags) ); } } } /* * Save the filters, if any. Note: although "ret" can be * misleading, i.e. set to "fl_both" when there really aren't * any filters, the declaration of "pipes" ensured they'd be * zero if not set. */ if (ret == fl_both || ret == fl_slow) pc->slow = pipes[0]; if (ret == fl_both || ret == fl_fast) pc->fast = pipes[1]; if (ret != fl_none) pc->output_type = Strdup (output_type); /* * Wait until now to allocate storage for the cpi/etc. * stuff, to make life easier above. */ if (prs->cpi) prs->cpi = Strdup(prs->cpi); if (prs->lpi) prs->lpi = Strdup(prs->lpi); if (prs->plen) prs->plen = Strdup(prs->plen); if (prs->pwid) prs->pwid = Strdup(prs->pwid); if (parms) Free ((char *)parms); if (modes) freelist (modes); return ((ret != fl_none)); }