Example #1
0
File: pac.c Project: coyizumi/cs111
/*
 * 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);
}
Example #2
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);
		}
	}
Example #3
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);
	}
}
Example #4
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);
}
Example #5
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);
}
Example #6
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);
}
Example #7
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");
	}
}