source: trunk/athena/bin/lpr/recvjob.c @ 11777

Revision 11777, 20.1 KB checked in by danw, 26 years ago (diff)
``Hey Rocky! Watch me pull a working patch for recvjob.c out of my hat!'' ``But that trick _never_ works!'' ``This time for sure!'' (tested by nathanw. *sigh*)
Line 
1/*
2 * Copyright (c) 1983 Regents of the University of California.
3 * All rights reserved.  The Berkeley software License Agreement
4 * specifies the terms and conditions for redistribution.
5 */
6
7#ifndef lint
8static char sccsid[] = "@(#)recvjob.c   5.4 (Berkeley) 6/6/86";
9static char *rcsid_recvjob_c = "$Id: recvjob.c,v 1.20 1998-07-20 16:04:07 danw Exp $";
10#endif
11
12/*
13 * Receive printer jobs from the network, queue them and
14 * start the printer daemon.
15 */
16
17#include "lp.h"
18#include <limits.h>
19
20#ifdef _AUX_SOURCE
21#include <sys/sysmacros.h>
22#include <ufs/ufsparam.h>
23#endif
24
25#if defined(SYSV)
26#define USE_USTAT
27#include <ustat.h>
28#else
29#ifdef __NetBSD__
30#include <ufs/ufs/dinode.h>
31#include <ufs/ffs/fs.h>
32#else
33#include <ufs/fs.h>
34#endif
35#endif
36
37#ifdef PQUOTA
38#include "quota.h"
39#include <time.h>
40#include <sys/time.h>
41#endif
42
43#ifdef _IBMR2
44#include <sys/select.h>
45#endif
46
47#if BUFSIZ != 1024
48#undef BUFSIZ
49#define BUFSIZ 1024
50#endif
51
52char    *sp = "";
53#define ack()   (void) write(1, sp, 1);
54
55int     lflag;                  /* should we log a trace? */
56char    tfname[40];             /* tmp copy of cf before linking */
57char    dfname[40];             /* data files */
58char    cfname[40];             /* control fle - fix compiler bug */
59int     minfree;                /* keep at least minfree blocks available */
60
61#ifdef USE_USTAT
62dev_t   ddev;                   /* disk device (for checking free space) */
63#else
64char    *ddev;                  /* disk device (for checking free space) */
65int     dfd;                    /* file system device descriptor */
66#endif
67
68#ifdef KERBEROS
69char    tempfile[40];           /* Same size as used for cfname and tfname */
70extern int kflag;
71#endif
72
73#ifdef _AUX_SOURCE
74/* They defined fds_bits correctly, but lose by not defining this */
75#define FD_ZERO(p)  ((p)->fds_bits[0] = 0)
76#define FD_SET(n, p)   ((p)->fds_bits[0] |= (1 << (n)))
77#define FD_ISSET(n, p)   ((p)->fds_bits[0] & (1 << (n)))
78#endif
79
80char    *find_dev();
81
82recvjob()
83{
84        struct stat stb;
85        char *bp = pbuf;
86        int status, rcleanup();
87        void *old_term, *old_pipe;
88
89        /*
90         * Perform lookup for printer name or abbreviation
91         */
92        if(lflag) syslog(LOG_INFO, "in recvjob");
93#ifdef HESIOD
94        if ((status = pgetent(line, printer)) <= 0) {
95                if (pralias(alibuf, printer))
96                        printer = alibuf;
97                if ((status = hpgetent(line, printer)) < 1)
98                        frecverr("unknown printer %s", printer);
99        }
100#else
101        if ((status = pgetent(line, printer)) < 0) {
102                frecverr("cannot open printer description file");
103        }
104        else if (status == 0)
105                frecverr("unknown printer %s", printer);
106#endif
107        if ((LF = pgetstr("lf", &bp)) == NULL)
108                LF = DEFLOGF;
109        if ((SD = pgetstr("sd", &bp)) == NULL)
110                SD = DEFSPOOL;
111        if ((LO = pgetstr("lo", &bp)) == NULL)
112                LO = DEFLOCK;
113
114        if (((RM = pgetstr("rm", &bp)) != NULL) && strcasecmp(RM, host)) {
115#ifdef KERBEROS
116                if (require_kerberos(printer) > 0)
117                       /* They are not for you */
118                       frecverr("%s: cannot forward to kerberized spooler",
119                                printer);
120#endif KERBEROS
121                SD = DEFSPOOL;
122        }
123
124#ifdef PQUOTA
125        RQ = pgetstr("rq", &bp);
126        QS = pgetstr("qs", &bp);
127#endif
128#ifdef LACL
129        AC = pgetstr("ac", &bp);
130        PA = pgetflag("pa");
131        RA = pgetflag("ra");
132#endif
133
134        (void) close(2);                        /* set up log file */
135        if (open(LF, O_WRONLY|O_APPEND, 0664) < 0) {
136                syslog(LOG_ERR, "%s: %m", LF);
137                (void) open("/dev/null", O_WRONLY);
138        }
139
140        if (chdir(SD) < 0)
141                frecverr("%s: %s: %m", printer, SD);
142        if (stat(LO, &stb) == 0) {
143                if (stb.st_mode & 010) {
144                        /* queue is disabled */
145                        putchar('\1');          /* return error code */
146                        exit(1);
147                }
148        } else if (stat(SD, &stb) < 0)
149                frecverr("%s: %s: %m", printer, SD);
150        minfree = read_number("minfree");
151
152#ifdef USE_USTAT
153        ddev = stb.st_dev;
154#else
155        ddev = find_dev(stb.st_dev, S_IFBLK);
156        if ((dfd = open(ddev, O_RDONLY)) < 0)
157                syslog(LOG_WARNING, "%s: %s: %m", printer, ddev);
158#endif
159
160
161        old_term = signal(SIGTERM, rcleanup);
162        old_pipe = signal(SIGPIPE, rcleanup);
163
164        if(lflag) syslog(LOG_INFO, "Reading job");
165
166        if (readjob())
167          {
168            signal(SIGTERM, old_term);
169            signal(SIGPIPE, old_pipe);
170
171            if (lflag) syslog(LOG_INFO, "Printing job..");
172
173            printjob();
174          }
175       
176}
177
178#ifndef USE_USTAT
179char *
180find_dev(dev, type)
181        register dev_t dev;
182        register int type;
183{
184        register DIR *dfd = opendir("/dev");
185#ifdef POSIX
186        struct dirent *dir;
187#else
188        struct direct *dir;
189#endif
190        struct stat stb;
191        char devname[MAXNAMLEN+6];
192        char *dp;
193
194        strcpy(devname, "/dev/");
195        while ((dir = readdir(dfd))) {
196                strcpy(devname + 5, dir->d_name);
197                if (stat(devname, &stb))
198                        continue;
199                if ((stb.st_mode & S_IFMT) != type)
200                        continue;
201                if (dev == stb.st_rdev) {
202                        closedir(dfd);
203                        dp = (char *)malloc(strlen(devname)+1);
204                        if (!dp)
205                                frecverr("out of memory while finding device %d, %d", major(dev), minor(dev));
206                        strcpy(dp, devname);
207                        return(dp);
208                }
209        }
210        closedir(dfd);
211        frecverr("cannot find device %d, %d", major(dev), minor(dev));
212        /*NOTREACHED*/
213}
214#endif /* USE_USTAT */
215
216/* Compute the next job number */
217jobnum()
218{
219    FILE *jfp;
220    int job = 0;
221
222    jfp = fopen(".seq", "r");
223    if (jfp) {
224      fscanf(jfp, "%d", &job);
225      job = (job+1) % 1000;
226      fclose(jfp);
227    }
228
229    jfp = fopen(".seq", "w");
230    if (jfp) {
231      fprintf(jfp, "%d\n", job);
232      fclose(jfp);
233    }
234    return job;
235}
236
237/*
238 * Read printer jobs sent by lpd and copy them to the spooling directory.
239 * Return the number of jobs successfully transfered.
240 */
241readjob()
242{
243        register int size, nfiles;
244        int n, toobig;
245        register char *cp;
246#if defined(PQUOTA) || defined(LACL)
247        char *cret;
248#endif
249#ifdef PQUOTA
250        char *check_quota();
251#endif
252#ifdef LACL
253        char *check_lacl(), *check_remhost();
254#endif
255
256        if (lflag) syslog(LOG_INFO, "In readjob");
257
258        ack();
259        nfiles = 0;
260        for (;;) {
261                /*
262                 * Read a command to tell us what to do
263                 */
264                cp = line;
265                n = 0;
266                toobig = 0;
267                do {
268                        if (++n >= sizeof(line)) {
269                                frecverr("%s: line too long", printer);
270                                return(nfiles);
271                        }
272                        if ((size = read(1, cp, 1)) != 1) {
273                                if (size < 0)
274                                        frecverr("%s: Lost connection",printer);
275                                if (lflag) syslog(LOG_INFO, "Returning from readjobs");
276                                return(nfiles);
277                        }
278                } while (*cp++ != '\n');
279                *--cp = '\0';
280                cp = line;
281                switch (*cp++) {
282                case '\1':      /* cleanup because data sent was bad */
283                        rcleanup();
284                        continue;
285
286                case '\2':      /* read cf file */
287                        size = 0;
288                        while (*cp >= '0' && *cp <= '9') {
289                                if (size > INT_MAX/10)
290                                        toobig = 1;
291                                size = size * 10 + (*cp++ - '0');
292                        }
293                        if (*cp++ != ' ' || toobig)
294                                break;
295
296                        if (!isalnum(cp[0]) || !isalnum(cp[1]) ||
297                            !isalnum(cp[2]) || !isalnum(cp[3]) ||
298                            !isalnum(cp[4]) || !isalnum(cp[5])) {
299                                syslog(LOG_ERR,
300                           "unexpected job character in cf %d.%d.%d.%d.%d.%d",
301                                       cp[0], cp[1], cp[2], cp[3],
302                                       cp[4], cp[5]);
303                                break;
304                        }
305                        if (cp[0] != 'c' || cp[1] != 'f' ||
306                            cp[2] != 'A' || !isxdigit(cp[3]) ||
307                            !isxdigit(cp[4]) || !isxdigit(cp[5])) {
308                                syslog(LOG_NOTICE,
309                           "nonstandard job character in cf %d.%d.%d.%d.%d.%d",
310                                       cp[0], cp[1], cp[2], cp[3],
311                                       cp[4], cp[5]);
312                        }
313
314                        /* Compute local filenames. */
315                        sprintf(cfname, "cfA%03d%s", jobnum(), from);
316                        strncpy(tfname, cp, sizeof(tfname));
317                        tfname[sizeof(tfname) - 1] = '\0';
318                        if (strchr(cfname, '/') || strchr(tfname, '/'))
319                          {
320                            syslog(LOG_ERR,
321                                   "/ found in control or temporary file name");
322                            break;
323                          }
324                        tfname[0] = 't';
325#ifdef KERBEROS
326                        strcpy(tempfile, tfname);
327                        tempfile[0] = 'T';
328#endif
329                        if (!chksize(size)) {
330                                (void) write(1, "\2", 1);
331                                continue;
332                        }
333                           
334                        /* Don't send final acknowledge beacuse we may wish to
335                           send error below */
336                        if (!readfile(tfname, size, 0, 't')) {
337                            syslog(LOG_DEBUG, "Failed read");
338                                rcleanup();
339                                continue;
340                        }
341
342                        if (!fixup_cf(tfname, tempfile)) {
343                                rcleanup();
344                                continue;
345                        }
346
347#ifdef LACL
348                        if(RA && ((cret = check_remhost()) != 0)) {
349                            (void) write(1, cret, 1);
350                            rcleanup();
351                            continue;
352                        }
353
354                        if(AC && (cret = check_lacl(tfname)) != 0) {
355                            /* We return !=0 for error. Old clients stupidly
356                             * don't print any error in this situation.
357                             * We do a cleanup cause we can't expect
358                             * client to do so. */
359                            (void) write(1, cret, 1);
360#ifdef DEBUG
361                            syslog(LOG_DEBUG, "Got %s", cret);
362#endif
363                            rcleanup();
364                            continue;
365                        }
366#endif /*LACL*/
367
368#ifdef PQUOTA
369                        if(kerberos_cf && (RQ != NULL) &&
370                           (cret = check_quota(tfname)) != 0) {
371                            /* We return !=0 for error. Old clients
372                               stupidly don't print any error in this sit.
373                               We do a cleanup cause we can't expect
374                               client to do so. */
375                            (void) write(1, cret, 1);
376#ifdef DEBUG
377                            syslog(LOG_DEBUG, "Got %s", cret);
378#endif
379                            rcleanup();
380                            continue;
381                        }
382#endif /* PQUOTA */
383
384                        /* Send acknowldege, cause we didn't before */
385                        ack();
386
387                        if (link(tfname, cfname) < 0)
388                                frecverr("%s: %m", tfname);
389
390                        (void) spool_unlink(tfname, 't', 1); 
391                        tfname[0] = '\0';
392                        nfiles++;
393                        continue;
394
395                case '\3':      /* read df file */
396                        size = 0;
397                        while (*cp >= '0' && *cp <= '9') {
398                                if (size > INT_MAX/10) toobig = 1;
399                                size = size * 10 + (*cp++ - '0');
400                        }
401                        if (*cp++ != ' ' || toobig)
402                                break;
403
404                        if (!isalnum(cp[0]) || !isalnum(cp[1]) ||
405                            !isalnum(cp[2]) || !isalnum(cp[3]) ||
406                            !isalnum(cp[4]) || !isalnum(cp[5])) {
407                                syslog(LOG_ERR,
408                           "unexpected job character in df %d.%d.%d.%d.%d.%d",
409                                       cp[0], cp[1], cp[2], cp[3],
410                                       cp[4], cp[5]);
411                                break;
412                        }
413                        if (cp[0] != 'd' || cp[1] != 'f' ||
414                            cp[2] != 'A' || !isxdigit(cp[3]) ||
415                            !isxdigit(cp[4]) || !isxdigit(cp[5])) {
416                                syslog(LOG_NOTICE,
417                           "nonstandard job character in df %d.%d.%d.%d.%d.%d",
418                                       cp[0], cp[1], cp[2], cp[3],
419                                       cp[4], cp[5]);
420                        }
421
422                        if (!chksize(size)) {
423                                (void) write(1, "\2", 1);
424                                continue;
425                        }
426
427                        (void) strncpy(dfname, cp, sizeof(dfname));
428                        dfname[sizeof(dfname) - 1] = '\0';
429                        if (strchr(dfname, '/'))
430                                frecverr("illegal path name");
431                        (void) readfile(dfname, size, 1, 'd');
432                        continue;
433                }
434                frecverr("protocol screwup");
435        }
436}
437
438/*
439 * Read files send by lpd and copy them to the spooling directory.
440 */
441readfile(file, size, acknowledge, flag)
442        char *file;
443        int size;
444        int acknowledge;
445        int flag;
446{
447        register char *cp;
448        char buf[BUFSIZ];
449        register int i, j, amt;
450        int fd, err;
451
452        fd = open(file, O_WRONLY|O_CREAT, FILMOD);
453        if (fd < 0)
454                frecverr("%s: %m", file);
455        ack();
456        err = 0;
457        for (i = 0; i < size; i += BUFSIZ) {
458                amt = BUFSIZ;
459                cp = buf;
460                if (i + amt > size)
461                        amt = size - i;
462                do {
463                        j = read(1, cp, amt);
464                        if (j <= 0)
465                                frecverr("Lost connection");
466                        amt -= j;
467                        cp += j;
468                } while (amt > 0);
469                amt = BUFSIZ;
470                if (i + amt > size)
471                        amt = size - i;
472                if (write(fd, buf, amt) != amt) {
473                        err++;
474                        break;
475                }
476        }
477        (void) close(fd);
478        if (err)
479                frecverr("%s: write error", file);
480        if (noresponse()) {             /* file sent had bad data in it */
481                (void) spool_unlink(file, flag, 1);
482                return(0);     
483            }
484        if(acknowledge)
485            ack();
486
487        return(1);
488}
489
490fixup_cf(file, tfile)
491char *file, *tfile;
492{
493        FILE *cfp, *tfp;
494        char kname[ANAME_SZ + INST_SZ + REALM_SZ + 3];
495        char oldname[ANAME_SZ + INST_SZ + REALM_SZ + 3];
496
497        oldname[0] = '\0';
498
499        /* Form a complete string name consisting of principal,
500         * instance and realm
501         */
502        make_kname(kprincipal, kinstance, krealm, kname);
503
504        /* If we cannot open tf file, then return error */
505        if ((cfp = fopen(file, "r")) == NULL)
506                return (0);
507
508        /* Read the control file for the person sending the job */
509        while (getline(cfp)) {
510                if (line[0] == 'P') {
511                        strncpy(oldname, line+1, sizeof(oldname)-1);
512                        break;
513                }
514        }
515        fclose(cfp);
516
517        /* Have we got a name in oldname, if not, then return error */
518        if (oldname[0] == '\0')
519                return(0);
520
521        /* Does kname match oldname. If so do nothing */
522        if (!strcmp(kname, oldname))
523                return(1); /* all a-okay */
524
525        /* hmm, doesnt match, guess we have to change the name in
526         * the control file by doing the following :
527         *
528         * (1) Move 'file' to 'tfile'
529         * (2) Copy all of 'tfile' back to 'file' but
530         *     changing the persons name
531         */
532        if (link(file, tfile) < 0)
533                return(0);
534        (void) spool_unlink(file, 't', 1);
535
536        /* If we cannot open tf file, then return error */
537        if ((tfp = fopen(tfile, "r")) == NULL)
538                return (0);
539        if ((cfp = fopen(file, "w")) == NULL) {
540                (void) fclose(tfp);
541                return (0);
542        }
543
544        while (getline(tfp)) {
545                /* Ignore any queue name that was specified in the original
546                 * .cf file -- we'll be adding it in shortly...
547                 */
548                if (line[0] == 'q') continue;
549
550#ifdef KERBEROS
551                if (kerberos_cf) {
552                    if (line[0] == 'P')
553                        strcpy(&line[1], kname);
554                    else if (line[0] == 'L')
555                        strcpy(&line[1], kname);
556                }
557#endif
558                fprintf(cfp, "%s\n", line);
559
560        }
561        fprintf(cfp, "q%s\n", printer);
562
563        (void) fclose(cfp);
564        (void) fclose(tfp);
565        (void) spool_unlink(tfile, 'T', 1);
566
567        return(1);
568}
569
570noresponse()
571{
572        char resp;
573
574        if (read(1, &resp, 1) != 1)
575                frecverr("Lost connection");
576        if (resp == '\0')
577                return(0);
578        return(1);
579}
580
581/*
582 * Check to see if there is enough space on the disk for size bytes.
583 * 1 == OK, 0 == Not OK.
584 */
585chksize(size)
586        int size;
587{
588#ifdef USE_USTAT
589        struct ustat ubuf;
590
591        if (ustat(ddev, &ubuf)) return 1;
592        size = (size+1023)/1024;
593        if (minfree + size > ubuf.f_tfree) return 0;
594        return 1;
595#else
596        int spacefree;
597        struct fs fs;
598
599        if (dfd < 0 || lseek(dfd, (long)(SBLOCK * DEV_BSIZE), 0) < 0)
600                return(1);
601        if (read(dfd, (char *)&fs, sizeof fs) != sizeof fs)
602                return(1);
603        spacefree = (fs.fs_cstotal.cs_nbfree * fs.fs_frag +
604                fs.fs_cstotal.cs_nffree - fs.fs_dsize * fs.fs_minfree / 100) *
605                        fs.fs_fsize / 1024;
606        size = (size + 1023) / 1024;
607        if (minfree + size > spacefree)
608                return(0);
609        return(1);
610#endif
611}
612
613read_number(fn)
614        char *fn;
615{
616        char lin[80];
617        register FILE *fp;
618
619        if ((fp = fopen(fn, "r")) == NULL)
620                return (0);
621        if (fgets(lin, 80, fp) == NULL) {
622                fclose(fp);
623                return (0);
624        }
625        fclose(fp);
626        return (atoi(lin));
627}
628
629/*
630 * Remove all the files associated with the current job being transfered.
631 */
632rcleanup()
633{
634
635        /* This was cretinous code.. which regularly walked off the end
636         * of the name space...  I changed the != to a >=..
637         */
638
639        if (tfname[0])
640                (void) spool_unlink(tfname, 't', 1);
641#ifdef KERBEROS
642        if (tempfile[0])
643                (void) spool_unlink(tempfile, 'T', 1);
644#endif
645        if (dfname[0])
646                do {
647                        do
648                                if ((spool_unlink(dfname, 'd', 0)) == -2)
649                                        return;
650                        while (dfname[2]-- >= 'A');
651                        dfname[2] = 'z';
652                } while (dfname[0]-- >= 'd');
653        dfname[0] = '\0';
654}
655
656/* VARARGS1 */
657frecverr(msg, a1, a2)
658        char *msg;
659{
660        rcleanup();
661        syslog(LOG_ERR, msg, a1, a2);
662        putchar('\1');          /* return error code */
663        exit(1);
664}
665
666#ifdef PQUOTA
667
668char* check_quota(file)
669char file[];
670    {
671        struct hostent *hp;
672        char outbuf[BUFSIZ], inbuf[BUFSIZ];
673        int t, act=0, s1;
674        FILE *cfp;
675        struct sockaddr_in sin_c;
676        int fd, retry;
677        struct servent *servname;
678        struct timeval tp;
679        fd_set set;
680
681        if(RQ == NULL)
682            return 0;
683        if((hp = gethostbyname(RQ)) == NULL) {
684            syslog(LOG_WARNING, "Cannot resolve quota servername %s", RQ);
685            return 0;
686        }
687
688        /* Setup output buffer.... */
689        outbuf[0] = QUOTA_QUERY_VERSION;
690        outbuf[1] = (char) UDPPROTOCOL;
691
692        /* Generate a sequence number... Since we fork the only realistic
693           thing to use is the time... */
694        t = htonl(time((char *) 0));
695        memcpy(outbuf + 2, &t,  4);
696        strncpy(outbuf + 5, printer, 30);
697
698
699        if(QS == NULL)
700            outbuf[40] = '\0';
701        else
702            strncpy(outbuf + 40, QS, 20);
703        /* If can't open the control file, then there is some error...
704           We'll return allowed to print, but somewhere else it will be caught.
705           Is this proper? XXX
706           */
707
708        if ((cfp = fopen(file, "r")) == NULL)
709                return 0;
710
711        /* Read the control file for the person sending the job */
712        while (getline(cfp)) {
713                if (line[0] == 'Q' || line[0] == 'A') { /* 'A' for old clients */
714                    if(sscanf(line + 1, "%d", &act) != 1) act=0;
715                    break;
716                }
717        }
718        fclose(cfp);
719
720        act = htonl(act);
721        memcpy(outbuf + 36, &act,  4);
722
723        strncpy(outbuf + 60, kprincipal, ANAME_SZ);
724        strncpy(outbuf + 60 + ANAME_SZ, kinstance, INST_SZ);
725        strncpy(outbuf + 60 + ANAME_SZ + INST_SZ, krealm, REALM_SZ);
726
727        if((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
728            syslog(LOG_WARNING, "Could not create UDP socket\n");
729            /* Allow print */
730            return 0;
731        }
732
733        memset((char *)&sin_c, 0, sizeof(sin_c));
734        sin_c.sin_family = AF_INET;
735        servname = getservbyname(QUOTASERVENTNAME,"udp");
736        if(!servname)
737            sin_c.sin_port = htons(QUOTASERVENT);
738        else
739            sin_c.sin_port = servname->s_port;
740
741        memcpy(&sin_c.sin_addr,hp->h_addr_list[0], sizeof(sin_c.sin_addr));
742
743        if(connect(fd, &sin_c, sizeof(sin_c)) < 0) {
744            syslog(LOG_WARNING, "Could not connect with UDP - quota server down?");
745            /* This means that the quota serve is down */
746            /* Allow printing */
747            return 0;
748        }
749
750        for(retry = 0; retry < RETRY_COUNT; retry++) {
751            if(send(fd, outbuf, 59+ANAME_SZ+REALM_SZ+INST_SZ+1,0)<
752               59+ANAME_SZ+REALM_SZ+INST_SZ+1) {
753                syslog(LOG_WARNING, "Send failed to quota");
754                continue;
755            }
756
757            FD_ZERO(&set);
758            FD_SET(fd, &set);
759            tp.tv_sec = UDPTIMEOUT;
760            tp.tv_usec = 0;
761
762            /* So, select and wait for reply */
763            if((s1=select(fd+1, &set, 0, 0, &tp))==0) {
764                /*Time out, retry */
765                continue;
766            }
767
768            if(s1 < 0) {
769                /* Error, which makes no sense. Oh well, display */
770                syslog(LOG_WARNING, "Error in UDP return errno=%d", errno);
771                /* Allow print */
772                return 0;
773            }
774
775            if((s1=recv(fd, inbuf, 36, 0)) != 36) {
776                syslog(LOG_WARNING, "Receive error in UDP contacting quota");
777                /* Retry */
778                continue;
779            }
780
781            if(memcmp(inbuf, outbuf, 36)) {
782                /* Wrong packet */
783#ifdef DEBUG
784                syslog(LOG_DEBUG, "Packet not for me on UDP");
785#endif
786                continue;
787            }
788
789            /* Packet good, send response */
790            switch ((int) inbuf[36]) {
791            case ALLOWEDTOPRINT:
792#ifdef DEBUG
793                syslog(LOG_DEBUG, "Allowed to print!!");
794#endif
795                return 0;
796            case NOALLOWEDTOPRINT:
797                return "\4";
798            case UNKNOWNUSER:
799                return "\3";
800            case UNKNOWNGROUP:
801                return "\5";
802            case USERNOTINGROUP:
803                return "\6";
804            case USERDELETED:
805                return "\7";
806            case GROUPDELETED:
807                return "\10";
808            default:
809                break;
810                /* Bogus, retry */
811            }
812        }
813
814        if(retry == RETRY_COUNT) {
815            /* We timed out in contacting... Allow printing*/
816            return 0;
817        }
818        return 0;
819    }
820
821#endif
822
823#ifdef LACL
824char *check_lacl(file)
825char *file;
826    {
827        FILE *cfp;
828        char person[BUFSIZ];
829#ifdef KERBEROS
830        extern char local_realm[];
831#endif
832        person[0] = '\0';
833
834        if(!AC) {
835            syslog(LOG_ERR, "ACL file not set in printcap");
836            return NULL;
837        }
838        if(access(AC, R_OK)) {
839            syslog(LOG_ERR, "Could not find ACL file %s", AC);
840            return NULL;
841        }
842
843        /* Read the control file for the person sending the job */
844        if ((cfp = fopen(file, "r")) == NULL)
845                return 0;
846        while (getline(cfp)) {
847                if (line[0] == 'P' && line[1]) {
848                    strcpy(person, line + 1);
849                    break;
850                }
851        }
852        fclose(cfp);
853
854        if(!person[0]) {
855#ifdef DEBUG
856            syslog(LOG_DEBUG, "Person not found :%s", line);
857#endif
858            goto notfound;
859        }
860#ifdef DEBUG
861        else
862            syslog(LOG_DEBUG, "Found person :%s:%s", line, person);
863#endif
864
865#ifdef KERBEROS
866        /* Now to tack the realm on */
867        if(kerberos_cf && !strchr(person, '@')) {
868            strcat(person,"@");
869            strcat(person, local_realm);
870        }
871
872#endif
873
874#ifdef DEBUG
875        syslog(LOG_DEBUG, "Checking on :%s: ", person);
876#endif
877
878        /* Now see if the person is in AC */
879        if ((cfp = fopen(AC, "r")) == NULL)
880                return 0;
881        while(getline(cfp)) {
882            if(!strcasecmp(person, line)) {
883                fclose(cfp);
884                goto found;
885            }
886        }
887        fclose(cfp);
888
889    notfound:
890        if(PA) return "\4"; /* NOALLOWEDTOPRINT */
891        else return NULL;
892
893    found:
894        if(PA) return NULL;
895        else return "\4"; /* NOALLOWEDTOPRINT */
896    }
897
898char *
899check_remhost()
900{
901    register char *cp, *sp;
902    extern char from_host[];
903    register FILE *hostf;
904    char ahost[MAXHOSTNAMELEN + 1];
905    int baselen = -1;
906
907    if(!strcasecmp(from_host, host)) return NULL;
908#if 0
909    syslog(LOG_DEBUG, "About to check on %s\n", from_host);
910#endif
911    sp = from_host;
912    cp = ahost;
913    while (*sp) {
914        if (*sp == '.') {
915            if (baselen == -1)
916                baselen = sp - from_host;
917            *cp++ = *sp++;
918        } else {
919            *cp++ = isupper(*sp) ? tolower(*sp++) : *sp++;
920        }
921    }
922    *cp = '\0';
923    hostf = fopen("/etc/hosts.lpd", "r");
924#define DUMMY ":nobody::"
925    if (hostf) {
926        if (!validuser(hostf, ahost, DUMMY, DUMMY, baselen)) {
927            (void) fclose(hostf);
928            return NULL;
929        }
930        (void) fclose(hostf);
931        return "\4";
932    } else {
933        /* Could not open hosts.lpd file */
934        return NULL;
935    }
936}
937#endif /* LACL */
Note: See TracBrowser for help on using the repository browser.