113954Ssam #ifndef lint 2*16762Sralph static char sccsid[] = "@(#)printjob.c 4.18 (Berkeley) 07/25/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 14*16762Sralph #define DORETURN 0 /* absorb fork error */ 15*16762Sralph #define DOABORT 1 /* abort if dofork fails */ 1612111Sralph 17*16762Sralph char title[80]; /* ``pr'' title */ 18*16762Sralph FILE *cfp; /* control file */ 19*16762Sralph int pfd; /* printer file descriptor */ 20*16762Sralph int ofd; /* output filter file descriptor */ 21*16762Sralph int lfd; /* lock file descriptor */ 22*16762Sralph int pid; /* pid of lpd process */ 23*16762Sralph int prchild; /* id of pr process */ 24*16762Sralph int child; /* id of any filters */ 25*16762Sralph int ofilter; /* id of output filter, if any */ 26*16762Sralph int tof; /* true if at top of form */ 27*16762Sralph int remote; /* true if sending files to remote */ 2812111Sralph 29*16762Sralph char fromhost[32]; /* user's host machine */ 30*16762Sralph char logname[32]; /* user's login name */ 31*16762Sralph char jobname[100]; /* job or file name */ 32*16762Sralph char class[32]; /* classification field */ 33*16762Sralph char width[10] = "-w"; /* page width in characters */ 34*16762Sralph char length[10] = "-l"; /* page length in lines */ 35*16762Sralph char pxwidth[10] = "-x"; /* page width in pixels */ 36*16762Sralph char pxlength[10] = "-y"; /* page length in pixels */ 37*16762Sralph char indent[10] = "-i0"; /* indentation size in characters */ 38*16762Sralph char tmpfile[] = "errsXXXXXX"; /* file name for filter output */ 3912111Sralph 4012111Sralph printjob() 4112111Sralph { 4212111Sralph struct stat stb; 4312111Sralph register struct queue *q, **qp; 4412111Sralph struct queue **queue; 4512111Sralph register int i, nitems; 4612111Sralph long pidoff; 47*16762Sralph int count = 0; 48*16762Sralph extern int abortpr(); 4912111Sralph 5012111Sralph init(); /* set up capabilities */ 5113442Sralph (void) write(1, "", 1); /* ack that daemon is started */ 52*16762Sralph setgid(getegid()); 5312463Sralph pid = getpid(); /* for use with lprm */ 5412111Sralph setpgrp(0, pid); 55*16762Sralph signal(SIGHUP, abortpr); 56*16762Sralph signal(SIGINT, abortpr); 57*16762Sralph signal(SIGQUIT, abortpr); 58*16762Sralph signal(SIGTERM, abortpr); 5912111Sralph 6015811Sralph (void) mktemp(tmpfile); 6115811Sralph 6212111Sralph /* 6312111Sralph * uses short form file names 6412111Sralph */ 6512111Sralph if (chdir(SD) < 0) { 66*16762Sralph syslog(LOG_ERR, "%s: %m", SD); 6712111Sralph exit(1); 6812111Sralph } 6912463Sralph if (stat(LO, &stb) == 0 && (stb.st_mode & 0100)) 7012463Sralph exit(0); /* printing disabled */ 7114150Sralph lfd = open(LO, O_WRONLY|O_CREAT, 0644); 7213169Sralph if (lfd < 0) { 73*16762Sralph syslog(LOG_ERR, "%s: %s: %m", printer, LO); 7413169Sralph exit(1); 7513169Sralph } 7613169Sralph if (flock(lfd, LOCK_EX|LOCK_NB) < 0) { 7712111Sralph if (errno == EWOULDBLOCK) /* active deamon present */ 7812111Sralph exit(0); 79*16762Sralph syslog(LOG_ERR, "%s: %s: %m", printer, LO); 8012111Sralph exit(1); 8112111Sralph } 8213148Ssam ftruncate(lfd, 0); 8312111Sralph /* 8412111Sralph * write process id for others to know 8512111Sralph */ 8612111Sralph sprintf(line, "%u\n", pid); 8712111Sralph pidoff = i = strlen(line); 8812463Sralph if (write(lfd, line, i) != i) { 89*16762Sralph syslog(LOG_ERR, "%s: %s: %m", printer, LO); 9012111Sralph exit(1); 9112111Sralph } 9212111Sralph /* 9312111Sralph * search the spool directory for work and sort by queue order. 9412111Sralph */ 9512111Sralph if ((nitems = getq(&queue)) < 0) { 96*16762Sralph syslog(LOG_ERR, "%s: can't scan %s", printer, SD); 9712111Sralph exit(1); 9812111Sralph } 9912463Sralph if (nitems == 0) /* no work to do */ 10012111Sralph exit(0); 10113169Sralph if (stb.st_mode & 01) { /* reset queue flag */ 10213169Sralph if (fchmod(lfd, stb.st_mode & 0776) < 0) 103*16762Sralph syslog(LOG_ERR, "%s: %s: %m", printer, LO); 10413169Sralph } 10512463Sralph openpr(); /* open printer or remote */ 10612463Sralph again: 10712111Sralph /* 10812111Sralph * we found something to do now do it -- 10912111Sralph * write the name of the current control file into the lock file 11012111Sralph * so the spool queue program can tell what we're working on 11112111Sralph */ 11212111Sralph for (qp = queue; nitems--; free((char *) q)) { 11312111Sralph q = *qp++; 11412111Sralph if (stat(q->q_name, &stb) < 0) 11512111Sralph continue; 11612463Sralph restart: 11712111Sralph (void) lseek(lfd, pidoff, 0); 11812111Sralph (void) sprintf(line, "%s\n", q->q_name); 11912111Sralph i = strlen(line); 12012111Sralph if (write(lfd, line, i) != i) 121*16762Sralph syslog(LOG_ERR, "%s: %s: %m", printer, LO); 12212111Sralph if (!remote) 12312111Sralph i = printit(q->q_name); 12412111Sralph else 12512111Sralph i = sendit(q->q_name); 12612463Sralph /* 12713169Sralph * Check to see if we are supposed to stop printing or 12813169Sralph * if we are to rebuild the queue. 12912463Sralph */ 13013169Sralph if (fstat(lfd, &stb) == 0) { 131*16762Sralph /* stop printing before starting next job? */ 13213169Sralph if (stb.st_mode & 0100) 13313169Sralph goto done; 134*16762Sralph /* rebuild queue (after lpc topq) */ 13513169Sralph if (stb.st_mode & 01) { 13613169Sralph for (free((char *) q); nitems--; free((char *) q)) 13713169Sralph q = *qp++; 13813169Sralph if (fchmod(lfd, stb.st_mode & 0776) < 0) 139*16762Sralph syslog(LOG_WARNING, "%s: %s: %m", 140*16762Sralph printer, LO); 14113169Sralph break; 14213169Sralph } 14313169Sralph } 14414150Sralph if (i == 0) /* file ok and printed */ 14514150Sralph count++; 14614150Sralph else if (i > 0) { /* try reprinting the job */ 147*16762Sralph syslog(LOG_INFO, "restarting %s", printer); 14812111Sralph if (ofilter > 0) { 14912111Sralph kill(ofilter, SIGCONT); /* to be sure */ 15012111Sralph (void) close(ofd); 15112111Sralph while ((i = wait(0)) > 0 && i != ofilter) 15212111Sralph ; 15312111Sralph ofilter = 0; 15412111Sralph } 15512463Sralph (void) close(pfd); /* close printer */ 15615811Sralph if (ftruncate(lfd, pidoff) < 0) 157*16762Sralph syslog(LOG_WARNING, "%s: %s: %m", printer, LO); 15812463Sralph openpr(); /* try to reopen printer */ 15912111Sralph goto restart; 16012111Sralph } 16112111Sralph } 16212111Sralph free((char *) queue); 16312463Sralph /* 16412463Sralph * search the spool directory for more work. 16512463Sralph */ 16612463Sralph if ((nitems = getq(&queue)) < 0) { 167*16762Sralph syslog(LOG_ERR, "%s: can't scan %s", printer, SD); 16812463Sralph exit(1); 16912463Sralph } 17012463Sralph if (nitems == 0) { /* no more work to do */ 17112463Sralph done: 17214150Sralph if (count > 0) { /* Files actually printed */ 17314150Sralph if (!SF && !tof) 17414150Sralph (void) write(ofd, FF, strlen(FF)); 17514150Sralph if (TR != NULL) /* output trailer */ 17614150Sralph (void) write(ofd, TR, strlen(TR)); 17714150Sralph } 17815811Sralph (void) unlink(tmpfile); 17912463Sralph exit(0); 18012463Sralph } 18112111Sralph goto again; 18212111Sralph } 18312111Sralph 18412111Sralph char fonts[4][50]; /* fonts for troff */ 18512111Sralph 186*16762Sralph char ifonts[4][18] = { 18712111Sralph "/usr/lib/vfont/R", 18812111Sralph "/usr/lib/vfont/I", 18912111Sralph "/usr/lib/vfont/B", 19012111Sralph "/usr/lib/vfont/S" 19112111Sralph }; 19212111Sralph 19312111Sralph /* 19412111Sralph * The remaining part is the reading of the control file (cf) 19512111Sralph * and performing the various actions. 19612111Sralph * Returns 0 if everthing was OK, 1 if we should try to reprint the job and 19712111Sralph * -1 if a non-recoverable error occured. 19812111Sralph */ 19912111Sralph printit(file) 20012111Sralph char *file; 20112111Sralph { 20212111Sralph register int i; 20312111Sralph int bombed = 0; 20412111Sralph 20512111Sralph /* 20612111Sralph * open control file 20712111Sralph */ 20812111Sralph if ((cfp = fopen(file, "r")) == NULL) { 209*16762Sralph syslog(LOG_INFO, "%s: %s: %m", printer, file); 21012111Sralph return(0); 21112111Sralph } 21212111Sralph /* 21312111Sralph * Reset troff fonts. 21412111Sralph */ 21512111Sralph for (i = 0; i < 4; i++) 21612111Sralph strcpy(fonts[i], ifonts[i]); 21712111Sralph 21812111Sralph /* 21912111Sralph * read the control file for work to do 22012111Sralph * 22112111Sralph * file format -- first character in the line is a command 22212111Sralph * rest of the line is the argument. 22312111Sralph * valid commands are: 22412111Sralph * 22512111Sralph * J -- "job name" on banner page 22612111Sralph * C -- "class name" on banner page 22712111Sralph * L -- "literal" user's name to print on banner 22812111Sralph * T -- "title" for pr 22912111Sralph * H -- "host name" of machine where lpr was done 23012111Sralph * P -- "person" user's login name 23112581Sralph * I -- "indent" amount to indent output 23212111Sralph * f -- "file name" name of text file to print 23312111Sralph * l -- "file name" text file with control chars 23412111Sralph * p -- "file name" text file to print with pr(1) 23512111Sralph * t -- "file name" troff(1) file to print 23613233Sralph * n -- "file name" ditroff(1) file to print 23712111Sralph * d -- "file name" dvi file to print 23812111Sralph * g -- "file name" plot(1G) file to print 23912111Sralph * v -- "file name" plain raster file to print 24012111Sralph * c -- "file name" cifplot file to print 24112111Sralph * 1 -- "R font file" for troff 24212111Sralph * 2 -- "I font file" for troff 24312111Sralph * 3 -- "B font file" for troff 24412111Sralph * 4 -- "S font file" for troff 24512111Sralph * N -- "name" of file (used by lpq) 24612111Sralph * U -- "unlink" name of file to remove 24712111Sralph * (after we print it. (Pass 2 only)). 24812111Sralph * M -- "mail" to user when done printing 24912111Sralph * 25012111Sralph * getline reads a line and expands tabs to blanks 25112111Sralph */ 25212111Sralph 25312111Sralph /* pass 1 */ 25412111Sralph 25512111Sralph while (getline(cfp)) 25612111Sralph switch (line[0]) { 25712111Sralph case 'H': 25814150Sralph strcpy(fromhost, line+1); 25912111Sralph if (class[0] == '\0') 26015552Sralph strncpy(class, line+1, sizeof(class)-1); 26112111Sralph continue; 26212111Sralph 26312111Sralph case 'P': 26415552Sralph strncpy(logname, line+1, sizeof(logname)-1); 26512463Sralph if (RS) { /* restricted */ 26612463Sralph if (getpwnam(logname) == (struct passwd *)0) { 26712463Sralph bombed = 2; 26815811Sralph sendmail(line+1, bombed); 26912463Sralph goto pass2; 27012463Sralph } 27112463Sralph } 27212111Sralph continue; 27312111Sralph 27412111Sralph case 'J': 27512111Sralph if (line[1] != '\0') 27615552Sralph strncpy(jobname, line+1, sizeof(jobname)-1); 27712111Sralph else 27812111Sralph strcpy(jobname, " "); 27912111Sralph continue; 28012111Sralph 28112111Sralph case 'C': 28212111Sralph if (line[1] != '\0') 28315552Sralph strncpy(class, line+1, sizeof(class)-1); 28412111Sralph else if (class[0] == '\0') 28515811Sralph gethostname(class, sizeof(class)); 28612111Sralph continue; 28712111Sralph 28812111Sralph case 'T': /* header title for pr */ 28915552Sralph strncpy(title, line+1, sizeof(title)-1); 29012111Sralph continue; 29112111Sralph 29212111Sralph case 'L': /* identification line */ 29312111Sralph if (!SH) 29412111Sralph banner(line+1, jobname); 29512111Sralph continue; 29612111Sralph 29712111Sralph case '1': /* troff fonts */ 29812111Sralph case '2': 29912111Sralph case '3': 30012111Sralph case '4': 30112111Sralph if (line[1] != '\0') 30212111Sralph strcpy(fonts[line[0]-'1'], line+1); 30312111Sralph continue; 30412111Sralph 30512111Sralph case 'W': /* page width */ 30615552Sralph strncpy(width+2, line+1, sizeof(width)-3); 30712111Sralph continue; 30812111Sralph 30912581Sralph case 'I': /* indent amount */ 31015552Sralph strncpy(indent+2, line+1, sizeof(indent)-3); 31112581Sralph continue; 31212581Sralph 31312111Sralph default: /* some file to print */ 31415811Sralph switch (i = print(line[0], line+1)) { 31515811Sralph case -1: 31615811Sralph if (!bombed) 31715811Sralph bombed = 1; 31815811Sralph break; 31915811Sralph case 1: 32012111Sralph (void) fclose(cfp); 32112111Sralph return(1); 32215811Sralph case 2: 32315811Sralph bombed = 3; 32415811Sralph sendmail(logname, bombed); 32515811Sralph } 32612111Sralph title[0] = '\0'; 32712111Sralph continue; 32812111Sralph 32912111Sralph case 'N': 33012111Sralph case 'U': 33112111Sralph case 'M': 33212111Sralph continue; 33312111Sralph } 33412111Sralph 33512111Sralph /* pass 2 */ 33612111Sralph 33712463Sralph pass2: 33812111Sralph fseek(cfp, 0L, 0); 33912111Sralph while (getline(cfp)) 34012111Sralph switch (line[0]) { 34112111Sralph case 'M': 34215811Sralph if (bombed < 2) /* already sent if >= 2 */ 34315811Sralph sendmail(line+1, bombed); 34412111Sralph continue; 34512111Sralph 34612111Sralph case 'U': 34712111Sralph (void) unlink(line+1); 34812111Sralph } 34912111Sralph /* 35015811Sralph * clean-up in case another control file exists 35112111Sralph */ 35212111Sralph (void) fclose(cfp); 35312111Sralph (void) unlink(file); 35414150Sralph return(bombed ? -1 : 0); 35512111Sralph } 35612111Sralph 35712111Sralph /* 35812111Sralph * Print a file. 35913233Sralph * Set up the chain [ PR [ | {IF, OF} ] ] or {IF, RF, TF, NF, DF, CF, VF}. 36015811Sralph * Return -1 if a non-recoverable error occured, 36115811Sralph * 2 if the filter detected some errors (but printed the job anyway), 36215811Sralph * 1 if we should try to reprint this job and 36312111Sralph * 0 if all is well. 36412111Sralph * Note: all filters take stdin as the file, stdout as the printer, 36512111Sralph * stderr as the log file, and must not ignore SIGINT. 36612111Sralph */ 36712111Sralph print(format, file) 36812111Sralph int format; 36912111Sralph char *file; 37012111Sralph { 37115811Sralph register int n; 37212111Sralph register char *prog; 37315811Sralph int fi, fo; 37412111Sralph char *av[15], buf[BUFSIZ]; 37512111Sralph int pid, p[2], stopped = 0; 37612111Sralph union wait status; 37712111Sralph 378*16762Sralph if ((fi = open(file, O_RDONLY)) < 0) 37912111Sralph return(-1); 38012111Sralph if (!SF && !tof) { /* start on a fresh page */ 38112111Sralph (void) write(ofd, FF, strlen(FF)); 38212111Sralph tof = 1; 38312111Sralph } 38412111Sralph if (IF == NULL && (format == 'f' || format == 'l')) { 38512111Sralph tof = 0; 38612111Sralph while ((n = read(fi, buf, BUFSIZ)) > 0) 38712111Sralph if (write(ofd, buf, n) != n) { 38812111Sralph (void) close(fi); 38912111Sralph return(1); 39012111Sralph } 39112111Sralph (void) close(fi); 39212111Sralph return(0); 39312111Sralph } 39412111Sralph switch (format) { 39512111Sralph case 'p': /* print file using 'pr' */ 39612111Sralph if (IF == NULL) { /* use output filter */ 39712111Sralph prog = PR; 39812111Sralph av[0] = "pr"; 39912111Sralph av[1] = width; 40012111Sralph av[2] = length; 40112111Sralph av[3] = "-h"; 40212111Sralph av[4] = *title ? title : " "; 40312111Sralph av[5] = 0; 40412111Sralph fo = ofd; 40512111Sralph goto start; 40612111Sralph } 40712111Sralph pipe(p); 40812111Sralph if ((prchild = dofork(DORETURN)) == 0) { /* child */ 40912111Sralph dup2(fi, 0); /* file is stdin */ 41012111Sralph dup2(p[1], 1); /* pipe is stdout */ 41112111Sralph for (n = 3; n < NOFILE; n++) 41212111Sralph (void) close(n); 41312111Sralph execl(PR, "pr", width, length, "-h", *title ? title : " ", 0); 414*16762Sralph syslog(LOG_ERR, "cannot execl %s", PR); 41512111Sralph exit(2); 41612111Sralph } 41712111Sralph (void) close(p[1]); /* close output side */ 41812111Sralph (void) close(fi); 41912111Sralph if (prchild < 0) { 42012111Sralph prchild = 0; 42112111Sralph (void) close(p[0]); 42212111Sralph return(-1); 42312111Sralph } 42412111Sralph fi = p[0]; /* use pipe for input */ 42512111Sralph case 'f': /* print plain text file */ 42612111Sralph prog = IF; 42712111Sralph av[1] = width; 42812111Sralph av[2] = length; 42912581Sralph av[3] = indent; 43012581Sralph n = 4; 43112111Sralph break; 43212111Sralph case 'l': /* like 'f' but pass control characters */ 43312111Sralph prog = IF; 43414325Sralph av[1] = "-c"; 43512111Sralph av[2] = width; 43612111Sralph av[3] = length; 43712581Sralph av[4] = indent; 43812581Sralph n = 5; 43912111Sralph break; 44012463Sralph case 'r': /* print a fortran text file */ 44112463Sralph prog = RF; 44212463Sralph av[1] = width; 44312463Sralph av[2] = length; 44412463Sralph n = 3; 44512463Sralph break; 44612111Sralph case 't': /* print troff output */ 44713233Sralph case 'n': /* print ditroff output */ 44812463Sralph case 'd': /* print tex output */ 44912111Sralph (void) unlink(".railmag"); 45012463Sralph if ((fo = creat(".railmag", FILMOD)) < 0) { 451*16762Sralph syslog(LOG_ERR, "%s: cannot create .railmag", printer); 45212111Sralph (void) unlink(".railmag"); 45312111Sralph } else { 45412111Sralph for (n = 0; n < 4; n++) { 45512111Sralph if (fonts[n][0] != '/') 45612111Sralph (void) write(fo, "/usr/lib/vfont/", 15); 45712111Sralph (void) write(fo, fonts[n], strlen(fonts[n])); 45812111Sralph (void) write(fo, "\n", 1); 45912111Sralph } 46012111Sralph (void) close(fo); 46112111Sralph } 46213233Sralph prog = (format == 't') ? TF : (format == 'n') ? NF : DF; 46312463Sralph av[1] = pxwidth; 46412463Sralph av[2] = pxlength; 46512463Sralph n = 3; 46612111Sralph break; 46712111Sralph case 'c': /* print cifplot output */ 46812111Sralph prog = CF; 46912463Sralph av[1] = pxwidth; 47012463Sralph av[2] = pxlength; 47112463Sralph n = 3; 47212111Sralph break; 47312111Sralph case 'g': /* print plot(1G) output */ 47412111Sralph prog = GF; 47512463Sralph av[1] = pxwidth; 47612463Sralph av[2] = pxlength; 47712463Sralph n = 3; 47812111Sralph break; 47912111Sralph case 'v': /* print raster output */ 48012111Sralph prog = VF; 48112463Sralph av[1] = pxwidth; 48212463Sralph av[2] = pxlength; 48312463Sralph n = 3; 48412111Sralph break; 48512111Sralph default: 48612111Sralph (void) close(fi); 487*16762Sralph syslog(LOG_ERR, "%s: illegal format character '%c'", 488*16762Sralph printer, format); 48912111Sralph return(-1); 49012111Sralph } 49112111Sralph if ((av[0] = rindex(prog, '/')) != NULL) 49212111Sralph av[0]++; 49312111Sralph else 49412111Sralph av[0] = prog; 49512111Sralph av[n++] = "-n"; 49612111Sralph av[n++] = logname; 49712111Sralph av[n++] = "-h"; 49814150Sralph av[n++] = fromhost; 49912111Sralph av[n++] = AF; 50012111Sralph av[n] = 0; 50112111Sralph fo = pfd; 50212111Sralph if (ofilter > 0) { /* stop output filter */ 50312111Sralph write(ofd, "\031\1", 2); 50412111Sralph while ((pid = wait3(&status, WUNTRACED, 0)) > 0 && pid != ofilter) 50512111Sralph ; 50612111Sralph if (status.w_stopval != WSTOPPED) { 50712111Sralph (void) close(fi); 508*16762Sralph syslog(LOG_WARNING, "%s: output filter died (%d)", 509*16762Sralph printer, status.w_retcode); 51012111Sralph return(1); 51112111Sralph } 51212111Sralph stopped++; 51312111Sralph } 51412111Sralph start: 51512111Sralph if ((child = dofork(DORETURN)) == 0) { /* child */ 51612111Sralph dup2(fi, 0); 51712111Sralph dup2(fo, 1); 51815811Sralph n = open(tmpfile, O_WRONLY|O_CREAT, 0664); 51915811Sralph if (n >= 0) 52015811Sralph dup2(n, 2); 52112111Sralph for (n = 3; n < NOFILE; n++) 52212111Sralph (void) close(n); 52312111Sralph execv(prog, av); 524*16762Sralph syslog(LOG_ERR, "cannot execv %s", prog); 52512111Sralph exit(2); 52612111Sralph } 52712111Sralph (void) close(fi); 52812111Sralph if (child < 0) 52912111Sralph status.w_retcode = 100; 53012111Sralph else 53112111Sralph while ((pid = wait(&status)) > 0 && pid != child) 53212111Sralph ; 53312111Sralph child = 0; 53412111Sralph prchild = 0; 53512111Sralph if (stopped) { /* restart output filter */ 53612111Sralph if (kill(ofilter, SIGCONT) < 0) { 537*16762Sralph syslog(LOG_ERR, "cannot restart output filter"); 53812111Sralph exit(1); 53912111Sralph } 54012111Sralph } 54112111Sralph tof = 0; 54215811Sralph if (!WIFEXITED(status)) { 543*16762Sralph syslog(LOG_WARNING, "%s: Daemon filter '%c' terminated (%d)", 544*16762Sralph printer, format, status.w_termsig); 54512111Sralph return(-1); 54615811Sralph } else if (status.w_retcode > 2) { 547*16762Sralph syslog(LOG_WARNING, "%s: Daemon filter '%c' exited (%d)", 548*16762Sralph printer, format, status.w_retcode); 54915811Sralph return(-1); 55015811Sralph } else if (status.w_retcode == 0) 55115811Sralph tof = 1; 55215811Sralph return(status.w_retcode); 55312111Sralph } 55412111Sralph 55512111Sralph /* 55612111Sralph * Send the daemon control file (cf) and any data files. 55712111Sralph * Return -1 if a non-recoverable error occured, 1 if a recoverable error and 55812111Sralph * 0 if all is well. 55912111Sralph */ 56012111Sralph sendit(file) 56112111Sralph char *file; 56212111Sralph { 56312111Sralph register int linelen, err = 0; 56412111Sralph char last[132]; 56512111Sralph 56612111Sralph /* 56712111Sralph * open control file 56812111Sralph */ 569*16762Sralph if ((cfp = fopen(file, "r")) == NULL) 57012111Sralph return(0); 57112111Sralph /* 57212111Sralph * read the control file for work to do 57312111Sralph * 57412111Sralph * file format -- first character in the line is a command 57512111Sralph * rest of the line is the argument. 57612111Sralph * commands of interest are: 57712111Sralph * 57812111Sralph * a-z -- "file name" name of file to print 57912111Sralph * U -- "unlink" name of file to remove 58012111Sralph * (after we print it. (Pass 2 only)). 58112111Sralph */ 58212111Sralph 58312111Sralph /* 58412111Sralph * pass 1 58512111Sralph */ 58612111Sralph while (getline(cfp)) { 58712111Sralph again: 58812111Sralph if (line[0] >= 'a' && line[0] <= 'z') { 58912111Sralph strcpy(last, line); 59012111Sralph while (linelen = getline(cfp)) 59112111Sralph if (strcmp(last, line)) 59212111Sralph break; 59312111Sralph if ((err = sendfile('\3', last+1)) > 0) { 59412111Sralph (void) fclose(cfp); 59512111Sralph return(1); 59612111Sralph } else if (err) 59712111Sralph break; 59812111Sralph if (linelen) 59912111Sralph goto again; 60012111Sralph break; 60112111Sralph } 60212111Sralph } 60312111Sralph if (!err && sendfile('\2', file) > 0) { 60412111Sralph (void) fclose(cfp); 60512111Sralph return(1); 60612111Sralph } 60712111Sralph /* 60812111Sralph * pass 2 60912111Sralph */ 61012111Sralph fseek(cfp, 0L, 0); 61112111Sralph while (getline(cfp)) 61212111Sralph if (line[0] == 'U') 61312111Sralph (void) unlink(line+1); 61412111Sralph /* 61512111Sralph * clean-up incase another control file exists 61612111Sralph */ 61712111Sralph (void) fclose(cfp); 61812111Sralph (void) unlink(file); 61912111Sralph return(0); 62012111Sralph } 62112111Sralph 62212111Sralph /* 62312111Sralph * Send a data file to the remote machine and spool it. 62412111Sralph * Return positive if we should try resending. 62512111Sralph */ 62612111Sralph sendfile(type, file) 62712111Sralph char type, *file; 62812111Sralph { 62912111Sralph register int f, i, amt; 63012111Sralph struct stat stb; 63112111Sralph char buf[BUFSIZ]; 632*16762Sralph int sizerr, resp; 63312111Sralph 634*16762Sralph if ((f = open(file, O_RDONLY)) < 0 || fstat(f, &stb) < 0) 63512111Sralph return(-1); 63612111Sralph (void) sprintf(buf, "%c%d %s\n", type, stb.st_size, file); 63712111Sralph amt = strlen(buf); 638*16762Sralph for (i = 0; ; i++) { 639*16762Sralph if (write(pfd, buf, amt) != amt || 640*16762Sralph (resp = response()) < 0 || resp == '\1') { 641*16762Sralph (void) close(f); 642*16762Sralph return(1); 643*16762Sralph } else if (resp == '\0') 644*16762Sralph break; 645*16762Sralph if (i == 0) 646*16762Sralph status("no space on remote; waiting for queue to drain"); 647*16762Sralph if (i == 10) 648*16762Sralph syslog(LOG_SALERT, "%s: can't send to %s; queue full", 649*16762Sralph printer, RM); 650*16762Sralph sleep(5 * 60); 65112692Sralph } 652*16762Sralph if (i) 653*16762Sralph status("sending to %s", RM); 65412111Sralph sizerr = 0; 65512111Sralph for (i = 0; i < stb.st_size; i += BUFSIZ) { 65612111Sralph amt = BUFSIZ; 65712111Sralph if (i + amt > stb.st_size) 65812111Sralph amt = stb.st_size - i; 65912111Sralph if (sizerr == 0 && read(f, buf, amt) != amt) 66012111Sralph sizerr = 1; 66112692Sralph if (write(pfd, buf, amt) != amt) { 66212692Sralph (void) close(f); 66312111Sralph return(1); 66412692Sralph } 66512111Sralph } 66612111Sralph (void) close(f); 66712111Sralph if (sizerr) { 668*16762Sralph syslog(LOG_INFO, "%s: %s: changed size", printer, file); 66912111Sralph (void) write(pfd, "\1", 1); /* tell recvjob to ignore this file */ 670*16762Sralph i = -1; 671*16762Sralph } else if (write(pfd, "", 1) != 1) 672*16762Sralph i = 1; 673*16762Sralph else if (response()) 674*16762Sralph i = 1; 675*16762Sralph else 676*16762Sralph i = 0; 677*16762Sralph return(i); 67812111Sralph } 67912111Sralph 68012111Sralph /* 68112111Sralph * Check to make sure there have been no errors and that both programs 68212111Sralph * are in sync with eachother. 68312111Sralph * Return non-zero if the connection was lost. 68412111Sralph */ 685*16762Sralph response() 68612111Sralph { 68712111Sralph char resp; 68812111Sralph 689*16762Sralph if (read(pfd, &resp, 1) != 1) { 690*16762Sralph syslog(LOG_INFO, "%s: lost connection", printer); 691*16762Sralph return(-1); 69212111Sralph } 693*16762Sralph return(resp); 69412111Sralph } 69512111Sralph 69612111Sralph /* 69712111Sralph * Banner printing stuff 69812111Sralph */ 69912111Sralph banner(name1, name2) 70012111Sralph char *name1, *name2; 70112111Sralph { 70212111Sralph time_t tvec; 70312111Sralph extern char *ctime(); 70412111Sralph 70512111Sralph time(&tvec); 70612111Sralph if (!SF && !tof) 70712111Sralph (void) write(ofd, FF, strlen(FF)); 70812111Sralph if (SB) { /* short banner only */ 70912111Sralph if (class[0]) { 71012111Sralph (void) write(ofd, class, strlen(class)); 71112111Sralph (void) write(ofd, ":", 1); 71212111Sralph } 71312111Sralph (void) write(ofd, name1, strlen(name1)); 71412111Sralph (void) write(ofd, " Job: ", 7); 71512111Sralph (void) write(ofd, name2, strlen(name2)); 71612111Sralph (void) write(ofd, " Date: ", 8); 71712111Sralph (void) write(ofd, ctime(&tvec), 24); 71812111Sralph (void) write(ofd, "\n", 1); 71912111Sralph } else { /* normal banner */ 72012111Sralph (void) write(ofd, "\n\n\n", 3); 72112111Sralph scan_out(ofd, name1, '\0'); 72212111Sralph (void) write(ofd, "\n\n", 2); 72312111Sralph scan_out(ofd, name2, '\0'); 72412111Sralph if (class[0]) { 72512111Sralph (void) write(ofd,"\n\n\n",3); 72612111Sralph scan_out(ofd, class, '\0'); 72712111Sralph } 72812111Sralph (void) write(ofd, "\n\n\n\n\t\t\t\t\tJob: ", 15); 72912111Sralph (void) write(ofd, name2, strlen(name2)); 73012111Sralph (void) write(ofd, "\n\t\t\t\t\tDate: ", 12); 73112111Sralph (void) write(ofd, ctime(&tvec), 24); 73212111Sralph (void) write(ofd, "\n", 1); 73312111Sralph } 73412111Sralph if (!SF) 73512111Sralph (void) write(ofd, FF, strlen(FF)); 73612111Sralph tof = 1; 73712111Sralph } 73812111Sralph 739*16762Sralph char * 74012111Sralph scnline(key, p, c) 74112111Sralph register char key, *p; 74212111Sralph char c; 74312111Sralph { 74412111Sralph register scnwidth; 74512111Sralph 74612111Sralph for (scnwidth = WIDTH; --scnwidth;) { 74712111Sralph key <<= 1; 74812111Sralph *p++ = key & 0200 ? c : BACKGND; 74912111Sralph } 75012111Sralph return (p); 75112111Sralph } 75212111Sralph 75312111Sralph #define TRC(q) (((q)-' ')&0177) 75412111Sralph 75512111Sralph scan_out(scfd, scsp, dlm) 75612111Sralph int scfd; 75712111Sralph char *scsp, dlm; 75812111Sralph { 75912111Sralph register char *strp; 76012111Sralph register nchrs, j; 76112111Sralph char outbuf[LINELEN+1], *sp, c, cc; 76212111Sralph int d, scnhgt; 76312111Sralph extern char scnkey[][HEIGHT]; /* in lpdchar.c */ 76412111Sralph 76512111Sralph for (scnhgt = 0; scnhgt++ < HEIGHT+DROP; ) { 76612111Sralph strp = &outbuf[0]; 76712111Sralph sp = scsp; 76812111Sralph for (nchrs = 0; ; ) { 76912111Sralph d = dropit(c = TRC(cc = *sp++)); 77012111Sralph if ((!d && scnhgt > HEIGHT) || (scnhgt <= DROP && d)) 77112111Sralph for (j = WIDTH; --j;) 77212111Sralph *strp++ = BACKGND; 77312111Sralph else 77412111Sralph strp = scnline(scnkey[c][scnhgt-1-d], strp, cc); 77512111Sralph if (*sp == dlm || *sp == '\0' || nchrs++ >= PW/(WIDTH+1)-1) 77612111Sralph break; 77712111Sralph *strp++ = BACKGND; 77812111Sralph *strp++ = BACKGND; 77912111Sralph } 78012111Sralph while (*--strp == BACKGND && strp >= outbuf) 78112111Sralph ; 78212111Sralph strp++; 78312111Sralph *strp++ = '\n'; 78412111Sralph (void) write(scfd, outbuf, strp-outbuf); 78512111Sralph } 78612111Sralph } 78712111Sralph 78812111Sralph dropit(c) 78912111Sralph char c; 79012111Sralph { 79112111Sralph switch(c) { 79212111Sralph 79312111Sralph case TRC('_'): 79412111Sralph case TRC(';'): 79512111Sralph case TRC(','): 79612111Sralph case TRC('g'): 79712111Sralph case TRC('j'): 79812111Sralph case TRC('p'): 79912111Sralph case TRC('q'): 80012111Sralph case TRC('y'): 80112111Sralph return (DROP); 80212111Sralph 80312111Sralph default: 80412111Sralph return (0); 80512111Sralph } 80612111Sralph } 80712111Sralph 80812111Sralph /* 80912111Sralph * sendmail --- 81012111Sralph * tell people about job completion 81112111Sralph */ 81215811Sralph sendmail(user, bombed) 81315811Sralph char *user; 81412111Sralph int bombed; 81512111Sralph { 81612111Sralph register int i; 81715811Sralph int p[2], s; 81812111Sralph register char *cp; 81912111Sralph char buf[100]; 82015811Sralph struct stat stb; 82115811Sralph FILE *fp; 82212111Sralph 82312111Sralph pipe(p); 82415811Sralph if ((s = dofork(DORETURN)) == 0) { /* child */ 82512111Sralph dup2(p[0], 0); 82612111Sralph for (i = 3; i < NOFILE; i++) 82712111Sralph (void) close(i); 82812111Sralph if ((cp = rindex(MAIL, '/')) != NULL) 82912111Sralph cp++; 83012111Sralph else 83112111Sralph cp = MAIL; 83215811Sralph sprintf(buf, "%s@%s", user, fromhost); 83312111Sralph execl(MAIL, cp, buf, 0); 83412111Sralph exit(0); 83515811Sralph } else if (s > 0) { /* parent */ 83612111Sralph dup2(p[1], 1); 83715811Sralph printf("To: %s@%s\n", user, fromhost); 83812111Sralph printf("Subject: printer job\n\n"); 83912111Sralph printf("Your printer job "); 84012111Sralph if (*jobname) 84112111Sralph printf("(%s) ", jobname); 84212463Sralph switch (bombed) { 84312463Sralph case 0: 84412463Sralph printf("\ncompleted successfully\n"); 84512463Sralph break; 84612463Sralph default: 84712463Sralph case 1: 84812463Sralph printf("\ncould not be printed\n"); 84912463Sralph break; 85012463Sralph case 2: 85112463Sralph printf("\ncould not be printed without an account on %s\n", host); 85212463Sralph break; 85315811Sralph case 3: 85415811Sralph if (stat(tmpfile, &stb) < 0 || stb.st_size == 0 || 85515811Sralph (fp = fopen(tmpfile, "r")) == NULL) { 85615811Sralph printf("\nwas printed but had some errors\n"); 85715811Sralph break; 85815811Sralph } 85915811Sralph printf("\nwas printed but had the following errors:\n"); 86015811Sralph while ((i = getc(fp)) != EOF) 86115811Sralph putchar(i); 86215811Sralph (void) fclose(fp); 86312463Sralph } 86412111Sralph fflush(stdout); 86512111Sralph (void) close(1); 86612111Sralph } 86712111Sralph (void) close(p[0]); 86812111Sralph (void) close(p[1]); 86915811Sralph wait(&s); 87012111Sralph } 87112111Sralph 87212111Sralph /* 87312111Sralph * dofork - fork with retries on failure 87412111Sralph */ 87512111Sralph dofork(action) 87612111Sralph int action; 87712111Sralph { 87812111Sralph register int i, pid; 87912111Sralph 88012111Sralph for (i = 0; i < 20; i++) { 88112463Sralph if ((pid = fork()) < 0) { 88212111Sralph sleep((unsigned)(i*i)); 88312463Sralph continue; 88412463Sralph } 88512463Sralph /* 88612463Sralph * Child should run as daemon instead of root 88712463Sralph */ 88812463Sralph if (pid == 0) 88912463Sralph setuid(DU); 89012463Sralph return(pid); 89112111Sralph } 892*16762Sralph syslog(LOG_ERR, "can't fork"); 89312111Sralph 89412111Sralph switch (action) { 89512111Sralph case DORETURN: 89612111Sralph return (-1); 89712111Sralph default: 898*16762Sralph syslog(LOG_ERR, "bad action (%d) to dofork", action); 89912111Sralph /*FALL THRU*/ 90012111Sralph case DOABORT: 90112111Sralph exit(1); 90212111Sralph } 90312111Sralph /*NOTREACHED*/ 90412111Sralph } 90512111Sralph 90612111Sralph /* 907*16762Sralph * Kill child processes to abort current job. 90812111Sralph */ 909*16762Sralph abortpr() 91012111Sralph { 91115811Sralph (void) unlink(tmpfile); 91212111Sralph kill(0, SIGINT); 91312111Sralph if (ofilter > 0) 91412111Sralph kill(ofilter, SIGCONT); 91512111Sralph while (wait(0) > 0) 91612111Sralph ; 91712111Sralph exit(0); 91812111Sralph } 91912111Sralph 92012111Sralph init() 92112111Sralph { 92212111Sralph int status; 92312111Sralph 92413169Sralph if ((status = pgetent(line, printer)) < 0) 92513169Sralph fatal("can't open printer description file"); 92613169Sralph else if (status == 0) 92713169Sralph fatal("unknown printer"); 92812111Sralph if ((LP = pgetstr("lp", &bp)) == NULL) 92912111Sralph LP = DEFDEVLP; 93012111Sralph if ((RP = pgetstr("rp", &bp)) == NULL) 93112463Sralph RP = DEFLP; 93212111Sralph if ((LO = pgetstr("lo", &bp)) == NULL) 93312111Sralph LO = DEFLOCK; 93412111Sralph if ((ST = pgetstr("st", &bp)) == NULL) 93512111Sralph ST = DEFSTAT; 93612111Sralph if ((LF = pgetstr("lf", &bp)) == NULL) 93712111Sralph LF = DEFLOGF; 93812111Sralph if ((SD = pgetstr("sd", &bp)) == NULL) 93912111Sralph SD = DEFSPOOL; 94012111Sralph if ((DU = pgetnum("du")) < 0) 94112111Sralph DU = DEFUID; 94212111Sralph if ((FF = pgetstr("ff", &bp)) == NULL) 94312111Sralph FF = DEFFF; 94412111Sralph if ((PW = pgetnum("pw")) < 0) 94512111Sralph PW = DEFWIDTH; 94612111Sralph sprintf(&width[2], "%d", PW); 94712111Sralph if ((PL = pgetnum("pl")) < 0) 94812111Sralph PL = DEFLENGTH; 94912111Sralph sprintf(&length[2], "%d", PL); 95012463Sralph if ((PX = pgetnum("px")) < 0) 95112463Sralph PX = 0; 95212463Sralph sprintf(&pxwidth[2], "%d", PX); 95312463Sralph if ((PY = pgetnum("py")) < 0) 95412463Sralph PY = 0; 95512463Sralph sprintf(&pxlength[2], "%d", PY); 95612111Sralph RM = pgetstr("rm", &bp); 95712111Sralph AF = pgetstr("af", &bp); 95812111Sralph OF = pgetstr("of", &bp); 95912111Sralph IF = pgetstr("if", &bp); 96012463Sralph RF = pgetstr("rf", &bp); 96112111Sralph TF = pgetstr("tf", &bp); 96213233Sralph NF = pgetstr("nf", &bp); 96312111Sralph DF = pgetstr("df", &bp); 96412111Sralph GF = pgetstr("gf", &bp); 96512111Sralph VF = pgetstr("vf", &bp); 96612111Sralph CF = pgetstr("cf", &bp); 96712111Sralph TR = pgetstr("tr", &bp); 96812463Sralph RS = pgetflag("rs"); 96912111Sralph SF = pgetflag("sf"); 97012111Sralph SH = pgetflag("sh"); 97112111Sralph SB = pgetflag("sb"); 97212111Sralph RW = pgetflag("rw"); 97312111Sralph BR = pgetnum("br"); 97412111Sralph if ((FC = pgetnum("fc")) < 0) 97512111Sralph FC = 0; 97612111Sralph if ((FS = pgetnum("fs")) < 0) 97712111Sralph FS = 0; 97812111Sralph if ((XC = pgetnum("xc")) < 0) 97912111Sralph XC = 0; 98012111Sralph if ((XS = pgetnum("xs")) < 0) 98112111Sralph XS = 0; 98212581Sralph tof = !pgetflag("fo"); 98312111Sralph } 98412111Sralph 98512463Sralph /* 98612463Sralph * Acquire line printer or remote connection. 98712463Sralph */ 98812463Sralph openpr() 98912463Sralph { 99012463Sralph register int i, n; 991*16762Sralph int resp; 99212463Sralph 99312463Sralph if (*LP) { 99412463Sralph for (i = 1; ; i = i < 32 ? i << 1 : i) { 99513148Ssam pfd = open(LP, RW ? O_RDWR : O_WRONLY); 99612463Sralph if (pfd >= 0) 99712463Sralph break; 99812463Sralph if (errno == ENOENT) { 999*16762Sralph syslog(LOG_ERR, "%s: %m", LP); 100012463Sralph exit(1); 100112463Sralph } 100212463Sralph if (i == 1) 100312463Sralph status("waiting for %s to become ready (offline ?)", printer); 100412463Sralph sleep(i); 100512463Sralph } 100612463Sralph if (isatty(pfd)) 100712463Sralph setty(); 100812463Sralph status("%s is ready and printing", printer); 100912463Sralph } else if (RM != NULL) { 1010*16762Sralph for (i = 1; ; i = i < 256 ? i << 1 : i) { 1011*16762Sralph resp = -1; 101212528Sralph pfd = getport(RM); 101312463Sralph if (pfd >= 0) { 101412463Sralph (void) sprintf(line, "\2%s\n", RP); 101512463Sralph n = strlen(line); 1016*16762Sralph if (write(pfd, line, n) == n && 1017*16762Sralph (resp = response()) == '\0') 101812463Sralph break; 101916031Sralph (void) close(pfd); 102012463Sralph } 102116031Sralph if (i == 1) { 1022*16762Sralph if (resp < 0) 102316031Sralph status("waiting for %s to come up", RM); 1024*16762Sralph else { 102516031Sralph status("waiting for queue to be enabled on %s", RM); 1026*16762Sralph i = 256; 1027*16762Sralph } 102816031Sralph } 102912463Sralph sleep(i); 103012463Sralph } 103112463Sralph status("sending to %s", RM); 103212463Sralph remote = 1; 103312463Sralph } else { 1034*16762Sralph syslog(LOG_ERR, "%s: no line printer device or host name", 1035*16762Sralph printer); 103612463Sralph exit(1); 103712463Sralph } 103812463Sralph /* 103912463Sralph * Start up an output filter, if needed. 104012463Sralph */ 104112463Sralph if (OF) { 104212463Sralph int p[2]; 104312463Sralph char *cp; 104412463Sralph 104512463Sralph pipe(p); 104612463Sralph if ((ofilter = dofork(DOABORT)) == 0) { /* child */ 104712463Sralph dup2(p[0], 0); /* pipe is std in */ 104812463Sralph dup2(pfd, 1); /* printer is std out */ 104912463Sralph for (i = 3; i < NOFILE; i++) 105012463Sralph (void) close(i); 105112463Sralph if ((cp = rindex(OF, '/')) == NULL) 105212463Sralph cp = OF; 105312463Sralph else 105412463Sralph cp++; 105512463Sralph execl(OF, cp, width, length, 0); 1056*16762Sralph syslog(LOG_ERR, "%s: %s: %m", printer, OF); 105712463Sralph exit(1); 105812463Sralph } 105912463Sralph (void) close(p[0]); /* close input side */ 106012463Sralph ofd = p[1]; /* use pipe for output */ 106112463Sralph } else { 106212463Sralph ofd = pfd; 106312463Sralph ofilter = 0; 106412463Sralph } 106512463Sralph } 106612463Sralph 106712111Sralph struct bauds { 106812111Sralph int baud; 106912111Sralph int speed; 107012111Sralph } bauds[] = { 107112111Sralph 50, B50, 107212111Sralph 75, B75, 107312111Sralph 110, B110, 107412111Sralph 134, B134, 107512111Sralph 150, B150, 107612111Sralph 200, B200, 107712111Sralph 300, B300, 107812111Sralph 600, B600, 107912111Sralph 1200, B1200, 108012111Sralph 1800, B1800, 108112111Sralph 2400, B2400, 108212111Sralph 4800, B4800, 108312111Sralph 9600, B9600, 108412111Sralph 19200, EXTA, 108512111Sralph 38400, EXTB, 108612111Sralph 0, 0 108712111Sralph }; 108812111Sralph 108912111Sralph /* 109012111Sralph * setup tty lines. 109112111Sralph */ 109212111Sralph setty() 109312111Sralph { 109412111Sralph struct sgttyb ttybuf; 109512111Sralph register struct bauds *bp; 109612111Sralph 109712111Sralph if (ioctl(pfd, TIOCEXCL, (char *)0) < 0) { 1098*16762Sralph syslog(LOG_ERR, "%s: ioctl(TIOCEXCL): %m", printer); 109912111Sralph exit(1); 110012111Sralph } 110112111Sralph if (ioctl(pfd, TIOCGETP, (char *)&ttybuf) < 0) { 1102*16762Sralph syslog(LOG_ERR, "%s: ioctl(TIOCGETP): %m", printer); 110312111Sralph exit(1); 110412111Sralph } 110512111Sralph if (BR > 0) { 110612111Sralph for (bp = bauds; bp->baud; bp++) 110712111Sralph if (BR == bp->baud) 110812111Sralph break; 110912111Sralph if (!bp->baud) { 1110*16762Sralph syslog(LOG_ERR, "%s: illegal baud rate %d", printer, BR); 111112111Sralph exit(1); 111212111Sralph } 111312111Sralph ttybuf.sg_ispeed = ttybuf.sg_ospeed = bp->speed; 111412111Sralph } 111513169Sralph ttybuf.sg_flags &= ~FC; 111613169Sralph ttybuf.sg_flags |= FS; 111712111Sralph if (ioctl(pfd, TIOCSETP, (char *)&ttybuf) < 0) { 1118*16762Sralph syslog(LOG_ERR, "%s: ioctl(TIOCSETP): %m", printer); 111912111Sralph exit(1); 112012111Sralph } 112112111Sralph if (XC) { 112212111Sralph if (ioctl(pfd, TIOCLBIC, &XC) < 0) { 1123*16762Sralph syslog(LOG_ERR, "%s: ioctl(TIOCLBIC): %m", printer); 112412111Sralph exit(1); 112512111Sralph } 112612111Sralph } 112712111Sralph if (XS) { 112812111Sralph if (ioctl(pfd, TIOCLBIS, &XS) < 0) { 1129*16762Sralph syslog(LOG_ERR, "%s: ioctl(TIOCLBIS): %m", printer); 113012111Sralph exit(1); 113112111Sralph } 113212111Sralph } 113312111Sralph } 113412463Sralph 113512463Sralph /*VARARGS1*/ 113612463Sralph status(msg, a1, a2, a3) 113712463Sralph char *msg; 113812463Sralph { 113912463Sralph register int fd; 114012463Sralph char buf[BUFSIZ]; 114112463Sralph 114212463Sralph umask(0); 114313148Ssam fd = open(ST, O_WRONLY|O_CREAT, 0664); 1144*16762Sralph if (fd < 0 || flock(fd, LOCK_EX) < 0) { 1145*16762Sralph syslog(LOG_ERR, "%s: %s: %m", printer, ST); 1146*16762Sralph exit(1); 1147*16762Sralph } 114813148Ssam ftruncate(fd, 0); 114912463Sralph sprintf(buf, msg, a1, a2, a3); 115012463Sralph strcat(buf, "\n"); 115112463Sralph (void) write(fd, buf, strlen(buf)); 115212463Sralph (void) close(fd); 115312463Sralph } 1154