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

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