source: trunk/athena/bin/lpr/common.c @ 10545

Revision 10545, 10.5 KB checked in by ghudson, 27 years ago (diff)
From mwhitson: expand pbuf. Just a hack. Will be fixed the right way later, if we don't nuke this code base entirely.
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[] = "@(#)common.c    5.2 (Berkeley) 5/6/86";
9#endif /* not lint */
10
11/*
12 * Routines and data common to all the line printer functions.
13 */
14
15#include "lp.h"
16#ifdef POSIX
17#include <stdlib.h>
18#endif
19#include <sys/types.h>
20#include <sys/stat.h>
21#include <sys/param.h>
22#include <string.h>
23
24
25int     DU;             /* daeomon user-id */
26int     MX;             /* maximum number of blocks to copy */
27int     MC;             /* maximum number of copies allowed */
28char    *LP;            /* line printer device name */
29char    *RM;            /* remote machine name */
30char    *RP;            /* remote printer name */
31char    *LO;            /* lock file name */
32char    *ST;            /* status file name */
33char    *SD;            /* spool directory */
34char    *AF;            /* accounting file */
35char    *LF;            /* log file for error messages */
36char    *OF;            /* name of output filter (created once) */
37char    *IF;            /* name of input filter (created per job) */
38char    *RF;            /* name of fortran text filter (per job) */
39char    *TF;            /* name of troff filter (per job) */
40char    *NF;            /* name of ditroff filter (per job) */
41char    *DF;            /* name of tex filter (per job) */
42char    *GF;            /* name of graph(1G) filter (per job) */
43char    *VF;            /* name of vplot filter (per job) */
44char    *CF;            /* name of cifplot filter (per job) */
45char    *PF;            /* name of vrast filter (per job) */
46char    *FF;            /* form feed string */
47char    *TR;            /* trailer string to be output when Q empties */
48char    *MS;            /* list of tty modes to set or clear */
49short   SC;             /* suppress multiple copies */
50short   SF;             /* suppress FF on each print job */
51short   SH;             /* suppress header page */
52short   SB;             /* short banner instead of normal header */
53short   HL;             /* print header last */
54short   RW;             /* open LP for reading and writing */
55short   PW;             /* page width */
56short   PL;             /* page length */
57short   PX;             /* page width in pixels */
58short   PY;             /* page length in pixels */
59short   BR;             /* baud rate if lp is a tty */
60int     FC;             /* flags to clear if lp is a tty */
61int     FS;             /* flags to set if lp is a tty */
62int     XC;             /* flags to clear for local mode */
63int     XS;             /* flags to set for local mode */
64short   RS;             /* restricted to those with local accounts */
65#ifdef PQUOTA
66char    *RQ;            /* Name of remote quota server */
67int     CP;             /* Cost per page */
68char    *QS;            /* Quota service for printer */
69#endif /* PQUOTA */
70#ifdef LACL
71char    *AC;            /* Local ACL file to use */
72short   PA;             /* ACL file used as positive ACL */
73short   RA;             /* Restricted host access */
74#endif /* LACL */
75
76char    line[BUFSIZ];
77char    pbuf[BUFSIZ * 16];      /* buffer for printcap strings */
78char    *bp = pbuf;     /* pointer into pbuf for pgetent() */
79char    *name;          /* program name */
80char    *printer;       /* printer name */
81char    host[MAXHOSTNAMELEN + 1]="";    /* host machine name */
82char    *from = host;   /* client's machine name */
83#ifdef HESIOD
84char    alibuf[BUFSIZ/2];       /* buffer for printer alias */
85#endif
86
87#ifdef SOLARIS
88/*
89 * The DIRSIZ macro is the minimum record length which will hold the directory
90 * entry. sizeof(dirent) includes a byte for the null termination, so 1 need
91 * not be added to the strlen().
92 */
93#undef DIRSIZ
94#define DIRSIZ(dp) ((sizeof (struct dirent)) + strlen(dp->d_name))
95
96int
97scandir(dirname, namelist, select, dcomp)
98        char *dirname;
99        struct dirent ***namelist;
100        int (*select)(), (*dcomp)();
101{
102        register struct dirent *d, *p, **names;
103        register size_t nitems;
104        struct stat stb;
105        long arraysz;
106        DIR *dirp;
107
108        if ((dirp = opendir(dirname)) == NULL)
109                return(-1);
110        if (fstat(dirp->dd_fd, &stb) < 0)
111                return(-1);
112
113        /*
114         * estimate the array size by taking the size of the directory file
115         * and dividing it by a multiple of the minimum size entry.
116         */
117        arraysz = (stb.st_size / 24);
118        names = (struct dirent **)malloc(arraysz * sizeof(struct dirent *));
119        if (names == NULL)
120                return(-1);
121
122        nitems = 0;
123        while ((d = readdir(dirp)) != NULL) {
124                if (select != NULL && !(*select)(d))
125                        continue;       /* just selected names */
126                /*
127                 * Make a minimum size copy of the data
128                 */
129                p = (struct dirent *)malloc(DIRSIZ(d));
130                if (p == NULL)
131                        return(-1);
132                p->d_ino = d->d_ino;
133                p->d_reclen = d->d_reclen;
134/*              p->d_namlen = d->d_namlen; */
135                memcpy(p->d_name, d->d_name, strlen(d->d_name)+1 );
136                /*
137                 * Check to make sure the array has space left and
138                 * realloc the maximum size.
139                 */
140                if (++nitems >= arraysz) {
141                        if (fstat(dirp->dd_fd, &stb) < 0)
142                                return(-1);     /* just might have grown */
143                        arraysz = stb.st_size / 12;
144                        names = (struct dirent **)realloc((char *)names,
145                                arraysz * sizeof(struct dirent *));
146                        if (names == NULL)
147                                return(-1);
148                }
149                names[nitems-1] = p;
150        }
151        closedir(dirp);
152        if (nitems && dcomp != NULL)
153                qsort(names, nitems, sizeof(struct dirent *), dcomp);
154        *namelist = names;
155        return(nitems);
156}
157
158
159/*
160 * Alphabetic order comparison routine for those who want it.
161 */
162int
163alphasort(d1, d2)
164        void *d1;
165        void *d2;
166{
167        return(strcmp((*(struct dirent **)d1)->d_name,
168            (*(struct dirent **)d2)->d_name));
169}
170/*
171 * File locking is not available via flock() but we can make one
172 */
173#define   LOCK_SH   1    /* shared lock */
174#define   LOCK_EX   2    /* exclusive lock */
175#define   LOCK_NB   4    /* don't block when locking */
176#define   LOCK_UN   8    /* unlock */
177
178#include <fcntl.h>
179#include <stdio.h>      /* SEEK_SET */
180
181int
182flock(int fd, int operation)
183{
184   struct flock lock;
185
186   lock.l_type = F_RDLCK;
187   if (operation & LOCK_EX) lock.l_type = F_WRLCK;
188   else if (operation & LOCK_UN) lock.l_type = F_UNLCK;
189
190   lock.l_start = lock.l_len = 0;
191   lock.l_whence = SEEK_SET;
192   return fcntl(fd, operation & LOCK_NB? F_SETLK: F_SETLKW, &lock);
193}
194#endif /* SOLARIS */
195
196#if defined(POSIX) && !defined(ultrix)
197#include <signal.h>
198typedef void    Sigfunc(int);   /* for signal handlers */
199
200                /* 4.3BSD Reno <signal.h> doesn't define SIG_ERR */
201#if     defined(SIG_IGN) && !defined(SIG_ERR)
202#define SIG_ERR ((Sigfunc *)-1)
203#endif
204
205/* Reliable signal()s (Stevens: Advanced UNIX PRG, pp. 298) */
206
207Sigfunc *
208signal(int signo, Sigfunc *func)
209{
210   struct sigaction act, oact;
211
212   act.sa_handler = func;
213   sigemptyset(&act.sa_mask);
214   act.sa_flags = 0;
215   if (signo == SIGALRM) {
216#ifdef SA_INTERRUPT
217      act.sa_flags |= SA_INTERRUPT;     /* SunOS */
218#endif
219   }
220   else {
221#ifdef SA_RESTART
222      act.sa_flags |= SA_RESTART;       /* SVR4, 4.3+BSD */
223#endif
224   }
225   if (sigaction(signo, &act, &oact) < 0)
226      return SIG_ERR;
227   return oact.sa_handler;
228}
229
230#endif /* POSIX !ultrix  */
231/*
232 * Compare modification times.
233 */
234static
235compar(p1, p2)
236        register struct queue_ **p1, **p2;
237{
238        if ((*p1)->q_time < (*p2)->q_time)
239                return(-1);
240        if ((*p1)->q_time > (*p2)->q_time)
241                return(1);
242        return(0);
243}
244
245/*
246 * Create a connection to the remote printer server.
247 * Most of this code comes from rcmd.c.
248 */
249getport(rhost)
250        char *rhost;
251{
252        struct hostent *hp;
253        struct servent *sp;
254        struct sockaddr_in sin;
255        int s, timo = 1, lport = IPPORT_RESERVED - 1;
256        int err;
257
258        /*
259         * Get the host address and port number to connect to.
260         */
261        if (rhost == NULL)
262                fatal("no remote host to connect to");
263        hp = gethostbyname(rhost);
264        if (hp == NULL)
265                fatal("unknown host %s", rhost);
266        sp = getservbyname("printer", "tcp");
267        if (sp == NULL)
268                fatal("printer/tcp: unknown service");
269        memset((char *)&sin, 0, sizeof(sin));
270        memcpy((caddr_t)&sin.sin_addr, hp->h_addr, sizeof(sin.sin_addr));
271        sin.sin_family = hp->h_addrtype;
272        sin.sin_port = sp->s_port;
273
274        /*
275         * Try connecting to the server.
276         */
277retry:
278        s = rresvport(&lport);
279
280        if (s < 0)
281                return(-1);
282        if (connect(s, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
283
284                err = errno;
285                (void) close(s);
286                errno = err;
287                if (errno == EADDRINUSE) {
288                        lport--;
289                        goto retry;
290                }
291                if (errno == ECONNREFUSED && timo <= 8) {
292                        sleep(timo);
293                        timo *= 2;
294                        goto retry;
295                }
296                return(-1);
297        }
298        return(s);
299}
300
301/*
302 * Getline reads a line from the control file cfp, removes tabs, converts
303 *  new-line to null and leaves it in line.
304 * Returns 0 at EOF or the number of characters read.
305 */
306getline(cfp)
307        FILE *cfp;
308{
309        register int linel = 0;
310        register char *lp = line;
311        register c;
312
313        while ((c = getc(cfp)) != '\n' && linel < BUFSIZ-8) {
314                if (c == EOF)
315                        return(0);
316                if (c == '\t') {
317                        do {
318                                *lp++ = ' ';
319                                linel++;
320                        } while ((linel & 07) != 0);
321                        continue;
322                }
323                *lp++ = c;
324                linel++;
325        }
326        *lp++ = '\0';
327        return(linel);
328}
329
330/*
331 * Scan the current directory and make a list of daemon files sorted by
332 * creation time.
333 * Return the number of entries and a pointer to the list.
334 */
335getq_(namelist)
336        struct queue_ *(*namelist[]);
337{
338#ifdef POSIX
339        register struct dirent *d;
340#else
341        register struct direct *d;
342#endif
343        register struct queue_ *q, **queue;
344        register int nitems;
345        struct stat stbuf;
346        int arraysz, compar();
347        DIR *dirp;
348
349        if ((dirp = opendir(SD)) == NULL)
350                return(-1);
351
352        if (fstat(dirp->dd_fd, &stbuf) < 0)
353                goto errdone;
354
355        /*
356         * Estimate the array size by taking the size of the directory file
357         * and dividing it by a multiple of the minimum size entry.
358         */
359        arraysz = (stbuf.st_size / 24);
360        queue = (struct queue_ **)malloc(arraysz * sizeof(struct queue_ *));
361        if (queue == NULL)
362                goto errdone;
363
364        nitems = 0;
365
366        while ((d = readdir(dirp)) != NULL) {
367
368                if (d->d_name[0] != 'c' || d->d_name[1] != 'f')
369                        continue;       /* daemon control files only */
370
371                if (stat(d->d_name, &stbuf) < 0)
372                        continue;       /* Doesn't exist */
373
374
375                q = (struct queue_ *)malloc(sizeof(time_t)+strlen(d->d_name)+1);
376                if (q == NULL)
377                        goto errdone;
378                q->q_time = stbuf.st_mtime;
379                strcpy(q->q_name, d->d_name);
380
381                /*
382                 * Check to make sure the array has space left and
383                 * realloc the maximum size.
384                 */
385                if (++nitems > arraysz) {
386                        queue = (struct queue_ **)realloc((char *)queue,
387                                (stbuf.st_size/12) * sizeof(struct queue_ *));
388                        if (queue == NULL)
389                                goto errdone;
390                }
391                queue[nitems-1] = q;
392        }
393        closedir(dirp);
394        if (nitems)
395                qsort(queue, nitems, sizeof(struct queue_ *), compar);
396        *namelist = queue;
397        return(nitems);
398
399errdone:
400        closedir(dirp);
401        return(-1);
402}
403
404
405/*VARARGS1*/
406fatal(msg, a1, a2, a3)
407        char *msg;
408{
409        if (from != host)
410                printf("%s: ", host);
411        printf("%s: ", name);
412        if (printer)
413                printf("%s: ", printer);
414        printf(msg, a1, a2, a3);
415        syslog(LOG_ERR, msg, a1, a2, a3);
416        putchar('\n');
417        exit(1);
418}
419
420#ifdef KERBEROS
421/* Form a complete string name consisting of principal,
422 * instance and realm
423 */
424make_kname(principal, instance, realm, out_name)
425char *principal, *instance, *realm, *out_name;
426{
427        if ((instance[0] == '\0') && (realm[0] == '\0'))
428                strcpy(out_name, principal);
429        else {
430                if (realm[0] == '\0')
431                        sprintf(out_name, "%s.%s", principal, instance);
432                else {
433                        if (instance[0] == '\0')
434                                sprintf(out_name, "%s@%s", principal, realm);
435                        else
436                                sprintf(out_name, "%s.%s@%s", principal,
437                                        instance, realm);
438                }
439        }
440}
441#endif /* KERBEROS */
Note: See TracBrowser for help on using the repository browser.