113954Ssam #ifndef lint 2*18127Sralph static char sccsid[] = "@(#)printjob.c 4.24 (Berkeley) 02/27/85"; 313954Ssam #endif 413954Ssam 512111Sralph /* 612111Sralph * printjob -- print jobs in the queue. 712111Sralph * 812111Sralph * NOTE: the lock file is used to pass information to lpq and lprm. 912111Sralph * it does not need to be removed because file locks are dynamic. 1012111Sralph */ 1112111Sralph 1212111Sralph #include "lp.h" 1312111Sralph 1416762Sralph #define DORETURN 0 /* absorb fork error */ 1516762Sralph #define DOABORT 1 /* abort if dofork fails */ 1612111Sralph 1717463Sralph /* 1817463Sralph * Error tokens 1917463Sralph */ 2017463Sralph #define REPRINT -2 2117463Sralph #define ERROR -1 2217463Sralph #define OK 0 2317463Sralph #define FATALERR 1 2417463Sralph #define NOACCT 2 2517463Sralph #define FILTERERR 3 2617463Sralph #define ACCESS 4 2717463Sralph 2816762Sralph char title[80]; /* ``pr'' title */ 2916762Sralph FILE *cfp; /* control file */ 3016762Sralph int pfd; /* printer file descriptor */ 3116762Sralph int ofd; /* output filter file descriptor */ 3216762Sralph int lfd; /* lock file descriptor */ 3316762Sralph int pid; /* pid of lpd process */ 3416762Sralph int prchild; /* id of pr process */ 3516762Sralph int child; /* id of any filters */ 3616762Sralph int ofilter; /* id of output filter, if any */ 3716762Sralph int tof; /* true if at top of form */ 3816762Sralph int remote; /* true if sending files to remote */ 3917463Sralph dev_t fdev; /* device of file pointed to by symlink */ 4017463Sralph ino_t fino; /* inode of file pointed to by symlink */ 4112111Sralph 4216762Sralph char fromhost[32]; /* user's host machine */ 4316762Sralph char logname[32]; /* user's login name */ 4416762Sralph char jobname[100]; /* job or file name */ 4516762Sralph char class[32]; /* classification field */ 4616762Sralph char width[10] = "-w"; /* page width in characters */ 4716762Sralph char length[10] = "-l"; /* page length in lines */ 4816762Sralph char pxwidth[10] = "-x"; /* page width in pixels */ 4916762Sralph char pxlength[10] = "-y"; /* page length in pixels */ 5016762Sralph char indent[10] = "-i0"; /* indentation size in characters */ 5116762Sralph char tmpfile[] = "errsXXXXXX"; /* file name for filter output */ 5212111Sralph 5312111Sralph printjob() 5412111Sralph { 5512111Sralph struct stat stb; 5612111Sralph register struct queue *q, **qp; 5712111Sralph struct queue **queue; 5812111Sralph register int i, nitems; 5912111Sralph long pidoff; 6016762Sralph int count = 0; 6116762Sralph extern int abortpr(); 6212111Sralph 6312111Sralph init(); /* set up capabilities */ 6413442Sralph (void) write(1, "", 1); /* ack that daemon is started */ 6516762Sralph setgid(getegid()); 6612463Sralph pid = getpid(); /* for use with lprm */ 6712111Sralph setpgrp(0, pid); 6816762Sralph signal(SIGHUP, abortpr); 6916762Sralph signal(SIGINT, abortpr); 7016762Sralph signal(SIGQUIT, abortpr); 7116762Sralph signal(SIGTERM, abortpr); 7212111Sralph 7315811Sralph (void) mktemp(tmpfile); 7415811Sralph 7512111Sralph /* 7612111Sralph * uses short form file names 7712111Sralph */ 7812111Sralph if (chdir(SD) < 0) { 7916762Sralph syslog(LOG_ERR, "%s: %m", SD); 8012111Sralph exit(1); 8112111Sralph } 8212463Sralph if (stat(LO, &stb) == 0 && (stb.st_mode & 0100)) 8312463Sralph exit(0); /* printing disabled */ 8414150Sralph lfd = open(LO, O_WRONLY|O_CREAT, 0644); 8513169Sralph if (lfd < 0) { 8616762Sralph syslog(LOG_ERR, "%s: %s: %m", printer, LO); 8713169Sralph exit(1); 8813169Sralph } 8913169Sralph if (flock(lfd, LOCK_EX|LOCK_NB) < 0) { 9012111Sralph if (errno == EWOULDBLOCK) /* active deamon present */ 9112111Sralph exit(0); 9216762Sralph syslog(LOG_ERR, "%s: %s: %m", printer, LO); 9312111Sralph exit(1); 9412111Sralph } 9513148Ssam ftruncate(lfd, 0); 9612111Sralph /* 9712111Sralph * write process id for others to know 9812111Sralph */ 9912111Sralph sprintf(line, "%u\n", pid); 10012111Sralph pidoff = i = strlen(line); 10112463Sralph if (write(lfd, line, i) != i) { 10216762Sralph syslog(LOG_ERR, "%s: %s: %m", printer, LO); 10312111Sralph exit(1); 10412111Sralph } 10512111Sralph /* 10612111Sralph * search the spool directory for work and sort by queue order. 10712111Sralph */ 10812111Sralph if ((nitems = getq(&queue)) < 0) { 10916762Sralph syslog(LOG_ERR, "%s: can't scan %s", printer, SD); 11012111Sralph exit(1); 11112111Sralph } 11212463Sralph if (nitems == 0) /* no work to do */ 11312111Sralph exit(0); 11413169Sralph if (stb.st_mode & 01) { /* reset queue flag */ 11513169Sralph if (fchmod(lfd, stb.st_mode & 0776) < 0) 11616762Sralph syslog(LOG_ERR, "%s: %s: %m", printer, LO); 11713169Sralph } 11812463Sralph openpr(); /* open printer or remote */ 11912463Sralph again: 12012111Sralph /* 12112111Sralph * we found something to do now do it -- 12212111Sralph * write the name of the current control file into the lock file 12312111Sralph * so the spool queue program can tell what we're working on 12412111Sralph */ 12512111Sralph for (qp = queue; nitems--; free((char *) q)) { 12612111Sralph q = *qp++; 12712111Sralph if (stat(q->q_name, &stb) < 0) 12812111Sralph continue; 12912463Sralph restart: 13012111Sralph (void) lseek(lfd, pidoff, 0); 13112111Sralph (void) sprintf(line, "%s\n", q->q_name); 13212111Sralph i = strlen(line); 13312111Sralph if (write(lfd, line, i) != i) 13416762Sralph syslog(LOG_ERR, "%s: %s: %m", printer, LO); 13512111Sralph if (!remote) 13612111Sralph i = printit(q->q_name); 13712111Sralph else 13812111Sralph i = sendit(q->q_name); 13912463Sralph /* 14013169Sralph * Check to see if we are supposed to stop printing or 14113169Sralph * if we are to rebuild the queue. 14212463Sralph */ 14313169Sralph if (fstat(lfd, &stb) == 0) { 14416762Sralph /* stop printing before starting next job? */ 14513169Sralph if (stb.st_mode & 0100) 14613169Sralph goto done; 14716762Sralph /* rebuild queue (after lpc topq) */ 14813169Sralph if (stb.st_mode & 01) { 14913169Sralph for (free((char *) q); nitems--; free((char *) q)) 15013169Sralph q = *qp++; 15113169Sralph if (fchmod(lfd, stb.st_mode & 0776) < 0) 15216762Sralph syslog(LOG_WARNING, "%s: %s: %m", 15316762Sralph printer, LO); 15413169Sralph break; 15513169Sralph } 15613169Sralph } 15717463Sralph if (i == OK) /* file ok and printed */ 15814150Sralph count++; 15917463Sralph else if (i == REPRINT) { /* try reprinting the job */ 16016762Sralph syslog(LOG_INFO, "restarting %s", printer); 16112111Sralph if (ofilter > 0) { 16212111Sralph kill(ofilter, SIGCONT); /* to be sure */ 16312111Sralph (void) close(ofd); 16412111Sralph while ((i = wait(0)) > 0 && i != ofilter) 16512111Sralph ; 16612111Sralph ofilter = 0; 16712111Sralph } 16812463Sralph (void) close(pfd); /* close printer */ 16915811Sralph if (ftruncate(lfd, pidoff) < 0) 17016762Sralph syslog(LOG_WARNING, "%s: %s: %m", printer, LO); 17112463Sralph openpr(); /* try to reopen printer */ 17212111Sralph goto restart; 17312111Sralph } 17412111Sralph } 17512111Sralph free((char *) queue); 17612463Sralph /* 17712463Sralph * search the spool directory for more work. 17812463Sralph */ 17912463Sralph if ((nitems = getq(&queue)) < 0) { 18016762Sralph syslog(LOG_ERR, "%s: can't scan %s", printer, SD); 18112463Sralph exit(1); 18212463Sralph } 18312463Sralph if (nitems == 0) { /* no more work to do */ 18412463Sralph done: 18514150Sralph if (count > 0) { /* Files actually printed */ 18614150Sralph if (!SF && !tof) 18714150Sralph (void) write(ofd, FF, strlen(FF)); 18814150Sralph if (TR != NULL) /* output trailer */ 18914150Sralph (void) write(ofd, TR, strlen(TR)); 19014150Sralph } 19115811Sralph (void) unlink(tmpfile); 19212463Sralph exit(0); 19312463Sralph } 19412111Sralph goto again; 19512111Sralph } 19612111Sralph 19712111Sralph char fonts[4][50]; /* fonts for troff */ 19812111Sralph 19916762Sralph char ifonts[4][18] = { 20012111Sralph "/usr/lib/vfont/R", 20112111Sralph "/usr/lib/vfont/I", 20212111Sralph "/usr/lib/vfont/B", 20312111Sralph "/usr/lib/vfont/S" 20412111Sralph }; 20512111Sralph 20612111Sralph /* 20712111Sralph * The remaining part is the reading of the control file (cf) 20812111Sralph * and performing the various actions. 20912111Sralph */ 21012111Sralph printit(file) 21112111Sralph char *file; 21212111Sralph { 21312111Sralph register int i; 21417463Sralph char *cp; 21517463Sralph int bombed = OK; 21612111Sralph 21712111Sralph /* 21817463Sralph * open control file; ignore if no longer there. 21912111Sralph */ 22012111Sralph if ((cfp = fopen(file, "r")) == NULL) { 22116762Sralph syslog(LOG_INFO, "%s: %s: %m", printer, file); 22217463Sralph return(OK); 22312111Sralph } 22412111Sralph /* 22512111Sralph * Reset troff fonts. 22612111Sralph */ 22712111Sralph for (i = 0; i < 4; i++) 22812111Sralph strcpy(fonts[i], ifonts[i]); 22917339Sralph strcpy(width+2, "0"); 23017302Sralph strcpy(indent+2, "0"); 23112111Sralph 23212111Sralph /* 23312111Sralph * read the control file for work to do 23412111Sralph * 23512111Sralph * file format -- first character in the line is a command 23612111Sralph * rest of the line is the argument. 23712111Sralph * valid commands are: 23812111Sralph * 23917463Sralph * S -- "stat info" for symbolic link protection 24012111Sralph * J -- "job name" on banner page 24112111Sralph * C -- "class name" on banner page 24212111Sralph * L -- "literal" user's name to print on banner 24312111Sralph * T -- "title" for pr 24412111Sralph * H -- "host name" of machine where lpr was done 24512111Sralph * P -- "person" user's login name 24612581Sralph * I -- "indent" amount to indent output 24712111Sralph * f -- "file name" name of text file to print 24812111Sralph * l -- "file name" text file with control chars 24912111Sralph * p -- "file name" text file to print with pr(1) 25012111Sralph * t -- "file name" troff(1) file to print 25113233Sralph * n -- "file name" ditroff(1) file to print 25212111Sralph * d -- "file name" dvi file to print 25312111Sralph * g -- "file name" plot(1G) file to print 25412111Sralph * v -- "file name" plain raster file to print 25512111Sralph * c -- "file name" cifplot file to print 25612111Sralph * 1 -- "R font file" for troff 25712111Sralph * 2 -- "I font file" for troff 25812111Sralph * 3 -- "B font file" for troff 25912111Sralph * 4 -- "S font file" for troff 26012111Sralph * N -- "name" of file (used by lpq) 26112111Sralph * U -- "unlink" name of file to remove 26212111Sralph * (after we print it. (Pass 2 only)). 26312111Sralph * M -- "mail" to user when done printing 26412111Sralph * 26512111Sralph * getline reads a line and expands tabs to blanks 26612111Sralph */ 26712111Sralph 26812111Sralph /* pass 1 */ 26912111Sralph 27012111Sralph while (getline(cfp)) 27112111Sralph switch (line[0]) { 27212111Sralph case 'H': 27314150Sralph strcpy(fromhost, line+1); 27412111Sralph if (class[0] == '\0') 27515552Sralph strncpy(class, line+1, sizeof(class)-1); 27612111Sralph continue; 27712111Sralph 27812111Sralph case 'P': 27915552Sralph strncpy(logname, line+1, sizeof(logname)-1); 28012463Sralph if (RS) { /* restricted */ 28112463Sralph if (getpwnam(logname) == (struct passwd *)0) { 28217463Sralph bombed = NOACCT; 28315811Sralph sendmail(line+1, bombed); 28412463Sralph goto pass2; 28512463Sralph } 28612463Sralph } 28712111Sralph continue; 28812111Sralph 28917463Sralph case 'S': 29017463Sralph cp = line+1; 29117463Sralph i = 0; 29217463Sralph while (*cp >= '0' && *cp <= '9') 29317463Sralph i = i * 10 + (*cp++ - '0'); 29417463Sralph fdev = i; 29517463Sralph cp++; 29617463Sralph i = 0; 29717463Sralph while (*cp >= '0' && *cp <= '9') 29817463Sralph i = i * 10 + (*cp++ - '0'); 29917463Sralph fino = i; 30017463Sralph continue; 30117463Sralph 30212111Sralph case 'J': 30312111Sralph if (line[1] != '\0') 30415552Sralph strncpy(jobname, line+1, sizeof(jobname)-1); 30512111Sralph else 30612111Sralph strcpy(jobname, " "); 30712111Sralph continue; 30812111Sralph 30912111Sralph case 'C': 31012111Sralph if (line[1] != '\0') 31115552Sralph strncpy(class, line+1, sizeof(class)-1); 31212111Sralph else if (class[0] == '\0') 31315811Sralph gethostname(class, sizeof(class)); 31412111Sralph continue; 31512111Sralph 31612111Sralph case 'T': /* header title for pr */ 31715552Sralph strncpy(title, line+1, sizeof(title)-1); 31812111Sralph continue; 31912111Sralph 32012111Sralph case 'L': /* identification line */ 321*18127Sralph if (!SH && !HL) 32212111Sralph banner(line+1, jobname); 32312111Sralph continue; 32412111Sralph 32512111Sralph case '1': /* troff fonts */ 32612111Sralph case '2': 32712111Sralph case '3': 32812111Sralph case '4': 32912111Sralph if (line[1] != '\0') 33012111Sralph strcpy(fonts[line[0]-'1'], line+1); 33112111Sralph continue; 33212111Sralph 33312111Sralph case 'W': /* page width */ 33415552Sralph strncpy(width+2, line+1, sizeof(width)-3); 33512111Sralph continue; 33612111Sralph 33712581Sralph case 'I': /* indent amount */ 33815552Sralph strncpy(indent+2, line+1, sizeof(indent)-3); 33912581Sralph continue; 34012581Sralph 34112111Sralph default: /* some file to print */ 34215811Sralph switch (i = print(line[0], line+1)) { 34317463Sralph case ERROR: 34417463Sralph if (bombed == OK) 34517463Sralph bombed = FATALERR; 34615811Sralph break; 34717463Sralph case REPRINT: 34812111Sralph (void) fclose(cfp); 34917463Sralph return(REPRINT); 35017463Sralph case FILTERERR: 35117463Sralph case ACCESS: 35217463Sralph bombed = i; 35315811Sralph sendmail(logname, bombed); 35415811Sralph } 35512111Sralph title[0] = '\0'; 35612111Sralph continue; 35712111Sralph 35812111Sralph case 'N': 35912111Sralph case 'U': 36012111Sralph case 'M': 36112111Sralph continue; 36212111Sralph } 36312111Sralph 36412111Sralph /* pass 2 */ 36512111Sralph 36612463Sralph pass2: 36712111Sralph fseek(cfp, 0L, 0); 36812111Sralph while (getline(cfp)) 36912111Sralph switch (line[0]) { 370*18127Sralph case 'L': /* identification line */ 371*18127Sralph if (!SH && HL) 372*18127Sralph banner(line+1, jobname); 373*18127Sralph continue; 374*18127Sralph 37512111Sralph case 'M': 37617463Sralph if (bombed < NOACCT) /* already sent if >= NOACCT */ 37715811Sralph sendmail(line+1, bombed); 37812111Sralph continue; 37912111Sralph 38012111Sralph case 'U': 38112111Sralph (void) unlink(line+1); 38212111Sralph } 38312111Sralph /* 38415811Sralph * clean-up in case another control file exists 38512111Sralph */ 38612111Sralph (void) fclose(cfp); 38712111Sralph (void) unlink(file); 38817463Sralph return(bombed == OK ? OK : ERROR); 38912111Sralph } 39012111Sralph 39112111Sralph /* 39212111Sralph * Print a file. 39313233Sralph * Set up the chain [ PR [ | {IF, OF} ] ] or {IF, RF, TF, NF, DF, CF, VF}. 39415811Sralph * Return -1 if a non-recoverable error occured, 39515811Sralph * 2 if the filter detected some errors (but printed the job anyway), 39615811Sralph * 1 if we should try to reprint this job and 39712111Sralph * 0 if all is well. 39812111Sralph * Note: all filters take stdin as the file, stdout as the printer, 39912111Sralph * stderr as the log file, and must not ignore SIGINT. 40012111Sralph */ 40112111Sralph print(format, file) 40212111Sralph int format; 40312111Sralph char *file; 40412111Sralph { 40515811Sralph register int n; 40612111Sralph register char *prog; 40715811Sralph int fi, fo; 40812111Sralph char *av[15], buf[BUFSIZ]; 40912111Sralph int pid, p[2], stopped = 0; 41012111Sralph union wait status; 41117463Sralph struct stat stb; 41212111Sralph 41317463Sralph if (lstat(file, &stb) < 0 || (fi = open(file, O_RDONLY)) < 0) 41417463Sralph return(ERROR); 41517463Sralph /* 41617463Sralph * Check to see if data file is a symbolic link. If so, it should 41717463Sralph * still point to the same file or someone is trying to print 41817463Sralph * something he shouldn't. 41917463Sralph */ 42017463Sralph if ((stb.st_mode & S_IFMT) == S_IFLNK && fstat(fi, &stb) == 0 && 42117463Sralph (stb.st_dev != fdev || stb.st_ino != fino)) 42217463Sralph return(ACCESS); 42312111Sralph if (!SF && !tof) { /* start on a fresh page */ 42412111Sralph (void) write(ofd, FF, strlen(FF)); 42512111Sralph tof = 1; 42612111Sralph } 42712111Sralph if (IF == NULL && (format == 'f' || format == 'l')) { 42812111Sralph tof = 0; 42912111Sralph while ((n = read(fi, buf, BUFSIZ)) > 0) 43012111Sralph if (write(ofd, buf, n) != n) { 43112111Sralph (void) close(fi); 43217463Sralph return(REPRINT); 43312111Sralph } 43412111Sralph (void) close(fi); 43517463Sralph return(OK); 43612111Sralph } 43712111Sralph switch (format) { 43812111Sralph case 'p': /* print file using 'pr' */ 43912111Sralph if (IF == NULL) { /* use output filter */ 44012111Sralph prog = PR; 44112111Sralph av[0] = "pr"; 44212111Sralph av[1] = width; 44312111Sralph av[2] = length; 44412111Sralph av[3] = "-h"; 44512111Sralph av[4] = *title ? title : " "; 44612111Sralph av[5] = 0; 44712111Sralph fo = ofd; 44812111Sralph goto start; 44912111Sralph } 45012111Sralph pipe(p); 45112111Sralph if ((prchild = dofork(DORETURN)) == 0) { /* child */ 45212111Sralph dup2(fi, 0); /* file is stdin */ 45312111Sralph dup2(p[1], 1); /* pipe is stdout */ 45412111Sralph for (n = 3; n < NOFILE; n++) 45512111Sralph (void) close(n); 45612111Sralph execl(PR, "pr", width, length, "-h", *title ? title : " ", 0); 45716762Sralph syslog(LOG_ERR, "cannot execl %s", PR); 45812111Sralph exit(2); 45912111Sralph } 46012111Sralph (void) close(p[1]); /* close output side */ 46112111Sralph (void) close(fi); 46212111Sralph if (prchild < 0) { 46312111Sralph prchild = 0; 46412111Sralph (void) close(p[0]); 46517463Sralph return(ERROR); 46612111Sralph } 46712111Sralph fi = p[0]; /* use pipe for input */ 46812111Sralph case 'f': /* print plain text file */ 46912111Sralph prog = IF; 47012111Sralph av[1] = width; 47112111Sralph av[2] = length; 47212581Sralph av[3] = indent; 47312581Sralph n = 4; 47412111Sralph break; 47512111Sralph case 'l': /* like 'f' but pass control characters */ 47612111Sralph prog = IF; 47714325Sralph av[1] = "-c"; 47812111Sralph av[2] = width; 47912111Sralph av[3] = length; 48012581Sralph av[4] = indent; 48112581Sralph n = 5; 48212111Sralph break; 48312463Sralph case 'r': /* print a fortran text file */ 48412463Sralph prog = RF; 48512463Sralph av[1] = width; 48612463Sralph av[2] = length; 48712463Sralph n = 3; 48812463Sralph break; 48912111Sralph case 't': /* print troff output */ 49013233Sralph case 'n': /* print ditroff output */ 49112463Sralph case 'd': /* print tex output */ 49212111Sralph (void) unlink(".railmag"); 49312463Sralph if ((fo = creat(".railmag", FILMOD)) < 0) { 49416762Sralph syslog(LOG_ERR, "%s: cannot create .railmag", printer); 49512111Sralph (void) unlink(".railmag"); 49612111Sralph } else { 49712111Sralph for (n = 0; n < 4; n++) { 49812111Sralph if (fonts[n][0] != '/') 49912111Sralph (void) write(fo, "/usr/lib/vfont/", 15); 50012111Sralph (void) write(fo, fonts[n], strlen(fonts[n])); 50112111Sralph (void) write(fo, "\n", 1); 50212111Sralph } 50312111Sralph (void) close(fo); 50412111Sralph } 50513233Sralph prog = (format == 't') ? TF : (format == 'n') ? NF : DF; 50612463Sralph av[1] = pxwidth; 50712463Sralph av[2] = pxlength; 50812463Sralph n = 3; 50912111Sralph break; 51012111Sralph case 'c': /* print cifplot output */ 51112111Sralph prog = CF; 51212463Sralph av[1] = pxwidth; 51312463Sralph av[2] = pxlength; 51412463Sralph n = 3; 51512111Sralph break; 51612111Sralph case 'g': /* print plot(1G) output */ 51712111Sralph prog = GF; 51812463Sralph av[1] = pxwidth; 51912463Sralph av[2] = pxlength; 52012463Sralph n = 3; 52112111Sralph break; 52212111Sralph case 'v': /* print raster output */ 52312111Sralph prog = VF; 52412463Sralph av[1] = pxwidth; 52512463Sralph av[2] = pxlength; 52612463Sralph n = 3; 52712111Sralph break; 52812111Sralph default: 52912111Sralph (void) close(fi); 53016762Sralph syslog(LOG_ERR, "%s: illegal format character '%c'", 53116762Sralph printer, format); 53217463Sralph return(ERROR); 53312111Sralph } 53412111Sralph if ((av[0] = rindex(prog, '/')) != NULL) 53512111Sralph av[0]++; 53612111Sralph else 53712111Sralph av[0] = prog; 53812111Sralph av[n++] = "-n"; 53912111Sralph av[n++] = logname; 54012111Sralph av[n++] = "-h"; 54114150Sralph av[n++] = fromhost; 54212111Sralph av[n++] = AF; 54312111Sralph av[n] = 0; 54412111Sralph fo = pfd; 54512111Sralph if (ofilter > 0) { /* stop output filter */ 54612111Sralph write(ofd, "\031\1", 2); 54712111Sralph while ((pid = wait3(&status, WUNTRACED, 0)) > 0 && pid != ofilter) 54812111Sralph ; 54912111Sralph if (status.w_stopval != WSTOPPED) { 55012111Sralph (void) close(fi); 55116762Sralph syslog(LOG_WARNING, "%s: output filter died (%d)", 55216762Sralph printer, status.w_retcode); 55317463Sralph return(REPRINT); 55412111Sralph } 55512111Sralph stopped++; 55612111Sralph } 55712111Sralph start: 55812111Sralph if ((child = dofork(DORETURN)) == 0) { /* child */ 55912111Sralph dup2(fi, 0); 56012111Sralph dup2(fo, 1); 56117304Sralph n = open(tmpfile, O_WRONLY|O_CREAT|O_TRUNC, 0664); 56215811Sralph if (n >= 0) 56315811Sralph dup2(n, 2); 56412111Sralph for (n = 3; n < NOFILE; n++) 56512111Sralph (void) close(n); 56612111Sralph execv(prog, av); 56716762Sralph syslog(LOG_ERR, "cannot execv %s", prog); 56812111Sralph exit(2); 56912111Sralph } 57012111Sralph (void) close(fi); 57112111Sralph if (child < 0) 57212111Sralph status.w_retcode = 100; 57312111Sralph else 57412111Sralph while ((pid = wait(&status)) > 0 && pid != child) 57512111Sralph ; 57612111Sralph child = 0; 57712111Sralph prchild = 0; 57812111Sralph if (stopped) { /* restart output filter */ 57912111Sralph if (kill(ofilter, SIGCONT) < 0) { 58016762Sralph syslog(LOG_ERR, "cannot restart output filter"); 58112111Sralph exit(1); 58212111Sralph } 58312111Sralph } 58412111Sralph tof = 0; 58515811Sralph if (!WIFEXITED(status)) { 58616762Sralph syslog(LOG_WARNING, "%s: Daemon filter '%c' terminated (%d)", 58716762Sralph printer, format, status.w_termsig); 58817463Sralph return(ERROR); 58917463Sralph } 59017463Sralph switch (status.w_retcode) { 59117463Sralph case 0: 59217463Sralph tof = 1; 59317463Sralph return(OK); 59417463Sralph case 1: 59517463Sralph return(REPRINT); 59617463Sralph default: 59716762Sralph syslog(LOG_WARNING, "%s: Daemon filter '%c' exited (%d)", 59816762Sralph printer, format, status.w_retcode); 59917463Sralph case 2: 60017463Sralph return(ERROR); 60117463Sralph } 60212111Sralph } 60312111Sralph 60412111Sralph /* 60512111Sralph * Send the daemon control file (cf) and any data files. 60612111Sralph * Return -1 if a non-recoverable error occured, 1 if a recoverable error and 60712111Sralph * 0 if all is well. 60812111Sralph */ 60912111Sralph sendit(file) 61012111Sralph char *file; 61112111Sralph { 61217463Sralph register int i, err = OK; 61317463Sralph char *cp, last[BUFSIZ]; 61412111Sralph 61512111Sralph /* 61612111Sralph * open control file 61712111Sralph */ 61816762Sralph if ((cfp = fopen(file, "r")) == NULL) 61917463Sralph return(OK); 62012111Sralph /* 62112111Sralph * read the control file for work to do 62212111Sralph * 62312111Sralph * file format -- first character in the line is a command 62412111Sralph * rest of the line is the argument. 62512111Sralph * commands of interest are: 62612111Sralph * 62712111Sralph * a-z -- "file name" name of file to print 62812111Sralph * U -- "unlink" name of file to remove 62912111Sralph * (after we print it. (Pass 2 only)). 63012111Sralph */ 63112111Sralph 63212111Sralph /* 63312111Sralph * pass 1 63412111Sralph */ 63512111Sralph while (getline(cfp)) { 63612111Sralph again: 63717463Sralph if (line[0] == 'S') { 63817463Sralph cp = line+1; 63917463Sralph i = 0; 64017463Sralph while (*cp >= '0' && *cp <= '9') 64117463Sralph i = i * 10 + (*cp++ - '0'); 64217463Sralph fdev = i; 64317463Sralph cp++; 64417463Sralph i = 0; 64517463Sralph while (*cp >= '0' && *cp <= '9') 64617463Sralph i = i * 10 + (*cp++ - '0'); 64717463Sralph fino = i; 64817463Sralph continue; 64917463Sralph } 65012111Sralph if (line[0] >= 'a' && line[0] <= 'z') { 65112111Sralph strcpy(last, line); 65217463Sralph while (i = getline(cfp)) 65312111Sralph if (strcmp(last, line)) 65412111Sralph break; 65517463Sralph switch (sendfile('\3', last+1)) { 65617463Sralph case OK: 65717463Sralph if (i) 65817463Sralph goto again; 65917463Sralph break; 66017463Sralph case REPRINT: 66112111Sralph (void) fclose(cfp); 66217463Sralph return(REPRINT); 66317463Sralph case ACCESS: 66417463Sralph sendmail(logname, ACCESS); 66517463Sralph case ERROR: 66617463Sralph err = ERROR; 66717463Sralph } 66812111Sralph break; 66912111Sralph } 67012111Sralph } 67117463Sralph if (err == OK && sendfile('\2', file) > 0) { 67212111Sralph (void) fclose(cfp); 67317463Sralph return(REPRINT); 67412111Sralph } 67512111Sralph /* 67612111Sralph * pass 2 67712111Sralph */ 67812111Sralph fseek(cfp, 0L, 0); 67912111Sralph while (getline(cfp)) 68012111Sralph if (line[0] == 'U') 68112111Sralph (void) unlink(line+1); 68212111Sralph /* 68317463Sralph * clean-up in case another control file exists 68412111Sralph */ 68512111Sralph (void) fclose(cfp); 68612111Sralph (void) unlink(file); 68717463Sralph return(err); 68812111Sralph } 68912111Sralph 69012111Sralph /* 69112111Sralph * Send a data file to the remote machine and spool it. 69212111Sralph * Return positive if we should try resending. 69312111Sralph */ 69412111Sralph sendfile(type, file) 69512111Sralph char type, *file; 69612111Sralph { 69712111Sralph register int f, i, amt; 69812111Sralph struct stat stb; 69912111Sralph char buf[BUFSIZ]; 70016762Sralph int sizerr, resp; 70112111Sralph 70217463Sralph if (lstat(file, &stb) < 0 || (f = open(file, O_RDONLY)) < 0) 70317463Sralph return(ERROR); 70417463Sralph /* 70517463Sralph * Check to see if data file is a symbolic link. If so, it should 70617463Sralph * still point to the same file or someone is trying to print something 70717463Sralph * he shouldn't. 70817463Sralph */ 70917463Sralph if ((stb.st_mode & S_IFMT) == S_IFLNK && fstat(f, &stb) == 0 && 71017463Sralph (stb.st_dev != fdev || stb.st_ino != fino)) 71117463Sralph return(ACCESS); 71212111Sralph (void) sprintf(buf, "%c%d %s\n", type, stb.st_size, file); 71312111Sralph amt = strlen(buf); 71416762Sralph for (i = 0; ; i++) { 71516762Sralph if (write(pfd, buf, amt) != amt || 71616762Sralph (resp = response()) < 0 || resp == '\1') { 71716762Sralph (void) close(f); 71817463Sralph return(REPRINT); 71916762Sralph } else if (resp == '\0') 72016762Sralph break; 72116762Sralph if (i == 0) 72216762Sralph status("no space on remote; waiting for queue to drain"); 72316762Sralph if (i == 10) 72416762Sralph syslog(LOG_SALERT, "%s: can't send to %s; queue full", 72516762Sralph printer, RM); 72616762Sralph sleep(5 * 60); 72712692Sralph } 72816762Sralph if (i) 72916762Sralph status("sending to %s", RM); 73012111Sralph sizerr = 0; 73112111Sralph for (i = 0; i < stb.st_size; i += BUFSIZ) { 73212111Sralph amt = BUFSIZ; 73312111Sralph if (i + amt > stb.st_size) 73412111Sralph amt = stb.st_size - i; 73512111Sralph if (sizerr == 0 && read(f, buf, amt) != amt) 73612111Sralph sizerr = 1; 73712692Sralph if (write(pfd, buf, amt) != amt) { 73812692Sralph (void) close(f); 73917463Sralph return(REPRINT); 74012692Sralph } 74112111Sralph } 74212111Sralph (void) close(f); 74312111Sralph if (sizerr) { 74416762Sralph syslog(LOG_INFO, "%s: %s: changed size", printer, file); 74517463Sralph /* tell recvjob to ignore this file */ 74617463Sralph (void) write(pfd, "\1", 1); 74717463Sralph return(ERROR); 74817463Sralph } 74917463Sralph if (write(pfd, "", 1) != 1 || response()) 75017463Sralph return(REPRINT); 75117463Sralph return(OK); 75212111Sralph } 75312111Sralph 75412111Sralph /* 75512111Sralph * Check to make sure there have been no errors and that both programs 75612111Sralph * are in sync with eachother. 75712111Sralph * Return non-zero if the connection was lost. 75812111Sralph */ 75916762Sralph response() 76012111Sralph { 76112111Sralph char resp; 76212111Sralph 76316762Sralph if (read(pfd, &resp, 1) != 1) { 76416762Sralph syslog(LOG_INFO, "%s: lost connection", printer); 76516762Sralph return(-1); 76612111Sralph } 76716762Sralph return(resp); 76812111Sralph } 76912111Sralph 77012111Sralph /* 77112111Sralph * Banner printing stuff 77212111Sralph */ 77312111Sralph banner(name1, name2) 77412111Sralph char *name1, *name2; 77512111Sralph { 77612111Sralph time_t tvec; 77712111Sralph extern char *ctime(); 77812111Sralph 77912111Sralph time(&tvec); 78012111Sralph if (!SF && !tof) 78112111Sralph (void) write(ofd, FF, strlen(FF)); 78212111Sralph if (SB) { /* short banner only */ 78312111Sralph if (class[0]) { 78412111Sralph (void) write(ofd, class, strlen(class)); 78512111Sralph (void) write(ofd, ":", 1); 78612111Sralph } 78712111Sralph (void) write(ofd, name1, strlen(name1)); 78812111Sralph (void) write(ofd, " Job: ", 7); 78912111Sralph (void) write(ofd, name2, strlen(name2)); 79012111Sralph (void) write(ofd, " Date: ", 8); 79112111Sralph (void) write(ofd, ctime(&tvec), 24); 79212111Sralph (void) write(ofd, "\n", 1); 79312111Sralph } else { /* normal banner */ 79412111Sralph (void) write(ofd, "\n\n\n", 3); 79512111Sralph scan_out(ofd, name1, '\0'); 79612111Sralph (void) write(ofd, "\n\n", 2); 79712111Sralph scan_out(ofd, name2, '\0'); 79812111Sralph if (class[0]) { 79912111Sralph (void) write(ofd,"\n\n\n",3); 80012111Sralph scan_out(ofd, class, '\0'); 80112111Sralph } 80212111Sralph (void) write(ofd, "\n\n\n\n\t\t\t\t\tJob: ", 15); 80312111Sralph (void) write(ofd, name2, strlen(name2)); 80412111Sralph (void) write(ofd, "\n\t\t\t\t\tDate: ", 12); 80512111Sralph (void) write(ofd, ctime(&tvec), 24); 80612111Sralph (void) write(ofd, "\n", 1); 80712111Sralph } 80812111Sralph if (!SF) 80912111Sralph (void) write(ofd, FF, strlen(FF)); 81012111Sralph tof = 1; 81112111Sralph } 81212111Sralph 81316762Sralph char * 81412111Sralph scnline(key, p, c) 81512111Sralph register char key, *p; 81612111Sralph char c; 81712111Sralph { 81812111Sralph register scnwidth; 81912111Sralph 82012111Sralph for (scnwidth = WIDTH; --scnwidth;) { 82112111Sralph key <<= 1; 82212111Sralph *p++ = key & 0200 ? c : BACKGND; 82312111Sralph } 82412111Sralph return (p); 82512111Sralph } 82612111Sralph 82712111Sralph #define TRC(q) (((q)-' ')&0177) 82812111Sralph 82912111Sralph scan_out(scfd, scsp, dlm) 83012111Sralph int scfd; 83112111Sralph char *scsp, dlm; 83212111Sralph { 83312111Sralph register char *strp; 83412111Sralph register nchrs, j; 83512111Sralph char outbuf[LINELEN+1], *sp, c, cc; 83612111Sralph int d, scnhgt; 83712111Sralph extern char scnkey[][HEIGHT]; /* in lpdchar.c */ 83812111Sralph 83912111Sralph for (scnhgt = 0; scnhgt++ < HEIGHT+DROP; ) { 84012111Sralph strp = &outbuf[0]; 84112111Sralph sp = scsp; 84212111Sralph for (nchrs = 0; ; ) { 84312111Sralph d = dropit(c = TRC(cc = *sp++)); 84412111Sralph if ((!d && scnhgt > HEIGHT) || (scnhgt <= DROP && d)) 84512111Sralph for (j = WIDTH; --j;) 84612111Sralph *strp++ = BACKGND; 84712111Sralph else 84812111Sralph strp = scnline(scnkey[c][scnhgt-1-d], strp, cc); 84912111Sralph if (*sp == dlm || *sp == '\0' || nchrs++ >= PW/(WIDTH+1)-1) 85012111Sralph break; 85112111Sralph *strp++ = BACKGND; 85212111Sralph *strp++ = BACKGND; 85312111Sralph } 85412111Sralph while (*--strp == BACKGND && strp >= outbuf) 85512111Sralph ; 85612111Sralph strp++; 85712111Sralph *strp++ = '\n'; 85812111Sralph (void) write(scfd, outbuf, strp-outbuf); 85912111Sralph } 86012111Sralph } 86112111Sralph 86212111Sralph dropit(c) 86312111Sralph char c; 86412111Sralph { 86512111Sralph switch(c) { 86612111Sralph 86712111Sralph case TRC('_'): 86812111Sralph case TRC(';'): 86912111Sralph case TRC(','): 87012111Sralph case TRC('g'): 87112111Sralph case TRC('j'): 87212111Sralph case TRC('p'): 87312111Sralph case TRC('q'): 87412111Sralph case TRC('y'): 87512111Sralph return (DROP); 87612111Sralph 87712111Sralph default: 87812111Sralph return (0); 87912111Sralph } 88012111Sralph } 88112111Sralph 88212111Sralph /* 88312111Sralph * sendmail --- 88412111Sralph * tell people about job completion 88512111Sralph */ 88615811Sralph sendmail(user, bombed) 88715811Sralph char *user; 88812111Sralph int bombed; 88912111Sralph { 89012111Sralph register int i; 89115811Sralph int p[2], s; 89212111Sralph register char *cp; 89312111Sralph char buf[100]; 89415811Sralph struct stat stb; 89515811Sralph FILE *fp; 89612111Sralph 89712111Sralph pipe(p); 89815811Sralph if ((s = dofork(DORETURN)) == 0) { /* child */ 89912111Sralph dup2(p[0], 0); 90012111Sralph for (i = 3; i < NOFILE; i++) 90112111Sralph (void) close(i); 90212111Sralph if ((cp = rindex(MAIL, '/')) != NULL) 90312111Sralph cp++; 90412111Sralph else 90512111Sralph cp = MAIL; 90615811Sralph sprintf(buf, "%s@%s", user, fromhost); 90712111Sralph execl(MAIL, cp, buf, 0); 90812111Sralph exit(0); 90915811Sralph } else if (s > 0) { /* parent */ 91012111Sralph dup2(p[1], 1); 91115811Sralph printf("To: %s@%s\n", user, fromhost); 91212111Sralph printf("Subject: printer job\n\n"); 91312111Sralph printf("Your printer job "); 91412111Sralph if (*jobname) 91512111Sralph printf("(%s) ", jobname); 91612463Sralph switch (bombed) { 91717463Sralph case OK: 91812463Sralph printf("\ncompleted successfully\n"); 91912463Sralph break; 92012463Sralph default: 92117463Sralph case FATALERR: 92212463Sralph printf("\ncould not be printed\n"); 92312463Sralph break; 92417463Sralph case NOACCT: 92512463Sralph printf("\ncould not be printed without an account on %s\n", host); 92612463Sralph break; 92717463Sralph case FILTERERR: 92815811Sralph if (stat(tmpfile, &stb) < 0 || stb.st_size == 0 || 92915811Sralph (fp = fopen(tmpfile, "r")) == NULL) { 93015811Sralph printf("\nwas printed but had some errors\n"); 93115811Sralph break; 93215811Sralph } 93315811Sralph printf("\nwas printed but had the following errors:\n"); 93415811Sralph while ((i = getc(fp)) != EOF) 93515811Sralph putchar(i); 93615811Sralph (void) fclose(fp); 93717463Sralph break; 93817463Sralph case ACCESS: 93917463Sralph printf("\nwas not printed because it was not linked to the original file\n"); 94012463Sralph } 94112111Sralph fflush(stdout); 94212111Sralph (void) close(1); 94312111Sralph } 94412111Sralph (void) close(p[0]); 94512111Sralph (void) close(p[1]); 94615811Sralph wait(&s); 94712111Sralph } 94812111Sralph 94912111Sralph /* 95012111Sralph * dofork - fork with retries on failure 95112111Sralph */ 95212111Sralph dofork(action) 95312111Sralph int action; 95412111Sralph { 95512111Sralph register int i, pid; 95612111Sralph 95712111Sralph for (i = 0; i < 20; i++) { 95812463Sralph if ((pid = fork()) < 0) { 95912111Sralph sleep((unsigned)(i*i)); 96012463Sralph continue; 96112463Sralph } 96212463Sralph /* 96312463Sralph * Child should run as daemon instead of root 96412463Sralph */ 96512463Sralph if (pid == 0) 96612463Sralph setuid(DU); 96712463Sralph return(pid); 96812111Sralph } 96916762Sralph syslog(LOG_ERR, "can't fork"); 97012111Sralph 97112111Sralph switch (action) { 97212111Sralph case DORETURN: 97312111Sralph return (-1); 97412111Sralph default: 97516762Sralph syslog(LOG_ERR, "bad action (%d) to dofork", action); 97612111Sralph /*FALL THRU*/ 97712111Sralph case DOABORT: 97812111Sralph exit(1); 97912111Sralph } 98012111Sralph /*NOTREACHED*/ 98112111Sralph } 98212111Sralph 98312111Sralph /* 98416762Sralph * Kill child processes to abort current job. 98512111Sralph */ 98616762Sralph abortpr() 98712111Sralph { 98815811Sralph (void) unlink(tmpfile); 98912111Sralph kill(0, SIGINT); 99012111Sralph if (ofilter > 0) 99112111Sralph kill(ofilter, SIGCONT); 99212111Sralph while (wait(0) > 0) 99312111Sralph ; 99412111Sralph exit(0); 99512111Sralph } 99612111Sralph 99712111Sralph init() 99812111Sralph { 99912111Sralph int status; 100012111Sralph 100113169Sralph if ((status = pgetent(line, printer)) < 0) 100213169Sralph fatal("can't open printer description file"); 100313169Sralph else if (status == 0) 100413169Sralph fatal("unknown printer"); 100512111Sralph if ((LP = pgetstr("lp", &bp)) == NULL) 100612111Sralph LP = DEFDEVLP; 100712111Sralph if ((RP = pgetstr("rp", &bp)) == NULL) 100812463Sralph RP = DEFLP; 100912111Sralph if ((LO = pgetstr("lo", &bp)) == NULL) 101012111Sralph LO = DEFLOCK; 101112111Sralph if ((ST = pgetstr("st", &bp)) == NULL) 101212111Sralph ST = DEFSTAT; 101312111Sralph if ((LF = pgetstr("lf", &bp)) == NULL) 101412111Sralph LF = DEFLOGF; 101512111Sralph if ((SD = pgetstr("sd", &bp)) == NULL) 101612111Sralph SD = DEFSPOOL; 101712111Sralph if ((DU = pgetnum("du")) < 0) 101812111Sralph DU = DEFUID; 101912111Sralph if ((FF = pgetstr("ff", &bp)) == NULL) 102012111Sralph FF = DEFFF; 102112111Sralph if ((PW = pgetnum("pw")) < 0) 102212111Sralph PW = DEFWIDTH; 102312111Sralph sprintf(&width[2], "%d", PW); 102412111Sralph if ((PL = pgetnum("pl")) < 0) 102512111Sralph PL = DEFLENGTH; 102612111Sralph sprintf(&length[2], "%d", PL); 102712463Sralph if ((PX = pgetnum("px")) < 0) 102812463Sralph PX = 0; 102912463Sralph sprintf(&pxwidth[2], "%d", PX); 103012463Sralph if ((PY = pgetnum("py")) < 0) 103112463Sralph PY = 0; 103212463Sralph sprintf(&pxlength[2], "%d", PY); 103312111Sralph RM = pgetstr("rm", &bp); 103412111Sralph AF = pgetstr("af", &bp); 103512111Sralph OF = pgetstr("of", &bp); 103612111Sralph IF = pgetstr("if", &bp); 103712463Sralph RF = pgetstr("rf", &bp); 103812111Sralph TF = pgetstr("tf", &bp); 103913233Sralph NF = pgetstr("nf", &bp); 104012111Sralph DF = pgetstr("df", &bp); 104112111Sralph GF = pgetstr("gf", &bp); 104212111Sralph VF = pgetstr("vf", &bp); 104312111Sralph CF = pgetstr("cf", &bp); 104412111Sralph TR = pgetstr("tr", &bp); 104512463Sralph RS = pgetflag("rs"); 104612111Sralph SF = pgetflag("sf"); 104712111Sralph SH = pgetflag("sh"); 104812111Sralph SB = pgetflag("sb"); 1049*18127Sralph HL = pgetflag("hl"); 105012111Sralph RW = pgetflag("rw"); 105112111Sralph BR = pgetnum("br"); 105212111Sralph if ((FC = pgetnum("fc")) < 0) 105312111Sralph FC = 0; 105412111Sralph if ((FS = pgetnum("fs")) < 0) 105512111Sralph FS = 0; 105612111Sralph if ((XC = pgetnum("xc")) < 0) 105712111Sralph XC = 0; 105812111Sralph if ((XS = pgetnum("xs")) < 0) 105912111Sralph XS = 0; 106012581Sralph tof = !pgetflag("fo"); 106112111Sralph } 106212111Sralph 106312463Sralph /* 106412463Sralph * Acquire line printer or remote connection. 106512463Sralph */ 106612463Sralph openpr() 106712463Sralph { 106812463Sralph register int i, n; 106916762Sralph int resp; 107012463Sralph 107112463Sralph if (*LP) { 107212463Sralph for (i = 1; ; i = i < 32 ? i << 1 : i) { 107313148Ssam pfd = open(LP, RW ? O_RDWR : O_WRONLY); 107412463Sralph if (pfd >= 0) 107512463Sralph break; 107612463Sralph if (errno == ENOENT) { 107716762Sralph syslog(LOG_ERR, "%s: %m", LP); 107812463Sralph exit(1); 107912463Sralph } 108012463Sralph if (i == 1) 108112463Sralph status("waiting for %s to become ready (offline ?)", printer); 108212463Sralph sleep(i); 108312463Sralph } 108412463Sralph if (isatty(pfd)) 108512463Sralph setty(); 108612463Sralph status("%s is ready and printing", printer); 108712463Sralph } else if (RM != NULL) { 108816762Sralph for (i = 1; ; i = i < 256 ? i << 1 : i) { 108916762Sralph resp = -1; 109012528Sralph pfd = getport(RM); 109112463Sralph if (pfd >= 0) { 109212463Sralph (void) sprintf(line, "\2%s\n", RP); 109312463Sralph n = strlen(line); 109416762Sralph if (write(pfd, line, n) == n && 109516762Sralph (resp = response()) == '\0') 109612463Sralph break; 109716031Sralph (void) close(pfd); 109812463Sralph } 109916031Sralph if (i == 1) { 110016762Sralph if (resp < 0) 110116031Sralph status("waiting for %s to come up", RM); 110216762Sralph else { 110316031Sralph status("waiting for queue to be enabled on %s", RM); 110416762Sralph i = 256; 110516762Sralph } 110616031Sralph } 110712463Sralph sleep(i); 110812463Sralph } 110912463Sralph status("sending to %s", RM); 111012463Sralph remote = 1; 111112463Sralph } else { 111216762Sralph syslog(LOG_ERR, "%s: no line printer device or host name", 111316762Sralph printer); 111412463Sralph exit(1); 111512463Sralph } 111612463Sralph /* 111712463Sralph * Start up an output filter, if needed. 111812463Sralph */ 111912463Sralph if (OF) { 112012463Sralph int p[2]; 112112463Sralph char *cp; 112212463Sralph 112312463Sralph pipe(p); 112412463Sralph if ((ofilter = dofork(DOABORT)) == 0) { /* child */ 112512463Sralph dup2(p[0], 0); /* pipe is std in */ 112612463Sralph dup2(pfd, 1); /* printer is std out */ 112712463Sralph for (i = 3; i < NOFILE; i++) 112812463Sralph (void) close(i); 112912463Sralph if ((cp = rindex(OF, '/')) == NULL) 113012463Sralph cp = OF; 113112463Sralph else 113212463Sralph cp++; 113312463Sralph execl(OF, cp, width, length, 0); 113416762Sralph syslog(LOG_ERR, "%s: %s: %m", printer, OF); 113512463Sralph exit(1); 113612463Sralph } 113712463Sralph (void) close(p[0]); /* close input side */ 113812463Sralph ofd = p[1]; /* use pipe for output */ 113912463Sralph } else { 114012463Sralph ofd = pfd; 114112463Sralph ofilter = 0; 114212463Sralph } 114312463Sralph } 114412463Sralph 114512111Sralph struct bauds { 114612111Sralph int baud; 114712111Sralph int speed; 114812111Sralph } bauds[] = { 114912111Sralph 50, B50, 115012111Sralph 75, B75, 115112111Sralph 110, B110, 115212111Sralph 134, B134, 115312111Sralph 150, B150, 115412111Sralph 200, B200, 115512111Sralph 300, B300, 115612111Sralph 600, B600, 115712111Sralph 1200, B1200, 115812111Sralph 1800, B1800, 115912111Sralph 2400, B2400, 116012111Sralph 4800, B4800, 116112111Sralph 9600, B9600, 116212111Sralph 19200, EXTA, 116312111Sralph 38400, EXTB, 116412111Sralph 0, 0 116512111Sralph }; 116612111Sralph 116712111Sralph /* 116812111Sralph * setup tty lines. 116912111Sralph */ 117012111Sralph setty() 117112111Sralph { 117212111Sralph struct sgttyb ttybuf; 117312111Sralph register struct bauds *bp; 117412111Sralph 117512111Sralph if (ioctl(pfd, TIOCEXCL, (char *)0) < 0) { 117616762Sralph syslog(LOG_ERR, "%s: ioctl(TIOCEXCL): %m", printer); 117712111Sralph exit(1); 117812111Sralph } 117912111Sralph if (ioctl(pfd, TIOCGETP, (char *)&ttybuf) < 0) { 118016762Sralph syslog(LOG_ERR, "%s: ioctl(TIOCGETP): %m", printer); 118112111Sralph exit(1); 118212111Sralph } 118312111Sralph if (BR > 0) { 118412111Sralph for (bp = bauds; bp->baud; bp++) 118512111Sralph if (BR == bp->baud) 118612111Sralph break; 118712111Sralph if (!bp->baud) { 118816762Sralph syslog(LOG_ERR, "%s: illegal baud rate %d", printer, BR); 118912111Sralph exit(1); 119012111Sralph } 119112111Sralph ttybuf.sg_ispeed = ttybuf.sg_ospeed = bp->speed; 119212111Sralph } 119313169Sralph ttybuf.sg_flags &= ~FC; 119413169Sralph ttybuf.sg_flags |= FS; 119512111Sralph if (ioctl(pfd, TIOCSETP, (char *)&ttybuf) < 0) { 119616762Sralph syslog(LOG_ERR, "%s: ioctl(TIOCSETP): %m", printer); 119712111Sralph exit(1); 119812111Sralph } 119917168Sralph if (XC || XS) { 120017168Sralph int ldisc = NTTYDISC; 120117168Sralph 120217168Sralph if (ioctl(pfd, TIOCSETD, &ldisc) < 0) { 120317168Sralph syslog(LOG_ERR, "%s: ioctl(TIOCSETD): %m", printer); 120417168Sralph exit(1); 120517168Sralph } 120617168Sralph } 120712111Sralph if (XC) { 120812111Sralph if (ioctl(pfd, TIOCLBIC, &XC) < 0) { 120916762Sralph syslog(LOG_ERR, "%s: ioctl(TIOCLBIC): %m", printer); 121012111Sralph exit(1); 121112111Sralph } 121212111Sralph } 121312111Sralph if (XS) { 121412111Sralph if (ioctl(pfd, TIOCLBIS, &XS) < 0) { 121516762Sralph syslog(LOG_ERR, "%s: ioctl(TIOCLBIS): %m", printer); 121612111Sralph exit(1); 121712111Sralph } 121812111Sralph } 121912111Sralph } 122012463Sralph 122112463Sralph /*VARARGS1*/ 122212463Sralph status(msg, a1, a2, a3) 122312463Sralph char *msg; 122412463Sralph { 122512463Sralph register int fd; 122612463Sralph char buf[BUFSIZ]; 122712463Sralph 122812463Sralph umask(0); 122913148Ssam fd = open(ST, O_WRONLY|O_CREAT, 0664); 123016762Sralph if (fd < 0 || flock(fd, LOCK_EX) < 0) { 123116762Sralph syslog(LOG_ERR, "%s: %s: %m", printer, ST); 123216762Sralph exit(1); 123316762Sralph } 123413148Ssam ftruncate(fd, 0); 123512463Sralph sprintf(buf, msg, a1, a2, a3); 123612463Sralph strcat(buf, "\n"); 123712463Sralph (void) write(fd, buf, strlen(buf)); 123812463Sralph (void) close(fd); 123912463Sralph } 1240