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