⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 printjob.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * Copyright (c) 1983, 1993 *	The Regents of the University of California.  All rights reserved. * * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software *    must display the following acknowledgement: *	This product includes software developed by the University of *	California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors *    may be used to endorse or promote products derived from this software *    without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */#ifndef lintstatic char copyright[] ="@(#) Copyright (c) 1983, 1993\n\	The Regents of the University of California.  All rights reserved.\n";#endif /* not lint */#ifndef lintstatic char sccsid[] = "@(#)printjob.c	8.2 (Berkeley) 4/16/94";#endif /* not lint *//* * printjob -- print jobs in the queue. * *	NOTE: the lock file is used to pass information to lpq and lprm. *	it does not need to be removed because file locks are dynamic. */#include <sys/param.h>#include <sys/wait.h>#include <sys/stat.h>#include <sys/types.h>#include <pwd.h>#include <unistd.h>#include <signal.h>#include <sgtty.h>#include <syslog.h>#include <fcntl.h>#include <dirent.h>#include <errno.h>#include <stdio.h>#include <string.h>#include <stdlib.h>#include "lp.h"#include "lp.local.h"#include "pathnames.h"#include "extern.h"#define DORETURN	0	/* absorb fork error */#define DOABORT		1	/* abort if dofork fails *//* * Error tokens */#define REPRINT		-2#define ERROR		-1#define	OK		0#define	FATALERR	1#define	NOACCT		2#define	FILTERERR	3#define	ACCESS		4static dev_t	 fdev;		/* device of file pointed to by symlink */static ino_t	 fino;		/* inode of file pointed to by symlink */static FILE	*cfp;		/* control file */static int	 child;		/* id of any filters */static int	 lfd;		/* lock file descriptor */static int	 ofd;		/* output filter file descriptor */static int	 ofilter;	/* id of output filter, if any */static int	 pfd;		/* prstatic inter file descriptor */static int	 pid;		/* pid of lpd process */static int	 prchild;	/* id of pr process */static int	 remote;	/* true if sending files to remote */static char	 title[80];	/* ``pr'' title */static int	 tof;		/* true if at top of form */static char	class[32];		/* classification field */static char	fromhost[32];		/* user's host machine */				/* indentation size in static characters */static char	indent[10] = "-i0"; static char	jobname[100];		/* job or file name */static char	length[10] = "-l";	/* page length in lines */static char	logname[32];		/* user's login name */static char	pxlength[10] = "-y";	/* page length in pixels */static char	pxwidth[10] = "-x";	/* page width in pixels */static char	tempfile[] = "errsXXXXXX"; /* file name for filter output */static char	width[10] = "-w";	/* page width in static characters */static void       abortpr __P((int));static void       banner __P((char *, char *));static int        dofork __P((int));static int        dropit __P((int));static void       init __P((void));static void       openpr __P((void));static int        print __P((int, char *));static int        printit __P((char *));static void       pstatus __P((const char *, ...));static char       response __P((void));static void       scan_out __P((int, char *, int));static char      *scnline __P((int, char *, int));static int        sendfile __P((int, char *));static int        sendit __P((char *));static void       sendmail __P((char *, int));static void       setty __P((void));voidprintjob(){	struct stat stb;	register struct queue *q, **qp;	struct queue **queue;	register int i, nitems;	long pidoff;	int count = 0;	init();					/* set up capabilities */	(void) write(1, "", 1);			/* ack that daemon is started */	(void) close(2);			/* set up log file */	if (open(LF, O_WRONLY|O_APPEND, 0664) < 0) {		syslog(LOG_ERR, "%s: %m", LF);		(void) open(_PATH_DEVNULL, O_WRONLY);	}	setgid(getegid());	pid = getpid();				/* for use with lprm */	setpgrp(0, pid);	signal(SIGHUP, abortpr);	signal(SIGINT, abortpr);	signal(SIGQUIT, abortpr);	signal(SIGTERM, abortpr);	(void) mktemp(tempfile);	/*	 * uses short form file names	 */	if (chdir(SD) < 0) {		syslog(LOG_ERR, "%s: %m", SD);		exit(1);	}	if (stat(LO, &stb) == 0 && (stb.st_mode & 0100))		exit(0);		/* printing disabled */	lfd = open(LO, O_WRONLY|O_CREAT, 0644);	if (lfd < 0) {		syslog(LOG_ERR, "%s: %s: %m", printer, LO);		exit(1);	}	if (flock(lfd, LOCK_EX|LOCK_NB) < 0) {		if (errno == EWOULDBLOCK)	/* active deamon present */			exit(0);		syslog(LOG_ERR, "%s: %s: %m", printer, LO);		exit(1);	}	ftruncate(lfd, 0);	/*	 * write process id for others to know	 */	sprintf(line, "%u\n", pid);	pidoff = i = strlen(line);	if (write(lfd, line, i) != i) {		syslog(LOG_ERR, "%s: %s: %m", printer, LO);		exit(1);	}	/*	 * search the spool directory for work and sort by queue order.	 */	if ((nitems = getq(&queue)) < 0) {		syslog(LOG_ERR, "%s: can't scan %s", printer, SD);		exit(1);	}	if (nitems == 0)		/* no work to do */		exit(0);	if (stb.st_mode & 01) {		/* reset queue flag */		if (fchmod(lfd, stb.st_mode & 0776) < 0)			syslog(LOG_ERR, "%s: %s: %m", printer, LO);	}	openpr();			/* open printer or remote */again:	/*	 * we found something to do now do it --	 *    write the name of the current control file into the lock file	 *    so the spool queue program can tell what we're working on	 */	for (qp = queue; nitems--; free((char *) q)) {		q = *qp++;		if (stat(q->q_name, &stb) < 0)			continue;	restart:		(void) lseek(lfd, (off_t)pidoff, 0);		(void) sprintf(line, "%s\n", q->q_name);		i = strlen(line);		if (write(lfd, line, i) != i)			syslog(LOG_ERR, "%s: %s: %m", printer, LO);		if (!remote)			i = printit(q->q_name);		else			i = sendit(q->q_name);		/*		 * Check to see if we are supposed to stop printing or		 * if we are to rebuild the queue.		 */		if (fstat(lfd, &stb) == 0) {			/* stop printing before starting next job? */			if (stb.st_mode & 0100)				goto done;			/* rebuild queue (after lpc topq) */			if (stb.st_mode & 01) {				for (free((char *) q); nitems--; free((char *) q))					q = *qp++;				if (fchmod(lfd, stb.st_mode & 0776) < 0)					syslog(LOG_WARNING, "%s: %s: %m",						printer, LO);				break;			}		}		if (i == OK)		/* file ok and printed */			count++;		else if (i == REPRINT) { /* try reprinting the job */			syslog(LOG_INFO, "restarting %s", printer);			if (ofilter > 0) {				kill(ofilter, SIGCONT);	/* to be sure */				(void) close(ofd);				while ((i = wait(0)) > 0 && i != ofilter)					;				ofilter = 0;			}			(void) close(pfd);	/* close printer */			if (ftruncate(lfd, pidoff) < 0)				syslog(LOG_WARNING, "%s: %s: %m", printer, LO);			openpr();		/* try to reopen printer */			goto restart;		}	}	free((char *) queue);	/*	 * search the spool directory for more work.	 */	if ((nitems = getq(&queue)) < 0) {		syslog(LOG_ERR, "%s: can't scan %s", printer, SD);		exit(1);	}	if (nitems == 0) {		/* no more work to do */	done:		if (count > 0) {	/* Files actually printed */			if (!SF && !tof)				(void) write(ofd, FF, strlen(FF));			if (TR != NULL)		/* output trailer */				(void) write(ofd, TR, strlen(TR));		}		(void) unlink(tempfile);		exit(0);	}	goto again;}char	fonts[4][50];	/* fonts for troff */char ifonts[4][40] = {	_PATH_VFONTR,	_PATH_VFONTI,	_PATH_VFONTB,	_PATH_VFONTS,};/* * The remaining part is the reading of the control file (cf) * and performing the various actions. */static intprintit(file)	char *file;{	register int i;	char *cp;	int bombed = OK;	/*	 * open control file; ignore if no longer there.	 */	if ((cfp = fopen(file, "r")) == NULL) {		syslog(LOG_INFO, "%s: %s: %m", printer, file);		return(OK);	}	/*	 * Reset troff fonts.	 */	for (i = 0; i < 4; i++)		strcpy(fonts[i], ifonts[i]);	sprintf(&width[2], "%d", PW);	strcpy(indent+2, "0");	/*	 *      read the control file for work to do	 *	 *      file format -- first character in the line is a command	 *      rest of the line is the argument.	 *      valid commands are:	 *	 *		S -- "stat info" for symbolic link protection	 *		J -- "job name" on banner page	 *		C -- "class name" on banner page	 *              L -- "literal" user's name to print on banner	 *		T -- "title" for pr	 *		H -- "host name" of machine where lpr was done	 *              P -- "person" user's login name	 *              I -- "indent" amount to indent output	 *              f -- "file name" name of text file to print	 *		l -- "file name" text file with control chars	 *		p -- "file name" text file to print with pr(1)	 *		t -- "file name" troff(1) file to print	 *		n -- "file name" ditroff(1) file to print	 *		d -- "file name" dvi file to print	 *		g -- "file name" plot(1G) file to print	 *		v -- "file name" plain raster file to print	 *		c -- "file name" cifplot file to print	 *		1 -- "R font file" for troff	 *		2 -- "I font file" for troff	 *		3 -- "B font file" for troff	 *		4 -- "S font file" for troff	 *		N -- "name" of file (used by lpq)	 *              U -- "unlink" name of file to remove	 *                    (after we print it. (Pass 2 only)).	 *		M -- "mail" to user when done printing	 *	 *      getline reads a line and expands tabs to blanks	 */	/* pass 1 */	while (getline(cfp))		switch (line[0]) {		case 'H':			strcpy(fromhost, line+1);			if (class[0] == '\0')				strncpy(class, line+1, sizeof(class)-1);			continue;		case 'P':			strncpy(logname, line+1, sizeof(logname)-1);			if (RS) {			/* restricted */				if (getpwnam(logname) == NULL) {					bombed = NOACCT;					sendmail(line+1, bombed);					goto pass2;				}			}			continue;		case 'S':			cp = line+1;			i = 0;			while (*cp >= '0' && *cp <= '9')				i = i * 10 + (*cp++ - '0');			fdev = i;			cp++;			i = 0;			while (*cp >= '0' && *cp <= '9')				i = i * 10 + (*cp++ - '0');			fino = i;			continue;		case 'J':			if (line[1] != '\0')				strncpy(jobname, line+1, sizeof(jobname)-1);			else				strcpy(jobname, " ");			continue;		case 'C':			if (line[1] != '\0')				strncpy(class, line+1, sizeof(class)-1);			else if (class[0] == '\0')				gethostname(class, sizeof(class));			continue;		case 'T':	/* header title for pr */			strncpy(title, line+1, sizeof(title)-1);			continue;		case 'L':	/* identification line */			if (!SH && !HL)				banner(line+1, jobname);			continue;		case '1':	/* troff fonts */		case '2':		case '3':		case '4':			if (line[1] != '\0')				strcpy(fonts[line[0]-'1'], line+1);			continue;		case 'W':	/* page width */			strncpy(width+2, line+1, sizeof(width)-3);			continue;		case 'I':	/* indent amount */			strncpy(indent+2, line+1, sizeof(indent)-3);			continue;		default:	/* some file to print */			switch (i = print(line[0], line+1)) {			case ERROR:				if (bombed == OK)					bombed = FATALERR;				break;			case REPRINT:				(void) fclose(cfp);				return(REPRINT);			case FILTERERR:			case ACCESS:				bombed = i;				sendmail(logname, bombed);			}			title[0] = '\0';			continue;		case 'N':		case 'U':		case 'M':			continue;		}	/* pass 2 */pass2:	fseek(cfp, 0L, 0);	while (getline(cfp))		switch (line[0]) {		case 'L':	/* identification line */			if (!SH && HL)				banner(line+1, jobname);			continue;		case 'M':			if (bombed < NOACCT)	/* already sent if >= NOACCT */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -