113954Ssam #ifndef lint 2*17302Sralph static char sccsid[] = "@(#)printjob.c 4.20 (Berkeley) 10/23/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 1716762Sralph char title[80]; /* ``pr'' title */ 1816762Sralph FILE *cfp; /* control file */ 1916762Sralph int pfd; /* printer file descriptor */ 2016762Sralph int ofd; /* output filter file descriptor */ 2116762Sralph int lfd; /* lock file descriptor */ 2216762Sralph int pid; /* pid of lpd process */ 2316762Sralph int prchild; /* id of pr process */ 2416762Sralph int child; /* id of any filters */ 2516762Sralph int ofilter; /* id of output filter, if any */ 2616762Sralph int tof; /* true if at top of form */ 2716762Sralph int remote; /* true if sending files to remote */ 2812111Sralph 2916762Sralph char fromhost[32]; /* user's host machine */ 3016762Sralph char logname[32]; /* user's login name */ 3116762Sralph char jobname[100]; /* job or file name */ 3216762Sralph char class[32]; /* classification field */ 3316762Sralph char width[10] = "-w"; /* page width in characters */ 3416762Sralph char length[10] = "-l"; /* page length in lines */ 3516762Sralph char pxwidth[10] = "-x"; /* page width in pixels */ 3616762Sralph char pxlength[10] = "-y"; /* page length in pixels */ 3716762Sralph char indent[10] = "-i0"; /* indentation size in characters */ 3816762Sralph 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; 4716762Sralph int count = 0; 4816762Sralph extern int abortpr(); 4912111Sralph 5012111Sralph init(); /* set up capabilities */ 5113442Sralph (void) write(1, "", 1); /* ack that daemon is started */ 5216762Sralph setgid(getegid()); 5312463Sralph pid = getpid(); /* for use with lprm */ 5412111Sralph setpgrp(0, pid); 5516762Sralph signal(SIGHUP, abortpr); 5616762Sralph signal(SIGINT, abortpr); 5716762Sralph signal(SIGQUIT, abortpr); 5816762Sralph signal(SIGTERM, abortpr); 5912111Sralph 6015811Sralph (void) mktemp(tmpfile); 6115811Sralph 6212111Sralph /* 6312111Sralph * uses short form file names 6412111Sralph */ 6512111Sralph if (chdir(SD) < 0) { 6616762Sralph 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) { 7316762Sralph 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); 7916762Sralph 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) { 8916762Sralph 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) { 9616762Sralph 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) 10316762Sralph 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) 12116762Sralph 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) { 13116762Sralph /* stop printing before starting next job? */ 13213169Sralph if (stb.st_mode & 0100) 13313169Sralph goto done; 13416762Sralph /* 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) 13916762Sralph syslog(LOG_WARNING, "%s: %s: %m", 14016762Sralph 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 */ 14716762Sralph 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) 15716762Sralph 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) { 16716762Sralph 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 18616762Sralph 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) { 20916762Sralph 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]); 217*17302Sralph strcpy(indent+2, "0"); 21812111Sralph 21912111Sralph /* 22012111Sralph * read the control file for work to do 22112111Sralph * 22212111Sralph * file format -- first character in the line is a command 22312111Sralph * rest of the line is the argument. 22412111Sralph * valid commands are: 22512111Sralph * 22612111Sralph * J -- "job name" on banner page 22712111Sralph * C -- "class name" on banner page 22812111Sralph * L -- "literal" user's name to print on banner 22912111Sralph * T -- "title" for pr 23012111Sralph * H -- "host name" of machine where lpr was done 23112111Sralph * P -- "person" user's login name 23212581Sralph * I -- "indent" amount to indent output 23312111Sralph * f -- "file name" name of text file to print 23412111Sralph * l -- "file name" text file with control chars 23512111Sralph * p -- "file name" text file to print with pr(1) 23612111Sralph * t -- "file name" troff(1) file to print 23713233Sralph * n -- "file name" ditroff(1) file to print 23812111Sralph * d -- "file name" dvi file to print 23912111Sralph * g -- "file name" plot(1G) file to print 24012111Sralph * v -- "file name" plain raster file to print 24112111Sralph * c -- "file name" cifplot file to print 24212111Sralph * 1 -- "R font file" for troff 24312111Sralph * 2 -- "I font file" for troff 24412111Sralph * 3 -- "B font file" for troff 24512111Sralph * 4 -- "S font file" for troff 24612111Sralph * N -- "name" of file (used by lpq) 24712111Sralph * U -- "unlink" name of file to remove 24812111Sralph * (after we print it. (Pass 2 only)). 24912111Sralph * M -- "mail" to user when done printing 25012111Sralph * 25112111Sralph * getline reads a line and expands tabs to blanks 25212111Sralph */ 25312111Sralph 25412111Sralph /* pass 1 */ 25512111Sralph 25612111Sralph while (getline(cfp)) 25712111Sralph switch (line[0]) { 25812111Sralph case 'H': 25914150Sralph strcpy(fromhost, line+1); 26012111Sralph if (class[0] == '\0') 26115552Sralph strncpy(class, line+1, sizeof(class)-1); 26212111Sralph continue; 26312111Sralph 26412111Sralph case 'P': 26515552Sralph strncpy(logname, line+1, sizeof(logname)-1); 26612463Sralph if (RS) { /* restricted */ 26712463Sralph if (getpwnam(logname) == (struct passwd *)0) { 26812463Sralph bombed = 2; 26915811Sralph sendmail(line+1, bombed); 27012463Sralph goto pass2; 27112463Sralph } 27212463Sralph } 27312111Sralph continue; 27412111Sralph 27512111Sralph case 'J': 27612111Sralph if (line[1] != '\0') 27715552Sralph strncpy(jobname, line+1, sizeof(jobname)-1); 27812111Sralph else 27912111Sralph strcpy(jobname, " "); 28012111Sralph continue; 28112111Sralph 28212111Sralph case 'C': 28312111Sralph if (line[1] != '\0') 28415552Sralph strncpy(class, line+1, sizeof(class)-1); 28512111Sralph else if (class[0] == '\0') 28615811Sralph gethostname(class, sizeof(class)); 28712111Sralph continue; 28812111Sralph 28912111Sralph case 'T': /* header title for pr */ 29015552Sralph strncpy(title, line+1, sizeof(title)-1); 29112111Sralph continue; 29212111Sralph 29312111Sralph case 'L': /* identification line */ 29412111Sralph if (!SH) 29512111Sralph banner(line+1, jobname); 29612111Sralph continue; 29712111Sralph 29812111Sralph case '1': /* troff fonts */ 29912111Sralph case '2': 30012111Sralph case '3': 30112111Sralph case '4': 30212111Sralph if (line[1] != '\0') 30312111Sralph strcpy(fonts[line[0]-'1'], line+1); 30412111Sralph continue; 30512111Sralph 30612111Sralph case 'W': /* page width */ 30715552Sralph strncpy(width+2, line+1, sizeof(width)-3); 30812111Sralph continue; 30912111Sralph 31012581Sralph case 'I': /* indent amount */ 31115552Sralph strncpy(indent+2, line+1, sizeof(indent)-3); 31212581Sralph continue; 31312581Sralph 31412111Sralph default: /* some file to print */ 31515811Sralph switch (i = print(line[0], line+1)) { 31615811Sralph case -1: 31715811Sralph if (!bombed) 31815811Sralph bombed = 1; 31915811Sralph break; 32015811Sralph case 1: 32112111Sralph (void) fclose(cfp); 32212111Sralph return(1); 32315811Sralph case 2: 32415811Sralph bombed = 3; 32515811Sralph sendmail(logname, bombed); 32615811Sralph } 32712111Sralph title[0] = '\0'; 32812111Sralph continue; 32912111Sralph 33012111Sralph case 'N': 33112111Sralph case 'U': 33212111Sralph case 'M': 33312111Sralph continue; 33412111Sralph } 33512111Sralph 33612111Sralph /* pass 2 */ 33712111Sralph 33812463Sralph pass2: 33912111Sralph fseek(cfp, 0L, 0); 34012111Sralph while (getline(cfp)) 34112111Sralph switch (line[0]) { 34212111Sralph case 'M': 34315811Sralph if (bombed < 2) /* already sent if >= 2 */ 34415811Sralph sendmail(line+1, bombed); 34512111Sralph continue; 34612111Sralph 34712111Sralph case 'U': 34812111Sralph (void) unlink(line+1); 34912111Sralph } 35012111Sralph /* 35115811Sralph * clean-up in case another control file exists 35212111Sralph */ 35312111Sralph (void) fclose(cfp); 35412111Sralph (void) unlink(file); 35514150Sralph return(bombed ? -1 : 0); 35612111Sralph } 35712111Sralph 35812111Sralph /* 35912111Sralph * Print a file. 36013233Sralph * Set up the chain [ PR [ | {IF, OF} ] ] or {IF, RF, TF, NF, DF, CF, VF}. 36115811Sralph * Return -1 if a non-recoverable error occured, 36215811Sralph * 2 if the filter detected some errors (but printed the job anyway), 36315811Sralph * 1 if we should try to reprint this job and 36412111Sralph * 0 if all is well. 36512111Sralph * Note: all filters take stdin as the file, stdout as the printer, 36612111Sralph * stderr as the log file, and must not ignore SIGINT. 36712111Sralph */ 36812111Sralph print(format, file) 36912111Sralph int format; 37012111Sralph char *file; 37112111Sralph { 37215811Sralph register int n; 37312111Sralph register char *prog; 37415811Sralph int fi, fo; 37512111Sralph char *av[15], buf[BUFSIZ]; 37612111Sralph int pid, p[2], stopped = 0; 37712111Sralph union wait status; 37812111Sralph 37916762Sralph if ((fi = open(file, O_RDONLY)) < 0) 38012111Sralph return(-1); 38112111Sralph if (!SF && !tof) { /* start on a fresh page */ 38212111Sralph (void) write(ofd, FF, strlen(FF)); 38312111Sralph tof = 1; 38412111Sralph } 38512111Sralph if (IF == NULL && (format == 'f' || format == 'l')) { 38612111Sralph tof = 0; 38712111Sralph while ((n = read(fi, buf, BUFSIZ)) > 0) 38812111Sralph if (write(ofd, buf, n) != n) { 38912111Sralph (void) close(fi); 39012111Sralph return(1); 39112111Sralph } 39212111Sralph (void) close(fi); 39312111Sralph return(0); 39412111Sralph } 39512111Sralph switch (format) { 39612111Sralph case 'p': /* print file using 'pr' */ 39712111Sralph if (IF == NULL) { /* use output filter */ 39812111Sralph prog = PR; 39912111Sralph av[0] = "pr"; 40012111Sralph av[1] = width; 40112111Sralph av[2] = length; 40212111Sralph av[3] = "-h"; 40312111Sralph av[4] = *title ? title : " "; 40412111Sralph av[5] = 0; 40512111Sralph fo = ofd; 40612111Sralph goto start; 40712111Sralph } 40812111Sralph pipe(p); 40912111Sralph if ((prchild = dofork(DORETURN)) == 0) { /* child */ 41012111Sralph dup2(fi, 0); /* file is stdin */ 41112111Sralph dup2(p[1], 1); /* pipe is stdout */ 41212111Sralph for (n = 3; n < NOFILE; n++) 41312111Sralph (void) close(n); 41412111Sralph execl(PR, "pr", width, length, "-h", *title ? title : " ", 0); 41516762Sralph syslog(LOG_ERR, "cannot execl %s", PR); 41612111Sralph exit(2); 41712111Sralph } 41812111Sralph (void) close(p[1]); /* close output side */ 41912111Sralph (void) close(fi); 42012111Sralph if (prchild < 0) { 42112111Sralph prchild = 0; 42212111Sralph (void) close(p[0]); 42312111Sralph return(-1); 42412111Sralph } 42512111Sralph fi = p[0]; /* use pipe for input */ 42612111Sralph case 'f': /* print plain text file */ 42712111Sralph prog = IF; 42812111Sralph av[1] = width; 42912111Sralph av[2] = length; 43012581Sralph av[3] = indent; 43112581Sralph n = 4; 43212111Sralph break; 43312111Sralph case 'l': /* like 'f' but pass control characters */ 43412111Sralph prog = IF; 43514325Sralph av[1] = "-c"; 43612111Sralph av[2] = width; 43712111Sralph av[3] = length; 43812581Sralph av[4] = indent; 43912581Sralph n = 5; 44012111Sralph break; 44112463Sralph case 'r': /* print a fortran text file */ 44212463Sralph prog = RF; 44312463Sralph av[1] = width; 44412463Sralph av[2] = length; 44512463Sralph n = 3; 44612463Sralph break; 44712111Sralph case 't': /* print troff output */ 44813233Sralph case 'n': /* print ditroff output */ 44912463Sralph case 'd': /* print tex output */ 45012111Sralph (void) unlink(".railmag"); 45112463Sralph if ((fo = creat(".railmag", FILMOD)) < 0) { 45216762Sralph syslog(LOG_ERR, "%s: cannot create .railmag", printer); 45312111Sralph (void) unlink(".railmag"); 45412111Sralph } else { 45512111Sralph for (n = 0; n < 4; n++) { 45612111Sralph if (fonts[n][0] != '/') 45712111Sralph (void) write(fo, "/usr/lib/vfont/", 15); 45812111Sralph (void) write(fo, fonts[n], strlen(fonts[n])); 45912111Sralph (void) write(fo, "\n", 1); 46012111Sralph } 46112111Sralph (void) close(fo); 46212111Sralph } 46313233Sralph prog = (format == 't') ? TF : (format == 'n') ? NF : DF; 46412463Sralph av[1] = pxwidth; 46512463Sralph av[2] = pxlength; 46612463Sralph n = 3; 46712111Sralph break; 46812111Sralph case 'c': /* print cifplot output */ 46912111Sralph prog = CF; 47012463Sralph av[1] = pxwidth; 47112463Sralph av[2] = pxlength; 47212463Sralph n = 3; 47312111Sralph break; 47412111Sralph case 'g': /* print plot(1G) output */ 47512111Sralph prog = GF; 47612463Sralph av[1] = pxwidth; 47712463Sralph av[2] = pxlength; 47812463Sralph n = 3; 47912111Sralph break; 48012111Sralph case 'v': /* print raster output */ 48112111Sralph prog = VF; 48212463Sralph av[1] = pxwidth; 48312463Sralph av[2] = pxlength; 48412463Sralph n = 3; 48512111Sralph break; 48612111Sralph default: 48712111Sralph (void) close(fi); 48816762Sralph syslog(LOG_ERR, "%s: illegal format character '%c'", 48916762Sralph printer, format); 49012111Sralph return(-1); 49112111Sralph } 49212111Sralph if ((av[0] = rindex(prog, '/')) != NULL) 49312111Sralph av[0]++; 49412111Sralph else 49512111Sralph av[0] = prog; 49612111Sralph av[n++] = "-n"; 49712111Sralph av[n++] = logname; 49812111Sralph av[n++] = "-h"; 49914150Sralph av[n++] = fromhost; 50012111Sralph av[n++] = AF; 50112111Sralph av[n] = 0; 50212111Sralph fo = pfd; 50312111Sralph if (ofilter > 0) { /* stop output filter */ 50412111Sralph write(ofd, "\031\1", 2); 50512111Sralph while ((pid = wait3(&status, WUNTRACED, 0)) > 0 && pid != ofilter) 50612111Sralph ; 50712111Sralph if (status.w_stopval != WSTOPPED) { 50812111Sralph (void) close(fi); 50916762Sralph syslog(LOG_WARNING, "%s: output filter died (%d)", 51016762Sralph printer, status.w_retcode); 51112111Sralph return(1); 51212111Sralph } 51312111Sralph stopped++; 51412111Sralph } 51512111Sralph start: 51612111Sralph if ((child = dofork(DORETURN)) == 0) { /* child */ 51712111Sralph dup2(fi, 0); 51812111Sralph dup2(fo, 1); 51915811Sralph n = open(tmpfile, O_WRONLY|O_CREAT, 0664); 52015811Sralph if (n >= 0) 52115811Sralph dup2(n, 2); 52212111Sralph for (n = 3; n < NOFILE; n++) 52312111Sralph (void) close(n); 52412111Sralph execv(prog, av); 52516762Sralph syslog(LOG_ERR, "cannot execv %s", prog); 52612111Sralph exit(2); 52712111Sralph } 52812111Sralph (void) close(fi); 52912111Sralph if (child < 0) 53012111Sralph status.w_retcode = 100; 53112111Sralph else 53212111Sralph while ((pid = wait(&status)) > 0 && pid != child) 53312111Sralph ; 53412111Sralph child = 0; 53512111Sralph prchild = 0; 53612111Sralph if (stopped) { /* restart output filter */ 53712111Sralph if (kill(ofilter, SIGCONT) < 0) { 53816762Sralph syslog(LOG_ERR, "cannot restart output filter"); 53912111Sralph exit(1); 54012111Sralph } 54112111Sralph } 54212111Sralph tof = 0; 54315811Sralph if (!WIFEXITED(status)) { 54416762Sralph syslog(LOG_WARNING, "%s: Daemon filter '%c' terminated (%d)", 54516762Sralph printer, format, status.w_termsig); 54612111Sralph return(-1); 54715811Sralph } else if (status.w_retcode > 2) { 54816762Sralph syslog(LOG_WARNING, "%s: Daemon filter '%c' exited (%d)", 54916762Sralph printer, format, status.w_retcode); 55015811Sralph return(-1); 55115811Sralph } else if (status.w_retcode == 0) 55215811Sralph tof = 1; 55315811Sralph return(status.w_retcode); 55412111Sralph } 55512111Sralph 55612111Sralph /* 55712111Sralph * Send the daemon control file (cf) and any data files. 55812111Sralph * Return -1 if a non-recoverable error occured, 1 if a recoverable error and 55912111Sralph * 0 if all is well. 56012111Sralph */ 56112111Sralph sendit(file) 56212111Sralph char *file; 56312111Sralph { 56412111Sralph register int linelen, err = 0; 56512111Sralph char last[132]; 56612111Sralph 56712111Sralph /* 56812111Sralph * open control file 56912111Sralph */ 57016762Sralph if ((cfp = fopen(file, "r")) == NULL) 57112111Sralph return(0); 57212111Sralph /* 57312111Sralph * read the control file for work to do 57412111Sralph * 57512111Sralph * file format -- first character in the line is a command 57612111Sralph * rest of the line is the argument. 57712111Sralph * commands of interest are: 57812111Sralph * 57912111Sralph * a-z -- "file name" name of file to print 58012111Sralph * U -- "unlink" name of file to remove 58112111Sralph * (after we print it. (Pass 2 only)). 58212111Sralph */ 58312111Sralph 58412111Sralph /* 58512111Sralph * pass 1 58612111Sralph */ 58712111Sralph while (getline(cfp)) { 58812111Sralph again: 58912111Sralph if (line[0] >= 'a' && line[0] <= 'z') { 59012111Sralph strcpy(last, line); 59112111Sralph while (linelen = getline(cfp)) 59212111Sralph if (strcmp(last, line)) 59312111Sralph break; 59412111Sralph if ((err = sendfile('\3', last+1)) > 0) { 59512111Sralph (void) fclose(cfp); 59612111Sralph return(1); 59712111Sralph } else if (err) 59812111Sralph break; 59912111Sralph if (linelen) 60012111Sralph goto again; 60112111Sralph break; 60212111Sralph } 60312111Sralph } 60412111Sralph if (!err && sendfile('\2', file) > 0) { 60512111Sralph (void) fclose(cfp); 60612111Sralph return(1); 60712111Sralph } 60812111Sralph /* 60912111Sralph * pass 2 61012111Sralph */ 61112111Sralph fseek(cfp, 0L, 0); 61212111Sralph while (getline(cfp)) 61312111Sralph if (line[0] == 'U') 61412111Sralph (void) unlink(line+1); 61512111Sralph /* 61612111Sralph * clean-up incase another control file exists 61712111Sralph */ 61812111Sralph (void) fclose(cfp); 61912111Sralph (void) unlink(file); 62012111Sralph return(0); 62112111Sralph } 62212111Sralph 62312111Sralph /* 62412111Sralph * Send a data file to the remote machine and spool it. 62512111Sralph * Return positive if we should try resending. 62612111Sralph */ 62712111Sralph sendfile(type, file) 62812111Sralph char type, *file; 62912111Sralph { 63012111Sralph register int f, i, amt; 63112111Sralph struct stat stb; 63212111Sralph char buf[BUFSIZ]; 63316762Sralph int sizerr, resp; 63412111Sralph 63516762Sralph if ((f = open(file, O_RDONLY)) < 0 || fstat(f, &stb) < 0) 63612111Sralph return(-1); 63712111Sralph (void) sprintf(buf, "%c%d %s\n", type, stb.st_size, file); 63812111Sralph amt = strlen(buf); 63916762Sralph for (i = 0; ; i++) { 64016762Sralph if (write(pfd, buf, amt) != amt || 64116762Sralph (resp = response()) < 0 || resp == '\1') { 64216762Sralph (void) close(f); 64316762Sralph return(1); 64416762Sralph } else if (resp == '\0') 64516762Sralph break; 64616762Sralph if (i == 0) 64716762Sralph status("no space on remote; waiting for queue to drain"); 64816762Sralph if (i == 10) 64916762Sralph syslog(LOG_SALERT, "%s: can't send to %s; queue full", 65016762Sralph printer, RM); 65116762Sralph sleep(5 * 60); 65212692Sralph } 65316762Sralph if (i) 65416762Sralph status("sending to %s", RM); 65512111Sralph sizerr = 0; 65612111Sralph for (i = 0; i < stb.st_size; i += BUFSIZ) { 65712111Sralph amt = BUFSIZ; 65812111Sralph if (i + amt > stb.st_size) 65912111Sralph amt = stb.st_size - i; 66012111Sralph if (sizerr == 0 && read(f, buf, amt) != amt) 66112111Sralph sizerr = 1; 66212692Sralph if (write(pfd, buf, amt) != amt) { 66312692Sralph (void) close(f); 66412111Sralph return(1); 66512692Sralph } 66612111Sralph } 66712111Sralph (void) close(f); 66812111Sralph if (sizerr) { 66916762Sralph syslog(LOG_INFO, "%s: %s: changed size", printer, file); 67012111Sralph (void) write(pfd, "\1", 1); /* tell recvjob to ignore this file */ 67116762Sralph i = -1; 67216762Sralph } else if (write(pfd, "", 1) != 1) 67316762Sralph i = 1; 67416762Sralph else if (response()) 67516762Sralph i = 1; 67616762Sralph else 67716762Sralph i = 0; 67816762Sralph return(i); 67912111Sralph } 68012111Sralph 68112111Sralph /* 68212111Sralph * Check to make sure there have been no errors and that both programs 68312111Sralph * are in sync with eachother. 68412111Sralph * Return non-zero if the connection was lost. 68512111Sralph */ 68616762Sralph response() 68712111Sralph { 68812111Sralph char resp; 68912111Sralph 69016762Sralph if (read(pfd, &resp, 1) != 1) { 69116762Sralph syslog(LOG_INFO, "%s: lost connection", printer); 69216762Sralph return(-1); 69312111Sralph } 69416762Sralph return(resp); 69512111Sralph } 69612111Sralph 69712111Sralph /* 69812111Sralph * Banner printing stuff 69912111Sralph */ 70012111Sralph banner(name1, name2) 70112111Sralph char *name1, *name2; 70212111Sralph { 70312111Sralph time_t tvec; 70412111Sralph extern char *ctime(); 70512111Sralph 70612111Sralph time(&tvec); 70712111Sralph if (!SF && !tof) 70812111Sralph (void) write(ofd, FF, strlen(FF)); 70912111Sralph if (SB) { /* short banner only */ 71012111Sralph if (class[0]) { 71112111Sralph (void) write(ofd, class, strlen(class)); 71212111Sralph (void) write(ofd, ":", 1); 71312111Sralph } 71412111Sralph (void) write(ofd, name1, strlen(name1)); 71512111Sralph (void) write(ofd, " Job: ", 7); 71612111Sralph (void) write(ofd, name2, strlen(name2)); 71712111Sralph (void) write(ofd, " Date: ", 8); 71812111Sralph (void) write(ofd, ctime(&tvec), 24); 71912111Sralph (void) write(ofd, "\n", 1); 72012111Sralph } else { /* normal banner */ 72112111Sralph (void) write(ofd, "\n\n\n", 3); 72212111Sralph scan_out(ofd, name1, '\0'); 72312111Sralph (void) write(ofd, "\n\n", 2); 72412111Sralph scan_out(ofd, name2, '\0'); 72512111Sralph if (class[0]) { 72612111Sralph (void) write(ofd,"\n\n\n",3); 72712111Sralph scan_out(ofd, class, '\0'); 72812111Sralph } 72912111Sralph (void) write(ofd, "\n\n\n\n\t\t\t\t\tJob: ", 15); 73012111Sralph (void) write(ofd, name2, strlen(name2)); 73112111Sralph (void) write(ofd, "\n\t\t\t\t\tDate: ", 12); 73212111Sralph (void) write(ofd, ctime(&tvec), 24); 73312111Sralph (void) write(ofd, "\n", 1); 73412111Sralph } 73512111Sralph if (!SF) 73612111Sralph (void) write(ofd, FF, strlen(FF)); 73712111Sralph tof = 1; 73812111Sralph } 73912111Sralph 74016762Sralph char * 74112111Sralph scnline(key, p, c) 74212111Sralph register char key, *p; 74312111Sralph char c; 74412111Sralph { 74512111Sralph register scnwidth; 74612111Sralph 74712111Sralph for (scnwidth = WIDTH; --scnwidth;) { 74812111Sralph key <<= 1; 74912111Sralph *p++ = key & 0200 ? c : BACKGND; 75012111Sralph } 75112111Sralph return (p); 75212111Sralph } 75312111Sralph 75412111Sralph #define TRC(q) (((q)-' ')&0177) 75512111Sralph 75612111Sralph scan_out(scfd, scsp, dlm) 75712111Sralph int scfd; 75812111Sralph char *scsp, dlm; 75912111Sralph { 76012111Sralph register char *strp; 76112111Sralph register nchrs, j; 76212111Sralph char outbuf[LINELEN+1], *sp, c, cc; 76312111Sralph int d, scnhgt; 76412111Sralph extern char scnkey[][HEIGHT]; /* in lpdchar.c */ 76512111Sralph 76612111Sralph for (scnhgt = 0; scnhgt++ < HEIGHT+DROP; ) { 76712111Sralph strp = &outbuf[0]; 76812111Sralph sp = scsp; 76912111Sralph for (nchrs = 0; ; ) { 77012111Sralph d = dropit(c = TRC(cc = *sp++)); 77112111Sralph if ((!d && scnhgt > HEIGHT) || (scnhgt <= DROP && d)) 77212111Sralph for (j = WIDTH; --j;) 77312111Sralph *strp++ = BACKGND; 77412111Sralph else 77512111Sralph strp = scnline(scnkey[c][scnhgt-1-d], strp, cc); 77612111Sralph if (*sp == dlm || *sp == '\0' || nchrs++ >= PW/(WIDTH+1)-1) 77712111Sralph break; 77812111Sralph *strp++ = BACKGND; 77912111Sralph *strp++ = BACKGND; 78012111Sralph } 78112111Sralph while (*--strp == BACKGND && strp >= outbuf) 78212111Sralph ; 78312111Sralph strp++; 78412111Sralph *strp++ = '\n'; 78512111Sralph (void) write(scfd, outbuf, strp-outbuf); 78612111Sralph } 78712111Sralph } 78812111Sralph 78912111Sralph dropit(c) 79012111Sralph char c; 79112111Sralph { 79212111Sralph switch(c) { 79312111Sralph 79412111Sralph case TRC('_'): 79512111Sralph case TRC(';'): 79612111Sralph case TRC(','): 79712111Sralph case TRC('g'): 79812111Sralph case TRC('j'): 79912111Sralph case TRC('p'): 80012111Sralph case TRC('q'): 80112111Sralph case TRC('y'): 80212111Sralph return (DROP); 80312111Sralph 80412111Sralph default: 80512111Sralph return (0); 80612111Sralph } 80712111Sralph } 80812111Sralph 80912111Sralph /* 81012111Sralph * sendmail --- 81112111Sralph * tell people about job completion 81212111Sralph */ 81315811Sralph sendmail(user, bombed) 81415811Sralph char *user; 81512111Sralph int bombed; 81612111Sralph { 81712111Sralph register int i; 81815811Sralph int p[2], s; 81912111Sralph register char *cp; 82012111Sralph char buf[100]; 82115811Sralph struct stat stb; 82215811Sralph FILE *fp; 82312111Sralph 82412111Sralph pipe(p); 82515811Sralph if ((s = dofork(DORETURN)) == 0) { /* child */ 82612111Sralph dup2(p[0], 0); 82712111Sralph for (i = 3; i < NOFILE; i++) 82812111Sralph (void) close(i); 82912111Sralph if ((cp = rindex(MAIL, '/')) != NULL) 83012111Sralph cp++; 83112111Sralph else 83212111Sralph cp = MAIL; 83315811Sralph sprintf(buf, "%s@%s", user, fromhost); 83412111Sralph execl(MAIL, cp, buf, 0); 83512111Sralph exit(0); 83615811Sralph } else if (s > 0) { /* parent */ 83712111Sralph dup2(p[1], 1); 83815811Sralph printf("To: %s@%s\n", user, fromhost); 83912111Sralph printf("Subject: printer job\n\n"); 84012111Sralph printf("Your printer job "); 84112111Sralph if (*jobname) 84212111Sralph printf("(%s) ", jobname); 84312463Sralph switch (bombed) { 84412463Sralph case 0: 84512463Sralph printf("\ncompleted successfully\n"); 84612463Sralph break; 84712463Sralph default: 84812463Sralph case 1: 84912463Sralph printf("\ncould not be printed\n"); 85012463Sralph break; 85112463Sralph case 2: 85212463Sralph printf("\ncould not be printed without an account on %s\n", host); 85312463Sralph break; 85415811Sralph case 3: 85515811Sralph if (stat(tmpfile, &stb) < 0 || stb.st_size == 0 || 85615811Sralph (fp = fopen(tmpfile, "r")) == NULL) { 85715811Sralph printf("\nwas printed but had some errors\n"); 85815811Sralph break; 85915811Sralph } 86015811Sralph printf("\nwas printed but had the following errors:\n"); 86115811Sralph while ((i = getc(fp)) != EOF) 86215811Sralph putchar(i); 86315811Sralph (void) fclose(fp); 86412463Sralph } 86512111Sralph fflush(stdout); 86612111Sralph (void) close(1); 86712111Sralph } 86812111Sralph (void) close(p[0]); 86912111Sralph (void) close(p[1]); 87015811Sralph wait(&s); 87112111Sralph } 87212111Sralph 87312111Sralph /* 87412111Sralph * dofork - fork with retries on failure 87512111Sralph */ 87612111Sralph dofork(action) 87712111Sralph int action; 87812111Sralph { 87912111Sralph register int i, pid; 88012111Sralph 88112111Sralph for (i = 0; i < 20; i++) { 88212463Sralph if ((pid = fork()) < 0) { 88312111Sralph sleep((unsigned)(i*i)); 88412463Sralph continue; 88512463Sralph } 88612463Sralph /* 88712463Sralph * Child should run as daemon instead of root 88812463Sralph */ 88912463Sralph if (pid == 0) 89012463Sralph setuid(DU); 89112463Sralph return(pid); 89212111Sralph } 89316762Sralph syslog(LOG_ERR, "can't fork"); 89412111Sralph 89512111Sralph switch (action) { 89612111Sralph case DORETURN: 89712111Sralph return (-1); 89812111Sralph default: 89916762Sralph syslog(LOG_ERR, "bad action (%d) to dofork", action); 90012111Sralph /*FALL THRU*/ 90112111Sralph case DOABORT: 90212111Sralph exit(1); 90312111Sralph } 90412111Sralph /*NOTREACHED*/ 90512111Sralph } 90612111Sralph 90712111Sralph /* 90816762Sralph * Kill child processes to abort current job. 90912111Sralph */ 91016762Sralph abortpr() 91112111Sralph { 91215811Sralph (void) unlink(tmpfile); 91312111Sralph kill(0, SIGINT); 91412111Sralph if (ofilter > 0) 91512111Sralph kill(ofilter, SIGCONT); 91612111Sralph while (wait(0) > 0) 91712111Sralph ; 91812111Sralph exit(0); 91912111Sralph } 92012111Sralph 92112111Sralph init() 92212111Sralph { 92312111Sralph int status; 92412111Sralph 92513169Sralph if ((status = pgetent(line, printer)) < 0) 92613169Sralph fatal("can't open printer description file"); 92713169Sralph else if (status == 0) 92813169Sralph fatal("unknown printer"); 92912111Sralph if ((LP = pgetstr("lp", &bp)) == NULL) 93012111Sralph LP = DEFDEVLP; 93112111Sralph if ((RP = pgetstr("rp", &bp)) == NULL) 93212463Sralph RP = DEFLP; 93312111Sralph if ((LO = pgetstr("lo", &bp)) == NULL) 93412111Sralph LO = DEFLOCK; 93512111Sralph if ((ST = pgetstr("st", &bp)) == NULL) 93612111Sralph ST = DEFSTAT; 93712111Sralph if ((LF = pgetstr("lf", &bp)) == NULL) 93812111Sralph LF = DEFLOGF; 93912111Sralph if ((SD = pgetstr("sd", &bp)) == NULL) 94012111Sralph SD = DEFSPOOL; 94112111Sralph if ((DU = pgetnum("du")) < 0) 94212111Sralph DU = DEFUID; 94312111Sralph if ((FF = pgetstr("ff", &bp)) == NULL) 94412111Sralph FF = DEFFF; 94512111Sralph if ((PW = pgetnum("pw")) < 0) 94612111Sralph PW = DEFWIDTH; 94712111Sralph sprintf(&width[2], "%d", PW); 94812111Sralph if ((PL = pgetnum("pl")) < 0) 94912111Sralph PL = DEFLENGTH; 95012111Sralph sprintf(&length[2], "%d", PL); 95112463Sralph if ((PX = pgetnum("px")) < 0) 95212463Sralph PX = 0; 95312463Sralph sprintf(&pxwidth[2], "%d", PX); 95412463Sralph if ((PY = pgetnum("py")) < 0) 95512463Sralph PY = 0; 95612463Sralph sprintf(&pxlength[2], "%d", PY); 95712111Sralph RM = pgetstr("rm", &bp); 95812111Sralph AF = pgetstr("af", &bp); 95912111Sralph OF = pgetstr("of", &bp); 96012111Sralph IF = pgetstr("if", &bp); 96112463Sralph RF = pgetstr("rf", &bp); 96212111Sralph TF = pgetstr("tf", &bp); 96313233Sralph NF = pgetstr("nf", &bp); 96412111Sralph DF = pgetstr("df", &bp); 96512111Sralph GF = pgetstr("gf", &bp); 96612111Sralph VF = pgetstr("vf", &bp); 96712111Sralph CF = pgetstr("cf", &bp); 96812111Sralph TR = pgetstr("tr", &bp); 96912463Sralph RS = pgetflag("rs"); 97012111Sralph SF = pgetflag("sf"); 97112111Sralph SH = pgetflag("sh"); 97212111Sralph SB = pgetflag("sb"); 97312111Sralph RW = pgetflag("rw"); 97412111Sralph BR = pgetnum("br"); 97512111Sralph if ((FC = pgetnum("fc")) < 0) 97612111Sralph FC = 0; 97712111Sralph if ((FS = pgetnum("fs")) < 0) 97812111Sralph FS = 0; 97912111Sralph if ((XC = pgetnum("xc")) < 0) 98012111Sralph XC = 0; 98112111Sralph if ((XS = pgetnum("xs")) < 0) 98212111Sralph XS = 0; 98312581Sralph tof = !pgetflag("fo"); 98412111Sralph } 98512111Sralph 98612463Sralph /* 98712463Sralph * Acquire line printer or remote connection. 98812463Sralph */ 98912463Sralph openpr() 99012463Sralph { 99112463Sralph register int i, n; 99216762Sralph int resp; 99312463Sralph 99412463Sralph if (*LP) { 99512463Sralph for (i = 1; ; i = i < 32 ? i << 1 : i) { 99613148Ssam pfd = open(LP, RW ? O_RDWR : O_WRONLY); 99712463Sralph if (pfd >= 0) 99812463Sralph break; 99912463Sralph if (errno == ENOENT) { 100016762Sralph syslog(LOG_ERR, "%s: %m", LP); 100112463Sralph exit(1); 100212463Sralph } 100312463Sralph if (i == 1) 100412463Sralph status("waiting for %s to become ready (offline ?)", printer); 100512463Sralph sleep(i); 100612463Sralph } 100712463Sralph if (isatty(pfd)) 100812463Sralph setty(); 100912463Sralph status("%s is ready and printing", printer); 101012463Sralph } else if (RM != NULL) { 101116762Sralph for (i = 1; ; i = i < 256 ? i << 1 : i) { 101216762Sralph resp = -1; 101312528Sralph pfd = getport(RM); 101412463Sralph if (pfd >= 0) { 101512463Sralph (void) sprintf(line, "\2%s\n", RP); 101612463Sralph n = strlen(line); 101716762Sralph if (write(pfd, line, n) == n && 101816762Sralph (resp = response()) == '\0') 101912463Sralph break; 102016031Sralph (void) close(pfd); 102112463Sralph } 102216031Sralph if (i == 1) { 102316762Sralph if (resp < 0) 102416031Sralph status("waiting for %s to come up", RM); 102516762Sralph else { 102616031Sralph status("waiting for queue to be enabled on %s", RM); 102716762Sralph i = 256; 102816762Sralph } 102916031Sralph } 103012463Sralph sleep(i); 103112463Sralph } 103212463Sralph status("sending to %s", RM); 103312463Sralph remote = 1; 103412463Sralph } else { 103516762Sralph syslog(LOG_ERR, "%s: no line printer device or host name", 103616762Sralph printer); 103712463Sralph exit(1); 103812463Sralph } 103912463Sralph /* 104012463Sralph * Start up an output filter, if needed. 104112463Sralph */ 104212463Sralph if (OF) { 104312463Sralph int p[2]; 104412463Sralph char *cp; 104512463Sralph 104612463Sralph pipe(p); 104712463Sralph if ((ofilter = dofork(DOABORT)) == 0) { /* child */ 104812463Sralph dup2(p[0], 0); /* pipe is std in */ 104912463Sralph dup2(pfd, 1); /* printer is std out */ 105012463Sralph for (i = 3; i < NOFILE; i++) 105112463Sralph (void) close(i); 105212463Sralph if ((cp = rindex(OF, '/')) == NULL) 105312463Sralph cp = OF; 105412463Sralph else 105512463Sralph cp++; 105612463Sralph execl(OF, cp, width, length, 0); 105716762Sralph syslog(LOG_ERR, "%s: %s: %m", printer, OF); 105812463Sralph exit(1); 105912463Sralph } 106012463Sralph (void) close(p[0]); /* close input side */ 106112463Sralph ofd = p[1]; /* use pipe for output */ 106212463Sralph } else { 106312463Sralph ofd = pfd; 106412463Sralph ofilter = 0; 106512463Sralph } 106612463Sralph } 106712463Sralph 106812111Sralph struct bauds { 106912111Sralph int baud; 107012111Sralph int speed; 107112111Sralph } bauds[] = { 107212111Sralph 50, B50, 107312111Sralph 75, B75, 107412111Sralph 110, B110, 107512111Sralph 134, B134, 107612111Sralph 150, B150, 107712111Sralph 200, B200, 107812111Sralph 300, B300, 107912111Sralph 600, B600, 108012111Sralph 1200, B1200, 108112111Sralph 1800, B1800, 108212111Sralph 2400, B2400, 108312111Sralph 4800, B4800, 108412111Sralph 9600, B9600, 108512111Sralph 19200, EXTA, 108612111Sralph 38400, EXTB, 108712111Sralph 0, 0 108812111Sralph }; 108912111Sralph 109012111Sralph /* 109112111Sralph * setup tty lines. 109212111Sralph */ 109312111Sralph setty() 109412111Sralph { 109512111Sralph struct sgttyb ttybuf; 109612111Sralph register struct bauds *bp; 109712111Sralph 109812111Sralph if (ioctl(pfd, TIOCEXCL, (char *)0) < 0) { 109916762Sralph syslog(LOG_ERR, "%s: ioctl(TIOCEXCL): %m", printer); 110012111Sralph exit(1); 110112111Sralph } 110212111Sralph if (ioctl(pfd, TIOCGETP, (char *)&ttybuf) < 0) { 110316762Sralph syslog(LOG_ERR, "%s: ioctl(TIOCGETP): %m", printer); 110412111Sralph exit(1); 110512111Sralph } 110612111Sralph if (BR > 0) { 110712111Sralph for (bp = bauds; bp->baud; bp++) 110812111Sralph if (BR == bp->baud) 110912111Sralph break; 111012111Sralph if (!bp->baud) { 111116762Sralph syslog(LOG_ERR, "%s: illegal baud rate %d", printer, BR); 111212111Sralph exit(1); 111312111Sralph } 111412111Sralph ttybuf.sg_ispeed = ttybuf.sg_ospeed = bp->speed; 111512111Sralph } 111613169Sralph ttybuf.sg_flags &= ~FC; 111713169Sralph ttybuf.sg_flags |= FS; 111812111Sralph if (ioctl(pfd, TIOCSETP, (char *)&ttybuf) < 0) { 111916762Sralph syslog(LOG_ERR, "%s: ioctl(TIOCSETP): %m", printer); 112012111Sralph exit(1); 112112111Sralph } 112217168Sralph if (XC || XS) { 112317168Sralph int ldisc = NTTYDISC; 112417168Sralph 112517168Sralph if (ioctl(pfd, TIOCSETD, &ldisc) < 0) { 112617168Sralph syslog(LOG_ERR, "%s: ioctl(TIOCSETD): %m", printer); 112717168Sralph exit(1); 112817168Sralph } 112917168Sralph } 113012111Sralph if (XC) { 113112111Sralph if (ioctl(pfd, TIOCLBIC, &XC) < 0) { 113216762Sralph syslog(LOG_ERR, "%s: ioctl(TIOCLBIC): %m", printer); 113312111Sralph exit(1); 113412111Sralph } 113512111Sralph } 113612111Sralph if (XS) { 113712111Sralph if (ioctl(pfd, TIOCLBIS, &XS) < 0) { 113816762Sralph syslog(LOG_ERR, "%s: ioctl(TIOCLBIS): %m", printer); 113912111Sralph exit(1); 114012111Sralph } 114112111Sralph } 114212111Sralph } 114312463Sralph 114412463Sralph /*VARARGS1*/ 114512463Sralph status(msg, a1, a2, a3) 114612463Sralph char *msg; 114712463Sralph { 114812463Sralph register int fd; 114912463Sralph char buf[BUFSIZ]; 115012463Sralph 115112463Sralph umask(0); 115213148Ssam fd = open(ST, O_WRONLY|O_CREAT, 0664); 115316762Sralph if (fd < 0 || flock(fd, LOCK_EX) < 0) { 115416762Sralph syslog(LOG_ERR, "%s: %s: %m", printer, ST); 115516762Sralph exit(1); 115616762Sralph } 115713148Ssam ftruncate(fd, 0); 115812463Sralph sprintf(buf, msg, a1, a2, a3); 115912463Sralph strcat(buf, "\n"); 116012463Sralph (void) write(fd, buf, strlen(buf)); 116112463Sralph (void) close(fd); 116212463Sralph } 1163