122437Sdist /* 222437Sdist * Copyright (c) 1983 Regents of the University of California. 334203Sbostic * All rights reserved. 434203Sbostic * 5*42802Sbostic * %sccs.include.redist.c% 622437Sdist */ 722437Sdist 813954Ssam #ifndef lint 9*42802Sbostic static char sccsid[] = "@(#)printjob.c 5.12 (Berkeley) 06/01/90"; 1034203Sbostic #endif /* not lint */ 1113954Ssam 1212111Sralph /* 1312111Sralph * printjob -- print jobs in the queue. 1412111Sralph * 1512111Sralph * NOTE: the lock file is used to pass information to lpq and lprm. 1612111Sralph * it does not need to be removed because file locks are dynamic. 1712111Sralph */ 1812111Sralph 1912111Sralph #include "lp.h" 2037968Sbostic #include "pathnames.h" 2112111Sralph 2216762Sralph #define DORETURN 0 /* absorb fork error */ 2316762Sralph #define DOABORT 1 /* abort if dofork fails */ 2412111Sralph 2517463Sralph /* 2617463Sralph * Error tokens 2717463Sralph */ 2817463Sralph #define REPRINT -2 2917463Sralph #define ERROR -1 3017463Sralph #define OK 0 3117463Sralph #define FATALERR 1 3217463Sralph #define NOACCT 2 3317463Sralph #define FILTERERR 3 3417463Sralph #define ACCESS 4 3517463Sralph 3616762Sralph char title[80]; /* ``pr'' title */ 3716762Sralph FILE *cfp; /* control file */ 3816762Sralph int pfd; /* printer file descriptor */ 3916762Sralph int ofd; /* output filter file descriptor */ 4016762Sralph int lfd; /* lock file descriptor */ 4116762Sralph int pid; /* pid of lpd process */ 4216762Sralph int prchild; /* id of pr process */ 4316762Sralph int child; /* id of any filters */ 4416762Sralph int ofilter; /* id of output filter, if any */ 4516762Sralph int tof; /* true if at top of form */ 4616762Sralph int remote; /* true if sending files to remote */ 4717463Sralph dev_t fdev; /* device of file pointed to by symlink */ 4817463Sralph ino_t fino; /* inode of file pointed to by symlink */ 4912111Sralph 5016762Sralph char fromhost[32]; /* user's host machine */ 5116762Sralph char logname[32]; /* user's login name */ 5216762Sralph char jobname[100]; /* job or file name */ 5316762Sralph char class[32]; /* classification field */ 5416762Sralph char width[10] = "-w"; /* page width in characters */ 5516762Sralph char length[10] = "-l"; /* page length in lines */ 5616762Sralph char pxwidth[10] = "-x"; /* page width in pixels */ 5716762Sralph char pxlength[10] = "-y"; /* page length in pixels */ 5816762Sralph char indent[10] = "-i0"; /* indentation size in characters */ 5939954Smckusick char tempfile[] = "errsXXXXXX"; /* file name for filter output */ 6012111Sralph 6112111Sralph printjob() 6212111Sralph { 6312111Sralph struct stat stb; 6412111Sralph register struct queue *q, **qp; 6512111Sralph struct queue **queue; 6612111Sralph register int i, nitems; 6712111Sralph long pidoff; 6816762Sralph int count = 0; 6916762Sralph extern int abortpr(); 7012111Sralph 7112111Sralph init(); /* set up capabilities */ 7213442Sralph (void) write(1, "", 1); /* ack that daemon is started */ 7325496Seric (void) close(2); /* set up log file */ 7425496Seric if (open(LF, O_WRONLY|O_APPEND, 0664) < 0) { 7525496Seric syslog(LOG_ERR, "%s: %m", LF); 7637968Sbostic (void) open(_PATH_DEVNULL, O_WRONLY); 7725496Seric } 7816762Sralph setgid(getegid()); 7912463Sralph pid = getpid(); /* for use with lprm */ 8012111Sralph setpgrp(0, pid); 8116762Sralph signal(SIGHUP, abortpr); 8216762Sralph signal(SIGINT, abortpr); 8316762Sralph signal(SIGQUIT, abortpr); 8416762Sralph signal(SIGTERM, abortpr); 8512111Sralph 8639954Smckusick (void) mktemp(tempfile); 8715811Sralph 8812111Sralph /* 8912111Sralph * uses short form file names 9012111Sralph */ 9112111Sralph if (chdir(SD) < 0) { 9216762Sralph syslog(LOG_ERR, "%s: %m", SD); 9312111Sralph exit(1); 9412111Sralph } 9512463Sralph if (stat(LO, &stb) == 0 && (stb.st_mode & 0100)) 9612463Sralph exit(0); /* printing disabled */ 9714150Sralph lfd = open(LO, O_WRONLY|O_CREAT, 0644); 9813169Sralph if (lfd < 0) { 9916762Sralph syslog(LOG_ERR, "%s: %s: %m", printer, LO); 10013169Sralph exit(1); 10113169Sralph } 10213169Sralph if (flock(lfd, LOCK_EX|LOCK_NB) < 0) { 10312111Sralph if (errno == EWOULDBLOCK) /* active deamon present */ 10412111Sralph exit(0); 10516762Sralph syslog(LOG_ERR, "%s: %s: %m", printer, LO); 10612111Sralph exit(1); 10712111Sralph } 10813148Ssam ftruncate(lfd, 0); 10912111Sralph /* 11012111Sralph * write process id for others to know 11112111Sralph */ 11212111Sralph sprintf(line, "%u\n", pid); 11312111Sralph pidoff = i = strlen(line); 11412463Sralph if (write(lfd, line, i) != i) { 11516762Sralph syslog(LOG_ERR, "%s: %s: %m", printer, LO); 11612111Sralph exit(1); 11712111Sralph } 11812111Sralph /* 11912111Sralph * search the spool directory for work and sort by queue order. 12012111Sralph */ 12112111Sralph if ((nitems = getq(&queue)) < 0) { 12216762Sralph syslog(LOG_ERR, "%s: can't scan %s", printer, SD); 12312111Sralph exit(1); 12412111Sralph } 12512463Sralph if (nitems == 0) /* no work to do */ 12612111Sralph exit(0); 12713169Sralph if (stb.st_mode & 01) { /* reset queue flag */ 12813169Sralph if (fchmod(lfd, stb.st_mode & 0776) < 0) 12916762Sralph syslog(LOG_ERR, "%s: %s: %m", printer, LO); 13013169Sralph } 13112463Sralph openpr(); /* open printer or remote */ 13212463Sralph again: 13312111Sralph /* 13412111Sralph * we found something to do now do it -- 13512111Sralph * write the name of the current control file into the lock file 13612111Sralph * so the spool queue program can tell what we're working on 13712111Sralph */ 13812111Sralph for (qp = queue; nitems--; free((char *) q)) { 13912111Sralph q = *qp++; 14012111Sralph if (stat(q->q_name, &stb) < 0) 14112111Sralph continue; 14212463Sralph restart: 14312111Sralph (void) lseek(lfd, pidoff, 0); 14412111Sralph (void) sprintf(line, "%s\n", q->q_name); 14512111Sralph i = strlen(line); 14612111Sralph if (write(lfd, line, i) != i) 14716762Sralph syslog(LOG_ERR, "%s: %s: %m", printer, LO); 14812111Sralph if (!remote) 14912111Sralph i = printit(q->q_name); 15012111Sralph else 15112111Sralph i = sendit(q->q_name); 15212463Sralph /* 15313169Sralph * Check to see if we are supposed to stop printing or 15413169Sralph * if we are to rebuild the queue. 15512463Sralph */ 15613169Sralph if (fstat(lfd, &stb) == 0) { 15716762Sralph /* stop printing before starting next job? */ 15813169Sralph if (stb.st_mode & 0100) 15913169Sralph goto done; 16016762Sralph /* rebuild queue (after lpc topq) */ 16113169Sralph if (stb.st_mode & 01) { 16213169Sralph for (free((char *) q); nitems--; free((char *) q)) 16313169Sralph q = *qp++; 16413169Sralph if (fchmod(lfd, stb.st_mode & 0776) < 0) 16516762Sralph syslog(LOG_WARNING, "%s: %s: %m", 16616762Sralph printer, LO); 16713169Sralph break; 16813169Sralph } 16913169Sralph } 17017463Sralph if (i == OK) /* file ok and printed */ 17114150Sralph count++; 17217463Sralph else if (i == REPRINT) { /* try reprinting the job */ 17316762Sralph syslog(LOG_INFO, "restarting %s", printer); 17412111Sralph if (ofilter > 0) { 17512111Sralph kill(ofilter, SIGCONT); /* to be sure */ 17612111Sralph (void) close(ofd); 17712111Sralph while ((i = wait(0)) > 0 && i != ofilter) 17812111Sralph ; 17912111Sralph ofilter = 0; 18012111Sralph } 18112463Sralph (void) close(pfd); /* close printer */ 18215811Sralph if (ftruncate(lfd, pidoff) < 0) 18316762Sralph syslog(LOG_WARNING, "%s: %s: %m", printer, LO); 18412463Sralph openpr(); /* try to reopen printer */ 18512111Sralph goto restart; 18612111Sralph } 18712111Sralph } 18812111Sralph free((char *) queue); 18912463Sralph /* 19012463Sralph * search the spool directory for more work. 19112463Sralph */ 19212463Sralph if ((nitems = getq(&queue)) < 0) { 19316762Sralph syslog(LOG_ERR, "%s: can't scan %s", printer, SD); 19412463Sralph exit(1); 19512463Sralph } 19612463Sralph if (nitems == 0) { /* no more work to do */ 19712463Sralph done: 19814150Sralph if (count > 0) { /* Files actually printed */ 19914150Sralph if (!SF && !tof) 20014150Sralph (void) write(ofd, FF, strlen(FF)); 20114150Sralph if (TR != NULL) /* output trailer */ 20214150Sralph (void) write(ofd, TR, strlen(TR)); 20314150Sralph } 20439954Smckusick (void) unlink(tempfile); 20512463Sralph exit(0); 20612463Sralph } 20712111Sralph goto again; 20812111Sralph } 20912111Sralph 21012111Sralph char fonts[4][50]; /* fonts for troff */ 21112111Sralph 21237968Sbostic char ifonts[4][40] = { 21337968Sbostic _PATH_VFONTR, 21437968Sbostic _PATH_VFONTI, 21537968Sbostic _PATH_VFONTB, 21637968Sbostic _PATH_VFONTS, 21712111Sralph }; 21812111Sralph 21912111Sralph /* 22012111Sralph * The remaining part is the reading of the control file (cf) 22112111Sralph * and performing the various actions. 22212111Sralph */ 22312111Sralph printit(file) 22412111Sralph char *file; 22512111Sralph { 22612111Sralph register int i; 22717463Sralph char *cp; 22817463Sralph int bombed = OK; 22912111Sralph 23012111Sralph /* 23117463Sralph * open control file; ignore if no longer there. 23212111Sralph */ 23312111Sralph if ((cfp = fopen(file, "r")) == NULL) { 23416762Sralph syslog(LOG_INFO, "%s: %s: %m", printer, file); 23517463Sralph return(OK); 23612111Sralph } 23712111Sralph /* 23812111Sralph * Reset troff fonts. 23912111Sralph */ 24012111Sralph for (i = 0; i < 4; i++) 24112111Sralph strcpy(fonts[i], ifonts[i]); 24217339Sralph strcpy(width+2, "0"); 24317302Sralph strcpy(indent+2, "0"); 24412111Sralph 24512111Sralph /* 24612111Sralph * read the control file for work to do 24712111Sralph * 24812111Sralph * file format -- first character in the line is a command 24912111Sralph * rest of the line is the argument. 25012111Sralph * valid commands are: 25112111Sralph * 25217463Sralph * S -- "stat info" for symbolic link protection 25312111Sralph * J -- "job name" on banner page 25412111Sralph * C -- "class name" on banner page 25512111Sralph * L -- "literal" user's name to print on banner 25612111Sralph * T -- "title" for pr 25712111Sralph * H -- "host name" of machine where lpr was done 25812111Sralph * P -- "person" user's login name 25912581Sralph * I -- "indent" amount to indent output 26012111Sralph * f -- "file name" name of text file to print 26112111Sralph * l -- "file name" text file with control chars 26212111Sralph * p -- "file name" text file to print with pr(1) 26312111Sralph * t -- "file name" troff(1) file to print 26413233Sralph * n -- "file name" ditroff(1) file to print 26512111Sralph * d -- "file name" dvi file to print 26612111Sralph * g -- "file name" plot(1G) file to print 26712111Sralph * v -- "file name" plain raster file to print 26812111Sralph * c -- "file name" cifplot file to print 26912111Sralph * 1 -- "R font file" for troff 27012111Sralph * 2 -- "I font file" for troff 27112111Sralph * 3 -- "B font file" for troff 27212111Sralph * 4 -- "S font file" for troff 27312111Sralph * N -- "name" of file (used by lpq) 27412111Sralph * U -- "unlink" name of file to remove 27512111Sralph * (after we print it. (Pass 2 only)). 27612111Sralph * M -- "mail" to user when done printing 27712111Sralph * 27812111Sralph * getline reads a line and expands tabs to blanks 27912111Sralph */ 28012111Sralph 28112111Sralph /* pass 1 */ 28212111Sralph 28312111Sralph while (getline(cfp)) 28412111Sralph switch (line[0]) { 28512111Sralph case 'H': 28614150Sralph strcpy(fromhost, line+1); 28712111Sralph if (class[0] == '\0') 28815552Sralph strncpy(class, line+1, sizeof(class)-1); 28912111Sralph continue; 29012111Sralph 29112111Sralph case 'P': 29215552Sralph strncpy(logname, line+1, sizeof(logname)-1); 29312463Sralph if (RS) { /* restricted */ 29412463Sralph if (getpwnam(logname) == (struct passwd *)0) { 29517463Sralph bombed = NOACCT; 29615811Sralph sendmail(line+1, bombed); 29712463Sralph goto pass2; 29812463Sralph } 29912463Sralph } 30012111Sralph continue; 30112111Sralph 30217463Sralph case 'S': 30317463Sralph cp = line+1; 30417463Sralph i = 0; 30517463Sralph while (*cp >= '0' && *cp <= '9') 30617463Sralph i = i * 10 + (*cp++ - '0'); 30717463Sralph fdev = i; 30817463Sralph cp++; 30917463Sralph i = 0; 31017463Sralph while (*cp >= '0' && *cp <= '9') 31117463Sralph i = i * 10 + (*cp++ - '0'); 31217463Sralph fino = i; 31317463Sralph continue; 31417463Sralph 31512111Sralph case 'J': 31612111Sralph if (line[1] != '\0') 31715552Sralph strncpy(jobname, line+1, sizeof(jobname)-1); 31812111Sralph else 31912111Sralph strcpy(jobname, " "); 32012111Sralph continue; 32112111Sralph 32212111Sralph case 'C': 32312111Sralph if (line[1] != '\0') 32415552Sralph strncpy(class, line+1, sizeof(class)-1); 32512111Sralph else if (class[0] == '\0') 32615811Sralph gethostname(class, sizeof(class)); 32712111Sralph continue; 32812111Sralph 32912111Sralph case 'T': /* header title for pr */ 33015552Sralph strncpy(title, line+1, sizeof(title)-1); 33112111Sralph continue; 33212111Sralph 33312111Sralph case 'L': /* identification line */ 33418127Sralph if (!SH && !HL) 33512111Sralph banner(line+1, jobname); 33612111Sralph continue; 33712111Sralph 33812111Sralph case '1': /* troff fonts */ 33912111Sralph case '2': 34012111Sralph case '3': 34112111Sralph case '4': 34212111Sralph if (line[1] != '\0') 34312111Sralph strcpy(fonts[line[0]-'1'], line+1); 34412111Sralph continue; 34512111Sralph 34612111Sralph case 'W': /* page width */ 34715552Sralph strncpy(width+2, line+1, sizeof(width)-3); 34812111Sralph continue; 34912111Sralph 35012581Sralph case 'I': /* indent amount */ 35115552Sralph strncpy(indent+2, line+1, sizeof(indent)-3); 35212581Sralph continue; 35312581Sralph 35412111Sralph default: /* some file to print */ 35515811Sralph switch (i = print(line[0], line+1)) { 35617463Sralph case ERROR: 35717463Sralph if (bombed == OK) 35817463Sralph bombed = FATALERR; 35915811Sralph break; 36017463Sralph case REPRINT: 36112111Sralph (void) fclose(cfp); 36217463Sralph return(REPRINT); 36317463Sralph case FILTERERR: 36417463Sralph case ACCESS: 36517463Sralph bombed = i; 36615811Sralph sendmail(logname, bombed); 36715811Sralph } 36812111Sralph title[0] = '\0'; 36912111Sralph continue; 37012111Sralph 37112111Sralph case 'N': 37212111Sralph case 'U': 37312111Sralph case 'M': 37412111Sralph continue; 37512111Sralph } 37612111Sralph 37712111Sralph /* pass 2 */ 37812111Sralph 37912463Sralph pass2: 38012111Sralph fseek(cfp, 0L, 0); 38112111Sralph while (getline(cfp)) 38212111Sralph switch (line[0]) { 38318127Sralph case 'L': /* identification line */ 38418127Sralph if (!SH && HL) 38518127Sralph banner(line+1, jobname); 38618127Sralph continue; 38718127Sralph 38812111Sralph case 'M': 38917463Sralph if (bombed < NOACCT) /* already sent if >= NOACCT */ 39015811Sralph sendmail(line+1, bombed); 39112111Sralph continue; 39212111Sralph 39312111Sralph case 'U': 39412111Sralph (void) unlink(line+1); 39512111Sralph } 39612111Sralph /* 39715811Sralph * clean-up in case another control file exists 39812111Sralph */ 39912111Sralph (void) fclose(cfp); 40012111Sralph (void) unlink(file); 40117463Sralph return(bombed == OK ? OK : ERROR); 40212111Sralph } 40312111Sralph 40412111Sralph /* 40512111Sralph * Print a file. 40613233Sralph * Set up the chain [ PR [ | {IF, OF} ] ] or {IF, RF, TF, NF, DF, CF, VF}. 40715811Sralph * Return -1 if a non-recoverable error occured, 40815811Sralph * 2 if the filter detected some errors (but printed the job anyway), 40915811Sralph * 1 if we should try to reprint this job and 41012111Sralph * 0 if all is well. 41112111Sralph * Note: all filters take stdin as the file, stdout as the printer, 41212111Sralph * stderr as the log file, and must not ignore SIGINT. 41312111Sralph */ 41412111Sralph print(format, file) 41512111Sralph int format; 41612111Sralph char *file; 41712111Sralph { 41815811Sralph register int n; 41912111Sralph register char *prog; 42015811Sralph int fi, fo; 42139954Smckusick FILE *fp; 42212111Sralph char *av[15], buf[BUFSIZ]; 42312111Sralph int pid, p[2], stopped = 0; 42412111Sralph union wait status; 42517463Sralph struct stat stb; 42612111Sralph 42717463Sralph if (lstat(file, &stb) < 0 || (fi = open(file, O_RDONLY)) < 0) 42817463Sralph return(ERROR); 42917463Sralph /* 43017463Sralph * Check to see if data file is a symbolic link. If so, it should 43117463Sralph * still point to the same file or someone is trying to print 43217463Sralph * something he shouldn't. 43317463Sralph */ 43417463Sralph if ((stb.st_mode & S_IFMT) == S_IFLNK && fstat(fi, &stb) == 0 && 43517463Sralph (stb.st_dev != fdev || stb.st_ino != fino)) 43617463Sralph return(ACCESS); 43712111Sralph if (!SF && !tof) { /* start on a fresh page */ 43812111Sralph (void) write(ofd, FF, strlen(FF)); 43912111Sralph tof = 1; 44012111Sralph } 44112111Sralph if (IF == NULL && (format == 'f' || format == 'l')) { 44212111Sralph tof = 0; 44312111Sralph while ((n = read(fi, buf, BUFSIZ)) > 0) 44412111Sralph if (write(ofd, buf, n) != n) { 44512111Sralph (void) close(fi); 44617463Sralph return(REPRINT); 44712111Sralph } 44812111Sralph (void) close(fi); 44917463Sralph return(OK); 45012111Sralph } 45112111Sralph switch (format) { 45212111Sralph case 'p': /* print file using 'pr' */ 45312111Sralph if (IF == NULL) { /* use output filter */ 45437968Sbostic prog = _PATH_PR; 45512111Sralph av[0] = "pr"; 45612111Sralph av[1] = width; 45712111Sralph av[2] = length; 45812111Sralph av[3] = "-h"; 45912111Sralph av[4] = *title ? title : " "; 46012111Sralph av[5] = 0; 46112111Sralph fo = ofd; 46212111Sralph goto start; 46312111Sralph } 46412111Sralph pipe(p); 46512111Sralph if ((prchild = dofork(DORETURN)) == 0) { /* child */ 46612111Sralph dup2(fi, 0); /* file is stdin */ 46712111Sralph dup2(p[1], 1); /* pipe is stdout */ 46812111Sralph for (n = 3; n < NOFILE; n++) 46912111Sralph (void) close(n); 47037968Sbostic execl(_PATH_PR, "pr", width, length, 47137968Sbostic "-h", *title ? title : " ", 0); 47237968Sbostic syslog(LOG_ERR, "cannot execl %s", _PATH_PR); 47312111Sralph exit(2); 47412111Sralph } 47512111Sralph (void) close(p[1]); /* close output side */ 47612111Sralph (void) close(fi); 47712111Sralph if (prchild < 0) { 47812111Sralph prchild = 0; 47912111Sralph (void) close(p[0]); 48017463Sralph return(ERROR); 48112111Sralph } 48212111Sralph fi = p[0]; /* use pipe for input */ 48312111Sralph case 'f': /* print plain text file */ 48412111Sralph prog = IF; 48512111Sralph av[1] = width; 48612111Sralph av[2] = length; 48712581Sralph av[3] = indent; 48812581Sralph n = 4; 48912111Sralph break; 49012111Sralph case 'l': /* like 'f' but pass control characters */ 49112111Sralph prog = IF; 49214325Sralph av[1] = "-c"; 49312111Sralph av[2] = width; 49412111Sralph av[3] = length; 49512581Sralph av[4] = indent; 49612581Sralph n = 5; 49712111Sralph break; 49812463Sralph case 'r': /* print a fortran text file */ 49912463Sralph prog = RF; 50012463Sralph av[1] = width; 50112463Sralph av[2] = length; 50212463Sralph n = 3; 50312463Sralph break; 50412111Sralph case 't': /* print troff output */ 50513233Sralph case 'n': /* print ditroff output */ 50612463Sralph case 'd': /* print tex output */ 50712111Sralph (void) unlink(".railmag"); 50812463Sralph if ((fo = creat(".railmag", FILMOD)) < 0) { 50916762Sralph syslog(LOG_ERR, "%s: cannot create .railmag", printer); 51012111Sralph (void) unlink(".railmag"); 51112111Sralph } else { 51212111Sralph for (n = 0; n < 4; n++) { 51312111Sralph if (fonts[n][0] != '/') 51437968Sbostic (void) write(fo, _PATH_VFONT, 15); 51512111Sralph (void) write(fo, fonts[n], strlen(fonts[n])); 51612111Sralph (void) write(fo, "\n", 1); 51712111Sralph } 51812111Sralph (void) close(fo); 51912111Sralph } 52013233Sralph prog = (format == 't') ? TF : (format == 'n') ? NF : DF; 52112463Sralph av[1] = pxwidth; 52212463Sralph av[2] = pxlength; 52312463Sralph n = 3; 52412111Sralph break; 52512111Sralph case 'c': /* print cifplot output */ 52612111Sralph prog = CF; 52712463Sralph av[1] = pxwidth; 52812463Sralph av[2] = pxlength; 52912463Sralph n = 3; 53012111Sralph break; 53112111Sralph case 'g': /* print plot(1G) output */ 53212111Sralph prog = GF; 53312463Sralph av[1] = pxwidth; 53412463Sralph av[2] = pxlength; 53512463Sralph n = 3; 53612111Sralph break; 53712111Sralph case 'v': /* print raster output */ 53812111Sralph prog = VF; 53912463Sralph av[1] = pxwidth; 54012463Sralph av[2] = pxlength; 54112463Sralph n = 3; 54212111Sralph break; 54312111Sralph default: 54412111Sralph (void) close(fi); 54516762Sralph syslog(LOG_ERR, "%s: illegal format character '%c'", 54616762Sralph printer, format); 54717463Sralph return(ERROR); 54812111Sralph } 54912111Sralph if ((av[0] = rindex(prog, '/')) != NULL) 55012111Sralph av[0]++; 55112111Sralph else 55212111Sralph av[0] = prog; 55312111Sralph av[n++] = "-n"; 55412111Sralph av[n++] = logname; 55512111Sralph av[n++] = "-h"; 55614150Sralph av[n++] = fromhost; 55712111Sralph av[n++] = AF; 55812111Sralph av[n] = 0; 55912111Sralph fo = pfd; 56012111Sralph if (ofilter > 0) { /* stop output filter */ 56112111Sralph write(ofd, "\031\1", 2); 56212111Sralph while ((pid = wait3(&status, WUNTRACED, 0)) > 0 && pid != ofilter) 56312111Sralph ; 56412111Sralph if (status.w_stopval != WSTOPPED) { 56512111Sralph (void) close(fi); 56616762Sralph syslog(LOG_WARNING, "%s: output filter died (%d)", 56716762Sralph printer, status.w_retcode); 56817463Sralph return(REPRINT); 56912111Sralph } 57012111Sralph stopped++; 57112111Sralph } 57212111Sralph start: 57312111Sralph if ((child = dofork(DORETURN)) == 0) { /* child */ 57412111Sralph dup2(fi, 0); 57512111Sralph dup2(fo, 1); 57639954Smckusick n = open(tempfile, O_WRONLY|O_CREAT|O_TRUNC, 0664); 57715811Sralph if (n >= 0) 57815811Sralph dup2(n, 2); 57912111Sralph for (n = 3; n < NOFILE; n++) 58012111Sralph (void) close(n); 58112111Sralph execv(prog, av); 58216762Sralph syslog(LOG_ERR, "cannot execv %s", prog); 58312111Sralph exit(2); 58412111Sralph } 58512111Sralph (void) close(fi); 58612111Sralph if (child < 0) 58712111Sralph status.w_retcode = 100; 58812111Sralph else 58912111Sralph while ((pid = wait(&status)) > 0 && pid != child) 59012111Sralph ; 59112111Sralph child = 0; 59212111Sralph prchild = 0; 59312111Sralph if (stopped) { /* restart output filter */ 59412111Sralph if (kill(ofilter, SIGCONT) < 0) { 59516762Sralph syslog(LOG_ERR, "cannot restart output filter"); 59612111Sralph exit(1); 59712111Sralph } 59812111Sralph } 59912111Sralph tof = 0; 60039954Smckusick 60139954Smckusick /* Copy filter output to "lf" logfile */ 60239954Smckusick if (fp = fopen(tempfile, "r")) { 60339954Smckusick char tbuf[512]; 60439954Smckusick 60539954Smckusick while (fgets(buf, sizeof(buf), fp)) 60639954Smckusick fputs(buf, stderr); 60739954Smckusick close(fp); 60839954Smckusick } 60939954Smckusick 61015811Sralph if (!WIFEXITED(status)) { 61116762Sralph syslog(LOG_WARNING, "%s: Daemon filter '%c' terminated (%d)", 61216762Sralph printer, format, status.w_termsig); 61317463Sralph return(ERROR); 61417463Sralph } 61517463Sralph switch (status.w_retcode) { 61617463Sralph case 0: 61717463Sralph tof = 1; 61817463Sralph return(OK); 61917463Sralph case 1: 62017463Sralph return(REPRINT); 62117463Sralph default: 62216762Sralph syslog(LOG_WARNING, "%s: Daemon filter '%c' exited (%d)", 62316762Sralph printer, format, status.w_retcode); 62417463Sralph case 2: 62517463Sralph return(ERROR); 62617463Sralph } 62712111Sralph } 62812111Sralph 62912111Sralph /* 63012111Sralph * Send the daemon control file (cf) and any data files. 63112111Sralph * Return -1 if a non-recoverable error occured, 1 if a recoverable error and 63212111Sralph * 0 if all is well. 63312111Sralph */ 63412111Sralph sendit(file) 63512111Sralph char *file; 63612111Sralph { 63717463Sralph register int i, err = OK; 63817463Sralph char *cp, last[BUFSIZ]; 63912111Sralph 64012111Sralph /* 64112111Sralph * open control file 64212111Sralph */ 64316762Sralph if ((cfp = fopen(file, "r")) == NULL) 64417463Sralph return(OK); 64512111Sralph /* 64612111Sralph * read the control file for work to do 64712111Sralph * 64812111Sralph * file format -- first character in the line is a command 64912111Sralph * rest of the line is the argument. 65012111Sralph * commands of interest are: 65112111Sralph * 65212111Sralph * a-z -- "file name" name of file to print 65312111Sralph * U -- "unlink" name of file to remove 65412111Sralph * (after we print it. (Pass 2 only)). 65512111Sralph */ 65612111Sralph 65712111Sralph /* 65812111Sralph * pass 1 65912111Sralph */ 66012111Sralph while (getline(cfp)) { 66112111Sralph again: 66217463Sralph if (line[0] == 'S') { 66317463Sralph cp = line+1; 66417463Sralph i = 0; 66517463Sralph while (*cp >= '0' && *cp <= '9') 66617463Sralph i = i * 10 + (*cp++ - '0'); 66717463Sralph fdev = i; 66817463Sralph cp++; 66917463Sralph i = 0; 67017463Sralph while (*cp >= '0' && *cp <= '9') 67117463Sralph i = i * 10 + (*cp++ - '0'); 67217463Sralph fino = i; 67317463Sralph continue; 67417463Sralph } 67512111Sralph if (line[0] >= 'a' && line[0] <= 'z') { 67612111Sralph strcpy(last, line); 67717463Sralph while (i = getline(cfp)) 67812111Sralph if (strcmp(last, line)) 67912111Sralph break; 68017463Sralph switch (sendfile('\3', last+1)) { 68117463Sralph case OK: 68217463Sralph if (i) 68317463Sralph goto again; 68417463Sralph break; 68517463Sralph case REPRINT: 68612111Sralph (void) fclose(cfp); 68717463Sralph return(REPRINT); 68817463Sralph case ACCESS: 68917463Sralph sendmail(logname, ACCESS); 69017463Sralph case ERROR: 69117463Sralph err = ERROR; 69217463Sralph } 69312111Sralph break; 69412111Sralph } 69512111Sralph } 69617463Sralph if (err == OK && sendfile('\2', file) > 0) { 69712111Sralph (void) fclose(cfp); 69817463Sralph return(REPRINT); 69912111Sralph } 70012111Sralph /* 70112111Sralph * pass 2 70212111Sralph */ 70312111Sralph fseek(cfp, 0L, 0); 70412111Sralph while (getline(cfp)) 70512111Sralph if (line[0] == 'U') 70612111Sralph (void) unlink(line+1); 70712111Sralph /* 70817463Sralph * clean-up in case another control file exists 70912111Sralph */ 71012111Sralph (void) fclose(cfp); 71112111Sralph (void) unlink(file); 71217463Sralph return(err); 71312111Sralph } 71412111Sralph 71512111Sralph /* 71612111Sralph * Send a data file to the remote machine and spool it. 71712111Sralph * Return positive if we should try resending. 71812111Sralph */ 71912111Sralph sendfile(type, file) 72012111Sralph char type, *file; 72112111Sralph { 72212111Sralph register int f, i, amt; 72312111Sralph struct stat stb; 72412111Sralph char buf[BUFSIZ]; 72516762Sralph int sizerr, resp; 72612111Sralph 72717463Sralph if (lstat(file, &stb) < 0 || (f = open(file, O_RDONLY)) < 0) 72817463Sralph return(ERROR); 72917463Sralph /* 73017463Sralph * Check to see if data file is a symbolic link. If so, it should 73117463Sralph * still point to the same file or someone is trying to print something 73217463Sralph * he shouldn't. 73317463Sralph */ 73417463Sralph if ((stb.st_mode & S_IFMT) == S_IFLNK && fstat(f, &stb) == 0 && 73517463Sralph (stb.st_dev != fdev || stb.st_ino != fino)) 73617463Sralph return(ACCESS); 73712111Sralph (void) sprintf(buf, "%c%d %s\n", type, stb.st_size, file); 73812111Sralph amt = strlen(buf); 73916762Sralph for (i = 0; ; i++) { 74016762Sralph if (write(pfd, buf, amt) != amt || 74116762Sralph (resp = response()) < 0 || resp == '\1') { 74216762Sralph (void) close(f); 74317463Sralph return(REPRINT); 74416762Sralph } else if (resp == '\0') 74516762Sralph break; 74616762Sralph if (i == 0) 74716762Sralph status("no space on remote; waiting for queue to drain"); 74816762Sralph if (i == 10) 74924861Seric syslog(LOG_ALERT, "%s: can't send to %s; queue full", 75016762Sralph printer, RM); 75116762Sralph sleep(5 * 60); 75212692Sralph } 75316762Sralph if (i) 75416762Sralph status("sending to %s", RM); 75512111Sralph sizerr = 0; 75612111Sralph for (i = 0; i < stb.st_size; i += BUFSIZ) { 75712111Sralph amt = BUFSIZ; 75812111Sralph if (i + amt > stb.st_size) 75912111Sralph amt = stb.st_size - i; 76012111Sralph if (sizerr == 0 && read(f, buf, amt) != amt) 76112111Sralph sizerr = 1; 76212692Sralph if (write(pfd, buf, amt) != amt) { 76312692Sralph (void) close(f); 76417463Sralph return(REPRINT); 76512692Sralph } 76612111Sralph } 76712111Sralph (void) close(f); 76812111Sralph if (sizerr) { 76916762Sralph syslog(LOG_INFO, "%s: %s: changed size", printer, file); 77017463Sralph /* tell recvjob to ignore this file */ 77117463Sralph (void) write(pfd, "\1", 1); 77217463Sralph return(ERROR); 77317463Sralph } 77417463Sralph if (write(pfd, "", 1) != 1 || response()) 77517463Sralph return(REPRINT); 77617463Sralph return(OK); 77712111Sralph } 77812111Sralph 77912111Sralph /* 78012111Sralph * Check to make sure there have been no errors and that both programs 78112111Sralph * are in sync with eachother. 78212111Sralph * Return non-zero if the connection was lost. 78312111Sralph */ 78416762Sralph response() 78512111Sralph { 78612111Sralph char resp; 78712111Sralph 78816762Sralph if (read(pfd, &resp, 1) != 1) { 78916762Sralph syslog(LOG_INFO, "%s: lost connection", printer); 79016762Sralph return(-1); 79112111Sralph } 79216762Sralph return(resp); 79312111Sralph } 79412111Sralph 79512111Sralph /* 79612111Sralph * Banner printing stuff 79712111Sralph */ 79812111Sralph banner(name1, name2) 79912111Sralph char *name1, *name2; 80012111Sralph { 80112111Sralph time_t tvec; 80212111Sralph extern char *ctime(); 80312111Sralph 80412111Sralph time(&tvec); 80512111Sralph if (!SF && !tof) 80612111Sralph (void) write(ofd, FF, strlen(FF)); 80712111Sralph if (SB) { /* short banner only */ 80812111Sralph if (class[0]) { 80912111Sralph (void) write(ofd, class, strlen(class)); 81012111Sralph (void) write(ofd, ":", 1); 81112111Sralph } 81212111Sralph (void) write(ofd, name1, strlen(name1)); 81312111Sralph (void) write(ofd, " Job: ", 7); 81412111Sralph (void) write(ofd, name2, strlen(name2)); 81512111Sralph (void) write(ofd, " Date: ", 8); 81612111Sralph (void) write(ofd, ctime(&tvec), 24); 81712111Sralph (void) write(ofd, "\n", 1); 81812111Sralph } else { /* normal banner */ 81912111Sralph (void) write(ofd, "\n\n\n", 3); 82012111Sralph scan_out(ofd, name1, '\0'); 82112111Sralph (void) write(ofd, "\n\n", 2); 82212111Sralph scan_out(ofd, name2, '\0'); 82312111Sralph if (class[0]) { 82412111Sralph (void) write(ofd,"\n\n\n",3); 82512111Sralph scan_out(ofd, class, '\0'); 82612111Sralph } 82712111Sralph (void) write(ofd, "\n\n\n\n\t\t\t\t\tJob: ", 15); 82812111Sralph (void) write(ofd, name2, strlen(name2)); 82912111Sralph (void) write(ofd, "\n\t\t\t\t\tDate: ", 12); 83012111Sralph (void) write(ofd, ctime(&tvec), 24); 83112111Sralph (void) write(ofd, "\n", 1); 83212111Sralph } 83312111Sralph if (!SF) 83412111Sralph (void) write(ofd, FF, strlen(FF)); 83512111Sralph tof = 1; 83612111Sralph } 83712111Sralph 83816762Sralph char * 83912111Sralph scnline(key, p, c) 84012111Sralph register char key, *p; 84112111Sralph char c; 84212111Sralph { 84312111Sralph register scnwidth; 84412111Sralph 84512111Sralph for (scnwidth = WIDTH; --scnwidth;) { 84612111Sralph key <<= 1; 84712111Sralph *p++ = key & 0200 ? c : BACKGND; 84812111Sralph } 84912111Sralph return (p); 85012111Sralph } 85112111Sralph 85212111Sralph #define TRC(q) (((q)-' ')&0177) 85312111Sralph 85412111Sralph scan_out(scfd, scsp, dlm) 85512111Sralph int scfd; 85612111Sralph char *scsp, dlm; 85712111Sralph { 85812111Sralph register char *strp; 85912111Sralph register nchrs, j; 86012111Sralph char outbuf[LINELEN+1], *sp, c, cc; 86112111Sralph int d, scnhgt; 86212111Sralph extern char scnkey[][HEIGHT]; /* in lpdchar.c */ 86312111Sralph 86412111Sralph for (scnhgt = 0; scnhgt++ < HEIGHT+DROP; ) { 86512111Sralph strp = &outbuf[0]; 86612111Sralph sp = scsp; 86712111Sralph for (nchrs = 0; ; ) { 86812111Sralph d = dropit(c = TRC(cc = *sp++)); 86912111Sralph if ((!d && scnhgt > HEIGHT) || (scnhgt <= DROP && d)) 87012111Sralph for (j = WIDTH; --j;) 87112111Sralph *strp++ = BACKGND; 87212111Sralph else 87312111Sralph strp = scnline(scnkey[c][scnhgt-1-d], strp, cc); 87412111Sralph if (*sp == dlm || *sp == '\0' || nchrs++ >= PW/(WIDTH+1)-1) 87512111Sralph break; 87612111Sralph *strp++ = BACKGND; 87712111Sralph *strp++ = BACKGND; 87812111Sralph } 87912111Sralph while (*--strp == BACKGND && strp >= outbuf) 88012111Sralph ; 88112111Sralph strp++; 88212111Sralph *strp++ = '\n'; 88312111Sralph (void) write(scfd, outbuf, strp-outbuf); 88412111Sralph } 88512111Sralph } 88612111Sralph 88712111Sralph dropit(c) 88812111Sralph char c; 88912111Sralph { 89012111Sralph switch(c) { 89112111Sralph 89212111Sralph case TRC('_'): 89312111Sralph case TRC(';'): 89412111Sralph case TRC(','): 89512111Sralph case TRC('g'): 89612111Sralph case TRC('j'): 89712111Sralph case TRC('p'): 89812111Sralph case TRC('q'): 89912111Sralph case TRC('y'): 90012111Sralph return (DROP); 90112111Sralph 90212111Sralph default: 90312111Sralph return (0); 90412111Sralph } 90512111Sralph } 90612111Sralph 90712111Sralph /* 90812111Sralph * sendmail --- 90912111Sralph * tell people about job completion 91012111Sralph */ 91115811Sralph sendmail(user, bombed) 91215811Sralph char *user; 91312111Sralph int bombed; 91412111Sralph { 91512111Sralph register int i; 91615811Sralph int p[2], s; 91712111Sralph register char *cp; 91812111Sralph char buf[100]; 91915811Sralph struct stat stb; 92015811Sralph FILE *fp; 92112111Sralph 92212111Sralph pipe(p); 92315811Sralph if ((s = dofork(DORETURN)) == 0) { /* child */ 92412111Sralph dup2(p[0], 0); 92512111Sralph for (i = 3; i < NOFILE; i++) 92612111Sralph (void) close(i); 92737968Sbostic if ((cp = rindex(_PATH_SENDMAIL, '/')) != NULL) 92812111Sralph cp++; 92912111Sralph else 93037968Sbostic cp = _PATH_SENDMAIL; 93115811Sralph sprintf(buf, "%s@%s", user, fromhost); 93237968Sbostic execl(_PATH_SENDMAIL, cp, buf, 0); 93312111Sralph exit(0); 93415811Sralph } else if (s > 0) { /* parent */ 93512111Sralph dup2(p[1], 1); 93615811Sralph printf("To: %s@%s\n", user, fromhost); 93712111Sralph printf("Subject: printer job\n\n"); 93812111Sralph printf("Your printer job "); 93912111Sralph if (*jobname) 94012111Sralph printf("(%s) ", jobname); 94112463Sralph switch (bombed) { 94217463Sralph case OK: 94312463Sralph printf("\ncompleted successfully\n"); 94412463Sralph break; 94512463Sralph default: 94617463Sralph case FATALERR: 94712463Sralph printf("\ncould not be printed\n"); 94812463Sralph break; 94917463Sralph case NOACCT: 95012463Sralph printf("\ncould not be printed without an account on %s\n", host); 95112463Sralph break; 95217463Sralph case FILTERERR: 95339954Smckusick if (stat(tempfile, &stb) < 0 || stb.st_size == 0 || 95439954Smckusick (fp = fopen(tempfile, "r")) == NULL) { 95515811Sralph printf("\nwas printed but had some errors\n"); 95615811Sralph break; 95715811Sralph } 95815811Sralph printf("\nwas printed but had the following errors:\n"); 95915811Sralph while ((i = getc(fp)) != EOF) 96015811Sralph putchar(i); 96115811Sralph (void) fclose(fp); 96217463Sralph break; 96317463Sralph case ACCESS: 96417463Sralph printf("\nwas not printed because it was not linked to the original file\n"); 96512463Sralph } 96612111Sralph fflush(stdout); 96712111Sralph (void) close(1); 96812111Sralph } 96912111Sralph (void) close(p[0]); 97012111Sralph (void) close(p[1]); 97115811Sralph wait(&s); 97212111Sralph } 97312111Sralph 97412111Sralph /* 97512111Sralph * dofork - fork with retries on failure 97612111Sralph */ 97712111Sralph dofork(action) 97812111Sralph int action; 97912111Sralph { 98012111Sralph register int i, pid; 98112111Sralph 98212111Sralph for (i = 0; i < 20; i++) { 98312463Sralph if ((pid = fork()) < 0) { 98412111Sralph sleep((unsigned)(i*i)); 98512463Sralph continue; 98612463Sralph } 98712463Sralph /* 98812463Sralph * Child should run as daemon instead of root 98912463Sralph */ 99012463Sralph if (pid == 0) 99112463Sralph setuid(DU); 99212463Sralph return(pid); 99312111Sralph } 99416762Sralph syslog(LOG_ERR, "can't fork"); 99512111Sralph 99612111Sralph switch (action) { 99712111Sralph case DORETURN: 99812111Sralph return (-1); 99912111Sralph default: 100016762Sralph syslog(LOG_ERR, "bad action (%d) to dofork", action); 100112111Sralph /*FALL THRU*/ 100212111Sralph case DOABORT: 100312111Sralph exit(1); 100412111Sralph } 100512111Sralph /*NOTREACHED*/ 100612111Sralph } 100712111Sralph 100812111Sralph /* 100916762Sralph * Kill child processes to abort current job. 101012111Sralph */ 101116762Sralph abortpr() 101212111Sralph { 101339954Smckusick (void) unlink(tempfile); 101412111Sralph kill(0, SIGINT); 101512111Sralph if (ofilter > 0) 101612111Sralph kill(ofilter, SIGCONT); 101712111Sralph while (wait(0) > 0) 101812111Sralph ; 101912111Sralph exit(0); 102012111Sralph } 102112111Sralph 102212111Sralph init() 102312111Sralph { 102412111Sralph int status; 102538736Stef char *s; 102612111Sralph 102725468Stef if ((status = pgetent(line, printer)) < 0) { 102825468Stef syslog(LOG_ERR, "can't open printer description file"); 102925468Stef exit(1); 103025468Stef } else if (status == 0) { 103125468Stef syslog(LOG_ERR, "unknown printer: %s", printer); 103225468Stef exit(1); 103325468Stef } 103412111Sralph if ((LP = pgetstr("lp", &bp)) == NULL) 103537968Sbostic LP = _PATH_DEFDEVLP; 103612111Sralph if ((RP = pgetstr("rp", &bp)) == NULL) 103712463Sralph RP = DEFLP; 103812111Sralph if ((LO = pgetstr("lo", &bp)) == NULL) 103912111Sralph LO = DEFLOCK; 104012111Sralph if ((ST = pgetstr("st", &bp)) == NULL) 104112111Sralph ST = DEFSTAT; 104212111Sralph if ((LF = pgetstr("lf", &bp)) == NULL) 104337968Sbostic LF = _PATH_CONSOLE; 104412111Sralph if ((SD = pgetstr("sd", &bp)) == NULL) 104537968Sbostic SD = _PATH_DEFSPOOL; 104612111Sralph if ((DU = pgetnum("du")) < 0) 104712111Sralph DU = DEFUID; 104812111Sralph if ((FF = pgetstr("ff", &bp)) == NULL) 104912111Sralph FF = DEFFF; 105012111Sralph if ((PW = pgetnum("pw")) < 0) 105112111Sralph PW = DEFWIDTH; 105212111Sralph sprintf(&width[2], "%d", PW); 105312111Sralph if ((PL = pgetnum("pl")) < 0) 105412111Sralph PL = DEFLENGTH; 105512111Sralph sprintf(&length[2], "%d", PL); 105612463Sralph if ((PX = pgetnum("px")) < 0) 105712463Sralph PX = 0; 105812463Sralph sprintf(&pxwidth[2], "%d", PX); 105912463Sralph if ((PY = pgetnum("py")) < 0) 106012463Sralph PY = 0; 106112463Sralph sprintf(&pxlength[2], "%d", PY); 106212111Sralph RM = pgetstr("rm", &bp); 106338736Stef if (s = checkremote()) 106438736Stef syslog(LOG_WARNING, s); 106525468Stef 106612111Sralph AF = pgetstr("af", &bp); 106712111Sralph OF = pgetstr("of", &bp); 106812111Sralph IF = pgetstr("if", &bp); 106912463Sralph RF = pgetstr("rf", &bp); 107012111Sralph TF = pgetstr("tf", &bp); 107113233Sralph NF = pgetstr("nf", &bp); 107212111Sralph DF = pgetstr("df", &bp); 107312111Sralph GF = pgetstr("gf", &bp); 107412111Sralph VF = pgetstr("vf", &bp); 107512111Sralph CF = pgetstr("cf", &bp); 107612111Sralph TR = pgetstr("tr", &bp); 107712463Sralph RS = pgetflag("rs"); 107812111Sralph SF = pgetflag("sf"); 107912111Sralph SH = pgetflag("sh"); 108012111Sralph SB = pgetflag("sb"); 108118127Sralph HL = pgetflag("hl"); 108212111Sralph RW = pgetflag("rw"); 108312111Sralph BR = pgetnum("br"); 108412111Sralph if ((FC = pgetnum("fc")) < 0) 108512111Sralph FC = 0; 108612111Sralph if ((FS = pgetnum("fs")) < 0) 108712111Sralph FS = 0; 108812111Sralph if ((XC = pgetnum("xc")) < 0) 108912111Sralph XC = 0; 109012111Sralph if ((XS = pgetnum("xs")) < 0) 109112111Sralph XS = 0; 109212581Sralph tof = !pgetflag("fo"); 109312111Sralph } 109412111Sralph 109512463Sralph /* 109612463Sralph * Acquire line printer or remote connection. 109712463Sralph */ 109812463Sralph openpr() 109912463Sralph { 110012463Sralph register int i, n; 110116762Sralph int resp; 110212463Sralph 110338736Stef if (!sendtorem && *LP) { 110412463Sralph for (i = 1; ; i = i < 32 ? i << 1 : i) { 110513148Ssam pfd = open(LP, RW ? O_RDWR : O_WRONLY); 110612463Sralph if (pfd >= 0) 110712463Sralph break; 110812463Sralph if (errno == ENOENT) { 110916762Sralph syslog(LOG_ERR, "%s: %m", LP); 111012463Sralph exit(1); 111112463Sralph } 111212463Sralph if (i == 1) 111312463Sralph status("waiting for %s to become ready (offline ?)", printer); 111412463Sralph sleep(i); 111512463Sralph } 111612463Sralph if (isatty(pfd)) 111712463Sralph setty(); 111812463Sralph status("%s is ready and printing", printer); 111912463Sralph } else if (RM != NULL) { 112016762Sralph for (i = 1; ; i = i < 256 ? i << 1 : i) { 112116762Sralph resp = -1; 112212528Sralph pfd = getport(RM); 112312463Sralph if (pfd >= 0) { 112412463Sralph (void) sprintf(line, "\2%s\n", RP); 112512463Sralph n = strlen(line); 112616762Sralph if (write(pfd, line, n) == n && 112716762Sralph (resp = response()) == '\0') 112812463Sralph break; 112916031Sralph (void) close(pfd); 113012463Sralph } 113116031Sralph if (i == 1) { 113216762Sralph if (resp < 0) 113316031Sralph status("waiting for %s to come up", RM); 113416762Sralph else { 113516031Sralph status("waiting for queue to be enabled on %s", RM); 113616762Sralph i = 256; 113716762Sralph } 113816031Sralph } 113912463Sralph sleep(i); 114012463Sralph } 114112463Sralph status("sending to %s", RM); 114212463Sralph remote = 1; 114312463Sralph } else { 114416762Sralph syslog(LOG_ERR, "%s: no line printer device or host name", 114516762Sralph printer); 114612463Sralph exit(1); 114712463Sralph } 114812463Sralph /* 114912463Sralph * Start up an output filter, if needed. 115012463Sralph */ 115140049Stef if (!remote && OF) { 115212463Sralph int p[2]; 115312463Sralph char *cp; 115412463Sralph 115512463Sralph pipe(p); 115612463Sralph if ((ofilter = dofork(DOABORT)) == 0) { /* child */ 115712463Sralph dup2(p[0], 0); /* pipe is std in */ 115812463Sralph dup2(pfd, 1); /* printer is std out */ 115912463Sralph for (i = 3; i < NOFILE; i++) 116012463Sralph (void) close(i); 116112463Sralph if ((cp = rindex(OF, '/')) == NULL) 116212463Sralph cp = OF; 116312463Sralph else 116412463Sralph cp++; 116512463Sralph execl(OF, cp, width, length, 0); 116616762Sralph syslog(LOG_ERR, "%s: %s: %m", printer, OF); 116712463Sralph exit(1); 116812463Sralph } 116912463Sralph (void) close(p[0]); /* close input side */ 117012463Sralph ofd = p[1]; /* use pipe for output */ 117112463Sralph } else { 117212463Sralph ofd = pfd; 117312463Sralph ofilter = 0; 117412463Sralph } 117512463Sralph } 117612463Sralph 117712111Sralph struct bauds { 117812111Sralph int baud; 117912111Sralph int speed; 118012111Sralph } bauds[] = { 118112111Sralph 50, B50, 118212111Sralph 75, B75, 118312111Sralph 110, B110, 118412111Sralph 134, B134, 118512111Sralph 150, B150, 118612111Sralph 200, B200, 118712111Sralph 300, B300, 118812111Sralph 600, B600, 118912111Sralph 1200, B1200, 119012111Sralph 1800, B1800, 119112111Sralph 2400, B2400, 119212111Sralph 4800, B4800, 119312111Sralph 9600, B9600, 119412111Sralph 19200, EXTA, 119512111Sralph 38400, EXTB, 119612111Sralph 0, 0 119712111Sralph }; 119812111Sralph 119912111Sralph /* 120012111Sralph * setup tty lines. 120112111Sralph */ 120212111Sralph setty() 120312111Sralph { 120412111Sralph struct sgttyb ttybuf; 120512111Sralph register struct bauds *bp; 120612111Sralph 120712111Sralph if (ioctl(pfd, TIOCEXCL, (char *)0) < 0) { 120816762Sralph syslog(LOG_ERR, "%s: ioctl(TIOCEXCL): %m", printer); 120912111Sralph exit(1); 121012111Sralph } 121112111Sralph if (ioctl(pfd, TIOCGETP, (char *)&ttybuf) < 0) { 121216762Sralph syslog(LOG_ERR, "%s: ioctl(TIOCGETP): %m", printer); 121312111Sralph exit(1); 121412111Sralph } 121512111Sralph if (BR > 0) { 121612111Sralph for (bp = bauds; bp->baud; bp++) 121712111Sralph if (BR == bp->baud) 121812111Sralph break; 121912111Sralph if (!bp->baud) { 122016762Sralph syslog(LOG_ERR, "%s: illegal baud rate %d", printer, BR); 122112111Sralph exit(1); 122212111Sralph } 122312111Sralph ttybuf.sg_ispeed = ttybuf.sg_ospeed = bp->speed; 122412111Sralph } 122513169Sralph ttybuf.sg_flags &= ~FC; 122613169Sralph ttybuf.sg_flags |= FS; 122712111Sralph if (ioctl(pfd, TIOCSETP, (char *)&ttybuf) < 0) { 122816762Sralph syslog(LOG_ERR, "%s: ioctl(TIOCSETP): %m", printer); 122912111Sralph exit(1); 123012111Sralph } 123112111Sralph if (XC) { 123212111Sralph if (ioctl(pfd, TIOCLBIC, &XC) < 0) { 123316762Sralph syslog(LOG_ERR, "%s: ioctl(TIOCLBIC): %m", printer); 123412111Sralph exit(1); 123512111Sralph } 123612111Sralph } 123712111Sralph if (XS) { 123812111Sralph if (ioctl(pfd, TIOCLBIS, &XS) < 0) { 123916762Sralph syslog(LOG_ERR, "%s: ioctl(TIOCLBIS): %m", printer); 124012111Sralph exit(1); 124112111Sralph } 124212111Sralph } 124312111Sralph } 124412463Sralph 124512463Sralph /*VARARGS1*/ 124612463Sralph status(msg, a1, a2, a3) 124712463Sralph char *msg; 124812463Sralph { 124912463Sralph register int fd; 125012463Sralph char buf[BUFSIZ]; 125112463Sralph 125212463Sralph umask(0); 125313148Ssam fd = open(ST, O_WRONLY|O_CREAT, 0664); 125416762Sralph if (fd < 0 || flock(fd, LOCK_EX) < 0) { 125516762Sralph syslog(LOG_ERR, "%s: %s: %m", printer, ST); 125616762Sralph exit(1); 125716762Sralph } 125813148Ssam ftruncate(fd, 0); 125912463Sralph sprintf(buf, msg, a1, a2, a3); 126012463Sralph strcat(buf, "\n"); 126112463Sralph (void) write(fd, buf, strlen(buf)); 126212463Sralph (void) close(fd); 126312463Sralph } 1264