source: trunk/athena/bin/lpr/printjob.25.c @ 12350

Revision 12350, 36.2 KB checked in by ghudson, 26 years ago (diff)
Some RCS ID cleanup: delete $Log$ and replace other RCS keywords with $Id$.
Line 
1/*
2 *      $Id: printjob.25.c,v 1.2 1999-01-22 23:10:44 ghudson Exp $
3 */
4
5/*
6 * Copyright (c) 1983 Regents of the University of California.
7 * All rights reserved.  The Berkeley software License Agreement
8 * specifies the terms and conditions for redistribution.
9 */
10
11#ifndef lint
12static char sccsid[] = "@(#)printjob.c  5.2 (Berkeley) 9/17/85";
13static char *rcsid_printjob_c = "$Id: printjob.25.c,v 1.2 1999-01-22 23:10:44 ghudson Exp $";
14#endif
15
16/*
17 * printjob -- print jobs in the queue.
18 *
19 *      NOTE: the lock file is used to pass information to lpq and lprm.
20 *      it does not need to be removed because file locks are dynamic.
21 */
22
23#include "lp.h"
24#ifdef _AUX_SOURCE
25#include <sys/termio.h>
26#endif
27
28#define DORETURN        0       /* absorb fork error */
29#define DOABORT         1       /* abort if dofork fails */
30/*
31 * Error tokens
32 */
33#define DEFER           -4      /* Defer printing file till later */
34#define REPRINT         -2
35#define ERROR           -1
36#define OK              0
37#define FATALERR        1
38#define NOACCT          2
39#define FILTERERR       3
40#define ACCESS          4
41
42static int      network;                /* true if network access to printer */
43#ifdef ZEPHYR
44#undef STAT
45#include <zephyr/zephyr.h>
46
47#define ZCLASS "MESSAGE"
48#define ZINSTANCE "PERSONAL"
49#define ZSENDER "Printer Daemon"
50#define ZDEFAULTFORMAT "$message"
51
52ZNotice_t notice;
53char zrecipient[40+REALM_SZ];
54char *zmessage[6];
55char zmessagetext[BUFSIZ];
56int zerrno;
57int zflag = 0;
58
59static char *zerrtext[]={"Document printing has been deferred",
60                         "This is impossible",
61                         "Attempting to reprint document",
62                         "Generic error",
63                         "Document has finished printing successfully",
64                         "Fatal error",
65                         "No local account, document not printed",
66                         "Error in document output filter",
67                         "Error accessing symlinked file"};
68
69static char *zerrtoken[]={"DEFER","IMPOSSIBLE","REPRINT","ERROR","OK",
70                          "FATALERR","NOACCT","FILTERERR","ACCESS"};
71
72#endif ZEPHYR
73
74
75char    title[80];              /* ``pr'' title */
76FILE    *cfp = NULL;            /* control file */
77int     pfd;                    /* printer file descriptor */
78int     ofd;                    /* output filter file descriptor */
79int     lfd = -1;               /* lock file descriptor */
80int     pid;                    /* pid of lpd process */
81int     prchild;                /* id of pr process */
82int     child;                  /* id of any filters */
83int     ofilter;                /* id of output filter, if any */
84int     tof;                    /* true if at top of form */
85int     remote;                 /* true if sending files to remote */
86dev_t   fdev;                   /* device of file pointed to by symlink */
87ino_t   fino;                   /* inode of file pointed to by symlink */
88
89char    fromhost[32];           /* user's host machine */
90#ifdef KERBEROS
91char    logname[ANAME_SZ + INST_SZ + REALM_SZ + 3];
92#else
93char    logname[32];            /* user's login name */
94#endif KERBEROS
95char    jobname[100];           /* job or file name */
96char    queuename[100];         /* print queue name */
97
98char    class[32];              /* classification field */
99char    width[10] = "-w";       /* page width in characters */
100char    length[10] = "-l";      /* page length in lines */
101char    pxwidth[10] = "-x";     /* page width in pixels */
102char    pxlength[10] = "-y";    /* page length in pixels */
103char    indent[10] = "-i0";     /* indentation size in characters */
104char    cost[10] = "-m";                /* Cost/page option */
105char    qacct[128] = "-a";
106char    tpfile[] = "errsXXXXXX"; /* file name for filter output */
107int     lflag;                  /* Log info flag */
108int     account_flag = 0;
109
110printjob()
111{
112         struct stat stb;
113
114         register struct queue_ *q, **qp;
115         struct queue_ **queue;
116         register int i, nitems;
117         long pidoff;
118         int count = 0;
119         extern int abortpr();
120
121         init();                                        /* set up capabilities */
122         (void) write(1, "", 1);                        /* ack that daemon is started */
123         setgid(getegid());
124         pid = getpid();                                /* for use with lprm */
125         setpgrp(0, pid);
126         signal(SIGHUP, abortpr);
127         signal(SIGINT, abortpr);
128         signal(SIGQUIT, abortpr);
129         signal(SIGTERM, abortpr);
130
131         (void) mktemp(tpfile);
132
133         /*
134          * uses short form file names
135          */
136         if (chdir(SD) < 0) {
137                 syslog(LOG_ERR, "%s: %m", SD);
138                 exit(1);
139         }
140         if (stat(LO, &stb) == 0 && (stb.st_mode & 0100))
141                 exit(0);               /* printing disabled */
142         lfd = open(LO, O_WRONLY|O_CREAT, 0644);
143         if (lfd < 0) {
144                 syslog(LOG_ERR, "%s: %s: %m", printer, LO);
145                 exit(1);
146         }
147         if (flock(lfd, LOCK_EX|LOCK_NB) < 0) {
148                 if (errno == EWOULDBLOCK)      /* active daemon present */
149                         exit(0);
150                 syslog(LOG_ERR, "%s: %s: %m", printer, LO);
151                 exit(1);
152         }
153         ftruncate(lfd, 0);
154         /*
155          * write process id for others to know
156          */
157         sprintf(line, "%u\n", pid);
158         pidoff = i = strlen(line);
159         if (write(lfd, line, i) != i) {
160                 syslog(LOG_ERR, "%s: %s: %m", printer, LO);
161                 exit(1);
162         }
163         /*
164          * search the spool directory for work and sort by queue order.
165          */
166         if ((nitems = getq_(&queue)) < 0) {
167                 syslog(LOG_ERR, "%s: can't scan %s", printer, SD);
168                 exit(1);
169         }
170         if (nitems == 0)               /* no work to do */
171           {
172             if (lflag) syslog(LOG_INFO, "No work on %s.", printer);
173             exit(0);
174           }
175         if (stb.st_mode & 01) {                /* reset queue flag */
176                 if (fchmod(lfd, stb.st_mode & 0776) < 0)
177                         syslog(LOG_ERR, "%s: %s: %m", printer, LO);
178         }
179         if(lflag) syslog("Opening printer on %s", printer);
180         openpr();                      /* open printer or remote */
181again:
182         /*
183          * we found something to do now do it --
184          *    write the name of the current control file into the lock file
185          *    so the spool queue program can tell what we're working on
186          */
187         if (lflag)syslog(LOG_INFO,"Got something to print..");
188         for (qp = queue; nitems--; free((char *) q)) {
189                 q = *qp++;
190                 if (stat(q->q_name, &stb) < 0) {
191                         continue;
192                     }
193         restart:
194                 (void) lseek(lfd, pidoff, 0);
195                 (void) sprintf(line, "%s\n", q->q_name);
196                 i = strlen(line);
197                 if (write(lfd, line, i) != i)
198                         syslog(LOG_ERR, "%s: %s: %m", printer, LO);
199                 if (!remote)
200                         i = printit(q->q_name);
201                 else
202                         i = sendit(q->q_name);
203                 /*
204                  * Check to see if we are supposed to stop printing or
205                  * if we are to rebuild the queue.
206                  */
207                 if (fstat(lfd, &stb) == 0) {
208                         /* stop printing before starting next job? */
209                         if (stb.st_mode & 0100)
210                                 goto done;
211                         /* rebuild queue (after lpc topq) */
212                         if (stb.st_mode & 01) {
213                                 for (free((char *) q); nitems--; free((char *) q))
214                                         q = *qp++;
215                                 if (fchmod(lfd, stb.st_mode & 0776) < 0)
216                                         syslog(LOG_WARNING, "%s: %s: %m",
217                                                 printer, LO);
218                                 break;
219                         }
220                         if (i == DEFER) {
221                                 if (fchmod(lfd, stb.st_mode | 001) < 0)
222                                         syslog(LOG_WARNING, "%s: %s: %m",
223                                                printer, LO);
224                                 continue;
225                         }
226                 }
227                 if (i == OK)           /* file ok and printed */
228                         count++;
229                 else if (i == REPRINT) { /* try reprinting the job */
230                         if (lflag)syslog(LOG_INFO, "restarting %s", printer);
231                         if (ofilter > 0) {
232                                 kill(ofilter, SIGCONT);        /* to be sure */
233                                 (void) close(ofd);
234                                 while ((i = wait(0)) > 0 && i != ofilter)
235                                         ;
236                                 ofilter = 0;
237                         }
238                         (void) close(pfd);     /* close printer */
239                         if (ftruncate(lfd, pidoff) < 0)
240                                 syslog(LOG_WARNING, "%s: %s: %m", printer, LO);
241                         openpr();              /* try to reopen printer */
242                         goto restart;
243                 }
244         }
245         free((char *) queue);
246         /*
247          * search the spool directory for more work.
248          */
249        if ((nitems = getq_(&queue)) < 0) {
250                syslog(LOG_ERR, "%s: can't scan %s", printer, SD);
251                exit(1);
252        }
253        if (nitems == 0) {              /* no more work to do */
254        done:
255                if (count > 0) {        /* Files actually printed */
256                        if (!SF && !tof)
257                                (void) write(ofd, FF, strlen(FF));
258                        if (TR != NULL)         /* output trailer */
259                                (void) write(ofd, TR, strlen(TR));
260                }
261                (void) UNLINK(tpfile);
262                exit(0);
263        }
264        goto again;
265}
266
267char    fonts[4][50];   /* fonts for troff */
268
269char ifonts[4][18] = {
270        "/usr/lib/vfont/R",
271        "/usr/lib/vfont/I",
272        "/usr/lib/vfont/B",
273        "/usr/lib/vfont/S"
274};
275
276/*
277 * The remaining part is the reading of the control file (cf)
278 * and performing the various actions.
279 */
280printit(file)
281        char *file;
282{
283        register int i;
284        char *cp;
285        int bombed = OK;
286
287        /*
288         * open control file; ignore if no longer there.
289         */
290        if ((cfp = fopen(file, "r")) == NULL) {
291                syslog(LOG_INFO, "%s: %s: %m", printer, file);
292                return(OK);
293        }
294        /*
295         * Try to lock control file.  If we fail, defer processing
296         * this file till later
297         */
298         if (!network && (flock(fileno(cfp), LOCK_EX|LOCK_NB) < 0)) {
299                 if (errno == EWOULDBLOCK) {
300                         /*
301                          * We couldn't get the lock.  Probably lprm
302                          * has locked it, in preparation for blowing
303                          * it away.  So we defer it till later;
304                          * usually it won't be there, but just in
305                          * case some other bozo locks the file....
306                          */
307                         fclose(cfp);
308                         cfp = NULL;
309                         return(DEFER);
310                 }
311                 syslog(LOG_ERR, "%s: %s: %m", printer, file);
312                 exit(1);
313         }
314       
315        /*
316         * Reset troff fonts.
317         */
318        for (i = 0; i < 4; i++)
319                strcpy(fonts[i], ifonts[i]);
320        sprintf(&width[2], "%d", PW);
321        strcpy(indent+2, "0");
322        qacct[2] = NULL;
323        jobname[0] = '\0';
324
325        /*
326         *      read the control file for work to do
327         *
328         *      file format -- first character in the line is a command
329         *      rest of the line is the argument.
330         *      valid commands are:
331         *
332         *              S -- "stat info" for symbolic link protection
333         *              J -- "job name" on banner page
334         *              C -- "class name" on banner page
335         *              L -- "literal" user's name to print on banner
336         *              T -- "title" for pr
337         *              H -- "host name" of machine where lpr was done
338         *              P -- "person" user's login name
339         *              W -- "width" width of page
340         *              I -- "indent" amount to indent output
341         *              f -- "file name" name of text file to print
342         *              l -- "file name" text file with control chars
343         *              p -- "file name" text file to print with pr(1)
344         *              t -- "file name" troff(1) file to print
345         *              n -- "file name" ditroff(1) file to print
346         *              d -- "file name" dvi file to print
347         *              g -- "file name" plot(1G) file to print
348         *              v -- "file name" plain raster file to print
349         *              c -- "file name" cifplot file to print
350         *              1 -- "R font file" for troff
351         *              2 -- "I font file" for troff
352         *              3 -- "B font file" for troff
353         *              4 -- "S font file" for troff
354         *              N -- "name" of file (used by lpq)
355         *              U -- "unlink" name of file to remove
356         *                    (after we print it. (Pass 2 only)).
357         *              M -- "mail" to user when done printing
358         *
359         *      Additions:
360         *              Z -- send zephyr message to user
361         *              Q -- Account number for quota management
362         *              q -- printer queue name
363         *      getline reads a line and expands tabs to blanks
364         */
365
366        /* pass 1 */
367
368        account_flag = 0;
369        while (getline(cfp))
370                switch (line[0]) {
371                case 'H':
372                        strcpy(fromhost, line+1);
373                        if (class[0] == '\0')
374                                strncpy(class, line+1, sizeof(class)-1);
375                        continue;
376
377                case 'P':
378                        strncpy(logname, line+1, sizeof(logname)-1);
379                        if (RS) {                       /* restricted */
380                                if (getpwnam(logname) == (struct passwd *)0) {
381                                        bombed = NOACCT;
382#ifdef ZEPHYR
383                                        sendzephyr(line+1, bombed);
384#else
385                                        sendmail(line+1, bombed);
386#endif ZEPHYR
387                                        goto pass2;
388                                }
389                        }
390                        continue;
391
392                case 'A':   /* For old client compatibility */
393                case 'Q':
394                        if (line[1] != '\0') {
395                            strcpy(&qacct[2], line+1);
396                            account_flag = 1;
397                        }
398                        continue;
399
400                case 'S':
401                        cp = line+1;
402                        i = 0;
403                        while (*cp >= '0' && *cp <= '9')
404                                i = i * 10 + (*cp++ - '0');
405                        fdev = i;
406                        cp++;
407                        i = 0;
408                        while (*cp >= '0' && *cp <= '9')
409                                i = i * 10 + (*cp++ - '0');
410                        fino = i;
411                        continue;
412
413                case 'J':
414                        if (line[1] != '\0')
415                                strncpy(jobname, line+1, sizeof(jobname)-1);
416                        else
417                                strcpy(jobname, " ");
418                        continue;
419
420                case 'C':
421                        if (line[1] != '\0')
422                                strncpy(class, line+1, sizeof(class)-1);
423                        else if (class[0] == '\0')
424                          {
425                                struct hostent *hp;
426                                gethostname(class, sizeof(class));
427                                hp = gethostbyname(class);
428                                if (hp) strcpy(class, hp -> h_name);
429                          }
430                        continue;
431
432                case 'T':       /* header title for pr */
433                        strncpy(title, line+1, sizeof(title)-1);
434                        continue;
435
436                case 'L':       /* identification line */
437                        if (!SH && !HL)
438                                banner(line+1, jobname);
439                        continue;
440
441                case '1':       /* troff fonts */
442                case '2':
443                case '3':
444                case '4':
445                        if (line[1] != '\0')
446                                strcpy(fonts[line[0]-'1'], line+1);
447                        continue;
448
449                case 'W':       /* page width */
450                        strncpy(width+2, line+1, sizeof(width)-3);
451                        continue;
452
453                case 'I':       /* indent amount */
454                        strncpy(indent+2, line+1, sizeof(indent)-3);
455                        continue;
456
457                default:        /* some file to print */
458                        switch (i = print(line[0], line+1)) {
459                        case ERROR:
460                                if (bombed == OK)
461                                        bombed = FATALERR;
462                                break;
463                        case REPRINT:
464                                (void) fclose(cfp);
465                                cfp = NULL;
466                               
467                                return(REPRINT);
468                        case FILTERERR:
469                        case ACCESS:
470                                bombed = i;
471#ifdef ZEPHYR
472                                sendzephyr(logname, bombed);
473#else
474                                sendmail(logname, bombed);
475#endif ZEPHYR
476                        }
477                        title[0] = '\0';
478                        continue;
479
480                case 'N':
481                case 'U':
482                case 'M':
483                case 'Z':
484                case 'E':       /* From multics days */
485                        continue;
486
487                case 'q':
488                        if (line[1]) {
489                            strncpy(queuename, line+1, sizeof(queuename)-1);
490                            printer = queuename;
491                        }
492                        continue;
493                }
494
495        /* pass 2 */
496
497pass2:
498        fseek(cfp, 0L, 0);
499        while (getline(cfp))
500                switch (line[0]) {
501                case 'L':       /* identification line */
502                        if (!SH && HL)
503                                banner(line+1, jobname);
504                        continue;
505
506                case 'M':
507                        if (bombed < NOACCT)    /* already sent if >= NOACCT */
508                                sendmail(line+1, bombed);
509                        continue;
510
511                case 'U':
512                        (void) UNLINK(line+1);
513                        continue;
514#ifdef ZEPHYR
515                case 'Z':
516                        if (bombed < NOACCT)    /* already sent if >= NOACCT */
517                                sendzephyr(line+1, bombed);
518                        continue;
519#endif ZEPHYR
520
521                }
522        /*
523         * clean-up in case another control file exists
524         */
525        (void) fclose(cfp);
526        cfp = NULL;
527        (void) UNLINK(file);
528        return(bombed == OK ? OK : ERROR);
529}
530
531/*
532 * Print a file.
533 * Set up the chain [ PR [ | {IF, OF} ] ] or {IF, RF, TF, NF, DF, CF, VF}.
534 * Return -1 if a non-recoverable error occured,
535 * 2 if the filter detected some errors (but printed the job anyway),
536 * 1 if we should try to reprint this job and
537 * 0 if all is well.
538 * Note: all filters take stdin as the file, stdout as the printer,
539 * stderr as the log file, and must not ignore SIGINT.
540 */
541print(format, file)
542        int format;
543        char *file;
544{
545        register int n;
546        register char *prog;
547        int fi, fo;
548        char *av[15], buf[BUFSIZ];
549        int pid, p[2], stopped = 0;
550#if defined(POSIX)
551        int status;
552#else
553        union wait status;
554#endif
555        struct stat stb;
556
557        if (lstat(file, &stb) < 0 || (fi = open(file, O_RDONLY)) < 0)
558                return(ERROR);
559        /*
560         * Check to see if data file is a symbolic link. If so, it should
561         * still point to the same file or someone is trying to print
562         * something he shouldn't.
563         */
564        if ((stb.st_mode & S_IFMT) == S_IFLNK && fstat(fi, &stb) == 0 &&
565            (stb.st_dev != fdev || stb.st_ino != fino))
566                return(ACCESS);
567        if (!SF && !tof) {              /* start on a fresh page */
568                (void) write(ofd, FF, strlen(FF));
569                tof = 1;
570        }
571        if (IF == NULL && (format == 'f' || format == 'l')) {
572                tof = 0;
573                while ((n = read(fi, buf, BUFSIZ)) > 0)
574                        if (write(ofd, buf, n) != n) {
575                                (void) close(fi);
576                                return(REPRINT);
577                        }
578                (void) close(fi);
579                return(OK);
580        }
581        switch (format) {
582        case 'p':       /* print file using 'pr' */
583                if (IF == NULL) {       /* use output filter */
584                        prog = PR;
585                        av[0] = "pr";
586                        av[1] = width;
587                        av[2] = length;
588                        av[3] = "-h";
589                        av[4] = *title ? title : " ";
590                        av[5] = 0;
591                        fo = ofd;
592                        goto start;
593                }
594                pipe(p);
595                if ((prchild = dofork(DORETURN)) == 0) {        /* child */
596                        dup2(fi, 0);            /* file is stdin */
597                        dup2(p[1], 1);          /* pipe is stdout */
598                        for (n = 3; n < NOFILE; n++)
599                                (void) close(n);
600                        execl(PR, "pr", width, length, "-h", *title ? title : " ", 0);
601                        syslog(LOG_ERR, "cannot execl %s", PR);
602                        exit(2);
603                }
604                (void) close(p[1]);             /* close output side */
605                (void) close(fi);
606                if (prchild < 0) {
607                        prchild = 0;
608                        (void) close(p[0]);
609                        return(ERROR);
610                }
611                fi = p[0];                      /* use pipe for input */
612        case 'f':       /* print plain text file */
613                prog = IF;
614                av[1] = width;
615                av[2] = length;
616                av[3] = indent;
617                n = 4;
618                break;
619        case 'l':       /* like 'f' but pass control characters */
620                prog = IF;
621                av[1] = "-c";
622                av[2] = width;
623                av[3] = length;
624                av[4] = indent;
625                n = 5;
626                break;
627        case 'r':       /* print a fortran text file */
628                prog = RF;
629                av[1] = width;
630                av[2] = length;
631                n = 3;
632                break;
633        case 't':       /* print troff output */
634        case 'n':       /* print ditroff output */
635        case 'd':       /* print tex output */
636                (void) UNLINK(".railmag");
637                if ((fo = creat(".railmag", FILMOD)) < 0) {
638                        syslog(LOG_ERR, "%s: cannot create .railmag", printer);
639                        (void) UNLINK(".railmag");
640                } else {
641                        for (n = 0; n < 4; n++) {
642                                if (fonts[n][0] != '/')
643                                        (void) write(fo, "/usr/lib/vfont/", 15);
644                                (void) write(fo, fonts[n], strlen(fonts[n]));
645                                (void) write(fo, "\n", 1);
646                        }
647                        (void) close(fo);
648                }
649                prog = (format == 't') ? TF : (format == 'n') ? NF : DF;
650                av[1] = pxwidth;
651                av[2] = pxlength;
652                n = 3;
653                break;
654        case 'c':       /* print cifplot output */
655                prog = CF;
656                av[1] = pxwidth;
657                av[2] = pxlength;
658                n = 3;
659                break;
660        case 'g':       /* print plot(1G) output */
661                prog = GF;
662                av[1] = pxwidth;
663                av[2] = pxlength;
664                n = 3;
665                break;
666        case 'v':       /* print raster output */
667                prog = VF;
668                av[1] = pxwidth;
669                av[2] = pxlength;
670                n = 3;
671                break;
672        default:
673                (void) close(fi);
674                syslog(LOG_ERR, "%s: illegal format character '%c'",
675                        printer, format);
676                return(ERROR);
677        }
678        if ((av[0] = rindex(prog, '/')) != NULL)
679                av[0]++;
680        else
681                av[0] = prog;
682        av[n++] = "-P";
683        av[n++] = printer;
684        av[n++] = "-n";
685        av[n++] = logname;
686        av[n++] = "-h";
687        av[n++] = fromhost;
688        av[n++] = cost;
689        if (account_flag)
690            av[n++] = qacct;
691        av[n++] = AF;
692        av[n] = 0;
693        fo = pfd;
694        if (ofilter > 0) {              /* stop output filter */
695                write(ofd, "\031\1", 2);
696#if defined(POSIX)
697                while ((pid = waitpid(-1,&status, WUNTRACED)) > 0 && pid != ofilter)
698#else
699                while ((pid = wait3(&status, WUNTRACED, 0)) > 0 && pid != ofilter)
700#endif
701                        ;
702                if (pid == -1 || !WIFSTOPPED(status)) {
703                        (void) close(fi);
704                        syslog(LOG_WARNING, "%s: output filter died (%d)",
705                                printer, status);
706                        return(REPRINT);
707                }
708                stopped++;
709        }
710start:
711        if ((child = dofork(DORETURN)) == 0) {  /* child */
712                dup2(fi, 0);
713                dup2(fo, 1);
714                n = open(tpfile, O_WRONLY|O_CREAT|O_TRUNC, 0664);
715                if (n >= 0)
716                        dup2(n, 2);
717                for (n = 3; n < NOFILE; n++)
718                        (void) close(n);
719                execv(prog, av);
720                syslog(LOG_ERR, "cannot execv %s", prog);
721                exit(2);
722        }
723        (void) close(fi);
724        if (child < 0)
725#if defined(POSIX)
726                status= 100;
727#else
728                status.w_retcode = 100;
729#endif
730        else
731                while ((pid = wait(&status)) > 0 && pid != child)
732                        ;
733        child = 0;
734        prchild = 0;
735        if (stopped) {          /* restart output filter */
736                if (kill(ofilter, SIGCONT) < 0) {
737                        syslog(LOG_ERR, "cannot restart output filter");
738                        exit(1);
739                }
740        }
741        tof = 0;
742#ifdef _AUX_SOURCE
743        /* WIFEXITED on the MAC with POSIX_SOURCE uses wrong macro */
744        if (!(((status).w_stopval != WSTOPPED && (status).w_termsig == 0))) {
745#else
746        if (!WIFEXITED(status)) {
747#endif
748                syslog(LOG_WARNING, "%s: Daemon filter '%c' terminated (%d)",
749                        printer, format, WTERMSIG(status));
750                return(ERROR);
751        }
752        switch (WEXITSTATUS(status)) {
753        case 0:
754                tof = 1;
755                return(OK);
756        case 1:
757                return(REPRINT);
758        default:
759                syslog(LOG_WARNING, "%s: Daemon filter '%c' exited (%d)",
760                        printer, format, WEXITSTATUS(status));
761        case 2:
762                return(ERROR);
763        }
764}
765
766/*
767 * Send the daemon control file (cf) and any data files.
768 * Return -1 if a non-recoverable error occured, 1 if a recoverable error and
769 * 0 if all is well.
770 */
771sendit(file)
772        char *file;
773{
774        register int i, err = OK;
775        char *cp, last[BUFSIZ];
776
777        /*
778         * open control file
779         */
780        if ((cfp = fopen(file, "r")) == NULL)
781                return(OK);
782        /*
783         *      read the control file for work to do
784         *
785         *      file format -- first character in the line is a command
786         *      rest of the line is the argument.
787         *      commands of interest are:
788         *
789         *            a-z -- "file name" name of file to print
790         *              U -- "unlink" name of file to remove
791         *                    (after we print it. (Pass 2 only)).
792         */
793
794        /*
795         * pass 1
796         */
797        while (getline(cfp)) {
798        again:
799                if (line[0] == 'S') {
800                        cp = line+1;
801                        i = 0;
802                        while (*cp >= '0' && *cp <= '9')
803                                i = i * 10 + (*cp++ - '0');
804                        fdev = i;
805                        cp++;
806                        i = 0;
807                        while (*cp >= '0' && *cp <= '9')
808                                i = i * 10 + (*cp++ - '0');
809                        fino = i;
810                        continue;
811                }
812                if (line[0] >= 'a' && line[0] <= 'z') {
813                        strcpy(last, line);
814                        while (i = getline(cfp))
815                                if (strcmp(last, line))
816                                        break;
817                        switch (sendfile('\3', last+1)) {
818                        case OK:
819                                if (i)
820                                        goto again;
821                                break;
822                        case REPRINT:
823                                (void) fclose(cfp);
824                                cfp = NULL;
825                                return(REPRINT);
826                        case ACCESS:
827#ifdef ZEPHYR
828                                sendmail(logname, ACCESS);
829#else
830                                sendzephyr(logname, ACCESS);
831#endif ZEPHYR
832                        case ERROR:
833                                err = ERROR;
834                        }
835                        break;
836                }
837        }
838        if (err == OK && sendfile('\2', file) > 0) {
839                (void) fclose(cfp);
840                cfp = NULL;
841                return(REPRINT);
842        }
843        /*
844         * pass 2
845         */
846        fseek(cfp, 0L, 0);
847        while (getline(cfp))
848                if (line[0] == 'U')
849                        (void) UNLINK(line+1);
850        /*
851         * clean-up in case another control file exists
852         */
853        (void) fclose(cfp);
854        cfp = NULL;
855        (void) UNLINK(file);
856        return(err);
857}
858
859/*
860 * Send a data file to the remote machine and spool it.
861 * Return positive if we should try resending.
862 */
863sendfile(type, file)
864        char type, *file;
865{
866        register int f, i, amt;
867        struct stat stb;
868        char buf[BUFSIZ];
869        int sizerr, resp;
870
871        if (lstat(file, &stb) < 0 || (f = open(file, O_RDONLY)) < 0)
872                return(ERROR);
873        /*
874         * Check to see if data file is a symbolic link. If so, it should
875         * still point to the same file or someone is trying to print something
876         * he shouldn't.
877         */
878        if ((stb.st_mode & S_IFMT) == S_IFLNK && fstat(f, &stb) == 0 &&
879            (stb.st_dev != fdev || stb.st_ino != fino))
880                return(ACCESS);
881        (void) sprintf(buf, "%c%d %s\n", type, stb.st_size, file);
882        amt = strlen(buf);
883        for (i = 0;  ; i++) {
884                if (write(pfd, buf, amt) != amt ||
885                    (resp = response()) < 0 || resp == '\1') {
886                        (void) close(f);
887                        return(REPRINT);
888                } else if (resp == '\0')
889                        break;
890                if (i == 0)
891                        status("no space on remote; waiting for queue to drain");
892                if (i == 10)
893                        syslog(LOG_ALERT, "%s: can't send to %s; queue full",
894                                printer, RM);
895                sleep(5 * 60);
896        }
897        if (i)
898                status("sending to %s", RM);
899        sizerr = 0;
900        for (i = 0; i < stb.st_size; i += BUFSIZ) {
901                amt = BUFSIZ;
902                if (i + amt > stb.st_size)
903                        amt = stb.st_size - i;
904                if (sizerr == 0 && read(f, buf, amt) != amt)
905                        sizerr = 1;
906                if (write(pfd, buf, amt) != amt) {
907                        (void) close(f);
908                        return(REPRINT);
909                }
910        }
911        (void) close(f);
912        if (sizerr) {
913                syslog(LOG_INFO, "%s: %s: changed size", printer, file);
914                /* tell recvjob to ignore this file */
915                (void) write(pfd, "\1", 1);
916                return(ERROR);
917        }
918        if (write(pfd, "", 1) != 1 || response())
919                return(REPRINT);
920        return(OK);
921}
922
923/*
924 * Check to make sure there have been no errors and that both programs
925 * are in sync with eachother.
926 * Return non-zero if the connection was lost.
927 */
928response()
929{
930        char resp;
931
932        if (read(pfd, &resp, 1) != 1) {
933                syslog(LOG_INFO, "%s: lost connection", printer);
934                return(-1);
935        }
936        return(resp);
937}
938
939/*
940 * Banner printing stuff
941 */
942banner(name1, name2)
943        char *name1, *name2;
944{
945        time_t tvec;
946        extern char *ctime();
947
948        time(&tvec);
949        if (!SF && !tof)
950                (void) write(ofd, FF, strlen(FF));
951        if (SB) {       /* short banner only */
952                if (class[0]) {
953                        (void) write(ofd, class, strlen(class));
954                        (void) write(ofd, ":", 1);
955                }
956                (void) write(ofd, name1, strlen(name1));
957                (void) write(ofd, "  Job: ", 7);
958                (void) write(ofd, name2, strlen(name2));
959                (void) write(ofd, "  Date: ", 8);
960                (void) write(ofd, ctime(&tvec), 24);
961                (void) write(ofd, "\n", 1);
962        } else {        /* normal banner */
963                (void) write(ofd, "\n\n\n", 3);
964                scan_out(ofd, name1, '\0');
965                (void) write(ofd, "\n\n", 2);
966                scan_out(ofd, name2, '\0');
967                if (class[0]) {
968                        register char *cp;
969                        (void) write(ofd,"\n\n\n",3);
970                        /* Take out domain names, if any */
971                        if (cp = index(class, '.')) *cp = '\0';
972                        scan_out(ofd, class, '\0');
973                }
974                (void) write(ofd, "\n\n\n\n\t\t\t\tJob:     ", 17);
975                (void) write(ofd, name2, strlen(name2));
976
977                (void) write(ofd, "\n\t\t\t\tUser:    ", 14);
978                if (logname[0]) (void) write (ofd, logname, strlen(logname));
979                else (void) write(ofd, name1, strlen(name1));
980
981                if (class[0] || fromhost[0]) {
982                        (void) write (ofd, "@", 1);
983                        if (fromhost[0]) {
984                                (void) write (ofd, fromhost, strlen(fromhost));
985                        }
986                        else {
987                                (void) write (ofd, class, strlen(class));
988                        }
989                }
990
991                (void) write(ofd, "\n\t\t\t\tDate:    ", 14);
992                (void) write(ofd, ctime(&tvec), 24);
993
994                if (printer != (char *) NULL && *printer != '\0') {
995                        (void) write (ofd, "\n\t\t\t\tPrinter: ", 14);
996                        (void) write (ofd, printer, strlen(printer));
997                        if (host != (char *) NULL && *host != '\0') {
998                                (void) write (ofd, " (on ", 5);
999                                (void) write (ofd, host, strlen(host));
1000                                (void) write (ofd, ")", 1);
1001                        }
1002                }
1003
1004                (void) write(ofd, "\n", 1);
1005        }
1006        if (!SF)
1007                (void) write(ofd, FF, strlen(FF));
1008        tof = 1;
1009}
1010
1011char *
1012scnline(key, p, c)
1013        register char key, *p;
1014        char c;
1015{
1016        register int scnwidth;
1017
1018        for (scnwidth = WIDTH; --scnwidth;) {
1019                key <<= 1;
1020                *p++ = key & 0200 ? c : BACKGND;
1021        }
1022        return (p);
1023}
1024
1025#define TRC(q)  (((q)-' ')&0177)
1026
1027scan_out(scfd, scsp, dlm)
1028        int scfd;
1029        char *scsp, dlm;
1030{
1031        register char *strp;
1032        register nchrs, j;
1033        char outbuf[LINELEN+1], *sp, c, cc;
1034        int d, scnhgt;
1035        extern char scnkey[][HEIGHT];   /* in lpdchar.c */
1036
1037        for (scnhgt = 0; scnhgt++ < HEIGHT+DROP; ) {
1038                strp = &outbuf[0];
1039                sp = scsp;
1040                for (nchrs = 0; ; ) {
1041                        d = dropit(c = TRC(cc = *sp++));
1042                        if ((!d && scnhgt > HEIGHT) || (scnhgt <= DROP && d))
1043                                for (j = WIDTH; --j;)
1044                                        *strp++ = BACKGND;
1045                        else
1046                                strp = scnline(scnkey[c][scnhgt-1-d], strp, cc);
1047                        if (*sp == dlm || *sp == '\0' || nchrs++ >= PW/(WIDTH+1)-1)
1048                                break;
1049                        *strp++ = BACKGND;
1050                        *strp++ = BACKGND;
1051                }
1052                while (*--strp == BACKGND && strp >= outbuf)
1053                        ;
1054                strp++;
1055                *strp++ = '\n';
1056                (void) write(scfd, outbuf, strp-outbuf);
1057        }
1058}
1059
1060dropit(c)
1061        char c;
1062{
1063        switch(c) {
1064
1065        case TRC('_'):
1066        case TRC(';'):
1067        case TRC(','):
1068        case TRC('g'):
1069        case TRC('j'):
1070        case TRC('p'):
1071        case TRC('q'):
1072        case TRC('y'):
1073                return (DROP);
1074
1075        default:
1076                return (0);
1077        }
1078}
1079
1080/*
1081 * sendmail ---
1082 *   tell people about job completion
1083 */
1084sendmail(user, bombed)
1085        char *user;
1086        int bombed;
1087{
1088        register int i;
1089        int p[2], s;
1090        register char *cp;
1091        char buf[100];
1092        struct stat stb;
1093        FILE *fp;
1094#ifdef ALLOW_MAIL
1095        pipe(p);
1096        if ((s = dofork(DORETURN)) == 0) {              /* child */
1097                dup2(p[0], 0);
1098                for (i = 3; i < NOFILE; i++)
1099                        (void) close(i);
1100                if ((cp = rindex(MAIL, '/')) != NULL)
1101                        cp++;
1102                else
1103                        cp = MAIL;
1104                sprintf(buf, "%s@%s", user, fromhost);
1105                execl(MAIL, cp, buf, 0);
1106                exit(0);
1107        } else if (s > 0) {                             /* parent */
1108                dup2(p[1], 1);
1109                printf("To: %s@%s\n", user, fromhost);
1110                printf("Subject: printer job\n\n");
1111                printf("Your printer job ");
1112                if (*jobname)
1113                        printf("(%s) ", jobname);
1114                switch (bombed) {
1115                case OK:
1116                        printf("\ncompleted successfully\n");
1117                        break;
1118                default:
1119                case FATALERR:
1120                        printf("\ncould not be printed\n");
1121                        break;
1122                case NOACCT:
1123                        printf("\ncould not be printed without an account on %s\n", host);
1124                        break;
1125                case FILTERERR:
1126                        if (stat(tpfile, &stb) < 0 || stb.st_size == 0 ||
1127                            (fp = fopen(tpfile, "r")) == NULL) {
1128                                printf("\nwas printed but had some errors\n");
1129                                break;
1130                        }
1131                        printf("\nwas printed but had the following errors:\n");
1132                        while ((i = getc(fp)) != EOF)
1133                                putchar(i);
1134                        (void) fclose(fp);
1135                        break;
1136                case ACCESS:
1137                        printf("\nwas not printed because it was not linked to the original file\n");
1138                }
1139                fflush(stdout);
1140                (void) close(1);
1141        }
1142        (void) close(p[0]);
1143        (void) close(p[1]);
1144        wait(&s);
1145#endif
1146}
1147
1148#ifdef ZEPHYR
1149sendzephyr(user, bombed)
1150char *user;
1151int bombed;
1152{
1153        notice.z_kind=UNACKED;
1154        notice.z_port=0;
1155        notice.z_class=ZCLASS;
1156        notice.z_class_inst=ZINSTANCE;
1157        notice.z_opcode="";
1158        notice.z_sender=ZSENDER;
1159        strcpy(zrecipient,logname);
1160        notice.z_recipient=zrecipient;
1161        notice.z_default_format=ZDEFAULTFORMAT;
1162        notice.z_num_other_fields=0;
1163
1164        if(*jobname)
1165            sprintf(zmessagetext,"Printer status for %s:\n\nJob name: %s\n%s",
1166                    printer,jobname,zerrtext[bombed+4]);
1167        else
1168            sprintf(zmessagetext,"Printer status for %s:\n\n%s",
1169                    printer,zerrtext[bombed+4]);
1170        zmessage[0]="Printer Daemon";
1171        zmessage[1]=zmessagetext;
1172        zmessage[2]=printer;
1173        zmessage[3]=line+1;
1174        zmessage[4]=zerrtext[bombed+4];
1175        zmessage[5]=zerrtoken[bombed+4];
1176
1177        if (zerrno=ZSendList(&notice,zmessage,6,ZNOAUTH))
1178                syslog(LOG_ERR,"Error sending zephyr notification: zerrno=%d",
1179                       zerrno);
1180}
1181#endif ZEPHYR
1182
1183       
1184/*
1185 * dofork - fork with retries on failure
1186 */
1187dofork(action)
1188        int action;
1189{
1190        register int i, pid;
1191
1192        for (i = 0; i < 20; i++) {
1193                if ((pid = fork()) < 0) {
1194                        sleep((unsigned)(i*i));
1195                        continue;
1196                }
1197                /*
1198                 * Child should run as daemon instead of root
1199                 */
1200                if (pid == 0)
1201                        setuid(DU);
1202                return(pid);
1203        }
1204        syslog(LOG_ERR, "can't fork");
1205
1206        switch (action) {
1207        case DORETURN:
1208                return (-1);
1209        default:
1210                syslog(LOG_ERR, "bad action (%d) to dofork", action);
1211                /*FALL THRU*/
1212        case DOABORT:
1213                exit(1);
1214        }
1215        /*NOTREACHED*/
1216}
1217
1218/*
1219 * Kill child processes to abort current job.
1220 */
1221abortpr()
1222{
1223        int     hard_kill();
1224       
1225        /* Drop the lock on the control file, if necessary */
1226        if (cfp)
1227                (void) fclose(cfp);
1228        /* Drop lock on lock file as well */
1229        if (lfd > 0)
1230                (void) close(lfd);
1231        (void) UNLINK(tpfile);
1232        kill(0, SIGINT);
1233        if (ofilter > 0)
1234                kill(ofilter, SIGCONT);
1235        signal(SIGALRM, hard_kill);
1236        alarm(30);
1237        while (wait(0) > 0)
1238                ;
1239        exit(0);
1240}
1241
1242hard_kill()
1243{
1244        kill(0, SIGKILL);
1245}
1246
1247init()
1248{
1249        int status;
1250
1251#ifdef HESIOD
1252        if ((status = pgetent(line, printer)) <= 0) {
1253                if (pralias(alibuf, printer))
1254                        printer = alibuf;
1255                if ((status = hpgetent(line, printer)) < 1)
1256                        fatal("unknown printer");
1257        }
1258#else
1259        if ((status = pgetent(line, printer)) < 0) {
1260                fatal("can't open printer description file");
1261        } else if (status == 0)
1262                fatal("unknown printer");
1263#endif HESIOD
1264        if ((LP = pgetstr("lp", &bp)) == NULL)
1265                LP = DEFDEVLP;
1266        if ((RP = pgetstr("rp", &bp)) == NULL)
1267                RP = DEFLP;
1268        if ((LO = pgetstr("lo", &bp)) == NULL)
1269                LO = DEFLOCK;
1270        if ((ST = pgetstr("st", &bp)) == NULL)
1271                ST = DEFSTAT;
1272        if ((LF = pgetstr("lf", &bp)) == NULL)
1273                LF = DEFLOGF;
1274        if ((SD = pgetstr("sd", &bp)) == NULL)
1275                SD = DEFSPOOL;
1276        if ((DU = pgetnum("du")) < 0)
1277                DU = DEFUID;
1278        if ((FF = pgetstr("ff", &bp)) == NULL)
1279                FF = DEFFF;
1280        if ((PW = pgetnum("pw")) < 0)
1281                PW = DEFWIDTH;
1282        sprintf(&width[2], "%d", PW);
1283        if ((PL = pgetnum("pl")) < 0)
1284                PL = DEFLENGTH;
1285        sprintf(&length[2], "%d", PL);
1286#ifdef PQUOTA
1287        if ((CP = pgetnum("pc")) < 0)
1288                CP = DEFPC;
1289        sprintf(&cost[2], "%d", CP);
1290#endif
1291        if ((PX = pgetnum("px")) < 0)
1292                PX = 0;
1293        sprintf(&pxwidth[2], "%d", PX);
1294        if ((PY = pgetnum("py")) < 0)
1295                PY = 0;
1296        sprintf(&pxlength[2], "%d", PY);
1297        RM = pgetstr("rm", &bp);
1298
1299
1300       /*
1301        * Figure out whether the local machine is the same as the remote
1302        * machine entry (if it exists).  If not, then ignore the local
1303        * queue information.
1304        */
1305
1306        if (RM != (char *) NULL) {
1307
1308               char name[255];
1309               struct hostent *hp;
1310
1311                       /* get the name of the local host */
1312               gethostname (name, sizeof(name) - 1);
1313               name[sizeof(name)-1] = '\0';
1314
1315                       /* get the network standard name of the local host */
1316               hp = gethostbyname (name);
1317               if (hp == (struct hostent *) NULL) {
1318                   printf ("unable to get hostname for local machine %s\n",
1319                               name);
1320               } else {
1321                        strcpy (name, hp->h_name);
1322
1323                        /* get the network standard name of RM */
1324                        hp = gethostbyname (RM);
1325                        if (hp == (struct hostent *) NULL) {
1326                          printf ("unable to get hostname for remote machine %s\n",
1327                                  RM);
1328                        }
1329                        /* if printer is not on local machine, ignore LP */
1330                        else if (strcasecmp(name, hp->h_name) != 0) *LP = '\0';
1331                      }
1332
1333             }
1334
1335     localcheck_done:
1336
1337        AF = pgetstr("af", &bp);
1338        OF = pgetstr("of", &bp);
1339        IF = pgetstr("if", &bp);
1340        RF = pgetstr("rf", &bp);
1341        TF = pgetstr("tf", &bp);
1342        NF = pgetstr("nf", &bp);
1343        DF = pgetstr("df", &bp);
1344        GF = pgetstr("gf", &bp);
1345        VF = pgetstr("vf", &bp);
1346        CF = pgetstr("cf", &bp);
1347        TR = pgetstr("tr", &bp);
1348        RS = pgetflag("rs");
1349        SF = pgetflag("sf");
1350        SH = pgetflag("sh");
1351        SB = pgetflag("sb");
1352        HL = pgetflag("hl");
1353        RW = pgetflag("rw");
1354        BR = pgetnum("br");
1355        if ((FC = pgetnum("fc")) < 0)
1356                FC = 0;
1357        if ((FS = pgetnum("fs")) < 0)
1358                FS = 0;
1359        if ((XC = pgetnum("xc")) < 0)
1360                XC = 0;
1361        if ((XS = pgetnum("xs")) < 0)
1362                XS = 0;
1363        tof = !pgetflag("fo");
1364}
1365
1366/*
1367 * Acquire line printer or remote connection.
1368 */
1369openpr()
1370{
1371        register int i, n;
1372        int resp;
1373
1374        if (lflag)syslog(LOG_INFO, "Opening printer (LP = \"%s\")", LP);
1375        if (*LP) {
1376                for (i = 1; ; i = i < 32 ? i << 1 : i) {
1377                        if (LP[0] == '@') {
1378                                pfd = tcp_conn(&LP[1]);
1379                                network = 1;
1380                        } else {
1381                                pfd = open(LP, RW ? O_RDWR : O_WRONLY);
1382                                network = 0;
1383                        }
1384                        if (lflag) syslog(LOG_INFO, "LP opened.");
1385                        if (pfd >= 0)
1386                                break;
1387                        if (errno == ENOENT) {
1388                                syslog(LOG_ERR, "%s: %m", LP);
1389                                exit(1);
1390                        }
1391                        else syslog(LOG_ERR, "%s: %m", LP);
1392                        if (i == 1)
1393                                status("waiting for %s (%s) to become ready (offline ?)", printer, LP);
1394                        sleep(i);
1395                }
1396                if (isatty(pfd))
1397                        setty();
1398                status("%s is ready and printing", printer);
1399                /*
1400                 * Start up an output filter, if needed.
1401                 */
1402                if (OF) {
1403                        int p[2];
1404                        char *cp;
1405                        if (lflag) syslog(LOG_INFO, "Starting filter on %s", LP);
1406
1407                        pipe(p);
1408                        if ((ofilter = dofork(DOABORT)) == 0) { /* child */
1409                                dup2(p[0], 0);          /* pipe is std in */
1410                                dup2(pfd, 1);           /* printer is std out */
1411                                for (i = 3; i < NOFILE; i++)
1412                                        (void) close(i);
1413                                if ((cp = rindex(OF, '/')) == NULL)
1414                                  cp = OF;
1415                                else   
1416                                  cp++;
1417                                execl(OF, cp, width, length,
1418                                      "-P", printer,
1419                                      0);
1420                                syslog(LOG_ERR, "%s: %s: %m", printer, OF);
1421                                exit(1);
1422                              }
1423                        (void) close(p[0]);             /* close input side */
1424                        ofd = p[1];                     /* use pipe for output */
1425                      } else {
1426                        ofd = pfd;
1427                        ofilter = 0;
1428                      }
1429
1430        } else if (RM != NULL) {
1431                if (lflag) syslog(LOG_INFO, "Connecting to %s..", RM);
1432                for (i = 1; ; i = i < 256 ? i << 1 : i) {
1433                        resp = -1;
1434                        pfd = getport(RM);
1435                        if (pfd >= 0) {
1436                                (void) sprintf(line, "\2%s\n", RP);
1437                                n = strlen(line);
1438                                if (write(pfd, line, n) == n &&
1439                                    (resp = response()) == '\0')
1440                                        break;
1441                                (void) close(pfd);
1442                        }
1443                        if (i == 1) {
1444                                if (resp < 0)
1445                                        status("waiting for %s to come up", RM);
1446                                else {
1447                                        status("waiting for queue to be enabled on %s", RM);
1448                                        i = 256;
1449                                }
1450                        }
1451                        sleep(i);
1452                }
1453                if (lflag) syslog(LOG_INFO, "Sending to %s..", RM);
1454                status("sending to %s", RM);
1455                remote = 1;
1456                ofd = pfd;
1457                ofilter = 0;
1458        } else {
1459                syslog(LOG_ERR, "%s: no line printer device or host name",
1460                        printer);
1461                exit(1);
1462        }
1463}
1464
1465struct bauds {
1466        int     baud;
1467        int     speed;
1468} bauds[] = {
1469        50,     B50,
1470        75,     B75,
1471        110,    B110,
1472        134,    B134,
1473        150,    B150,
1474        200,    B200,
1475        300,    B300,
1476        600,    B600,
1477        1200,   B1200,
1478        1800,   B1800,
1479        2400,   B2400,
1480        4800,   B4800,
1481        9600,   B9600,
1482        19200,  EXTA,
1483        38400,  EXTB,
1484        0,      0
1485};
1486
1487/*
1488 * setup tty lines.
1489 */
1490setty()
1491{
1492#ifndef POSIX
1493        struct sgttyb ttybuf;
1494#else
1495        struct termios ttybuf;
1496#endif
1497        register struct bauds *bp;
1498
1499#ifndef POSIX
1500        /* I cannot determine if under AUX you can open a line exclusively */
1501        if (ioctl(pfd, TIOCEXCL, (char *)0) < 0) {
1502                syslog(LOG_ERR, "%s: ioctl(TIOCEXCL): %m", printer);
1503                exit(1);
1504        }
1505#endif
1506#ifndef POSIX
1507        if (ioctl(pfd, TIOCGETP, (char *)&ttybuf) < 0) {
1508                syslog(LOG_ERR, "%s: ioctl(TIOCGETP): %m", printer);
1509                exit(1);
1510        }
1511#else
1512        if (tcgetattr(pfd, &ttybuf) < 0) {
1513                syslog(LOG_ERR, "%s: tcgetattr: %m", printer);
1514                exit(1);
1515        }
1516#endif
1517        if (BR > 0) {
1518                for (bp = bauds; bp->baud; bp++)
1519                        if (BR == bp->baud)
1520                                break;
1521                if (!bp->baud) {
1522                        syslog(LOG_ERR, "%s: illegal baud rate %d", printer, BR);
1523                        exit(1);
1524                }
1525#ifndef POSIX
1526                ttybuf.sg_ispeed = ttybuf.sg_ospeed = bp->speed;
1527#else
1528                ttybuf.c_cflag &= ~CBAUD;
1529                ttybuf.c_cflag |= bp->speed;
1530                if (XC) ttybuf.c_lflag &= ~XC;
1531                if (XS) ttybuf.c_lflag |=  XS;
1532#endif
1533        }
1534#ifndef POSIX
1535        ttybuf.sg_flags &= ~FC;
1536        ttybuf.sg_flags |= FS;
1537        if (ioctl(pfd, TIOCSETP, (char *)&ttybuf) < 0) {
1538                syslog(LOG_INFO, "SETP failed..");
1539                syslog(LOG_ERR, "%s: ioctl(TIOCSETP): %m", printer);
1540                exit(1);
1541        }
1542#else
1543        ttybuf.c_cflag &= ~FC;
1544        ttybuf.c_cflag |= FS;
1545        if (tcsetattr(pfd, TCSANOW,&ttybuf) < 0) {
1546                syslog(LOG_INFO, "tcsetattr failed..");
1547                syslog(LOG_ERR, "%s: tcsetattr: %m", printer);
1548                exit(1);
1549        }
1550#endif /* POSIX */
1551#ifndef POSIX
1552        /* AUX does not appear to have old/new line disciplines that
1553           do anything */
1554        if (XC || XS) {
1555                int ldisc = NTTYDISC;
1556
1557                if (ioctl(pfd, TIOCSETD, &ldisc) < 0) {
1558                        syslog(LOG_ERR, "%s: ioctl(TIOCSETD): %m", printer);
1559                        exit(1);
1560                }
1561        }
1562        /* For AUX, XC and XS handled above */
1563        if (XC) {
1564                if (ioctl(pfd, TIOCLBIC, &XC) < 0) {
1565                        syslog(LOG_ERR, "%s: ioctl(TIOCLBIC): %m", printer);
1566                        exit(1);
1567                }
1568        }
1569
1570        if (XS) {
1571                if (ioctl(pfd, TIOCLBIS, &XS) < 0) {
1572                        syslog(LOG_ERR, "%s: ioctl(TIOCLBIS): %m", printer);
1573                        exit(1);
1574                }
1575        }
1576#endif
1577}
1578
1579/*VARARGS1*/
1580status(msg, a1, a2, a3)
1581        char *msg;
1582{
1583        register int fd;
1584        char buf[BUFSIZ];
1585
1586        umask(0);
1587        fd = open(ST, O_WRONLY|O_CREAT, 0664);
1588        if (fd < 0 || flock(fd, LOCK_EX) < 0) {
1589                syslog(LOG_ERR, "%s: %s: %m", printer, ST);
1590                exit(1);
1591        }
1592        ftruncate(fd, 0);
1593        sprintf(buf, msg, a1, a2, a3);
1594        strcat(buf, "\n");
1595        (void) write(fd, buf, strlen(buf));
1596        (void) close(fd);
1597}
Note: See TracBrowser for help on using the repository browser.