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

📄 printjob.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 3 页
字号:
				sendmail(line+1, bombed);			continue;		case 'U':			(void) unlink(line+1);		}	/*	 * clean-up in case another control file exists	 */	(void) fclose(cfp);	(void) unlink(file);	return(bombed == OK ? OK : ERROR);}/* * Print a file. * Set up the chain [ PR [ | {IF, OF} ] ] or {IF, RF, TF, NF, DF, CF, VF}. * Return -1 if a non-recoverable error occured, * 2 if the filter detected some errors (but printed the job anyway), * 1 if we should try to reprint this job and * 0 if all is well. * Note: all filters take stdin as the file, stdout as the printer, * stderr as the log file, and must not ignore SIGINT. */static intprint(format, file)	int format;	char *file;{	register int n;	register char *prog;	int fi, fo;	FILE *fp;	char *av[15], buf[BUFSIZ];	int pid, p[2], stopped = 0;	union wait status;	struct stat stb;	if (lstat(file, &stb) < 0 || (fi = open(file, O_RDONLY)) < 0)		return(ERROR);	/*	 * Check to see if data file is a symbolic link. If so, it should	 * still point to the same file or someone is trying to print	 * something he shouldn't.	 */	if ((stb.st_mode & S_IFMT) == S_IFLNK && fstat(fi, &stb) == 0 &&	    (stb.st_dev != fdev || stb.st_ino != fino))		return(ACCESS);	if (!SF && !tof) {		/* start on a fresh page */		(void) write(ofd, FF, strlen(FF));		tof = 1;	}	if (IF == NULL && (format == 'f' || format == 'l')) {		tof = 0;		while ((n = read(fi, buf, BUFSIZ)) > 0)			if (write(ofd, buf, n) != n) {				(void) close(fi);				return(REPRINT);			}		(void) close(fi);		return(OK);	}	switch (format) {	case 'p':	/* print file using 'pr' */		if (IF == NULL) {	/* use output filter */			prog = _PATH_PR;			av[0] = "pr";			av[1] = width;			av[2] = length;			av[3] = "-h";			av[4] = *title ? title : " ";			av[5] = 0;			fo = ofd;			goto start;		}		pipe(p);		if ((prchild = dofork(DORETURN)) == 0) {	/* child */			dup2(fi, 0);		/* file is stdin */			dup2(p[1], 1);		/* pipe is stdout */			for (n = 3; n < NOFILE; n++)				(void) close(n);			execl(_PATH_PR, "pr", width, length,			    "-h", *title ? title : " ", 0);			syslog(LOG_ERR, "cannot execl %s", _PATH_PR);			exit(2);		}		(void) close(p[1]);		/* close output side */		(void) close(fi);		if (prchild < 0) {			prchild = 0;			(void) close(p[0]);			return(ERROR);		}		fi = p[0];			/* use pipe for input */	case 'f':	/* print plain text file */		prog = IF;		av[1] = width;		av[2] = length;		av[3] = indent;		n = 4;		break;	case 'l':	/* like 'f' but pass control characters */		prog = IF;		av[1] = "-c";		av[2] = width;		av[3] = length;		av[4] = indent;		n = 5;		break;	case 'r':	/* print a fortran text file */		prog = RF;		av[1] = width;		av[2] = length;		n = 3;		break;	case 't':	/* print troff output */	case 'n':	/* print ditroff output */	case 'd':	/* print tex output */		(void) unlink(".railmag");		if ((fo = creat(".railmag", FILMOD)) < 0) {			syslog(LOG_ERR, "%s: cannot create .railmag", printer);			(void) unlink(".railmag");		} else {			for (n = 0; n < 4; n++) {				if (fonts[n][0] != '/')					(void) write(fo, _PATH_VFONT,					    sizeof(_PATH_VFONT) - 1);				(void) write(fo, fonts[n], strlen(fonts[n]));				(void) write(fo, "\n", 1);			}			(void) close(fo);		}		prog = (format == 't') ? TF : (format == 'n') ? NF : DF;		av[1] = pxwidth;		av[2] = pxlength;		n = 3;		break;	case 'c':	/* print cifplot output */		prog = CF;		av[1] = pxwidth;		av[2] = pxlength;		n = 3;		break;	case 'g':	/* print plot(1G) output */		prog = GF;		av[1] = pxwidth;		av[2] = pxlength;		n = 3;		break;	case 'v':	/* print raster output */		prog = VF;		av[1] = pxwidth;		av[2] = pxlength;		n = 3;		break;	default:		(void) close(fi);		syslog(LOG_ERR, "%s: illegal format character '%c'",			printer, format);		return(ERROR);	}	if ((av[0] = rindex(prog, '/')) != NULL)		av[0]++;	else		av[0] = prog;	av[n++] = "-n";	av[n++] = logname;	av[n++] = "-h";	av[n++] = fromhost;	av[n++] = AF;	av[n] = 0;	fo = pfd;	if (ofilter > 0) {		/* stop output filter */		write(ofd, "\031\1", 2);		while ((pid =		    wait3((int *)&status, WUNTRACED, 0)) > 0 && pid != ofilter)			;		if (status.w_stopval != WSTOPPED) {			(void) close(fi);			syslog(LOG_WARNING, "%s: output filter died (%d)",				printer, status.w_retcode);			return(REPRINT);		}		stopped++;	}start:	if ((child = dofork(DORETURN)) == 0) {	/* child */		dup2(fi, 0);		dup2(fo, 1);		n = open(tempfile, O_WRONLY|O_CREAT|O_TRUNC, 0664);		if (n >= 0)			dup2(n, 2);		for (n = 3; n < NOFILE; n++)			(void) close(n);		execv(prog, av);		syslog(LOG_ERR, "cannot execv %s", prog);		exit(2);	}	(void) close(fi);	if (child < 0)		status.w_retcode = 100;	else		while ((pid = wait((int *)&status)) > 0 && pid != child)			;	child = 0;	prchild = 0;	if (stopped) {		/* restart output filter */		if (kill(ofilter, SIGCONT) < 0) {			syslog(LOG_ERR, "cannot restart output filter");			exit(1);		}	}	tof = 0;	/* Copy filter output to "lf" logfile */	if (fp = fopen(tempfile, "r")) {		while (fgets(buf, sizeof(buf), fp))			fputs(buf, stderr);		fclose(fp);	}	if (!WIFEXITED(status)) {		syslog(LOG_WARNING, "%s: Daemon filter '%c' terminated (%d)",			printer, format, status.w_termsig);		return(ERROR);	}	switch (status.w_retcode) {	case 0:		tof = 1;		return(OK);	case 1:		return(REPRINT);	default:		syslog(LOG_WARNING, "%s: Daemon filter '%c' exited (%d)",			printer, format, status.w_retcode);	case 2:		return(ERROR);	}}/* * Send the daemon control file (cf) and any data files. * Return -1 if a non-recoverable error occured, 1 if a recoverable error and * 0 if all is well. */static intsendit(file)	char *file;{	register int i, err = OK;	char *cp, last[BUFSIZ];	/*	 * open control file	 */	if ((cfp = fopen(file, "r")) == NULL)		return(OK);	/*	 *      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.	 *      commands of interest are:	 *	 *            a-z -- "file name" name of file to print	 *              U -- "unlink" name of file to remove	 *                    (after we print it. (Pass 2 only)).	 */	/*	 * pass 1	 */	while (getline(cfp)) {	again:		if (line[0] == '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;		}		if (line[0] >= 'a' && line[0] <= 'z') {			strcpy(last, line);			while (i = getline(cfp))				if (strcmp(last, line))					break;			switch (sendfile('\3', last+1)) {			case OK:				if (i)					goto again;				break;			case REPRINT:				(void) fclose(cfp);				return(REPRINT);			case ACCESS:				sendmail(logname, ACCESS);			case ERROR:				err = ERROR;			}			break;		}	}	if (err == OK && sendfile('\2', file) > 0) {		(void) fclose(cfp);		return(REPRINT);	}	/*	 * pass 2	 */	fseek(cfp, 0L, 0);	while (getline(cfp))		if (line[0] == 'U')			(void) unlink(line+1);	/*	 * clean-up in case another control file exists	 */	(void) fclose(cfp);	(void) unlink(file);	return(err);}/* * Send a data file to the remote machine and spool it. * Return positive if we should try resending. */static intsendfile(type, file)	int type;	char *file;{	register int f, i, amt;	struct stat stb;	char buf[BUFSIZ];	int sizerr, resp;	if (lstat(file, &stb) < 0 || (f = open(file, O_RDONLY)) < 0)		return(ERROR);	/*	 * Check to see if data file is a symbolic link. If so, it should	 * still point to the same file or someone is trying to print something	 * he shouldn't.	 */	if ((stb.st_mode & S_IFMT) == S_IFLNK && fstat(f, &stb) == 0 &&	    (stb.st_dev != fdev || stb.st_ino != fino))		return(ACCESS);	(void) sprintf(buf, "%c%qd %s\n", type, stb.st_size, file);	amt = strlen(buf);	for (i = 0;  ; i++) {		if (write(pfd, buf, amt) != amt ||		    (resp = response()) < 0 || resp == '\1') {			(void) close(f);			return(REPRINT);		} else if (resp == '\0')			break;		if (i == 0)			pstatus("no space on remote; waiting for queue to drain");		if (i == 10)			syslog(LOG_ALERT, "%s: can't send to %s; queue full",				printer, RM);		sleep(5 * 60);	}	if (i)		pstatus("sending to %s", RM);	sizerr = 0;	for (i = 0; i < stb.st_size; i += BUFSIZ) {		amt = BUFSIZ;		if (i + amt > stb.st_size)			amt = stb.st_size - i;		if (sizerr == 0 && read(f, buf, amt) != amt)			sizerr = 1;		if (write(pfd, buf, amt) != amt) {			(void) close(f);			return(REPRINT);		}	}	(void) close(f);	if (sizerr) {		syslog(LOG_INFO, "%s: %s: changed size", printer, file);		/* tell recvjob to ignore this file */		(void) write(pfd, "\1", 1);		return(ERROR);	}	if (write(pfd, "", 1) != 1 || response())		return(REPRINT);	return(OK);}/* * Check to make sure there have been no errors and that both programs * are in sync with eachother. * Return non-zero if the connection was lost. */static charresponse(){	char resp;	if (read(pfd, &resp, 1) != 1) {		syslog(LOG_INFO, "%s: lost connection", printer);		return(-1);	}	return(resp);}/* * Banner printing stuff */static voidbanner(name1, name2)	char *name1, *name2;{	time_t tvec;	extern char *ctime();	time(&tvec);	if (!SF && !tof)		(void) write(ofd, FF, strlen(FF));	if (SB) {	/* short banner only */		if (class[0]) {			(void) write(ofd, class, strlen(class));			(void) write(ofd, ":", 1);		}		(void) write(ofd, name1, strlen(name1));		(void) write(ofd, "  Job: ", 7);		(void) write(ofd, name2, strlen(name2));		(void) write(ofd, "  Date: ", 8);		(void) write(ofd, ctime(&tvec), 24);		(void) write(ofd, "\n", 1);	} else {	/* normal banner */		(void) write(ofd, "\n\n\n", 3);		scan_out(ofd, name1, '\0');		(void) write(ofd, "\n\n", 2);		scan_out(ofd, name2, '\0');		if (class[0]) {			(void) write(ofd,"\n\n\n",3);			scan_out(ofd, class, '\0');		}		(void) write(ofd, "\n\n\n\n\t\t\t\t\tJob:  ", 15);		(void) write(ofd, name2, strlen(name2));		(void) write(ofd, "\n\t\t\t\t\tDate: ", 12);		(void) write(ofd, ctime(&tvec), 24);		(void) write(ofd, "\n", 1);	}	if (!SF)		(void) write(ofd, FF, strlen(FF));	tof = 1;}static char *scnline(key, p, c)

⌨️ 快捷键说明

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