Exemple #1
0
/*
 * Routine to get the information for a single printer (which will be
 * called by the routines which implement individual commands).
 * Note: This is for commands operating on a *single* printer.
 */
struct printer *
setup_myprinter(char *pwanted, struct printer *pp, int sump_opts)
{
	int cdres, cmdstatus;

	init_printer(pp);
	cmdstatus = getprintcap(pwanted, pp);
	switch (cmdstatus) {
	default:
		fatal(pp, "%s", pcaperr(cmdstatus));
		/* NOTREACHED */
	case PCAPERR_NOTFOUND:
		printf("unknown printer %s\n", pwanted);
		return (NULL);
	case PCAPERR_TCOPEN:
		printf("warning: %s: unresolved tc= reference(s)", pwanted);
		break;
	case PCAPERR_SUCCESS:
		break;
	}
	if ((sump_opts & SUMP_NOHEADER) == 0)
		printf("%s:\n", pp->printer);

	if (sump_opts & SUMP_CHDIR_SD) {
		PRIV_START
		cdres = chdir(pp->spool_dir);
		PRIV_END
		if (cdres < 0) {
			printf("\tcannot chdir to %s\n", pp->spool_dir);
			free_printer(pp);
			return (NULL);
		}
	}
Exemple #2
0
/*
 * Perform lookup for printer name or abbreviation --
 */
static int
chkprinter(const char *ptrname)
{
	int stat;
	struct printer myprinter, *pp = &myprinter;

	init_printer(&myprinter);
	stat = getprintcap(ptrname, pp);
	switch(stat) {
	case PCAPERR_OSERR:
		printf("pac: getprintcap: %s\n", pcaperr(stat));
		exit(3);
	case PCAPERR_NOTFOUND:
		return 0;
	case PCAPERR_TCLOOP:
		fatal(pp, "%s", pcaperr(stat));
	}
	if ((acctfile = pp->acct_file) == NULL)
		errx(3, "accounting not enabled for printer %s", ptrname);
	if (!pflag && pp->price100)
		price = pp->price100/10000.0;
	sumfile = (char *) calloc(sizeof(char), strlen(acctfile)+5);
	if (sumfile == NULL)
		errx(1, "calloc failed");
	strcpy(sumfile, acctfile);
	strcat(sumfile, "_sum");
	return(1);
}
Exemple #3
0
/*
 * Perform lookup for printer name or abbreviation --
 */
static void
chkprinter(const char *s)
{
	char *cp;

	getprintcap(s);
	RG = cgetstr(bp, "rg", &cp) == -1 ? NULL : cp;
	if (cgetnum(bp, "mx", &MX) < 0)
		MX = DEFMX;
	if (cgetnum(bp,"mc", &MC) < 0)
		MC = DEFMAXCOPIES;
	if (cgetnum(bp, "du", &DU) < 0)
		DU = DEFUID;
	SC = (cgetcap(bp, "sc", ':') != NULL);
}
Exemple #4
0
/*
 * Perform lookup for printer name or abbreviation --
 */
static void
chkprinter(const char *ptrname, struct printer *pp)
{
	int status;

	init_printer(pp);
	status = getprintcap(ptrname, pp);
	switch(status) {
	case PCAPERR_OSERR:
	case PCAPERR_TCLOOP:
		errx(1, "%s: %s", ptrname, pcaperr(status));
	case PCAPERR_NOTFOUND:
		errx(1, "%s: unknown printer", ptrname);
	case PCAPERR_TCOPEN:
		warnx("%s: unresolved tc= reference(s)", ptrname);
	}
}
Exemple #5
0
void
rmjob(const char *printer)
{
	register int i, nitems;
	int assassinated = 0;
	struct dirent **files;
	char *cp;
	struct printer myprinter, *pp = &myprinter;

	init_printer(pp);
	if ((i = getprintcap(printer, pp)) < 0)
		fatal(pp, "getprintcap: %s", pcaperr(i));
	if ((cp = checkremote(pp))) {
		printf("Warning: %s\n", cp);
		free(cp);
	}

	/*
	 * If the format was `lprm -' and the user isn't the super-user,
	 *  then fake things to look like he said `lprm user'.
	 */
	if (users < 0) {
		if (getuid() == 0)
			all = 1;	/* all files in local queue */
		else {
			user[0] = person;
			users = 1;
		}
	}
	if (!strcmp(person, "-all")) {
		if (from_host == local_host)
			fatal(pp, "The login name \"-all\" is reserved");
		all = 1;	/* all those from 'from_host' */
		person = root;
	}

	seteuid(euid);
	if (chdir(pp->spool_dir) < 0)
		fatal(pp, "cannot chdir to spool directory");
	if ((nitems = scandir(".", &files, iscf, NULL)) < 0)
		fatal(pp, "cannot access spool directory");
	seteuid(uid);

	if (nitems) {
		/*
		 * Check for an active printer daemon (in which case we
		 *  kill it if it is reading our file) then remove stuff
		 *  (after which we have to restart the daemon).
		 */
		if (lockchk(pp, pp->lock_file) && chk(current)) {
			seteuid(euid);
			assassinated = kill(cur_daemon, SIGINT) == 0;
			seteuid(uid);
			if (!assassinated)
				fatal(pp, "cannot kill printer daemon");
		}
		/*
		 * process the files
		 */
		for (i = 0; i < nitems; i++)
			process(pp, files[i]->d_name);
	}
	rmremote(pp);
	/*
	 * Restart the printer daemon if it was killed
	 */
	if (assassinated && !startdaemon(pp))
		fatal(pp, "cannot restart printer daemon\n");
	exit(0);
}
Exemple #6
0
int
main(int argc, char **argv)
{
	int ch, aflag, lflag;
	const char *printer;
	struct printer myprinter, *pp = &myprinter;

	printer = NULL;
	euid = geteuid();
	uid = getuid();
	seteuid(uid);
	progname = *argv;
	if (gethostname(local_host, sizeof(local_host)))
		err(1, "gethostname");
	openlog("lpd", 0, LOG_LPR);

	aflag = lflag = 0;
	while ((ch = getopt(argc, argv, "alP:")) != -1)
		switch((char)ch) {
		case 'a':
			++aflag;
			break;
		case 'l':			/* long output */
			++lflag;
			break;
		case 'P':		/* printer name */
			printer = optarg;
			break;
		case '?':
		default:
			usage();
		}

	if (!aflag && printer == NULL && (printer = getenv("PRINTER")) == NULL)
		printer = DEFLP;

	for (argc -= optind, argv += optind; argc; --argc, ++argv)
		if (isdigit(argv[0][0])) {
			if (requests >= MAXREQUESTS)
				fatal(0, "too many requests");
			requ[requests++] = atoi(*argv);
		}
		else {
			if (users >= MAXUSERS)
				fatal(0, "too many users");
			user[users++] = *argv;
		}

	if (aflag) {
		int more, status;

		more = firstprinter(pp, &status);
		if (status)
			goto looperr;
		while (more) {
			if (ckqueue(pp) > 0) {
				printf("%s:\n", pp->printer);
				displayq(pp, lflag);
				printf("\n");
			}
			do {
				more = nextprinter(pp, &status);
looperr:
				switch (status) {
				case PCAPERR_TCOPEN:
					printf("warning: %s: unresolved "
					       "tc= reference(s) ",
					       pp->printer);
				case PCAPERR_SUCCESS:
					break;
				default:
					fatal(pp, "%s", pcaperr(status));
				}
			} while (more && status);
		}
	} else {
		int status;

		init_printer(pp);
		status = getprintcap(printer, pp);
		if (status < 0)
			fatal(pp, "%s", pcaperr(status));

		displayq(pp, lflag);
	}
	exit(0);
}
Exemple #7
0
void
generic(void (*specificrtn)(struct printer *_pp), int cmdopts,
    void (*initrtn)(int _argc, char *_argv[]), int argc, char *argv[])
{
	int cmdstatus, more, targc;
	struct printer myprinter, *pp;
	char **margv, **targv;

	if (argc == 1) {
		/*
		 * Usage needs a special case for 'down': The user must
		 * either include `-msg', or only the first parameter
		 * that they give will be processed as a printer name.
		 */
		printf("usage: %s  {all | printer ...}", argv[0]);
		if (strcmp(argv[0], "down") == 0) {
			printf(" -msg [<text> ...]\n");
			printf("   or: down  {all | printer} [<text> ...]");
		} else if (cmdopts & LPC_MSGOPT)
			printf(" [-msg <text> ...]");
		printf("\n");
		return;
	}

	/* The first argument is the command name. */
	generic_cmdname = *argv++;
	argc--;

	/*
	 * The initialization routine for a command might set a generic
	 * "wrapup" routine, which should be called after processing all
	 * the printers in the command.  This might print summary info.
	 *
	 * Note that the initialization routine may also parse (and
	 * nullify) some of the parameters given on the command, leaving
	 * only the parameters which have to do with printer names.
	 */
	pp = &myprinter;
	generic_wrapup = NULL;
	generic_qselect = QSEL_UNKNOWN;
	cmdstatus = 0;
	/* this just needs to be a distinct value of type 'char *' */
	if (generic_nullarg == NULL)
		generic_nullarg = strdup("");

	/*
	 * Some commands accept a -msg argument, which indicates that
	 * all remaining arguments should be combined into a string.
	 */
	generic_msg = NULL;
	if (cmdopts & LPC_MSGOPT) {
		targc = argc;
		targv = argv;
		for (; targc > 0; targc--, targv++) {
			if (strcmp(*targv, "-msg") == 0) {
				argc -= targc;
				generic_msg = args2line(targc - 1, targv + 1);
				break;
			}
		}
	}

	/* call initialization routine, if there is one for this cmd */
	if (initrtn != NULL) {
		generic_initerr = 0;
		(*initrtn)(argc, argv);
		if (generic_initerr)
			return;
		/*
		 * The initrtn may have null'ed out some of the parameters.
		 * Compact the parameter list to remove those nulls, and
		 * correct the arg-count.
		 */
		targc = argc;
		targv = argv;
		margv = argv;
		argc = 0;
		for (; targc > 0; targc--, targv++) {
			if (*targv != generic_nullarg) {
				if (targv != margv)
					*margv = *targv;
				margv++;
				argc++;
			}
		}
	}

	if (argc == 1 && strcmp(*argv, "all") == 0) {
		generic_qselect = QSEL_ALL;
		more = firstprinter(pp, &cmdstatus);
		if (cmdstatus)
			goto looperr;
		while (more) {
			(*specificrtn)(pp);
			do {
				more = nextprinter(pp, &cmdstatus);
looperr:
				switch (cmdstatus) {
				case PCAPERR_TCOPEN:
					printf("warning: %s: unresolved "
					       "tc= reference(s) ",
					       pp->printer);
				case PCAPERR_SUCCESS:
					break;
				default:
					fatal(pp, "%s", pcaperr(cmdstatus));
				}
			} while (more && cmdstatus);
		}
		goto wrapup;
	}

	generic_qselect = QSEL_BYNAME;		/* specifically-named ptrs */
	for (; argc > 0; argc--, argv++) {
		init_printer(pp);
		cmdstatus = getprintcap(*argv, pp);
		switch (cmdstatus) {
		default:
			fatal(pp, "%s", pcaperr(cmdstatus));
		case PCAPERR_NOTFOUND:
			printf("unknown printer %s\n", *argv);
			continue;
		case PCAPERR_TCOPEN:
			printf("warning: %s: unresolved tc= reference(s)\n",
			       *argv);
			break;
		case PCAPERR_SUCCESS:
			break;
		}
		(*specificrtn)(pp);
	}

wrapup:
	if (generic_wrapup) {
		(*generic_wrapup)(cmdstatus);
	}
	free_printer(pp);
	if (generic_msg)
		free(generic_msg);
}
Exemple #8
0
static void
doit(void)
{
	char *cp, *printer;
	int n;
	int status;
	struct printer myprinter, *pp = &myprinter;

	init_printer(&myprinter);

	for (;;) {
		cp = cbuf;
		do {
			if (cp >= &cbuf[sizeof(cbuf) - 1])
				fatal(0, "Command line too long");
			if ((n = read(STDOUT_FILENO, cp, 1)) != 1) {
				if (n < 0)
					fatal(0, "Lost connection");
				return;
			}
		} while (*cp++ != '\n');
		*--cp = '\0';
		cp = cbuf;
		if (lflag) {
			if (*cp >= '\1' && *cp <= '\5')
				syslog(LOG_INFO, "%s requests %s %s",
					from_host, cmdnames[(u_char)*cp], cp+1);
			else
				syslog(LOG_INFO, "bad request (%d) from %s",
					*cp, from_host);
		}
		switch (*cp++) {
		case CMD_CHECK_QUE: /* check the queue, print any jobs there */
			startprinting(cp);
			break;
		case CMD_TAKE_THIS: /* receive files to be queued */
			if (!from_remote) {
				syslog(LOG_INFO, "illegal request (%d)", *cp);
				exit(1);
			}
			recvjob(cp);
			break;
		case CMD_SHOWQ_SHORT: /* display the queue (short form) */
		case CMD_SHOWQ_LONG: /* display the queue (long form) */
			/* XXX - this all needs to be redone. */
			printer = cp;
			while (*cp) {
				if (*cp != ' ') {
					cp++;
					continue;
				}
				*cp++ = '\0';
				while (isspace(*cp))
					cp++;
				if (*cp == '\0')
					break;
				if (isdigit(*cp)) {
					if (requests >= MAXREQUESTS)
						fatal(0, "Too many requests");
					requ[requests++] = atoi(cp);
				} else {
					if (users >= MAXUSERS)
						fatal(0, "Too many users");
					user[users++] = cp;
				}
			}
			status = getprintcap(printer, pp);
			if (status < 0)
				fatal(pp, "%s", pcaperr(status));
			displayq(pp, cbuf[0] == CMD_SHOWQ_LONG);
			exit(0);
		case CMD_RMJOB:	/* remove a job from the queue */
			if (!from_remote) {
				syslog(LOG_INFO, "illegal request (%d)", *cp);
				exit(1);
			}
			printer = cp;
			while (*cp && *cp != ' ')
				cp++;
			if (!*cp)
				break;
			*cp++ = '\0';
			person = cp;
			while (*cp) {
				if (*cp != ' ') {
					cp++;
					continue;
				}
				*cp++ = '\0';
				while (isspace(*cp))
					cp++;
				if (*cp == '\0')
					break;
				if (isdigit(*cp)) {
					if (requests >= MAXREQUESTS)
						fatal(0, "Too many requests");
					requ[requests++] = atoi(cp);
				} else {
					if (users >= MAXUSERS)
						fatal(0, "Too many users");
					user[users++] = cp;
				}
			}
			rmjob(printer);
			break;
		}
		fatal(0, "Illegal service request");
	}
}
Exemple #9
0
/*
 * Display the current state of the queue. Format = 1 if long format.
 */
void
displayq(int format)
{
	struct queue *q;
	int i, nitems, fd, ret;
	char *cp, *ecp;
	struct queue **queue;
	struct stat statb;
	FILE *fp;

	lflag = format;
	totsize = 0;
	rank = -1;
	getprintcap(printer);

	/*
	 * Print out local queue
	 * Find all the control files in the spooling directory
	 */
	seteuid(euid);
	if (chdir(SD) < 0)
		fatal("cannot chdir to spooling directory");
	seteuid(uid);
	if ((nitems = getq(&queue)) < 0)
		fatal("cannot examine spooling area\n");
	seteuid(euid);
	ret = stat(LO, &statb);
	seteuid(uid);
	if (ret >= 0) {
		if (statb.st_mode & S_IXUSR) {
			if (remote)
				printf("%s: ", host);
			printf("Warning: %s is down: ", printer);
			seteuid(euid);
			fd = open(ST, O_RDONLY);
			seteuid(uid);
			if (fd >= 0) {
				(void)flock(fd, LOCK_SH);
				while ((i = read(fd, line, sizeof(line))) > 0)
					(void)fwrite(line, 1, (size_t)i, stdout);
				(void)close(fd);	/* unlocks as well */
			} else
				putchar('\n');
		}
		if (statb.st_mode & S_IXGRP) {
			if (remote)
				printf("%s: ", host);
			printf("Warning: %s queue is turned off\n", printer);
		}
	}

	if (nitems) {
		seteuid(euid);
		fp = fopen(LO, "r");
		seteuid(uid);
		if (fp == NULL)
			nodaemon();
		else {
			/* get daemon pid */
			cp = current;
			ecp = cp + sizeof(current) - 1;
			while ((i = getc(fp)) != EOF && i != '\n') {
				if (cp < ecp)
					*cp++ = i;
			}
			*cp = '\0';
			i = atoi(current);
			if (i <= 0) {
				ret = -1;
			} else {
				seteuid(euid);
				ret = kill(i, 0);
				seteuid(uid);
			}
			if (ret < 0) {
				nodaemon();
			} else {
				/* read current file name */
				cp = current;
		    		ecp = cp + sizeof(current) - 1;
				while ((i = getc(fp)) != EOF && i != '\n') {
					if (cp < ecp)
						*cp++ = i;
				}
				*cp = '\0';
				/*
				 * Print the status file.
				 */
				if (remote)
					printf("%s: ", host);
				seteuid(euid);
				fd = open(ST, O_RDONLY);
				seteuid(uid);
				if (fd >= 0) {
					(void)flock(fd, LOCK_SH);
					while ((i = read(fd, line, sizeof(line))) > 0)
						(void)fwrite(line, 1, (size_t)i, stdout);
					(void)close(fd);	/* unlocks as well */
				} else
					putchar('\n');
			}
			(void)fclose(fp);
		}
		/*
		 * Now, examine the control files and print out the jobs to
		 * be done for each user.
		 */
		if (!lflag)
			header();
		for (i = 0; i < nitems; i++) {
			q = queue[i];
			inform(q->q_name);
		}
	}
	freeq(queue, nitems);
	if (!remote) {
		if (nitems == 0)
			puts("no entries");
		return;
	}

	/*
	 * Print foreign queue
	 * Note that a file in transit may show up in either queue.
	 */
	if (nitems)
		putchar('\n');
	(void)snprintf(line, sizeof(line), "%c%s", format + '\3', RP);
	cp = line;
	ecp = line + sizeof(line);
	for (i = 0;
	    i < requests && (size_t)(cp - line + 11) < sizeof(line) - 2;
	    i++) {
		cp += strlen(cp);
		(void)snprintf(cp, ecp - cp, " %d", requ[i]);
	}
	for (i = 0;
	    i < users && cp - line + 1 + strlen(user[i]) < sizeof(line) - 2;
	    i++) {
		cp += strlen(cp);
		if ((size_t)(cp - line) > sizeof(line) - 2)
			break;
		*cp++ = ' ';
		/* truncation may happen */
		(void)strlcpy(cp, user[i], ecp - cp);
	}
	(void)strlcat(line, "\n", sizeof(line));
	fd = getport(RM);
	if (fd < 0) {
		if (from != host)
			printf("%s: ", host);
		(void)printf("connection to %s is down\n", RM);
	}
	else {
		struct sigaction osa, nsa;

		i = strlen(line);
		if (write(fd, line, (size_t)i) != i)
			fatal("Lost connection");
		nsa.sa_handler = alarmer;
		sigemptyset(&nsa.sa_mask);
		sigaddset(&nsa.sa_mask, SIGALRM);
		nsa.sa_flags = 0;
		(void)sigaction(SIGALRM, &nsa, &osa);
		alarm(wait_time);
		while ((i = read(fd, line, sizeof(line))) > 0) {
			(void)fwrite(line, 1, (size_t)i, stdout);
			alarm(wait_time);
		}
		alarm(0);
		(void)sigaction(SIGALRM, &osa, NULL);
		(void)close(fd);
	}
}