113954Ssam #ifndef lint 2*17463Sralph static char sccsid[] = "@(#)printjob.c 4.23 (Berkeley) 12/05/84"; 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 17*17463Sralph /* 18*17463Sralph * Error tokens 19*17463Sralph */ 20*17463Sralph #define REPRINT -2 21*17463Sralph #define ERROR -1 22*17463Sralph #define OK 0 23*17463Sralph #define FATALERR 1 24*17463Sralph #define NOACCT 2 25*17463Sralph #define FILTERERR 3 26*17463Sralph #define ACCESS 4 27*17463Sralph 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 */ 39*17463Sralph dev_t fdev; /* device of file pointed to by symlink */ 40*17463Sralph 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 } 157*17463Sralph if (i == OK) /* file ok and printed */ 15814150Sralph count++; 159*17463Sralph 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; 214*17463Sralph char *cp; 215*17463Sralph int bombed = OK; 21612111Sralph 21712111Sralph /* 218*17463Sralph * 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); 222*17463Sralph 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 * 239*17463Sralph * 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) { 282*17463Sralph bombed = NOACCT; 28315811Sralph sendmail(line+1, bombed); 28412463Sralph goto pass2; 28512463Sralph } 28612463Sralph } 28712111Sralph continue; 28812111Sralph 289*17463Sralph case 'S': 290*17463Sralph cp = line+1; 291*17463Sralph i = 0; 292*17463Sralph while (*cp >= '0' && *cp <= '9') 293*17463Sralph i = i * 10 + (*cp++ - '0'); 294*17463Sralph fdev = i; 295*17463Sralph cp++; 296*17463Sralph i = 0; 297*17463Sralph while (*cp >= '0' && *cp <= '9') 298*17463Sralph i = i * 10 + (*cp++ - '0'); 299*17463Sralph fino = i; 300*17463Sralph continue; 301*17463Sralph 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 */ 32112111Sralph if (!SH) 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)) { 343*17463Sralph case ERROR: 344*17463Sralph if (bombed == OK) 345*17463Sralph bombed = FATALERR; 34615811Sralph break; 347*17463Sralph case REPRINT: 34812111Sralph (void) fclose(cfp); 349*17463Sralph return(REPRINT); 350*17463Sralph case FILTERERR: 351*17463Sralph case ACCESS: 352*17463Sralph 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]) { 37012111Sralph case 'M': 371*17463Sralph if (bombed < NOACCT) /* already sent if >= NOACCT */ 37215811Sralph sendmail(line+1, bombed); 37312111Sralph continue; 37412111Sralph 37512111Sralph case 'U': 37612111Sralph (void) unlink(line+1); 37712111Sralph } 37812111Sralph /* 37915811Sralph * clean-up in case another control file exists 38012111Sralph */ 38112111Sralph (void) fclose(cfp); 38212111Sralph (void) unlink(file); 383*17463Sralph return(bombed == OK ? OK : ERROR); 38412111Sralph } 38512111Sralph 38612111Sralph /* 38712111Sralph * Print a file. 38813233Sralph * Set up the chain [ PR [ | {IF, OF} ] ] or {IF, RF, TF, NF, DF, CF, VF}. 38915811Sralph * Return -1 if a non-recoverable error occured, 39015811Sralph * 2 if the filter detected some errors (but printed the job anyway), 39115811Sralph * 1 if we should try to reprint this job and 39212111Sralph * 0 if all is well. 39312111Sralph * Note: all filters take stdin as the file, stdout as the printer, 39412111Sralph * stderr as the log file, and must not ignore SIGINT. 39512111Sralph */ 39612111Sralph print(format, file) 39712111Sralph int format; 39812111Sralph char *file; 39912111Sralph { 40015811Sralph register int n; 40112111Sralph register char *prog; 40215811Sralph int fi, fo; 40312111Sralph char *av[15], buf[BUFSIZ]; 40412111Sralph int pid, p[2], stopped = 0; 40512111Sralph union wait status; 406*17463Sralph struct stat stb; 40712111Sralph 408*17463Sralph if (lstat(file, &stb) < 0 || (fi = open(file, O_RDONLY)) < 0) 409*17463Sralph return(ERROR); 410*17463Sralph /* 411*17463Sralph * Check to see if data file is a symbolic link. If so, it should 412*17463Sralph * still point to the same file or someone is trying to print 413*17463Sralph * something he shouldn't. 414*17463Sralph */ 415*17463Sralph if ((stb.st_mode & S_IFMT) == S_IFLNK && fstat(fi, &stb) == 0 && 416*17463Sralph (stb.st_dev != fdev || stb.st_ino != fino)) 417*17463Sralph return(ACCESS); 41812111Sralph if (!SF && !tof) { /* start on a fresh page */ 41912111Sralph (void) write(ofd, FF, strlen(FF)); 42012111Sralph tof = 1; 42112111Sralph } 42212111Sralph if (IF == NULL && (format == 'f' || format == 'l')) { 42312111Sralph tof = 0; 42412111Sralph while ((n = read(fi, buf, BUFSIZ)) > 0) 42512111Sralph if (write(ofd, buf, n) != n) { 42612111Sralph (void) close(fi); 427*17463Sralph return(REPRINT); 42812111Sralph } 42912111Sralph (void) close(fi); 430*17463Sralph return(OK); 43112111Sralph } 43212111Sralph switch (format) { 43312111Sralph case 'p': /* print file using 'pr' */ 43412111Sralph if (IF == NULL) { /* use output filter */ 43512111Sralph prog = PR; 43612111Sralph av[0] = "pr"; 43712111Sralph av[1] = width; 43812111Sralph av[2] = length; 43912111Sralph av[3] = "-h"; 44012111Sralph av[4] = *title ? title : " "; 44112111Sralph av[5] = 0; 44212111Sralph fo = ofd; 44312111Sralph goto start; 44412111Sralph } 44512111Sralph pipe(p); 44612111Sralph if ((prchild = dofork(DORETURN)) == 0) { /* child */ 44712111Sralph dup2(fi, 0); /* file is stdin */ 44812111Sralph dup2(p[1], 1); /* pipe is stdout */ 44912111Sralph for (n = 3; n < NOFILE; n++) 45012111Sralph (void) close(n); 45112111Sralph execl(PR, "pr", width, length, "-h", *title ? title : " ", 0); 45216762Sralph syslog(LOG_ERR, "cannot execl %s", PR); 45312111Sralph exit(2); 45412111Sralph } 45512111Sralph (void) close(p[1]); /* close output side */ 45612111Sralph (void) close(fi); 45712111Sralph if (prchild < 0) { 45812111Sralph prchild = 0; 45912111Sralph (void) close(p[0]); 460*17463Sralph return(ERROR); 46112111Sralph } 46212111Sralph fi = p[0]; /* use pipe for input */ 46312111Sralph case 'f': /* print plain text file */ 46412111Sralph prog = IF; 46512111Sralph av[1] = width; 46612111Sralph av[2] = length; 46712581Sralph av[3] = indent; 46812581Sralph n = 4; 46912111Sralph break; 47012111Sralph case 'l': /* like 'f' but pass control characters */ 47112111Sralph prog = IF; 47214325Sralph av[1] = "-c"; 47312111Sralph av[2] = width; 47412111Sralph av[3] = length; 47512581Sralph av[4] = indent; 47612581Sralph n = 5; 47712111Sralph break; 47812463Sralph case 'r': /* print a fortran text file */ 47912463Sralph prog = RF; 48012463Sralph av[1] = width; 48112463Sralph av[2] = length; 48212463Sralph n = 3; 48312463Sralph break; 48412111Sralph case 't': /* print troff output */ 48513233Sralph case 'n': /* print ditroff output */ 48612463Sralph case 'd': /* print tex output */ 48712111Sralph (void) unlink(".railmag"); 48812463Sralph if ((fo = creat(".railmag", FILMOD)) < 0) { 48916762Sralph syslog(LOG_ERR, "%s: cannot create .railmag", printer); 49012111Sralph (void) unlink(".railmag"); 49112111Sralph } else { 49212111Sralph for (n = 0; n < 4; n++) { 49312111Sralph if (fonts[n][0] != '/') 49412111Sralph (void) write(fo, "/usr/lib/vfont/", 15); 49512111Sralph (void) write(fo, fonts[n], strlen(fonts[n])); 49612111Sralph (void) write(fo, "\n", 1); 49712111Sralph } 49812111Sralph (void) close(fo); 49912111Sralph } 50013233Sralph prog = (format == 't') ? TF : (format == 'n') ? NF : DF; 50112463Sralph av[1] = pxwidth; 50212463Sralph av[2] = pxlength; 50312463Sralph n = 3; 50412111Sralph break; 50512111Sralph case 'c': /* print cifplot output */ 50612111Sralph prog = CF; 50712463Sralph av[1] = pxwidth; 50812463Sralph av[2] = pxlength; 50912463Sralph n = 3; 51012111Sralph break; 51112111Sralph case 'g': /* print plot(1G) output */ 51212111Sralph prog = GF; 51312463Sralph av[1] = pxwidth; 51412463Sralph av[2] = pxlength; 51512463Sralph n = 3; 51612111Sralph break; 51712111Sralph case 'v': /* print raster output */ 51812111Sralph prog = VF; 51912463Sralph av[1] = pxwidth; 52012463Sralph av[2] = pxlength; 52112463Sralph n = 3; 52212111Sralph break; 52312111Sralph default: 52412111Sralph (void) close(fi); 52516762Sralph syslog(LOG_ERR, "%s: illegal format character '%c'", 52616762Sralph printer, format); 527*17463Sralph return(ERROR); 52812111Sralph } 52912111Sralph if ((av[0] = rindex(prog, '/')) != NULL) 53012111Sralph av[0]++; 53112111Sralph else 53212111Sralph av[0] = prog; 53312111Sralph av[n++] = "-n"; 53412111Sralph av[n++] = logname; 53512111Sralph av[n++] = "-h"; 53614150Sralph av[n++] = fromhost; 53712111Sralph av[n++] = AF; 53812111Sralph av[n] = 0; 53912111Sralph fo = pfd; 54012111Sralph if (ofilter > 0) { /* stop output filter */ 54112111Sralph write(ofd, "\031\1", 2); 54212111Sralph while ((pid = wait3(&status, WUNTRACED, 0)) > 0 && pid != ofilter) 54312111Sralph ; 54412111Sralph if (status.w_stopval != WSTOPPED) { 54512111Sralph (void) close(fi); 54616762Sralph syslog(LOG_WARNING, "%s: output filter died (%d)", 54716762Sralph printer, status.w_retcode); 548*17463Sralph return(REPRINT); 54912111Sralph } 55012111Sralph stopped++; 55112111Sralph } 55212111Sralph start: 55312111Sralph if ((child = dofork(DORETURN)) == 0) { /* child */ 55412111Sralph dup2(fi, 0); 55512111Sralph dup2(fo, 1); 55617304Sralph n = open(tmpfile, O_WRONLY|O_CREAT|O_TRUNC, 0664); 55715811Sralph if (n >= 0) 55815811Sralph dup2(n, 2); 55912111Sralph for (n = 3; n < NOFILE; n++) 56012111Sralph (void) close(n); 56112111Sralph execv(prog, av); 56216762Sralph syslog(LOG_ERR, "cannot execv %s", prog); 56312111Sralph exit(2); 56412111Sralph } 56512111Sralph (void) close(fi); 56612111Sralph if (child < 0) 56712111Sralph status.w_retcode = 100; 56812111Sralph else 56912111Sralph while ((pid = wait(&status)) > 0 && pid != child) 57012111Sralph ; 57112111Sralph child = 0; 57212111Sralph prchild = 0; 57312111Sralph if (stopped) { /* restart output filter */ 57412111Sralph if (kill(ofilter, SIGCONT) < 0) { 57516762Sralph syslog(LOG_ERR, "cannot restart output filter"); 57612111Sralph exit(1); 57712111Sralph } 57812111Sralph } 57912111Sralph tof = 0; 58015811Sralph if (!WIFEXITED(status)) { 58116762Sralph syslog(LOG_WARNING, "%s: Daemon filter '%c' terminated (%d)", 58216762Sralph printer, format, status.w_termsig); 583*17463Sralph return(ERROR); 584*17463Sralph } 585*17463Sralph switch (status.w_retcode) { 586*17463Sralph case 0: 587*17463Sralph tof = 1; 588*17463Sralph return(OK); 589*17463Sralph case 1: 590*17463Sralph return(REPRINT); 591*17463Sralph default: 59216762Sralph syslog(LOG_WARNING, "%s: Daemon filter '%c' exited (%d)", 59316762Sralph printer, format, status.w_retcode); 594*17463Sralph case 2: 595*17463Sralph return(ERROR); 596*17463Sralph } 59712111Sralph } 59812111Sralph 59912111Sralph /* 60012111Sralph * Send the daemon control file (cf) and any data files. 60112111Sralph * Return -1 if a non-recoverable error occured, 1 if a recoverable error and 60212111Sralph * 0 if all is well. 60312111Sralph */ 60412111Sralph sendit(file) 60512111Sralph char *file; 60612111Sralph { 607*17463Sralph register int i, err = OK; 608*17463Sralph char *cp, last[BUFSIZ]; 60912111Sralph 61012111Sralph /* 61112111Sralph * open control file 61212111Sralph */ 61316762Sralph if ((cfp = fopen(file, "r")) == NULL) 614*17463Sralph return(OK); 61512111Sralph /* 61612111Sralph * read the control file for work to do 61712111Sralph * 61812111Sralph * file format -- first character in the line is a command 61912111Sralph * rest of the line is the argument. 62012111Sralph * commands of interest are: 62112111Sralph * 62212111Sralph * a-z -- "file name" name of file to print 62312111Sralph * U -- "unlink" name of file to remove 62412111Sralph * (after we print it. (Pass 2 only)). 62512111Sralph */ 62612111Sralph 62712111Sralph /* 62812111Sralph * pass 1 62912111Sralph */ 63012111Sralph while (getline(cfp)) { 63112111Sralph again: 632*17463Sralph if (line[0] == 'S') { 633*17463Sralph cp = line+1; 634*17463Sralph i = 0; 635*17463Sralph while (*cp >= '0' && *cp <= '9') 636*17463Sralph i = i * 10 + (*cp++ - '0'); 637*17463Sralph fdev = i; 638*17463Sralph cp++; 639*17463Sralph i = 0; 640*17463Sralph while (*cp >= '0' && *cp <= '9') 641*17463Sralph i = i * 10 + (*cp++ - '0'); 642*17463Sralph fino = i; 643*17463Sralph continue; 644*17463Sralph } 64512111Sralph if (line[0] >= 'a' && line[0] <= 'z') { 64612111Sralph strcpy(last, line); 647*17463Sralph while (i = getline(cfp)) 64812111Sralph if (strcmp(last, line)) 64912111Sralph break; 650*17463Sralph switch (sendfile('\3', last+1)) { 651*17463Sralph case OK: 652*17463Sralph if (i) 653*17463Sralph goto again; 654*17463Sralph break; 655*17463Sralph case REPRINT: 65612111Sralph (void) fclose(cfp); 657*17463Sralph return(REPRINT); 658*17463Sralph case ACCESS: 659*17463Sralph sendmail(logname, ACCESS); 660*17463Sralph case ERROR: 661*17463Sralph err = ERROR; 662*17463Sralph } 66312111Sralph break; 66412111Sralph } 66512111Sralph } 666*17463Sralph if (err == OK && sendfile('\2', file) > 0) { 66712111Sralph (void) fclose(cfp); 668*17463Sralph return(REPRINT); 66912111Sralph } 67012111Sralph /* 67112111Sralph * pass 2 67212111Sralph */ 67312111Sralph fseek(cfp, 0L, 0); 67412111Sralph while (getline(cfp)) 67512111Sralph if (line[0] == 'U') 67612111Sralph (void) unlink(line+1); 67712111Sralph /* 678*17463Sralph * clean-up in case another control file exists 67912111Sralph */ 68012111Sralph (void) fclose(cfp); 68112111Sralph (void) unlink(file); 682*17463Sralph return(err); 68312111Sralph } 68412111Sralph 68512111Sralph /* 68612111Sralph * Send a data file to the remote machine and spool it. 68712111Sralph * Return positive if we should try resending. 68812111Sralph */ 68912111Sralph sendfile(type, file) 69012111Sralph char type, *file; 69112111Sralph { 69212111Sralph register int f, i, amt; 69312111Sralph struct stat stb; 69412111Sralph char buf[BUFSIZ]; 69516762Sralph int sizerr, resp; 69612111Sralph 697*17463Sralph if (lstat(file, &stb) < 0 || (f = open(file, O_RDONLY)) < 0) 698*17463Sralph return(ERROR); 699*17463Sralph /* 700*17463Sralph * Check to see if data file is a symbolic link. If so, it should 701*17463Sralph * still point to the same file or someone is trying to print something 702*17463Sralph * he shouldn't. 703*17463Sralph */ 704*17463Sralph if ((stb.st_mode & S_IFMT) == S_IFLNK && fstat(f, &stb) == 0 && 705*17463Sralph (stb.st_dev != fdev || stb.st_ino != fino)) 706*17463Sralph return(ACCESS); 70712111Sralph (void) sprintf(buf, "%c%d %s\n", type, stb.st_size, file); 70812111Sralph amt = strlen(buf); 70916762Sralph for (i = 0; ; i++) { 71016762Sralph if (write(pfd, buf, amt) != amt || 71116762Sralph (resp = response()) < 0 || resp == '\1') { 71216762Sralph (void) close(f); 713*17463Sralph return(REPRINT); 71416762Sralph } else if (resp == '\0') 71516762Sralph break; 71616762Sralph if (i == 0) 71716762Sralph status("no space on remote; waiting for queue to drain"); 71816762Sralph if (i == 10) 71916762Sralph syslog(LOG_SALERT, "%s: can't send to %s; queue full", 72016762Sralph printer, RM); 72116762Sralph sleep(5 * 60); 72212692Sralph } 72316762Sralph if (i) 72416762Sralph status("sending to %s", RM); 72512111Sralph sizerr = 0; 72612111Sralph for (i = 0; i < stb.st_size; i += BUFSIZ) { 72712111Sralph amt = BUFSIZ; 72812111Sralph if (i + amt > stb.st_size) 72912111Sralph amt = stb.st_size - i; 73012111Sralph if (sizerr == 0 && read(f, buf, amt) != amt) 73112111Sralph sizerr = 1; 73212692Sralph if (write(pfd, buf, amt) != amt) { 73312692Sralph (void) close(f); 734*17463Sralph return(REPRINT); 73512692Sralph } 73612111Sralph } 73712111Sralph (void) close(f); 73812111Sralph if (sizerr) { 73916762Sralph syslog(LOG_INFO, "%s: %s: changed size", printer, file); 740*17463Sralph /* tell recvjob to ignore this file */ 741*17463Sralph (void) write(pfd, "\1", 1); 742*17463Sralph return(ERROR); 743*17463Sralph } 744*17463Sralph if (write(pfd, "", 1) != 1 || response()) 745*17463Sralph return(REPRINT); 746*17463Sralph return(OK); 74712111Sralph } 74812111Sralph 74912111Sralph /* 75012111Sralph * Check to make sure there have been no errors and that both programs 75112111Sralph * are in sync with eachother. 75212111Sralph * Return non-zero if the connection was lost. 75312111Sralph */ 75416762Sralph response() 75512111Sralph { 75612111Sralph char resp; 75712111Sralph 75816762Sralph if (read(pfd, &resp, 1) != 1) { 75916762Sralph syslog(LOG_INFO, "%s: lost connection", printer); 76016762Sralph return(-1); 76112111Sralph } 76216762Sralph return(resp); 76312111Sralph } 76412111Sralph 76512111Sralph /* 76612111Sralph * Banner printing stuff 76712111Sralph */ 76812111Sralph banner(name1, name2) 76912111Sralph char *name1, *name2; 77012111Sralph { 77112111Sralph time_t tvec; 77212111Sralph extern char *ctime(); 77312111Sralph 77412111Sralph time(&tvec); 77512111Sralph if (!SF && !tof) 77612111Sralph (void) write(ofd, FF, strlen(FF)); 77712111Sralph if (SB) { /* short banner only */ 77812111Sralph if (class[0]) { 77912111Sralph (void) write(ofd, class, strlen(class)); 78012111Sralph (void) write(ofd, ":", 1); 78112111Sralph } 78212111Sralph (void) write(ofd, name1, strlen(name1)); 78312111Sralph (void) write(ofd, " Job: ", 7); 78412111Sralph (void) write(ofd, name2, strlen(name2)); 78512111Sralph (void) write(ofd, " Date: ", 8); 78612111Sralph (void) write(ofd, ctime(&tvec), 24); 78712111Sralph (void) write(ofd, "\n", 1); 78812111Sralph } else { /* normal banner */ 78912111Sralph (void) write(ofd, "\n\n\n", 3); 79012111Sralph scan_out(ofd, name1, '\0'); 79112111Sralph (void) write(ofd, "\n\n", 2); 79212111Sralph scan_out(ofd, name2, '\0'); 79312111Sralph if (class[0]) { 79412111Sralph (void) write(ofd,"\n\n\n",3); 79512111Sralph scan_out(ofd, class, '\0'); 79612111Sralph } 79712111Sralph (void) write(ofd, "\n\n\n\n\t\t\t\t\tJob: ", 15); 79812111Sralph (void) write(ofd, name2, strlen(name2)); 79912111Sralph (void) write(ofd, "\n\t\t\t\t\tDate: ", 12); 80012111Sralph (void) write(ofd, ctime(&tvec), 24); 80112111Sralph (void) write(ofd, "\n", 1); 80212111Sralph } 80312111Sralph if (!SF) 80412111Sralph (void) write(ofd, FF, strlen(FF)); 80512111Sralph tof = 1; 80612111Sralph } 80712111Sralph 80816762Sralph char * 80912111Sralph scnline(key, p, c) 81012111Sralph register char key, *p; 81112111Sralph char c; 81212111Sralph { 81312111Sralph register scnwidth; 81412111Sralph 81512111Sralph for (scnwidth = WIDTH; --scnwidth;) { 81612111Sralph key <<= 1; 81712111Sralph *p++ = key & 0200 ? c : BACKGND; 81812111Sralph } 81912111Sralph return (p); 82012111Sralph } 82112111Sralph 82212111Sralph #define TRC(q) (((q)-' ')&0177) 82312111Sralph 82412111Sralph scan_out(scfd, scsp, dlm) 82512111Sralph int scfd; 82612111Sralph char *scsp, dlm; 82712111Sralph { 82812111Sralph register char *strp; 82912111Sralph register nchrs, j; 83012111Sralph char outbuf[LINELEN+1], *sp, c, cc; 83112111Sralph int d, scnhgt; 83212111Sralph extern char scnkey[][HEIGHT]; /* in lpdchar.c */ 83312111Sralph 83412111Sralph for (scnhgt = 0; scnhgt++ < HEIGHT+DROP; ) { 83512111Sralph strp = &outbuf[0]; 83612111Sralph sp = scsp; 83712111Sralph for (nchrs = 0; ; ) { 83812111Sralph d = dropit(c = TRC(cc = *sp++)); 83912111Sralph if ((!d && scnhgt > HEIGHT) || (scnhgt <= DROP && d)) 84012111Sralph for (j = WIDTH; --j;) 84112111Sralph *strp++ = BACKGND; 84212111Sralph else 84312111Sralph strp = scnline(scnkey[c][scnhgt-1-d], strp, cc); 84412111Sralph if (*sp == dlm || *sp == '\0' || nchrs++ >= PW/(WIDTH+1)-1) 84512111Sralph break; 84612111Sralph *strp++ = BACKGND; 84712111Sralph *strp++ = BACKGND; 84812111Sralph } 84912111Sralph while (*--strp == BACKGND && strp >= outbuf) 85012111Sralph ; 85112111Sralph strp++; 85212111Sralph *strp++ = '\n'; 85312111Sralph (void) write(scfd, outbuf, strp-outbuf); 85412111Sralph } 85512111Sralph } 85612111Sralph 85712111Sralph dropit(c) 85812111Sralph char c; 85912111Sralph { 86012111Sralph switch(c) { 86112111Sralph 86212111Sralph case TRC('_'): 86312111Sralph case TRC(';'): 86412111Sralph case TRC(','): 86512111Sralph case TRC('g'): 86612111Sralph case TRC('j'): 86712111Sralph case TRC('p'): 86812111Sralph case TRC('q'): 86912111Sralph case TRC('y'): 87012111Sralph return (DROP); 87112111Sralph 87212111Sralph default: 87312111Sralph return (0); 87412111Sralph } 87512111Sralph } 87612111Sralph 87712111Sralph /* 87812111Sralph * sendmail --- 87912111Sralph * tell people about job completion 88012111Sralph */ 88115811Sralph sendmail(user, bombed) 88215811Sralph char *user; 88312111Sralph int bombed; 88412111Sralph { 88512111Sralph register int i; 88615811Sralph int p[2], s; 88712111Sralph register char *cp; 88812111Sralph char buf[100]; 88915811Sralph struct stat stb; 89015811Sralph FILE *fp; 89112111Sralph 89212111Sralph pipe(p); 89315811Sralph if ((s = dofork(DORETURN)) == 0) { /* child */ 89412111Sralph dup2(p[0], 0); 89512111Sralph for (i = 3; i < NOFILE; i++) 89612111Sralph (void) close(i); 89712111Sralph if ((cp = rindex(MAIL, '/')) != NULL) 89812111Sralph cp++; 89912111Sralph else 90012111Sralph cp = MAIL; 90115811Sralph sprintf(buf, "%s@%s", user, fromhost); 90212111Sralph execl(MAIL, cp, buf, 0); 90312111Sralph exit(0); 90415811Sralph } else if (s > 0) { /* parent */ 90512111Sralph dup2(p[1], 1); 90615811Sralph printf("To: %s@%s\n", user, fromhost); 90712111Sralph printf("Subject: printer job\n\n"); 90812111Sralph printf("Your printer job "); 90912111Sralph if (*jobname) 91012111Sralph printf("(%s) ", jobname); 91112463Sralph switch (bombed) { 912*17463Sralph case OK: 91312463Sralph printf("\ncompleted successfully\n"); 91412463Sralph break; 91512463Sralph default: 916*17463Sralph case FATALERR: 91712463Sralph printf("\ncould not be printed\n"); 91812463Sralph break; 919*17463Sralph case NOACCT: 92012463Sralph printf("\ncould not be printed without an account on %s\n", host); 92112463Sralph break; 922*17463Sralph case FILTERERR: 92315811Sralph if (stat(tmpfile, &stb) < 0 || stb.st_size == 0 || 92415811Sralph (fp = fopen(tmpfile, "r")) == NULL) { 92515811Sralph printf("\nwas printed but had some errors\n"); 92615811Sralph break; 92715811Sralph } 92815811Sralph printf("\nwas printed but had the following errors:\n"); 92915811Sralph while ((i = getc(fp)) != EOF) 93015811Sralph putchar(i); 93115811Sralph (void) fclose(fp); 932*17463Sralph break; 933*17463Sralph case ACCESS: 934*17463Sralph printf("\nwas not printed because it was not linked to the original file\n"); 93512463Sralph } 93612111Sralph fflush(stdout); 93712111Sralph (void) close(1); 93812111Sralph } 93912111Sralph (void) close(p[0]); 94012111Sralph (void) close(p[1]); 94115811Sralph wait(&s); 94212111Sralph } 94312111Sralph 94412111Sralph /* 94512111Sralph * dofork - fork with retries on failure 94612111Sralph */ 94712111Sralph dofork(action) 94812111Sralph int action; 94912111Sralph { 95012111Sralph register int i, pid; 95112111Sralph 95212111Sralph for (i = 0; i < 20; i++) { 95312463Sralph if ((pid = fork()) < 0) { 95412111Sralph sleep((unsigned)(i*i)); 95512463Sralph continue; 95612463Sralph } 95712463Sralph /* 95812463Sralph * Child should run as daemon instead of root 95912463Sralph */ 96012463Sralph if (pid == 0) 96112463Sralph setuid(DU); 96212463Sralph return(pid); 96312111Sralph } 96416762Sralph syslog(LOG_ERR, "can't fork"); 96512111Sralph 96612111Sralph switch (action) { 96712111Sralph case DORETURN: 96812111Sralph return (-1); 96912111Sralph default: 97016762Sralph syslog(LOG_ERR, "bad action (%d) to dofork", action); 97112111Sralph /*FALL THRU*/ 97212111Sralph case DOABORT: 97312111Sralph exit(1); 97412111Sralph } 97512111Sralph /*NOTREACHED*/ 97612111Sralph } 97712111Sralph 97812111Sralph /* 97916762Sralph * Kill child processes to abort current job. 98012111Sralph */ 98116762Sralph abortpr() 98212111Sralph { 98315811Sralph (void) unlink(tmpfile); 98412111Sralph kill(0, SIGINT); 98512111Sralph if (ofilter > 0) 98612111Sralph kill(ofilter, SIGCONT); 98712111Sralph while (wait(0) > 0) 98812111Sralph ; 98912111Sralph exit(0); 99012111Sralph } 99112111Sralph 99212111Sralph init() 99312111Sralph { 99412111Sralph int status; 99512111Sralph 99613169Sralph if ((status = pgetent(line, printer)) < 0) 99713169Sralph fatal("can't open printer description file"); 99813169Sralph else if (status == 0) 99913169Sralph fatal("unknown printer"); 100012111Sralph if ((LP = pgetstr("lp", &bp)) == NULL) 100112111Sralph LP = DEFDEVLP; 100212111Sralph if ((RP = pgetstr("rp", &bp)) == NULL) 100312463Sralph RP = DEFLP; 100412111Sralph if ((LO = pgetstr("lo", &bp)) == NULL) 100512111Sralph LO = DEFLOCK; 100612111Sralph if ((ST = pgetstr("st", &bp)) == NULL) 100712111Sralph ST = DEFSTAT; 100812111Sralph if ((LF = pgetstr("lf", &bp)) == NULL) 100912111Sralph LF = DEFLOGF; 101012111Sralph if ((SD = pgetstr("sd", &bp)) == NULL) 101112111Sralph SD = DEFSPOOL; 101212111Sralph if ((DU = pgetnum("du")) < 0) 101312111Sralph DU = DEFUID; 101412111Sralph if ((FF = pgetstr("ff", &bp)) == NULL) 101512111Sralph FF = DEFFF; 101612111Sralph if ((PW = pgetnum("pw")) < 0) 101712111Sralph PW = DEFWIDTH; 101812111Sralph sprintf(&width[2], "%d", PW); 101912111Sralph if ((PL = pgetnum("pl")) < 0) 102012111Sralph PL = DEFLENGTH; 102112111Sralph sprintf(&length[2], "%d", PL); 102212463Sralph if ((PX = pgetnum("px")) < 0) 102312463Sralph PX = 0; 102412463Sralph sprintf(&pxwidth[2], "%d", PX); 102512463Sralph if ((PY = pgetnum("py")) < 0) 102612463Sralph PY = 0; 102712463Sralph sprintf(&pxlength[2], "%d", PY); 102812111Sralph RM = pgetstr("rm", &bp); 102912111Sralph AF = pgetstr("af", &bp); 103012111Sralph OF = pgetstr("of", &bp); 103112111Sralph IF = pgetstr("if", &bp); 103212463Sralph RF = pgetstr("rf", &bp); 103312111Sralph TF = pgetstr("tf", &bp); 103413233Sralph NF = pgetstr("nf", &bp); 103512111Sralph DF = pgetstr("df", &bp); 103612111Sralph GF = pgetstr("gf", &bp); 103712111Sralph VF = pgetstr("vf", &bp); 103812111Sralph CF = pgetstr("cf", &bp); 103912111Sralph TR = pgetstr("tr", &bp); 104012463Sralph RS = pgetflag("rs"); 104112111Sralph SF = pgetflag("sf"); 104212111Sralph SH = pgetflag("sh"); 104312111Sralph SB = pgetflag("sb"); 104412111Sralph RW = pgetflag("rw"); 104512111Sralph BR = pgetnum("br"); 104612111Sralph if ((FC = pgetnum("fc")) < 0) 104712111Sralph FC = 0; 104812111Sralph if ((FS = pgetnum("fs")) < 0) 104912111Sralph FS = 0; 105012111Sralph if ((XC = pgetnum("xc")) < 0) 105112111Sralph XC = 0; 105212111Sralph if ((XS = pgetnum("xs")) < 0) 105312111Sralph XS = 0; 105412581Sralph tof = !pgetflag("fo"); 105512111Sralph } 105612111Sralph 105712463Sralph /* 105812463Sralph * Acquire line printer or remote connection. 105912463Sralph */ 106012463Sralph openpr() 106112463Sralph { 106212463Sralph register int i, n; 106316762Sralph int resp; 106412463Sralph 106512463Sralph if (*LP) { 106612463Sralph for (i = 1; ; i = i < 32 ? i << 1 : i) { 106713148Ssam pfd = open(LP, RW ? O_RDWR : O_WRONLY); 106812463Sralph if (pfd >= 0) 106912463Sralph break; 107012463Sralph if (errno == ENOENT) { 107116762Sralph syslog(LOG_ERR, "%s: %m", LP); 107212463Sralph exit(1); 107312463Sralph } 107412463Sralph if (i == 1) 107512463Sralph status("waiting for %s to become ready (offline ?)", printer); 107612463Sralph sleep(i); 107712463Sralph } 107812463Sralph if (isatty(pfd)) 107912463Sralph setty(); 108012463Sralph status("%s is ready and printing", printer); 108112463Sralph } else if (RM != NULL) { 108216762Sralph for (i = 1; ; i = i < 256 ? i << 1 : i) { 108316762Sralph resp = -1; 108412528Sralph pfd = getport(RM); 108512463Sralph if (pfd >= 0) { 108612463Sralph (void) sprintf(line, "\2%s\n", RP); 108712463Sralph n = strlen(line); 108816762Sralph if (write(pfd, line, n) == n && 108916762Sralph (resp = response()) == '\0') 109012463Sralph break; 109116031Sralph (void) close(pfd); 109212463Sralph } 109316031Sralph if (i == 1) { 109416762Sralph if (resp < 0) 109516031Sralph status("waiting for %s to come up", RM); 109616762Sralph else { 109716031Sralph status("waiting for queue to be enabled on %s", RM); 109816762Sralph i = 256; 109916762Sralph } 110016031Sralph } 110112463Sralph sleep(i); 110212463Sralph } 110312463Sralph status("sending to %s", RM); 110412463Sralph remote = 1; 110512463Sralph } else { 110616762Sralph syslog(LOG_ERR, "%s: no line printer device or host name", 110716762Sralph printer); 110812463Sralph exit(1); 110912463Sralph } 111012463Sralph /* 111112463Sralph * Start up an output filter, if needed. 111212463Sralph */ 111312463Sralph if (OF) { 111412463Sralph int p[2]; 111512463Sralph char *cp; 111612463Sralph 111712463Sralph pipe(p); 111812463Sralph if ((ofilter = dofork(DOABORT)) == 0) { /* child */ 111912463Sralph dup2(p[0], 0); /* pipe is std in */ 112012463Sralph dup2(pfd, 1); /* printer is std out */ 112112463Sralph for (i = 3; i < NOFILE; i++) 112212463Sralph (void) close(i); 112312463Sralph if ((cp = rindex(OF, '/')) == NULL) 112412463Sralph cp = OF; 112512463Sralph else 112612463Sralph cp++; 112712463Sralph execl(OF, cp, width, length, 0); 112816762Sralph syslog(LOG_ERR, "%s: %s: %m", printer, OF); 112912463Sralph exit(1); 113012463Sralph } 113112463Sralph (void) close(p[0]); /* close input side */ 113212463Sralph ofd = p[1]; /* use pipe for output */ 113312463Sralph } else { 113412463Sralph ofd = pfd; 113512463Sralph ofilter = 0; 113612463Sralph } 113712463Sralph } 113812463Sralph 113912111Sralph struct bauds { 114012111Sralph int baud; 114112111Sralph int speed; 114212111Sralph } bauds[] = { 114312111Sralph 50, B50, 114412111Sralph 75, B75, 114512111Sralph 110, B110, 114612111Sralph 134, B134, 114712111Sralph 150, B150, 114812111Sralph 200, B200, 114912111Sralph 300, B300, 115012111Sralph 600, B600, 115112111Sralph 1200, B1200, 115212111Sralph 1800, B1800, 115312111Sralph 2400, B2400, 115412111Sralph 4800, B4800, 115512111Sralph 9600, B9600, 115612111Sralph 19200, EXTA, 115712111Sralph 38400, EXTB, 115812111Sralph 0, 0 115912111Sralph }; 116012111Sralph 116112111Sralph /* 116212111Sralph * setup tty lines. 116312111Sralph */ 116412111Sralph setty() 116512111Sralph { 116612111Sralph struct sgttyb ttybuf; 116712111Sralph register struct bauds *bp; 116812111Sralph 116912111Sralph if (ioctl(pfd, TIOCEXCL, (char *)0) < 0) { 117016762Sralph syslog(LOG_ERR, "%s: ioctl(TIOCEXCL): %m", printer); 117112111Sralph exit(1); 117212111Sralph } 117312111Sralph if (ioctl(pfd, TIOCGETP, (char *)&ttybuf) < 0) { 117416762Sralph syslog(LOG_ERR, "%s: ioctl(TIOCGETP): %m", printer); 117512111Sralph exit(1); 117612111Sralph } 117712111Sralph if (BR > 0) { 117812111Sralph for (bp = bauds; bp->baud; bp++) 117912111Sralph if (BR == bp->baud) 118012111Sralph break; 118112111Sralph if (!bp->baud) { 118216762Sralph syslog(LOG_ERR, "%s: illegal baud rate %d", printer, BR); 118312111Sralph exit(1); 118412111Sralph } 118512111Sralph ttybuf.sg_ispeed = ttybuf.sg_ospeed = bp->speed; 118612111Sralph } 118713169Sralph ttybuf.sg_flags &= ~FC; 118813169Sralph ttybuf.sg_flags |= FS; 118912111Sralph if (ioctl(pfd, TIOCSETP, (char *)&ttybuf) < 0) { 119016762Sralph syslog(LOG_ERR, "%s: ioctl(TIOCSETP): %m", printer); 119112111Sralph exit(1); 119212111Sralph } 119317168Sralph if (XC || XS) { 119417168Sralph int ldisc = NTTYDISC; 119517168Sralph 119617168Sralph if (ioctl(pfd, TIOCSETD, &ldisc) < 0) { 119717168Sralph syslog(LOG_ERR, "%s: ioctl(TIOCSETD): %m", printer); 119817168Sralph exit(1); 119917168Sralph } 120017168Sralph } 120112111Sralph if (XC) { 120212111Sralph if (ioctl(pfd, TIOCLBIC, &XC) < 0) { 120316762Sralph syslog(LOG_ERR, "%s: ioctl(TIOCLBIC): %m", printer); 120412111Sralph exit(1); 120512111Sralph } 120612111Sralph } 120712111Sralph if (XS) { 120812111Sralph if (ioctl(pfd, TIOCLBIS, &XS) < 0) { 120916762Sralph syslog(LOG_ERR, "%s: ioctl(TIOCLBIS): %m", printer); 121012111Sralph exit(1); 121112111Sralph } 121212111Sralph } 121312111Sralph } 121412463Sralph 121512463Sralph /*VARARGS1*/ 121612463Sralph status(msg, a1, a2, a3) 121712463Sralph char *msg; 121812463Sralph { 121912463Sralph register int fd; 122012463Sralph char buf[BUFSIZ]; 122112463Sralph 122212463Sralph umask(0); 122313148Ssam fd = open(ST, O_WRONLY|O_CREAT, 0664); 122416762Sralph if (fd < 0 || flock(fd, LOCK_EX) < 0) { 122516762Sralph syslog(LOG_ERR, "%s: %s: %m", printer, ST); 122616762Sralph exit(1); 122716762Sralph } 122813148Ssam ftruncate(fd, 0); 122912463Sralph sprintf(buf, msg, a1, a2, a3); 123012463Sralph strcat(buf, "\n"); 123112463Sralph (void) write(fd, buf, strlen(buf)); 123212463Sralph (void) close(fd); 123312463Sralph } 1234