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

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