xref: /plan9-contrib/sys/src/cmd/lp/lpdaemon.c (revision 219b2ee8daee37f4aad58d63f21287faa8e4ffdc)
1*219b2ee8SDavid du Colombier /* these includes are needed for plan 9 ape */
2*219b2ee8SDavid du Colombier #include <sys/types.h>
3*219b2ee8SDavid du Colombier #include <unistd.h>
4*219b2ee8SDavid du Colombier #include <stdlib.h>
5*219b2ee8SDavid du Colombier #include <sys/wait.h>
6*219b2ee8SDavid du Colombier #include <fcntl.h>
7*219b2ee8SDavid du Colombier 
8*219b2ee8SDavid du Colombier #include <stdio.h>
9*219b2ee8SDavid du Colombier #include <signal.h>
10*219b2ee8SDavid du Colombier #include <errno.h>
11*219b2ee8SDavid du Colombier #include <time.h>
12*219b2ee8SDavid du Colombier #include <string.h>
13bd389b36SDavid du Colombier 
14bd389b36SDavid du Colombier /* for Plan 9 */
15*219b2ee8SDavid du Colombier #ifdef PLAN9
16bd389b36SDavid du Colombier #define LP	"/bin/lp"
17*219b2ee8SDavid du Colombier #define TMPDIR "/sys/lib/lp/tmp"
18*219b2ee8SDavid du Colombier #define LPDAEMONLOG	"/sys/lib/lp/log/lpdaemonl"
19*219b2ee8SDavid du Colombier #endif
20bd389b36SDavid du Colombier /* for Tenth Edition systems */
21*219b2ee8SDavid du Colombier #ifdef V10
22*219b2ee8SDavid du Colombier #define LP	"/usr/bin/lp"
23*219b2ee8SDavid du Colombier #define TMPDIR "/tmp"
24bd389b36SDavid du Colombier #define LPDAEMONLOG	"/tmp/lpdaemonl"
25*219b2ee8SDavid du Colombier #endif
26*219b2ee8SDavid du Colombier /* for System V or BSD systems */
27*219b2ee8SDavid du Colombier #if defined(SYSV) || defined(BSD)
28*219b2ee8SDavid du Colombier #define LP	"/v/bin/lp"
29*219b2ee8SDavid du Colombier #define TMPDIR "/tmp"
30*219b2ee8SDavid du Colombier #define LPDAEMONLOG	"/tmp/lpdaemonl"
31*219b2ee8SDavid du Colombier #endif
32bd389b36SDavid du Colombier 
33bd389b36SDavid du Colombier #define ARGSIZ 4096
34*219b2ee8SDavid du Colombier #define NAMELEN 30
35bd389b36SDavid du Colombier 
36bd389b36SDavid du Colombier char argvstr[ARGSIZ];		/* arguments after parsing */
37bd389b36SDavid du Colombier char *argvals[ARGSIZ/2+1];	/* pointers to arguments after parsing */
38bd389b36SDavid du Colombier int ascnt = 0, argcnt = 0;	/* number of arguments parsed */
39*219b2ee8SDavid du Colombier /* for 'stuff' gleened from lpr cntrl file */
40*219b2ee8SDavid du Colombier struct jobinfo {
41*219b2ee8SDavid du Colombier 	char user[NAMELEN+1];
42*219b2ee8SDavid du Colombier 	char host[NAMELEN+1];
43*219b2ee8SDavid du Colombier } *getjobinfo();
44bd389b36SDavid du Colombier 
45*219b2ee8SDavid du Colombier #define MIN(a,b)	((a<b)?a:b)
46*219b2ee8SDavid du Colombier 
47*219b2ee8SDavid du Colombier #define	CPYFIELD(src, dst)	{ while (*(src)!=' ' && *(src)!='\t' && *(src)!='\r' && *(src)!='\n' && *(src)!='\0') *(dst)++ = *(src)++; }
48*219b2ee8SDavid du Colombier 
49*219b2ee8SDavid du Colombier #define	ACK()	write(1, "", 1)
50*219b2ee8SDavid du Colombier #define NAK()	write(1, "\001", 1)
51*219b2ee8SDavid du Colombier 
52*219b2ee8SDavid du Colombier #define LNBFSZ	4096
53*219b2ee8SDavid du Colombier char lnbuf[LNBFSZ];
54*219b2ee8SDavid du Colombier int readline();
55*219b2ee8SDavid du Colombier 
56*219b2ee8SDavid du Colombier #define	RDSIZE 512
57*219b2ee8SDavid du Colombier char jobbuf[RDSIZE];
58*219b2ee8SDavid du Colombier 
59*219b2ee8SDavid du Colombier int datafd[400], cntrlfd;
60*219b2ee8SDavid du Colombier 
61*219b2ee8SDavid du Colombier int dbgstate = 0;
62*219b2ee8SDavid du Colombier char *dbgstrings[] = {
63*219b2ee8SDavid du Colombier 	"",
64*219b2ee8SDavid du Colombier 	"sendack1",
65*219b2ee8SDavid du Colombier 	"send",
66*219b2ee8SDavid du Colombier 	"rcvack",
67*219b2ee8SDavid du Colombier 	"sendack2",
68*219b2ee8SDavid du Colombier 	"done"
69*219b2ee8SDavid du Colombier };
70bd389b36SDavid du Colombier 
71bd389b36SDavid du Colombier void
72*219b2ee8SDavid du Colombier error(char *s1, ...)
73bd389b36SDavid du Colombier {
74*219b2ee8SDavid du Colombier 	FILE *fp;
75*219b2ee8SDavid du Colombier 	long thetime;
76*219b2ee8SDavid du Colombier 	char *chartime;
77*219b2ee8SDavid du Colombier 	va_list ap;
78*219b2ee8SDavid du Colombier 	char *args[8];
79*219b2ee8SDavid du Colombier 	int argno = 0;
80bd389b36SDavid du Colombier 
81*219b2ee8SDavid du Colombier 	if((fp=fopen(LPDAEMONLOG, "a"))==NULL) {
82*219b2ee8SDavid du Colombier fprintf(stderr, "fopen of %s failed\n", LPDAEMONLOG);
83*219b2ee8SDavid du Colombier 		return;
84bd389b36SDavid du Colombier 	}
85bd389b36SDavid du Colombier 
86*219b2ee8SDavid du Colombier 	time(&thetime);
87*219b2ee8SDavid du Colombier 	chartime = ctime(&thetime);
88*219b2ee8SDavid du Colombier 	fprintf(fp, "%.15s ", &(chartime[4]));
89*219b2ee8SDavid du Colombier 	va_start(ap, s1);
90*219b2ee8SDavid du Colombier 	while((args[argno++] = va_arg(ap, char*)) && argno<8);
91*219b2ee8SDavid du Colombier 	va_end(ap);
92*219b2ee8SDavid du Colombier 	fprintf(fp, s1, args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]);
93*219b2ee8SDavid du Colombier 	fclose(fp);
94*219b2ee8SDavid du Colombier 	return;
95*219b2ee8SDavid du Colombier }
96*219b2ee8SDavid du Colombier 
97*219b2ee8SDavid du Colombier void
98*219b2ee8SDavid du Colombier forklp(int inputfd)
99*219b2ee8SDavid du Colombier {
100*219b2ee8SDavid du Colombier 	int i, cpid;
101*219b2ee8SDavid du Colombier 	char *bp, *cp;
102*219b2ee8SDavid du Colombier 	char logent[LNBFSZ];
103*219b2ee8SDavid du Colombier 
104*219b2ee8SDavid du Colombier 	/* log this call to lp */
105*219b2ee8SDavid du Colombier 	cp = logent;
106*219b2ee8SDavid du Colombier 	for (i=1; i<argcnt; i++) {
107*219b2ee8SDavid du Colombier 		bp = argvals[i];
108*219b2ee8SDavid du Colombier 		if (cp+strlen(bp)+1 < logent+LNBFSZ-1) {
109*219b2ee8SDavid du Colombier 			CPYFIELD(bp, cp);
110*219b2ee8SDavid du Colombier 			*cp++ = ' ';
111*219b2ee8SDavid du Colombier 		}
112*219b2ee8SDavid du Colombier 	}
113*219b2ee8SDavid du Colombier 	*--cp = '\n';
114*219b2ee8SDavid du Colombier 	*++cp = '\0';
115*219b2ee8SDavid du Colombier 	error(logent);
116*219b2ee8SDavid du Colombier 	switch((cpid=fork())){
117*219b2ee8SDavid du Colombier 	case -1:
118*219b2ee8SDavid du Colombier 		error("fork error\n");
119*219b2ee8SDavid du Colombier 		exit(2);
120*219b2ee8SDavid du Colombier 	case 0:
121*219b2ee8SDavid du Colombier 		if (inputfd != 0)
122*219b2ee8SDavid du Colombier 			dup2(inputfd, 0);
123*219b2ee8SDavid du Colombier 		dup2(1, 2);
124*219b2ee8SDavid du Colombier 		lseek(0, 0L, 0);
125*219b2ee8SDavid du Colombier 		execvp(LP, argvals);
126*219b2ee8SDavid du Colombier 		error("exec failed\n");
127*219b2ee8SDavid du Colombier 		exit(3);
128*219b2ee8SDavid du Colombier 	default:
129*219b2ee8SDavid du Colombier 		while(wait((int *)0) != cpid);
130*219b2ee8SDavid du Colombier 	}
131*219b2ee8SDavid du Colombier }
132*219b2ee8SDavid du Colombier 
133*219b2ee8SDavid du Colombier int
134*219b2ee8SDavid du Colombier tempfile(void)
135*219b2ee8SDavid du Colombier {
136*219b2ee8SDavid du Colombier 	static tindx = 0;
137*219b2ee8SDavid du Colombier 	char tmpf[20];
138*219b2ee8SDavid du Colombier 	int crtfd, tmpfd;
139*219b2ee8SDavid du Colombier 
140*219b2ee8SDavid du Colombier 	sprintf(tmpf, "%s/lp%d.%d", TMPDIR, getpid(), tindx++);
141*219b2ee8SDavid du Colombier 	if((crtfd=creat(tmpf, 0666)) < 0) {
142*219b2ee8SDavid du Colombier 		error("cannot create temp file %s\n", tmpf);
143*219b2ee8SDavid du Colombier 		NAK();
144*219b2ee8SDavid du Colombier 		exit(3);
145*219b2ee8SDavid du Colombier 	}
146*219b2ee8SDavid du Colombier 	if((tmpfd=open(tmpf, 2)) < 0) {
147*219b2ee8SDavid du Colombier 		error("cannot open temp file %s\n", tmpf);
148*219b2ee8SDavid du Colombier 		NAK();
149*219b2ee8SDavid du Colombier 		exit(3);
150*219b2ee8SDavid du Colombier 	}
151*219b2ee8SDavid du Colombier 	close(crtfd);
152*219b2ee8SDavid du Colombier 	unlink(tmpf);	/* comment out for debugging */
153*219b2ee8SDavid du Colombier 	return(tmpfd);
154*219b2ee8SDavid du Colombier }
155*219b2ee8SDavid du Colombier 
156*219b2ee8SDavid du Colombier int
157*219b2ee8SDavid du Colombier readfile(int outfd, int bsize)
158*219b2ee8SDavid du Colombier {
159*219b2ee8SDavid du Colombier 	int rv;
160*219b2ee8SDavid du Colombier 
161*219b2ee8SDavid du Colombier 	dbgstate = 1;
162*219b2ee8SDavid du Colombier 	alarm(60);
163*219b2ee8SDavid du Colombier 	ACK();
164*219b2ee8SDavid du Colombier 	dbgstate = 2;
165*219b2ee8SDavid du Colombier 	for(; bsize > 0; bsize -= rv) {
166*219b2ee8SDavid du Colombier 		alarm(60);
167*219b2ee8SDavid du Colombier 		if((rv=read(0, jobbuf, MIN(bsize,RDSIZE))) < 0) {
168*219b2ee8SDavid du Colombier 			error("error reading input, %d unread\n", bsize);
169*219b2ee8SDavid du Colombier 			exit(4);
170*219b2ee8SDavid du Colombier 		} else if((write(outfd, jobbuf, rv)) != rv) {
171*219b2ee8SDavid du Colombier 			error("error writing temp file, %d unread\n", bsize);
172*219b2ee8SDavid du Colombier 			exit(5);
173*219b2ee8SDavid du Colombier 		}
174*219b2ee8SDavid du Colombier 	}
175*219b2ee8SDavid du Colombier 	dbgstate = 3;
176*219b2ee8SDavid du Colombier 	alarm(60);
177*219b2ee8SDavid du Colombier 	if (((rv=read(0, jobbuf, 1))==1) && (*jobbuf=='\0')) {
178*219b2ee8SDavid du Colombier 		alarm(60);
179*219b2ee8SDavid du Colombier 		ACK();
180*219b2ee8SDavid du Colombier 		dbgstate = 4;
181*219b2ee8SDavid du Colombier 		alarm(0);
182*219b2ee8SDavid du Colombier 		return(outfd);
183*219b2ee8SDavid du Colombier 	}
184*219b2ee8SDavid du Colombier 	alarm(0);
185*219b2ee8SDavid du Colombier 	error("received bad status <%d> from sender\n", *jobbuf);
186*219b2ee8SDavid du Colombier 	error("rv=%d\n", rv);
187*219b2ee8SDavid du Colombier 	NAK();
188*219b2ee8SDavid du Colombier 	return(-1);
189*219b2ee8SDavid du Colombier }
190*219b2ee8SDavid du Colombier 
191*219b2ee8SDavid du Colombier /* reads a line from the input into lnbuf
192*219b2ee8SDavid du Colombier  * if there is no error, it returns
193*219b2ee8SDavid du Colombier  *   the number of characters in the buffer
194*219b2ee8SDavid du Colombier  * if there is an error and there where characters
195*219b2ee8SDavid du Colombier  *   read, it returns the negative value of the
196*219b2ee8SDavid du Colombier  *   number of characters read
197*219b2ee8SDavid du Colombier  * if there is an error and no characters were read,
198*219b2ee8SDavid du Colombier  *   it returns the negative value of 1 greater than
199*219b2ee8SDavid du Colombier  *   the size of the line buffer
200*219b2ee8SDavid du Colombier  */
201*219b2ee8SDavid du Colombier int
202*219b2ee8SDavid du Colombier readline(int inpfd)
203*219b2ee8SDavid du Colombier {
204*219b2ee8SDavid du Colombier 	char *ap;
205*219b2ee8SDavid du Colombier 	int i, rv;
206*219b2ee8SDavid du Colombier 
207*219b2ee8SDavid du Colombier 	ap = lnbuf;
208*219b2ee8SDavid du Colombier 	i = 0;
209*219b2ee8SDavid du Colombier 	do {
210*219b2ee8SDavid du Colombier 		rv = read(inpfd, ap, 1);
211*219b2ee8SDavid du Colombier 	} while (rv==1 && ++i && *ap != '\n' && ap++ && (i < LNBFSZ - 2));
212*219b2ee8SDavid du Colombier 	if (i != 0 && *ap != '\n') {
213*219b2ee8SDavid du Colombier 		*++ap = '\n';
214*219b2ee8SDavid du Colombier 		i++;
215*219b2ee8SDavid du Colombier 	}
216*219b2ee8SDavid du Colombier 	*++ap = '\0';
217*219b2ee8SDavid du Colombier 	if (rv < 0) {
218*219b2ee8SDavid du Colombier 		error("read error; lost connection\n");
219*219b2ee8SDavid du Colombier 		if (i==0) i = -(LNBFSZ+1);
220*219b2ee8SDavid du Colombier 		else i = -i;
221*219b2ee8SDavid du Colombier 	}
222*219b2ee8SDavid du Colombier 	return(i);
223*219b2ee8SDavid du Colombier }
224*219b2ee8SDavid du Colombier 
225*219b2ee8SDavid du Colombier int
226*219b2ee8SDavid du Colombier getfiles(void)
227*219b2ee8SDavid du Colombier {
228*219b2ee8SDavid du Colombier 	char *ap;
229*219b2ee8SDavid du Colombier 	int filecnt, bsize, rv;
230*219b2ee8SDavid du Colombier 
231*219b2ee8SDavid du Colombier 	filecnt = 0;
232*219b2ee8SDavid du Colombier 	/* get a line, hopefully containing a ctrl char, size, and name */
233*219b2ee8SDavid du Colombier 	for(;;) {
234*219b2ee8SDavid du Colombier 		ap = lnbuf;
235*219b2ee8SDavid du Colombier 		if ((rv=readline(0)) < 0) NAK();
236*219b2ee8SDavid du Colombier 		if (rv <= 0) return(filecnt);
237*219b2ee8SDavid du Colombier 		switch(*ap++) {
238*219b2ee8SDavid du Colombier 		case '\1':		/* cleanup - data sent was bad (whatever that means) */
239*219b2ee8SDavid du Colombier 			break;
240*219b2ee8SDavid du Colombier 		case '\2':		/* read control file */
241*219b2ee8SDavid du Colombier 			bsize = atoi(ap);
242*219b2ee8SDavid du Colombier 			cntrlfd = tempfile();
243*219b2ee8SDavid du Colombier 			if (readfile(cntrlfd, bsize) < 0) {
244*219b2ee8SDavid du Colombier 				close(cntrlfd);
245*219b2ee8SDavid du Colombier 				NAK();
246*219b2ee8SDavid du Colombier 				return(0);
247*219b2ee8SDavid du Colombier 			}
248*219b2ee8SDavid du Colombier 			break;
249*219b2ee8SDavid du Colombier 		case '\3':		/* read data file */
250*219b2ee8SDavid du Colombier 			bsize = atoi(ap);
251*219b2ee8SDavid du Colombier 			datafd[filecnt] = tempfile();
252*219b2ee8SDavid du Colombier 			if (readfile(datafd[filecnt], bsize) < 0) {
253*219b2ee8SDavid du Colombier 				close(datafd[filecnt]);
254*219b2ee8SDavid du Colombier 				NAK();
255*219b2ee8SDavid du Colombier 				return(0);
256*219b2ee8SDavid du Colombier 			}
257*219b2ee8SDavid du Colombier 			filecnt++;
258*219b2ee8SDavid du Colombier 			break;
259*219b2ee8SDavid du Colombier 		default:
260*219b2ee8SDavid du Colombier 			error("protocol error <%d>\n", *(ap-1));
261*219b2ee8SDavid du Colombier 			NAK();
262*219b2ee8SDavid du Colombier 		}
263*219b2ee8SDavid du Colombier 	}
264*219b2ee8SDavid du Colombier 	return(filecnt);
265*219b2ee8SDavid du Colombier }
266*219b2ee8SDavid du Colombier 
267*219b2ee8SDavid du Colombier struct jobinfo *
268*219b2ee8SDavid du Colombier getjobinfo(int fd)
269*219b2ee8SDavid du Colombier {
270*219b2ee8SDavid du Colombier 	register char *ap;
271*219b2ee8SDavid du Colombier 	int rv;
272*219b2ee8SDavid du Colombier 	static struct jobinfo info;
273*219b2ee8SDavid du Colombier 
274*219b2ee8SDavid du Colombier 	if (lseek(fd, 0L, 0) < 0) {
275*219b2ee8SDavid du Colombier 		error("error seeking in temp file\n");
276*219b2ee8SDavid du Colombier 		exit(7);
277*219b2ee8SDavid du Colombier 	}
278*219b2ee8SDavid du Colombier 	/* the following strings should be < NAMELEN or else they will not
279*219b2ee8SDavid du Colombier 	 * be null terminated.
280*219b2ee8SDavid du Colombier 	 */
281*219b2ee8SDavid du Colombier 	strncpy(info.user, "daemon", NAMELEN);
282*219b2ee8SDavid du Colombier 	strncpy(info.host, "nowhere", NAMELEN);
283*219b2ee8SDavid du Colombier 	/* there may be a space after the name and host.  It will be filtered out
284*219b2ee8SDavid du Colombier 	 * by CPYFIELD.
285*219b2ee8SDavid du Colombier 	 */
286*219b2ee8SDavid du Colombier 	while ((rv=readline(fd)) > 0) {
287*219b2ee8SDavid du Colombier 		ap = lnbuf;
288*219b2ee8SDavid du Colombier 		ap[rv-1] = '\0';	/* remove newline from string */
289*219b2ee8SDavid du Colombier 		switch (*ap) {
290*219b2ee8SDavid du Colombier 		case 'H':
291*219b2ee8SDavid du Colombier 			if (ap[1] == '\0')
292*219b2ee8SDavid du Colombier 				strncpy(info.host, "unknown", NAMELEN);
293*219b2ee8SDavid du Colombier 			else
294*219b2ee8SDavid du Colombier 				strncpy(info.host, &ap[1], NAMELEN);
295*219b2ee8SDavid du Colombier 			info.host[strlen(info.host)] = '\0';
296*219b2ee8SDavid du Colombier 			break;
297*219b2ee8SDavid du Colombier 		case 'P':
298*219b2ee8SDavid du Colombier 			if (ap[1] == '\0')
299*219b2ee8SDavid du Colombier 				strncpy(info.user, "unknown", NAMELEN);
300*219b2ee8SDavid du Colombier 			else
301*219b2ee8SDavid du Colombier 				strncpy(info.user, &ap[1], NAMELEN);
302*219b2ee8SDavid du Colombier 			info.user[strlen(info.user)] = '\0';
303*219b2ee8SDavid du Colombier 			break;
304*219b2ee8SDavid du Colombier 		}
305*219b2ee8SDavid du Colombier 	}
306*219b2ee8SDavid du Colombier 	return(&info);
307*219b2ee8SDavid du Colombier }
308*219b2ee8SDavid du Colombier 
309*219b2ee8SDavid du Colombier void
310*219b2ee8SDavid du Colombier alarmhandler(int sig) {
311*219b2ee8SDavid du Colombier 	signal(sig, alarmhandler);
312*219b2ee8SDavid du Colombier 	error("alarm at %d - %s\n", dbgstate, dbgstrings[dbgstate]);
313*219b2ee8SDavid du Colombier }
314*219b2ee8SDavid du Colombier 
315*219b2ee8SDavid du Colombier main()
316*219b2ee8SDavid du Colombier {
317*219b2ee8SDavid du Colombier 	char *ap, *bp, *cp, *savbufpnt;
318*219b2ee8SDavid du Colombier 	int i, blen, rv, saveflg, savargcnt;
319*219b2ee8SDavid du Colombier 	struct jobinfo *jinfop;
320*219b2ee8SDavid du Colombier 
321*219b2ee8SDavid du Colombier 	signal(1, SIG_IGN);		/* SIGHUP not in lcc */
322*219b2ee8SDavid du Colombier 	signal(14, alarmhandler);	/* SIGALRM not in lcc */
323*219b2ee8SDavid du Colombier 	cp = argvstr;
324bd389b36SDavid du Colombier 	/* setup argv[0] for exec */
325*219b2ee8SDavid du Colombier 	argvals[argcnt++] = cp;
326*219b2ee8SDavid du Colombier 	for (bp = LP, i = 0; (*bp != '\0') && (i < ARGSIZ-1); *cp++ = *bp++, i++);
327*219b2ee8SDavid du Colombier 	*cp++ = '\0';
328*219b2ee8SDavid du Colombier 	/* get the first line sent and parse it as arguments for lp */
329*219b2ee8SDavid du Colombier 	if ((rv=readline(0)) < 0)
330*219b2ee8SDavid du Colombier 		exit(1);
331*219b2ee8SDavid du Colombier 	ap = lnbuf;
332*219b2ee8SDavid du Colombier 	bp = ap;
333bd389b36SDavid du Colombier 	/* setup the remaining arguments */
334*219b2ee8SDavid du Colombier 	/* check for BSD style request */
335*219b2ee8SDavid du Colombier 	/* ^A, ^B, ^C, ^D, ^E (for BSD lpr) */
336*219b2ee8SDavid du Colombier 	switch (*bp) {
337*219b2ee8SDavid du Colombier 	case '\001':
338*219b2ee8SDavid du Colombier 	case '\003':
339*219b2ee8SDavid du Colombier 	case '\004':
340*219b2ee8SDavid du Colombier 		bp++;	/* drop the ctrl character from the input */
341*219b2ee8SDavid du Colombier 		argvals[argcnt++] = cp;
342*219b2ee8SDavid du Colombier 		*cp++ = '-'; *cp++ = 'q'; *cp++ = '\0';		/* -q */
343*219b2ee8SDavid du Colombier 		argvals[argcnt++] = cp;
344*219b2ee8SDavid du Colombier 		*cp++ = '-'; *cp++ = 'd'; 			/* -d */
345*219b2ee8SDavid du Colombier 		CPYFIELD(bp, cp);				/* printer */
346*219b2ee8SDavid du Colombier 		*cp++ = '\0';
347*219b2ee8SDavid du Colombier 		break;
348*219b2ee8SDavid du Colombier 	case '\002':
349*219b2ee8SDavid du Colombier 		bp++;	/* drop the ctrl character from the input */
350*219b2ee8SDavid du Colombier 		argvals[argcnt++] = cp;
351*219b2ee8SDavid du Colombier 		*cp++ = '-'; *cp++ = 'd'; 			/* -d */
352*219b2ee8SDavid du Colombier 		CPYFIELD(bp, cp);				/* printer */
353*219b2ee8SDavid du Colombier 		*cp++ = '\0';
354*219b2ee8SDavid du Colombier 		ACK();
355*219b2ee8SDavid du Colombier 		savargcnt = argcnt;
356*219b2ee8SDavid du Colombier 		savbufpnt = cp;
357*219b2ee8SDavid du Colombier 		while ((rv=getfiles())) {
358*219b2ee8SDavid du Colombier 			jinfop = getjobinfo(cntrlfd);
359*219b2ee8SDavid du Colombier 			close(cntrlfd);
360*219b2ee8SDavid du Colombier 			argcnt = savargcnt;
361*219b2ee8SDavid du Colombier 			cp = savbufpnt;
362*219b2ee8SDavid du Colombier 			argvals[argcnt++] = cp;
363*219b2ee8SDavid du Colombier 			*cp++ = '-'; *cp++ = 'M'; 			/* -M */
364*219b2ee8SDavid du Colombier 			bp = jinfop->host;
365*219b2ee8SDavid du Colombier 			CPYFIELD(bp, cp);				/* host name */
366*219b2ee8SDavid du Colombier 			*cp++ = '\0';
367*219b2ee8SDavid du Colombier 			argvals[argcnt++] = cp;
368*219b2ee8SDavid du Colombier 			*cp++ = '-'; *cp++ = 'u'; 			/* -u */
369*219b2ee8SDavid du Colombier 			bp = jinfop->user;
370*219b2ee8SDavid du Colombier 			CPYFIELD(bp, cp);				/* user name */
371*219b2ee8SDavid du Colombier 			*cp++ = '\0';
372*219b2ee8SDavid du Colombier 			for(i=0;i<rv;i++)
373*219b2ee8SDavid du Colombier 				forklp(datafd[i]);
374*219b2ee8SDavid du Colombier 		}
375*219b2ee8SDavid du Colombier 		exit(0);
376*219b2ee8SDavid du Colombier 	case '\005':
377*219b2ee8SDavid du Colombier 		bp++;	/* drop the ctrl character from the input */
378*219b2ee8SDavid du Colombier 		argvals[argcnt++] = cp;
379*219b2ee8SDavid du Colombier 		*cp++ = '-'; *cp++ = 'k'; *cp++ = '\0';		/* -k */
380*219b2ee8SDavid du Colombier 		argvals[argcnt++] = cp;
381*219b2ee8SDavid du Colombier 		*cp++ = '-'; *cp++ = 'd'; 			/* -d */
382*219b2ee8SDavid du Colombier 		CPYFIELD(bp, cp);				/* printer */
383*219b2ee8SDavid du Colombier 		*cp++ = '\0';
384*219b2ee8SDavid du Colombier 		argvals[argcnt++] = cp;
385*219b2ee8SDavid du Colombier 		*cp++ = '-'; *cp++ = 'u'; 			/* -u */
386*219b2ee8SDavid du Colombier 		CPYFIELD(bp, cp);				/* username */
387*219b2ee8SDavid du Colombier 		*cp++ = '\0';
388*219b2ee8SDavid du Colombier 		datafd[0] = tempfile();
389*219b2ee8SDavid du Colombier 		blen = strlen(bp);
390*219b2ee8SDavid du Colombier 		if (write(datafd[0], bp, blen) != blen) {
391*219b2ee8SDavid du Colombier 			error("write error\n");
392*219b2ee8SDavid du Colombier 			exit(6);
393*219b2ee8SDavid du Colombier 		}
394*219b2ee8SDavid du Colombier 		if (write(datafd[0], "\n", 1) != 1) {
395*219b2ee8SDavid du Colombier 			error("write error\n");
396*219b2ee8SDavid du Colombier 			exit(6);
397*219b2ee8SDavid du Colombier 		}
398*219b2ee8SDavid du Colombier 		break;
399*219b2ee8SDavid du Colombier 	default:
400*219b2ee8SDavid du Colombier 		/* otherwise get my lp arguments */
401bd389b36SDavid du Colombier 		do {
402bd389b36SDavid du Colombier 			/* move to next non-white space */
403*219b2ee8SDavid du Colombier 			while (*bp==' '||*bp=='\t')
404bd389b36SDavid du Colombier 				++bp;
405*219b2ee8SDavid du Colombier 			if (*bp=='\n') continue;
406bd389b36SDavid du Colombier 			/* only accept arguments beginning with -
407bd389b36SDavid du Colombier 			 * this is done to prevent the printing of
408bd389b36SDavid du Colombier 			 * local files from the destination host
409bd389b36SDavid du Colombier 			 */
410bd389b36SDavid du Colombier 			if (*bp=='-') {
411*219b2ee8SDavid du Colombier 				argvals[argcnt++] = cp;
412bd389b36SDavid du Colombier 				saveflg = 1;
413bd389b36SDavid du Colombier 			} else
414bd389b36SDavid du Colombier 				saveflg = 0;
415bd389b36SDavid du Colombier 			/* move to next white space copying text to argument buffer */
416*219b2ee8SDavid du Colombier 			while (*bp!=' ' && *bp!='\t' && *bp!='\n'
417bd389b36SDavid du Colombier 			    && *bp!='\0') {
418*219b2ee8SDavid du Colombier 				*cp = *bp++;
419*219b2ee8SDavid du Colombier 				cp += saveflg;
420bd389b36SDavid du Colombier 			}
421*219b2ee8SDavid du Colombier 			*cp = '\0';
422*219b2ee8SDavid du Colombier 			cp += saveflg;
423*219b2ee8SDavid du Colombier 		} while (*bp!='\n');
424*219b2ee8SDavid du Colombier 		if (readline(0) == 0) exit(7);
425*219b2ee8SDavid du Colombier 		datafd[0] = tempfile();
426*219b2ee8SDavid du Colombier 		if(readfile(datafd[0], atoi(lnbuf)) < 0) {
427*219b2ee8SDavid du Colombier 			error("readfile failed\n");
428*219b2ee8SDavid du Colombier 			exit(8);
429bd389b36SDavid du Colombier 		}
430bd389b36SDavid du Colombier 	}
431*219b2ee8SDavid du Colombier 	forklp(datafd[0]);
432*219b2ee8SDavid du Colombier 	exit(0);
433bd389b36SDavid du Colombier }
434