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