1 /*
2  * Copyright (c) 1983 Regents of the University of California.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms are permitted
6  * provided that this notice is preserved and that due credit is given
7  * to the University of California at Berkeley. The name of the University
8  * may not be used to endorse or promote products derived from this
9  * software without specific prior written permission. This software
10  * is provided ``as is'' without express or implied warranty.
11  */
12 
13 #ifndef lint
14 static char sccsid[] = "@(#)common.c	5.3 (Berkeley) 05/05/88";
15 #endif /* not lint */
16 
17 /*
18  * Routines and data common to all the line printer functions.
19  */
20 
21 #include "lp.h"
22 
23 int	DU;		/* daeomon user-id */
24 int	MX;		/* maximum number of blocks to copy */
25 int	MC;		/* maximum number of copies allowed */
26 char	*LP;		/* line printer device name */
27 char	*RM;		/* remote machine name */
28 char	*RP;		/* remote printer name */
29 char	*LO;		/* lock file name */
30 char	*ST;		/* status file name */
31 char	*SD;		/* spool directory */
32 char	*AF;		/* accounting file */
33 char	*LF;		/* log file for error messages */
34 char	*OF;		/* name of output filter (created once) */
35 char	*IF;		/* name of input filter (created per job) */
36 char	*RF;		/* name of fortran text filter (per job) */
37 char	*TF;		/* name of troff filter (per job) */
38 char	*NF;		/* name of ditroff filter (per job) */
39 char	*DF;		/* name of tex filter (per job) */
40 char	*GF;		/* name of graph(1G) filter (per job) */
41 char	*VF;		/* name of vplot filter (per job) */
42 char	*CF;		/* name of cifplot filter (per job) */
43 char	*PF;		/* name of vrast filter (per job) */
44 char	*FF;		/* form feed string */
45 char	*TR;		/* trailer string to be output when Q empties */
46 short	SC;		/* suppress multiple copies */
47 short	SF;		/* suppress FF on each print job */
48 short	SH;		/* suppress header page */
49 short	SB;		/* short banner instead of normal header */
50 short	HL;		/* print header last */
51 short	RW;		/* open LP for reading and writing */
52 short	PW;		/* page width */
53 short	PL;		/* page length */
54 short	PX;		/* page width in pixels */
55 short	PY;		/* page length in pixels */
56 short	BR;		/* baud rate if lp is a tty */
57 int	FC;		/* flags to clear if lp is a tty */
58 int	FS;		/* flags to set if lp is a tty */
59 int	XC;		/* flags to clear for local mode */
60 int	XS;		/* flags to set for local mode */
61 short	RS;		/* restricted to those with local accounts */
62 
63 char	line[BUFSIZ];
64 char	pbuf[BUFSIZ/2];	/* buffer for printcap strings */
65 char	*bp = pbuf;	/* pointer into pbuf for pgetent() */
66 char	*name;		/* program name */
67 char	*printer;	/* printer name */
68 char	host[32];	/* host machine name */
69 char	*from = host;	/* client's machine name */
70 
71 /*
72  * Create a connection to the remote printer server.
73  * Most of this code comes from rcmd.c.
74  */
75 getport(rhost)
76 	char *rhost;
77 {
78 	struct hostent *hp;
79 	struct servent *sp;
80 	struct sockaddr_in sin;
81 	int s, timo = 1, lport = IPPORT_RESERVED - 1;
82 	int err;
83 
84 	/*
85 	 * Get the host address and port number to connect to.
86 	 */
87 	if (rhost == NULL)
88 		fatal("no remote host to connect to");
89 	hp = gethostbyname(rhost);
90 	if (hp == NULL)
91 		fatal("unknown host %s", rhost);
92 	sp = getservbyname("printer", "tcp");
93 	if (sp == NULL)
94 		fatal("printer/tcp: unknown service");
95 	bzero((char *)&sin, sizeof(sin));
96 	bcopy(hp->h_addr, (caddr_t)&sin.sin_addr, hp->h_length);
97 	sin.sin_family = hp->h_addrtype;
98 	sin.sin_port = sp->s_port;
99 
100 	/*
101 	 * Try connecting to the server.
102 	 */
103 retry:
104 	s = rresvport(&lport);
105 	if (s < 0)
106 		return(-1);
107 	if (connect(s, (caddr_t)&sin, sizeof(sin), 0) < 0) {
108 		err = errno;
109 		(void) close(s);
110 		errno = err;
111 		if (errno == EADDRINUSE) {
112 			lport--;
113 			goto retry;
114 		}
115 		if (errno == ECONNREFUSED && timo <= 16) {
116 			sleep(timo);
117 			timo *= 2;
118 			goto retry;
119 		}
120 		return(-1);
121 	}
122 	return(s);
123 }
124 
125 /*
126  * Getline reads a line from the control file cfp, removes tabs, converts
127  *  new-line to null and leaves it in line.
128  * Returns 0 at EOF or the number of characters read.
129  */
130 getline(cfp)
131 	FILE *cfp;
132 {
133 	register int linel = 0;
134 	register char *lp = line;
135 	register c;
136 
137 	while ((c = getc(cfp)) != '\n') {
138 		if (c == EOF)
139 			return(0);
140 		if (c == '\t') {
141 			do {
142 				*lp++ = ' ';
143 				linel++;
144 			} while ((linel & 07) != 0);
145 			continue;
146 		}
147 		*lp++ = c;
148 		linel++;
149 	}
150 	*lp++ = '\0';
151 	return(linel);
152 }
153 
154 /*
155  * Scan the current directory and make a list of daemon files sorted by
156  * creation time.
157  * Return the number of entries and a pointer to the list.
158  */
159 getq(namelist)
160 	struct queue *(*namelist[]);
161 {
162 	register struct direct *d;
163 	register struct queue *q, **queue;
164 	register int nitems;
165 	struct stat stbuf;
166 	int arraysz, compar();
167 	DIR *dirp;
168 
169 	if ((dirp = opendir(SD)) == NULL)
170 		return(-1);
171 	if (fstat(dirp->dd_fd, &stbuf) < 0)
172 		goto errdone;
173 
174 	/*
175 	 * Estimate the array size by taking the size of the directory file
176 	 * and dividing it by a multiple of the minimum size entry.
177 	 */
178 	arraysz = (stbuf.st_size / 24);
179 	queue = (struct queue **)malloc(arraysz * sizeof(struct queue *));
180 	if (queue == NULL)
181 		goto errdone;
182 
183 	nitems = 0;
184 	while ((d = readdir(dirp)) != NULL) {
185 		if (d->d_name[0] != 'c' || d->d_name[1] != 'f')
186 			continue;	/* daemon control files only */
187 		if (stat(d->d_name, &stbuf) < 0)
188 			continue;	/* Doesn't exist */
189 		q = (struct queue *)malloc(sizeof(time_t)+strlen(d->d_name)+1);
190 		if (q == NULL)
191 			goto errdone;
192 		q->q_time = stbuf.st_mtime;
193 		strcpy(q->q_name, d->d_name);
194 		/*
195 		 * Check to make sure the array has space left and
196 		 * realloc the maximum size.
197 		 */
198 		if (++nitems > arraysz) {
199 			queue = (struct queue **)realloc((char *)queue,
200 				(stbuf.st_size/12) * sizeof(struct queue *));
201 			if (queue == NULL)
202 				goto errdone;
203 		}
204 		queue[nitems-1] = q;
205 	}
206 	closedir(dirp);
207 	if (nitems)
208 		qsort(queue, nitems, sizeof(struct queue *), compar);
209 	*namelist = queue;
210 	return(nitems);
211 
212 errdone:
213 	closedir(dirp);
214 	return(-1);
215 }
216 
217 /*
218  * Compare modification times.
219  */
220 static
221 compar(p1, p2)
222 	register struct queue **p1, **p2;
223 {
224 	if ((*p1)->q_time < (*p2)->q_time)
225 		return(-1);
226 	if ((*p1)->q_time > (*p2)->q_time)
227 		return(1);
228 	return(0);
229 }
230 
231 /*VARARGS1*/
232 fatal(msg, a1, a2, a3)
233 	char *msg;
234 {
235 	if (from != host)
236 		printf("%s: ", host);
237 	printf("%s: ", name);
238 	if (printer)
239 		printf("%s: ", printer);
240 	printf(msg, a1, a2, a3);
241 	putchar('\n');
242 	exit(1);
243 }
244