📄 printjob.c
字号:
/* * 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 + -