122437Sdist /* 222437Sdist * Copyright (c) 1983 Regents of the University of California. 334203Sbostic * All rights reserved. 434203Sbostic * 542802Sbostic * %sccs.include.redist.c% 622437Sdist */ 722437Sdist 813954Ssam #ifndef lint 9*46912Sbostic static char sccsid[] = "@(#)printjob.c 5.13 (Berkeley) 03/02/91"; 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; 69*46912Sbostic void 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); 562*46912Sbostic while ((pid = 563*46912Sbostic wait3((int *)&status, WUNTRACED, 0)) > 0 && pid != ofilter) 56412111Sralph ; 56512111Sralph if (status.w_stopval != WSTOPPED) { 56612111Sralph (void) close(fi); 56716762Sralph syslog(LOG_WARNING, "%s: output filter died (%d)", 56816762Sralph printer, status.w_retcode); 56917463Sralph return(REPRINT); 57012111Sralph } 57112111Sralph stopped++; 57212111Sralph } 57312111Sralph start: 57412111Sralph if ((child = dofork(DORETURN)) == 0) { /* child */ 57512111Sralph dup2(fi, 0); 57612111Sralph dup2(fo, 1); 57739954Smckusick n = open(tempfile, O_WRONLY|O_CREAT|O_TRUNC, 0664); 57815811Sralph if (n >= 0) 57915811Sralph dup2(n, 2); 58012111Sralph for (n = 3; n < NOFILE; n++) 58112111Sralph (void) close(n); 58212111Sralph execv(prog, av); 58316762Sralph syslog(LOG_ERR, "cannot execv %s", prog); 58412111Sralph exit(2); 58512111Sralph } 58612111Sralph (void) close(fi); 58712111Sralph if (child < 0) 58812111Sralph status.w_retcode = 100; 58912111Sralph else 590*46912Sbostic while ((pid = wait((int *)&status)) > 0 && pid != child) 59112111Sralph ; 59212111Sralph child = 0; 59312111Sralph prchild = 0; 59412111Sralph if (stopped) { /* restart output filter */ 59512111Sralph if (kill(ofilter, SIGCONT) < 0) { 59616762Sralph syslog(LOG_ERR, "cannot restart output filter"); 59712111Sralph exit(1); 59812111Sralph } 59912111Sralph } 60012111Sralph tof = 0; 60139954Smckusick 60239954Smckusick /* Copy filter output to "lf" logfile */ 60339954Smckusick if (fp = fopen(tempfile, "r")) { 60439954Smckusick char tbuf[512]; 60539954Smckusick 60639954Smckusick while (fgets(buf, sizeof(buf), fp)) 60739954Smckusick fputs(buf, stderr); 60839954Smckusick close(fp); 60939954Smckusick } 61039954Smckusick 61115811Sralph if (!WIFEXITED(status)) { 61216762Sralph syslog(LOG_WARNING, "%s: Daemon filter '%c' terminated (%d)", 61316762Sralph printer, format, status.w_termsig); 61417463Sralph return(ERROR); 61517463Sralph } 61617463Sralph switch (status.w_retcode) { 61717463Sralph case 0: 61817463Sralph tof = 1; 61917463Sralph return(OK); 62017463Sralph case 1: 62117463Sralph return(REPRINT); 62217463Sralph default: 62316762Sralph syslog(LOG_WARNING, "%s: Daemon filter '%c' exited (%d)", 62416762Sralph printer, format, status.w_retcode); 62517463Sralph case 2: 62617463Sralph return(ERROR); 62717463Sralph } 62812111Sralph } 62912111Sralph 63012111Sralph /* 63112111Sralph * Send the daemon control file (cf) and any data files. 63212111Sralph * Return -1 if a non-recoverable error occured, 1 if a recoverable error and 63312111Sralph * 0 if all is well. 63412111Sralph */ 63512111Sralph sendit(file) 63612111Sralph char *file; 63712111Sralph { 63817463Sralph register int i, err = OK; 63917463Sralph char *cp, last[BUFSIZ]; 64012111Sralph 64112111Sralph /* 64212111Sralph * open control file 64312111Sralph */ 64416762Sralph if ((cfp = fopen(file, "r")) == NULL) 64517463Sralph return(OK); 64612111Sralph /* 64712111Sralph * read the control file for work to do 64812111Sralph * 64912111Sralph * file format -- first character in the line is a command 65012111Sralph * rest of the line is the argument. 65112111Sralph * commands of interest are: 65212111Sralph * 65312111Sralph * a-z -- "file name" name of file to print 65412111Sralph * U -- "unlink" name of file to remove 65512111Sralph * (after we print it. (Pass 2 only)). 65612111Sralph */ 65712111Sralph 65812111Sralph /* 65912111Sralph * pass 1 66012111Sralph */ 66112111Sralph while (getline(cfp)) { 66212111Sralph again: 66317463Sralph if (line[0] == 'S') { 66417463Sralph cp = line+1; 66517463Sralph i = 0; 66617463Sralph while (*cp >= '0' && *cp <= '9') 66717463Sralph i = i * 10 + (*cp++ - '0'); 66817463Sralph fdev = i; 66917463Sralph cp++; 67017463Sralph i = 0; 67117463Sralph while (*cp >= '0' && *cp <= '9') 67217463Sralph i = i * 10 + (*cp++ - '0'); 67317463Sralph fino = i; 67417463Sralph continue; 67517463Sralph } 67612111Sralph if (line[0] >= 'a' && line[0] <= 'z') { 67712111Sralph strcpy(last, line); 67817463Sralph while (i = getline(cfp)) 67912111Sralph if (strcmp(last, line)) 68012111Sralph break; 68117463Sralph switch (sendfile('\3', last+1)) { 68217463Sralph case OK: 68317463Sralph if (i) 68417463Sralph goto again; 68517463Sralph break; 68617463Sralph case REPRINT: 68712111Sralph (void) fclose(cfp); 68817463Sralph return(REPRINT); 68917463Sralph case ACCESS: 69017463Sralph sendmail(logname, ACCESS); 69117463Sralph case ERROR: 69217463Sralph err = ERROR; 69317463Sralph } 69412111Sralph break; 69512111Sralph } 69612111Sralph } 69717463Sralph if (err == OK && sendfile('\2', file) > 0) { 69812111Sralph (void) fclose(cfp); 69917463Sralph return(REPRINT); 70012111Sralph } 70112111Sralph /* 70212111Sralph * pass 2 70312111Sralph */ 70412111Sralph fseek(cfp, 0L, 0); 70512111Sralph while (getline(cfp)) 70612111Sralph if (line[0] == 'U') 70712111Sralph (void) unlink(line+1); 70812111Sralph /* 70917463Sralph * clean-up in case another control file exists 71012111Sralph */ 71112111Sralph (void) fclose(cfp); 71212111Sralph (void) unlink(file); 71317463Sralph return(err); 71412111Sralph } 71512111Sralph 71612111Sralph /* 71712111Sralph * Send a data file to the remote machine and spool it. 71812111Sralph * Return positive if we should try resending. 71912111Sralph */ 72012111Sralph sendfile(type, file) 72112111Sralph char type, *file; 72212111Sralph { 72312111Sralph register int f, i, amt; 72412111Sralph struct stat stb; 72512111Sralph char buf[BUFSIZ]; 72616762Sralph int sizerr, resp; 72712111Sralph 72817463Sralph if (lstat(file, &stb) < 0 || (f = open(file, O_RDONLY)) < 0) 72917463Sralph return(ERROR); 73017463Sralph /* 73117463Sralph * Check to see if data file is a symbolic link. If so, it should 73217463Sralph * still point to the same file or someone is trying to print something 73317463Sralph * he shouldn't. 73417463Sralph */ 73517463Sralph if ((stb.st_mode & S_IFMT) == S_IFLNK && fstat(f, &stb) == 0 && 73617463Sralph (stb.st_dev != fdev || stb.st_ino != fino)) 73717463Sralph return(ACCESS); 73812111Sralph (void) sprintf(buf, "%c%d %s\n", type, stb.st_size, file); 73912111Sralph amt = strlen(buf); 74016762Sralph for (i = 0; ; i++) { 74116762Sralph if (write(pfd, buf, amt) != amt || 74216762Sralph (resp = response()) < 0 || resp == '\1') { 74316762Sralph (void) close(f); 74417463Sralph return(REPRINT); 74516762Sralph } else if (resp == '\0') 74616762Sralph break; 74716762Sralph if (i == 0) 74816762Sralph status("no space on remote; waiting for queue to drain"); 74916762Sralph if (i == 10) 75024861Seric syslog(LOG_ALERT, "%s: can't send to %s; queue full", 75116762Sralph printer, RM); 75216762Sralph sleep(5 * 60); 75312692Sralph } 75416762Sralph if (i) 75516762Sralph status("sending to %s", RM); 75612111Sralph sizerr = 0; 75712111Sralph for (i = 0; i < stb.st_size; i += BUFSIZ) { 75812111Sralph amt = BUFSIZ; 75912111Sralph if (i + amt > stb.st_size) 76012111Sralph amt = stb.st_size - i; 76112111Sralph if (sizerr == 0 && read(f, buf, amt) != amt) 76212111Sralph sizerr = 1; 76312692Sralph if (write(pfd, buf, amt) != amt) { 76412692Sralph (void) close(f); 76517463Sralph return(REPRINT); 76612692Sralph } 76712111Sralph } 76812111Sralph (void) close(f); 76912111Sralph if (sizerr) { 77016762Sralph syslog(LOG_INFO, "%s: %s: changed size", printer, file); 77117463Sralph /* tell recvjob to ignore this file */ 77217463Sralph (void) write(pfd, "\1", 1); 77317463Sralph return(ERROR); 77417463Sralph } 77517463Sralph if (write(pfd, "", 1) != 1 || response()) 77617463Sralph return(REPRINT); 77717463Sralph return(OK); 77812111Sralph } 77912111Sralph 78012111Sralph /* 78112111Sralph * Check to make sure there have been no errors and that both programs 78212111Sralph * are in sync with eachother. 78312111Sralph * Return non-zero if the connection was lost. 78412111Sralph */ 78516762Sralph response() 78612111Sralph { 78712111Sralph char resp; 78812111Sralph 78916762Sralph if (read(pfd, &resp, 1) != 1) { 79016762Sralph syslog(LOG_INFO, "%s: lost connection", printer); 79116762Sralph return(-1); 79212111Sralph } 79316762Sralph return(resp); 79412111Sralph } 79512111Sralph 79612111Sralph /* 79712111Sralph * Banner printing stuff 79812111Sralph */ 79912111Sralph banner(name1, name2) 80012111Sralph char *name1, *name2; 80112111Sralph { 80212111Sralph time_t tvec; 80312111Sralph extern char *ctime(); 80412111Sralph 80512111Sralph time(&tvec); 80612111Sralph if (!SF && !tof) 80712111Sralph (void) write(ofd, FF, strlen(FF)); 80812111Sralph if (SB) { /* short banner only */ 80912111Sralph if (class[0]) { 81012111Sralph (void) write(ofd, class, strlen(class)); 81112111Sralph (void) write(ofd, ":", 1); 81212111Sralph } 81312111Sralph (void) write(ofd, name1, strlen(name1)); 81412111Sralph (void) write(ofd, " Job: ", 7); 81512111Sralph (void) write(ofd, name2, strlen(name2)); 81612111Sralph (void) write(ofd, " Date: ", 8); 81712111Sralph (void) write(ofd, ctime(&tvec), 24); 81812111Sralph (void) write(ofd, "\n", 1); 81912111Sralph } else { /* normal banner */ 82012111Sralph (void) write(ofd, "\n\n\n", 3); 82112111Sralph scan_out(ofd, name1, '\0'); 82212111Sralph (void) write(ofd, "\n\n", 2); 82312111Sralph scan_out(ofd, name2, '\0'); 82412111Sralph if (class[0]) { 82512111Sralph (void) write(ofd,"\n\n\n",3); 82612111Sralph scan_out(ofd, class, '\0'); 82712111Sralph } 82812111Sralph (void) write(ofd, "\n\n\n\n\t\t\t\t\tJob: ", 15); 82912111Sralph (void) write(ofd, name2, strlen(name2)); 83012111Sralph (void) write(ofd, "\n\t\t\t\t\tDate: ", 12); 83112111Sralph (void) write(ofd, ctime(&tvec), 24); 83212111Sralph (void) write(ofd, "\n", 1); 83312111Sralph } 83412111Sralph if (!SF) 83512111Sralph (void) write(ofd, FF, strlen(FF)); 83612111Sralph tof = 1; 83712111Sralph } 83812111Sralph 83916762Sralph char * 84012111Sralph scnline(key, p, c) 84112111Sralph register char key, *p; 84212111Sralph char c; 84312111Sralph { 84412111Sralph register scnwidth; 84512111Sralph 84612111Sralph for (scnwidth = WIDTH; --scnwidth;) { 84712111Sralph key <<= 1; 84812111Sralph *p++ = key & 0200 ? c : BACKGND; 84912111Sralph } 85012111Sralph return (p); 85112111Sralph } 85212111Sralph 85312111Sralph #define TRC(q) (((q)-' ')&0177) 85412111Sralph 85512111Sralph scan_out(scfd, scsp, dlm) 85612111Sralph int scfd; 85712111Sralph char *scsp, dlm; 85812111Sralph { 85912111Sralph register char *strp; 86012111Sralph register nchrs, j; 86112111Sralph char outbuf[LINELEN+1], *sp, c, cc; 86212111Sralph int d, scnhgt; 86312111Sralph extern char scnkey[][HEIGHT]; /* in lpdchar.c */ 86412111Sralph 86512111Sralph for (scnhgt = 0; scnhgt++ < HEIGHT+DROP; ) { 86612111Sralph strp = &outbuf[0]; 86712111Sralph sp = scsp; 86812111Sralph for (nchrs = 0; ; ) { 86912111Sralph d = dropit(c = TRC(cc = *sp++)); 87012111Sralph if ((!d && scnhgt > HEIGHT) || (scnhgt <= DROP && d)) 87112111Sralph for (j = WIDTH; --j;) 87212111Sralph *strp++ = BACKGND; 87312111Sralph else 87412111Sralph strp = scnline(scnkey[c][scnhgt-1-d], strp, cc); 87512111Sralph if (*sp == dlm || *sp == '\0' || nchrs++ >= PW/(WIDTH+1)-1) 87612111Sralph break; 87712111Sralph *strp++ = BACKGND; 87812111Sralph *strp++ = BACKGND; 87912111Sralph } 88012111Sralph while (*--strp == BACKGND && strp >= outbuf) 88112111Sralph ; 88212111Sralph strp++; 88312111Sralph *strp++ = '\n'; 88412111Sralph (void) write(scfd, outbuf, strp-outbuf); 88512111Sralph } 88612111Sralph } 88712111Sralph 88812111Sralph dropit(c) 88912111Sralph char c; 89012111Sralph { 89112111Sralph switch(c) { 89212111Sralph 89312111Sralph case TRC('_'): 89412111Sralph case TRC(';'): 89512111Sralph case TRC(','): 89612111Sralph case TRC('g'): 89712111Sralph case TRC('j'): 89812111Sralph case TRC('p'): 89912111Sralph case TRC('q'): 90012111Sralph case TRC('y'): 90112111Sralph return (DROP); 90212111Sralph 90312111Sralph default: 90412111Sralph return (0); 90512111Sralph } 90612111Sralph } 90712111Sralph 90812111Sralph /* 90912111Sralph * sendmail --- 91012111Sralph * tell people about job completion 91112111Sralph */ 91215811Sralph sendmail(user, bombed) 91315811Sralph char *user; 91412111Sralph int bombed; 91512111Sralph { 91612111Sralph register int i; 91715811Sralph int p[2], s; 91812111Sralph register char *cp; 91912111Sralph char buf[100]; 92015811Sralph struct stat stb; 92115811Sralph FILE *fp; 92212111Sralph 92312111Sralph pipe(p); 92415811Sralph if ((s = dofork(DORETURN)) == 0) { /* child */ 92512111Sralph dup2(p[0], 0); 92612111Sralph for (i = 3; i < NOFILE; i++) 92712111Sralph (void) close(i); 92837968Sbostic if ((cp = rindex(_PATH_SENDMAIL, '/')) != NULL) 92912111Sralph cp++; 93012111Sralph else 93137968Sbostic cp = _PATH_SENDMAIL; 93215811Sralph sprintf(buf, "%s@%s", user, fromhost); 93337968Sbostic execl(_PATH_SENDMAIL, cp, buf, 0); 93412111Sralph exit(0); 93515811Sralph } else if (s > 0) { /* parent */ 93612111Sralph dup2(p[1], 1); 93715811Sralph printf("To: %s@%s\n", user, fromhost); 93812111Sralph printf("Subject: printer job\n\n"); 93912111Sralph printf("Your printer job "); 94012111Sralph if (*jobname) 94112111Sralph printf("(%s) ", jobname); 94212463Sralph switch (bombed) { 94317463Sralph case OK: 94412463Sralph printf("\ncompleted successfully\n"); 94512463Sralph break; 94612463Sralph default: 94717463Sralph case FATALERR: 94812463Sralph printf("\ncould not be printed\n"); 94912463Sralph break; 95017463Sralph case NOACCT: 95112463Sralph printf("\ncould not be printed without an account on %s\n", host); 95212463Sralph break; 95317463Sralph case FILTERERR: 95439954Smckusick if (stat(tempfile, &stb) < 0 || stb.st_size == 0 || 95539954Smckusick (fp = fopen(tempfile, "r")) == NULL) { 95615811Sralph printf("\nwas printed but had some errors\n"); 95715811Sralph break; 95815811Sralph } 95915811Sralph printf("\nwas printed but had the following errors:\n"); 96015811Sralph while ((i = getc(fp)) != EOF) 96115811Sralph putchar(i); 96215811Sralph (void) fclose(fp); 96317463Sralph break; 96417463Sralph case ACCESS: 96517463Sralph printf("\nwas not printed because it was not linked to the original file\n"); 96612463Sralph } 96712111Sralph fflush(stdout); 96812111Sralph (void) close(1); 96912111Sralph } 97012111Sralph (void) close(p[0]); 97112111Sralph (void) close(p[1]); 97215811Sralph wait(&s); 97312111Sralph } 97412111Sralph 97512111Sralph /* 97612111Sralph * dofork - fork with retries on failure 97712111Sralph */ 97812111Sralph dofork(action) 97912111Sralph int action; 98012111Sralph { 98112111Sralph register int i, pid; 98212111Sralph 98312111Sralph for (i = 0; i < 20; i++) { 98412463Sralph if ((pid = fork()) < 0) { 98512111Sralph sleep((unsigned)(i*i)); 98612463Sralph continue; 98712463Sralph } 98812463Sralph /* 98912463Sralph * Child should run as daemon instead of root 99012463Sralph */ 99112463Sralph if (pid == 0) 99212463Sralph setuid(DU); 99312463Sralph return(pid); 99412111Sralph } 99516762Sralph syslog(LOG_ERR, "can't fork"); 99612111Sralph 99712111Sralph switch (action) { 99812111Sralph case DORETURN: 99912111Sralph return (-1); 100012111Sralph default: 100116762Sralph syslog(LOG_ERR, "bad action (%d) to dofork", action); 100212111Sralph /*FALL THRU*/ 100312111Sralph case DOABORT: 100412111Sralph exit(1); 100512111Sralph } 100612111Sralph /*NOTREACHED*/ 100712111Sralph } 100812111Sralph 100912111Sralph /* 101016762Sralph * Kill child processes to abort current job. 101112111Sralph */ 1012*46912Sbostic void 101316762Sralph abortpr() 101412111Sralph { 101539954Smckusick (void) unlink(tempfile); 101612111Sralph kill(0, SIGINT); 101712111Sralph if (ofilter > 0) 101812111Sralph kill(ofilter, SIGCONT); 1019*46912Sbostic while (wait(NULL) > 0) 102012111Sralph ; 102112111Sralph exit(0); 102212111Sralph } 102312111Sralph 102412111Sralph init() 102512111Sralph { 102612111Sralph int status; 102738736Stef char *s; 102812111Sralph 102925468Stef if ((status = pgetent(line, printer)) < 0) { 103025468Stef syslog(LOG_ERR, "can't open printer description file"); 103125468Stef exit(1); 103225468Stef } else if (status == 0) { 103325468Stef syslog(LOG_ERR, "unknown printer: %s", printer); 103425468Stef exit(1); 103525468Stef } 103612111Sralph if ((LP = pgetstr("lp", &bp)) == NULL) 103737968Sbostic LP = _PATH_DEFDEVLP; 103812111Sralph if ((RP = pgetstr("rp", &bp)) == NULL) 103912463Sralph RP = DEFLP; 104012111Sralph if ((LO = pgetstr("lo", &bp)) == NULL) 104112111Sralph LO = DEFLOCK; 104212111Sralph if ((ST = pgetstr("st", &bp)) == NULL) 104312111Sralph ST = DEFSTAT; 104412111Sralph if ((LF = pgetstr("lf", &bp)) == NULL) 104537968Sbostic LF = _PATH_CONSOLE; 104612111Sralph if ((SD = pgetstr("sd", &bp)) == NULL) 104737968Sbostic SD = _PATH_DEFSPOOL; 104812111Sralph if ((DU = pgetnum("du")) < 0) 104912111Sralph DU = DEFUID; 105012111Sralph if ((FF = pgetstr("ff", &bp)) == NULL) 105112111Sralph FF = DEFFF; 105212111Sralph if ((PW = pgetnum("pw")) < 0) 105312111Sralph PW = DEFWIDTH; 105412111Sralph sprintf(&width[2], "%d", PW); 105512111Sralph if ((PL = pgetnum("pl")) < 0) 105612111Sralph PL = DEFLENGTH; 105712111Sralph sprintf(&length[2], "%d", PL); 105812463Sralph if ((PX = pgetnum("px")) < 0) 105912463Sralph PX = 0; 106012463Sralph sprintf(&pxwidth[2], "%d", PX); 106112463Sralph if ((PY = pgetnum("py")) < 0) 106212463Sralph PY = 0; 106312463Sralph sprintf(&pxlength[2], "%d", PY); 106412111Sralph RM = pgetstr("rm", &bp); 106538736Stef if (s = checkremote()) 106638736Stef syslog(LOG_WARNING, s); 106725468Stef 106812111Sralph AF = pgetstr("af", &bp); 106912111Sralph OF = pgetstr("of", &bp); 107012111Sralph IF = pgetstr("if", &bp); 107112463Sralph RF = pgetstr("rf", &bp); 107212111Sralph TF = pgetstr("tf", &bp); 107313233Sralph NF = pgetstr("nf", &bp); 107412111Sralph DF = pgetstr("df", &bp); 107512111Sralph GF = pgetstr("gf", &bp); 107612111Sralph VF = pgetstr("vf", &bp); 107712111Sralph CF = pgetstr("cf", &bp); 107812111Sralph TR = pgetstr("tr", &bp); 107912463Sralph RS = pgetflag("rs"); 108012111Sralph SF = pgetflag("sf"); 108112111Sralph SH = pgetflag("sh"); 108212111Sralph SB = pgetflag("sb"); 108318127Sralph HL = pgetflag("hl"); 108412111Sralph RW = pgetflag("rw"); 108512111Sralph BR = pgetnum("br"); 108612111Sralph if ((FC = pgetnum("fc")) < 0) 108712111Sralph FC = 0; 108812111Sralph if ((FS = pgetnum("fs")) < 0) 108912111Sralph FS = 0; 109012111Sralph if ((XC = pgetnum("xc")) < 0) 109112111Sralph XC = 0; 109212111Sralph if ((XS = pgetnum("xs")) < 0) 109312111Sralph XS = 0; 109412581Sralph tof = !pgetflag("fo"); 109512111Sralph } 109612111Sralph 109712463Sralph /* 109812463Sralph * Acquire line printer or remote connection. 109912463Sralph */ 110012463Sralph openpr() 110112463Sralph { 110212463Sralph register int i, n; 110316762Sralph int resp; 110412463Sralph 110538736Stef if (!sendtorem && *LP) { 110612463Sralph for (i = 1; ; i = i < 32 ? i << 1 : i) { 110713148Ssam pfd = open(LP, RW ? O_RDWR : O_WRONLY); 110812463Sralph if (pfd >= 0) 110912463Sralph break; 111012463Sralph if (errno == ENOENT) { 111116762Sralph syslog(LOG_ERR, "%s: %m", LP); 111212463Sralph exit(1); 111312463Sralph } 111412463Sralph if (i == 1) 111512463Sralph status("waiting for %s to become ready (offline ?)", printer); 111612463Sralph sleep(i); 111712463Sralph } 111812463Sralph if (isatty(pfd)) 111912463Sralph setty(); 112012463Sralph status("%s is ready and printing", printer); 112112463Sralph } else if (RM != NULL) { 112216762Sralph for (i = 1; ; i = i < 256 ? i << 1 : i) { 112316762Sralph resp = -1; 112412528Sralph pfd = getport(RM); 112512463Sralph if (pfd >= 0) { 112612463Sralph (void) sprintf(line, "\2%s\n", RP); 112712463Sralph n = strlen(line); 112816762Sralph if (write(pfd, line, n) == n && 112916762Sralph (resp = response()) == '\0') 113012463Sralph break; 113116031Sralph (void) close(pfd); 113212463Sralph } 113316031Sralph if (i == 1) { 113416762Sralph if (resp < 0) 113516031Sralph status("waiting for %s to come up", RM); 113616762Sralph else { 113716031Sralph status("waiting for queue to be enabled on %s", RM); 113816762Sralph i = 256; 113916762Sralph } 114016031Sralph } 114112463Sralph sleep(i); 114212463Sralph } 114312463Sralph status("sending to %s", RM); 114412463Sralph remote = 1; 114512463Sralph } else { 114616762Sralph syslog(LOG_ERR, "%s: no line printer device or host name", 114716762Sralph printer); 114812463Sralph exit(1); 114912463Sralph } 115012463Sralph /* 115112463Sralph * Start up an output filter, if needed. 115212463Sralph */ 115340049Stef if (!remote && OF) { 115412463Sralph int p[2]; 115512463Sralph char *cp; 115612463Sralph 115712463Sralph pipe(p); 115812463Sralph if ((ofilter = dofork(DOABORT)) == 0) { /* child */ 115912463Sralph dup2(p[0], 0); /* pipe is std in */ 116012463Sralph dup2(pfd, 1); /* printer is std out */ 116112463Sralph for (i = 3; i < NOFILE; i++) 116212463Sralph (void) close(i); 116312463Sralph if ((cp = rindex(OF, '/')) == NULL) 116412463Sralph cp = OF; 116512463Sralph else 116612463Sralph cp++; 116712463Sralph execl(OF, cp, width, length, 0); 116816762Sralph syslog(LOG_ERR, "%s: %s: %m", printer, OF); 116912463Sralph exit(1); 117012463Sralph } 117112463Sralph (void) close(p[0]); /* close input side */ 117212463Sralph ofd = p[1]; /* use pipe for output */ 117312463Sralph } else { 117412463Sralph ofd = pfd; 117512463Sralph ofilter = 0; 117612463Sralph } 117712463Sralph } 117812463Sralph 117912111Sralph struct bauds { 118012111Sralph int baud; 118112111Sralph int speed; 118212111Sralph } bauds[] = { 118312111Sralph 50, B50, 118412111Sralph 75, B75, 118512111Sralph 110, B110, 118612111Sralph 134, B134, 118712111Sralph 150, B150, 118812111Sralph 200, B200, 118912111Sralph 300, B300, 119012111Sralph 600, B600, 119112111Sralph 1200, B1200, 119212111Sralph 1800, B1800, 119312111Sralph 2400, B2400, 119412111Sralph 4800, B4800, 119512111Sralph 9600, B9600, 119612111Sralph 19200, EXTA, 119712111Sralph 38400, EXTB, 119812111Sralph 0, 0 119912111Sralph }; 120012111Sralph 120112111Sralph /* 120212111Sralph * setup tty lines. 120312111Sralph */ 120412111Sralph setty() 120512111Sralph { 120612111Sralph struct sgttyb ttybuf; 120712111Sralph register struct bauds *bp; 120812111Sralph 120912111Sralph if (ioctl(pfd, TIOCEXCL, (char *)0) < 0) { 121016762Sralph syslog(LOG_ERR, "%s: ioctl(TIOCEXCL): %m", printer); 121112111Sralph exit(1); 121212111Sralph } 121312111Sralph if (ioctl(pfd, TIOCGETP, (char *)&ttybuf) < 0) { 121416762Sralph syslog(LOG_ERR, "%s: ioctl(TIOCGETP): %m", printer); 121512111Sralph exit(1); 121612111Sralph } 121712111Sralph if (BR > 0) { 121812111Sralph for (bp = bauds; bp->baud; bp++) 121912111Sralph if (BR == bp->baud) 122012111Sralph break; 122112111Sralph if (!bp->baud) { 122216762Sralph syslog(LOG_ERR, "%s: illegal baud rate %d", printer, BR); 122312111Sralph exit(1); 122412111Sralph } 122512111Sralph ttybuf.sg_ispeed = ttybuf.sg_ospeed = bp->speed; 122612111Sralph } 122713169Sralph ttybuf.sg_flags &= ~FC; 122813169Sralph ttybuf.sg_flags |= FS; 122912111Sralph if (ioctl(pfd, TIOCSETP, (char *)&ttybuf) < 0) { 123016762Sralph syslog(LOG_ERR, "%s: ioctl(TIOCSETP): %m", printer); 123112111Sralph exit(1); 123212111Sralph } 123312111Sralph if (XC) { 123412111Sralph if (ioctl(pfd, TIOCLBIC, &XC) < 0) { 123516762Sralph syslog(LOG_ERR, "%s: ioctl(TIOCLBIC): %m", printer); 123612111Sralph exit(1); 123712111Sralph } 123812111Sralph } 123912111Sralph if (XS) { 124012111Sralph if (ioctl(pfd, TIOCLBIS, &XS) < 0) { 124116762Sralph syslog(LOG_ERR, "%s: ioctl(TIOCLBIS): %m", printer); 124212111Sralph exit(1); 124312111Sralph } 124412111Sralph } 124512111Sralph } 124612463Sralph 124712463Sralph /*VARARGS1*/ 124812463Sralph status(msg, a1, a2, a3) 124912463Sralph char *msg; 125012463Sralph { 125112463Sralph register int fd; 125212463Sralph char buf[BUFSIZ]; 125312463Sralph 125412463Sralph umask(0); 125513148Ssam fd = open(ST, O_WRONLY|O_CREAT, 0664); 125616762Sralph if (fd < 0 || flock(fd, LOCK_EX) < 0) { 125716762Sralph syslog(LOG_ERR, "%s: %s: %m", printer, ST); 125816762Sralph exit(1); 125916762Sralph } 126013148Ssam ftruncate(fd, 0); 126112463Sralph sprintf(buf, msg, a1, a2, a3); 126212463Sralph strcat(buf, "\n"); 126312463Sralph (void) write(fd, buf, strlen(buf)); 126412463Sralph (void) close(fd); 126512463Sralph } 1266