source: trunk/athena/bin/lpr/printjob.c @ 5305

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