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