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

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