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