xref: /plan9/sys/src/cmd/lp/lpdaemon.c (revision ea9142f784780976853734326525003db057e8e9)
1219b2ee8SDavid du Colombier #include <stdio.h>
243af371bSDavid du Colombier #include <stdlib.h>
3219b2ee8SDavid du Colombier #include <string.h>
443af371bSDavid du Colombier #include <errno.h>
543af371bSDavid du Colombier #include <fcntl.h>
643af371bSDavid du Colombier #include <signal.h>
77dd7cddfSDavid du Colombier #include <stdarg.h>
843af371bSDavid du Colombier #include <time.h>
943af371bSDavid du Colombier #include <unistd.h>
1043af371bSDavid du Colombier #include <sys/types.h>
1143af371bSDavid du Colombier #include <sys/wait.h>
12bd389b36SDavid du Colombier 
13bd389b36SDavid du Colombier /* for Plan 9 */
14219b2ee8SDavid du Colombier #ifdef PLAN9
15bd389b36SDavid du Colombier #define LP	"/bin/lp"
16219b2ee8SDavid du Colombier #define TMPDIR "/sys/lib/lp/tmp"
17219b2ee8SDavid du Colombier #define LPDAEMONLOG	"/sys/lib/lp/log/lpdaemonl"
18219b2ee8SDavid du Colombier #endif
19bd389b36SDavid du Colombier /* for Tenth Edition systems */
20219b2ee8SDavid du Colombier #ifdef V10
21219b2ee8SDavid du Colombier #define LP	"/usr/bin/lp"
22219b2ee8SDavid du Colombier #define TMPDIR "/tmp"
23bd389b36SDavid du Colombier #define LPDAEMONLOG	"/tmp/lpdaemonl"
24219b2ee8SDavid du Colombier #endif
25219b2ee8SDavid du Colombier /* for System V or BSD systems */
26219b2ee8SDavid du Colombier #if defined(SYSV) || defined(BSD)
27219b2ee8SDavid du Colombier #define LP	"/v/bin/lp"
28219b2ee8SDavid du Colombier #define TMPDIR "/tmp"
29219b2ee8SDavid du Colombier #define LPDAEMONLOG	"/tmp/lpdaemonl"
30219b2ee8SDavid du Colombier #endif
31bd389b36SDavid du Colombier 
32bd389b36SDavid du Colombier #define ARGSIZ 4096
33219b2ee8SDavid du Colombier #define NAMELEN 30
34bd389b36SDavid du Colombier 
3580ee5cbfSDavid du Colombier unsigned char argvstr[ARGSIZ];		/* arguments after parsing */
3680ee5cbfSDavid du Colombier unsigned char *argvals[ARGSIZ/2+1];	/* pointers to arguments after parsing */
37bd389b36SDavid du Colombier int ascnt = 0, argcnt = 0;	/* number of arguments parsed */
38219b2ee8SDavid du Colombier /* for 'stuff' gleened from lpr cntrl file */
39219b2ee8SDavid du Colombier struct jobinfo {
40219b2ee8SDavid du Colombier 	char user[NAMELEN+1];
41219b2ee8SDavid du Colombier 	char host[NAMELEN+1];
42219b2ee8SDavid du Colombier } *getjobinfo();
43bd389b36SDavid du Colombier 
44219b2ee8SDavid du Colombier #define MIN(a,b)	((a<b)?a:b)
45219b2ee8SDavid du Colombier 
46219b2ee8SDavid du Colombier #define	CPYFIELD(src, dst)	{ while (*(src)!=' ' && *(src)!='\t' && *(src)!='\r' && *(src)!='\n' && *(src)!='\0') *(dst)++ = *(src)++; }
47219b2ee8SDavid du Colombier 
48219b2ee8SDavid du Colombier #define	ACK()	write(1, "", 1)
49219b2ee8SDavid du Colombier #define NAK()	write(1, "\001", 1)
50219b2ee8SDavid du Colombier 
51219b2ee8SDavid du Colombier #define LNBFSZ	4096
5280ee5cbfSDavid du Colombier unsigned char lnbuf[LNBFSZ];
53219b2ee8SDavid du Colombier 
54219b2ee8SDavid du Colombier #define	RDSIZE 512
5580ee5cbfSDavid du Colombier unsigned char jobbuf[RDSIZE];
56219b2ee8SDavid du Colombier 
577dd7cddfSDavid du Colombier int datafd[400], cntrlfd = -1;
58219b2ee8SDavid du Colombier 
59219b2ee8SDavid du Colombier int dbgstate = 0;
60219b2ee8SDavid du Colombier char *dbgstrings[] = {
61219b2ee8SDavid du Colombier 	"",
62219b2ee8SDavid du Colombier 	"sendack1",
63219b2ee8SDavid du Colombier 	"send",
64219b2ee8SDavid du Colombier 	"rcvack",
65219b2ee8SDavid du Colombier 	"sendack2",
66219b2ee8SDavid du Colombier 	"done"
67219b2ee8SDavid du Colombier };
68bd389b36SDavid du Colombier 
69bd389b36SDavid du Colombier void
error(char * s1,...)70219b2ee8SDavid du Colombier error(char *s1, ...)
71bd389b36SDavid du Colombier {
72219b2ee8SDavid du Colombier 	FILE *fp;
73219b2ee8SDavid du Colombier 	long thetime;
74219b2ee8SDavid du Colombier 	char *chartime;
75219b2ee8SDavid du Colombier 	va_list ap;
76219b2ee8SDavid du Colombier 	char *args[8];
77219b2ee8SDavid du Colombier 	int argno = 0;
78bd389b36SDavid du Colombier 
79219b2ee8SDavid du Colombier 	if((fp=fopen(LPDAEMONLOG, "a"))==NULL) {
807dd7cddfSDavid du Colombier 		fprintf(stderr, "cannot open %s in append mode\n", LPDAEMONLOG);
81219b2ee8SDavid du Colombier 		return;
82bd389b36SDavid du Colombier 	}
83219b2ee8SDavid du Colombier 	time(&thetime);
84219b2ee8SDavid du Colombier 	chartime = ctime(&thetime);
857dd7cddfSDavid du Colombier 	fprintf(fp, "%.15s [%5.5d] ", &(chartime[4]), getpid());
86219b2ee8SDavid du Colombier 	va_start(ap, s1);
8743af371bSDavid du Colombier 	while((args[argno++] = va_arg(ap, char*)) && argno<8)
8843af371bSDavid du Colombier 		;
89219b2ee8SDavid du Colombier 	va_end(ap);
90219b2ee8SDavid du Colombier 	fprintf(fp, s1, args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]);
91219b2ee8SDavid du Colombier 	fclose(fp);
92219b2ee8SDavid du Colombier }
93219b2ee8SDavid du Colombier 
94219b2ee8SDavid du Colombier void
forklp(int inputfd)95219b2ee8SDavid du Colombier forklp(int inputfd)
96219b2ee8SDavid du Colombier {
97219b2ee8SDavid du Colombier 	int i, cpid;
9880ee5cbfSDavid du Colombier 	unsigned char *bp, *cp;
9980ee5cbfSDavid du Colombier 	unsigned char logent[LNBFSZ];
100219b2ee8SDavid du Colombier 
101219b2ee8SDavid du Colombier 	/* log this call to lp */
102219b2ee8SDavid du Colombier 	cp = logent;
103219b2ee8SDavid du Colombier 	for (i=1; i<argcnt; i++) {
104219b2ee8SDavid du Colombier 		bp = argvals[i];
10580ee5cbfSDavid du Colombier 		if (cp+strlen((const char *)bp)+1 < logent+LNBFSZ-1) {
106219b2ee8SDavid du Colombier 			CPYFIELD(bp, cp);
107219b2ee8SDavid du Colombier 			*cp++ = ' ';
108219b2ee8SDavid du Colombier 		}
109219b2ee8SDavid du Colombier 	}
110219b2ee8SDavid du Colombier 	*--cp = '\n';
111219b2ee8SDavid du Colombier 	*++cp = '\0';
11280ee5cbfSDavid du Colombier 	error((const char *)logent);
113219b2ee8SDavid du Colombier 	switch((cpid=fork())){
114219b2ee8SDavid du Colombier 	case -1:
115219b2ee8SDavid du Colombier 		error("fork error\n");
116219b2ee8SDavid du Colombier 		exit(2);
117219b2ee8SDavid du Colombier 	case 0:
118219b2ee8SDavid du Colombier 		if (inputfd != 0)
119219b2ee8SDavid du Colombier 			dup2(inputfd, 0);
120219b2ee8SDavid du Colombier 		dup2(1, 2);
121219b2ee8SDavid du Colombier 		lseek(0, 0L, 0);
12280ee5cbfSDavid du Colombier 		execvp(LP, (const char **)argvals);
123219b2ee8SDavid du Colombier 		error("exec failed\n");
124219b2ee8SDavid du Colombier 		exit(3);
125219b2ee8SDavid du Colombier 	default:
12643af371bSDavid du Colombier 		while(wait((int *)0) != cpid)
12743af371bSDavid du Colombier 			;
128219b2ee8SDavid du Colombier 	}
129219b2ee8SDavid du Colombier }
130219b2ee8SDavid du Colombier 
131219b2ee8SDavid du Colombier int
tempfile(void)132219b2ee8SDavid du Colombier tempfile(void)
133219b2ee8SDavid du Colombier {
134219b2ee8SDavid du Colombier 	static tindx = 0;
1357dd7cddfSDavid du Colombier 	char tmpf[sizeof(TMPDIR)+64];
136219b2ee8SDavid du Colombier 	int crtfd, tmpfd;
137219b2ee8SDavid du Colombier 
138219b2ee8SDavid du Colombier 	sprintf(tmpf, "%s/lp%d.%d", TMPDIR, getpid(), tindx++);
139219b2ee8SDavid du Colombier 	if((crtfd=creat(tmpf, 0666)) < 0) {
140219b2ee8SDavid du Colombier 		error("cannot create temp file %s\n", tmpf);
141219b2ee8SDavid du Colombier 		NAK();
142219b2ee8SDavid du Colombier 		exit(3);
143219b2ee8SDavid du Colombier 	}
144219b2ee8SDavid du Colombier 	if((tmpfd=open(tmpf, 2)) < 0) {
145219b2ee8SDavid du Colombier 		error("cannot open temp file %s\n", tmpf);
146219b2ee8SDavid du Colombier 		NAK();
147219b2ee8SDavid du Colombier 		exit(3);
148219b2ee8SDavid du Colombier 	}
149219b2ee8SDavid du Colombier 	close(crtfd);
150219b2ee8SDavid du Colombier 	unlink(tmpf);	/* comment out for debugging */
151219b2ee8SDavid du Colombier 	return(tmpfd);
152219b2ee8SDavid du Colombier }
153219b2ee8SDavid du Colombier 
154219b2ee8SDavid du Colombier int
readfile(int outfd,int bsize)155219b2ee8SDavid du Colombier readfile(int outfd, int bsize)
156219b2ee8SDavid du Colombier {
157219b2ee8SDavid du Colombier 	int rv;
158219b2ee8SDavid du Colombier 
159219b2ee8SDavid du Colombier 	dbgstate = 1;
160219b2ee8SDavid du Colombier 	alarm(60);
161219b2ee8SDavid du Colombier 	ACK();
162219b2ee8SDavid du Colombier 	dbgstate = 2;
163219b2ee8SDavid du Colombier 	for(; bsize > 0; bsize -= rv) {
164219b2ee8SDavid du Colombier 		alarm(60);
165219b2ee8SDavid du Colombier 		if((rv=read(0, jobbuf, MIN(bsize,RDSIZE))) < 0) {
166219b2ee8SDavid du Colombier 			error("error reading input, %d unread\n", bsize);
167219b2ee8SDavid du Colombier 			exit(4);
1687dd7cddfSDavid du Colombier 		} else if (rv == 0) {
1697dd7cddfSDavid du Colombier 			error("connection closed prematurely\n");
1707dd7cddfSDavid du Colombier 			exit(4);
171219b2ee8SDavid du Colombier 		} else if((write(outfd, jobbuf, rv)) != rv) {
172219b2ee8SDavid du Colombier 			error("error writing temp file, %d unread\n", bsize);
173219b2ee8SDavid du Colombier 			exit(5);
174219b2ee8SDavid du Colombier 		}
175219b2ee8SDavid du Colombier 	}
176219b2ee8SDavid du Colombier 	dbgstate = 3;
177219b2ee8SDavid du Colombier 	alarm(60);
178219b2ee8SDavid du Colombier 	if (((rv=read(0, jobbuf, 1))==1) && (*jobbuf=='\0')) {
179219b2ee8SDavid du Colombier 		alarm(60);
180219b2ee8SDavid du Colombier 		ACK();
181219b2ee8SDavid du Colombier 		dbgstate = 4;
182219b2ee8SDavid du Colombier 		alarm(0);
183219b2ee8SDavid du Colombier 		return(outfd);
184219b2ee8SDavid du Colombier 	}
185219b2ee8SDavid du Colombier 	alarm(0);
186219b2ee8SDavid du Colombier 	error("received bad status <%d> from sender\n", *jobbuf);
187219b2ee8SDavid du Colombier 	error("rv=%d\n", rv);
188219b2ee8SDavid du Colombier 	NAK();
189219b2ee8SDavid du Colombier 	return(-1);
190219b2ee8SDavid du Colombier }
191219b2ee8SDavid du Colombier 
192219b2ee8SDavid du Colombier /* reads a line from the input into lnbuf
193219b2ee8SDavid du Colombier  * if there is no error, it returns
194219b2ee8SDavid du Colombier  *   the number of characters in the buffer
195219b2ee8SDavid du Colombier  * if there is an error and there where characters
196219b2ee8SDavid du Colombier  *   read, it returns the negative value of the
197219b2ee8SDavid du Colombier  *   number of characters read
198219b2ee8SDavid du Colombier  * if there is an error and no characters were read,
199219b2ee8SDavid du Colombier  *   it returns the negative value of 1 greater than
200219b2ee8SDavid du Colombier  *   the size of the line buffer
201219b2ee8SDavid du Colombier  */
202219b2ee8SDavid du Colombier int
readline(int inpfd)203219b2ee8SDavid du Colombier readline(int inpfd)
204219b2ee8SDavid du Colombier {
20580ee5cbfSDavid du Colombier 	unsigned char *ap;
206219b2ee8SDavid du Colombier 	int i, rv;
207219b2ee8SDavid du Colombier 
208219b2ee8SDavid du Colombier 	ap = lnbuf;
2097dd7cddfSDavid du Colombier 	lnbuf[0] = '\0';
210219b2ee8SDavid du Colombier 	i = 0;
2117dd7cddfSDavid du Colombier 	alarm(60);
212219b2ee8SDavid du Colombier 	do {
213219b2ee8SDavid du Colombier 		rv = read(inpfd, ap, 1);
214219b2ee8SDavid du Colombier 	} while (rv==1 && ++i && *ap != '\n' && ap++ && (i < LNBFSZ - 2));
2157dd7cddfSDavid du Colombier 	alarm(0);
216219b2ee8SDavid du Colombier 	if (i != 0 && *ap != '\n') {
217219b2ee8SDavid du Colombier 		*++ap = '\n';
218219b2ee8SDavid du Colombier 		i++;
219219b2ee8SDavid du Colombier 	}
220219b2ee8SDavid du Colombier 	*++ap = '\0';
221219b2ee8SDavid du Colombier 	if (rv < 0) {
222219b2ee8SDavid du Colombier 		error("read error; lost connection\n");
223219b2ee8SDavid du Colombier 		if (i==0) i = -(LNBFSZ+1);
224219b2ee8SDavid du Colombier 		else i = -i;
225219b2ee8SDavid du Colombier 	}
226219b2ee8SDavid du Colombier 	return(i);
227219b2ee8SDavid du Colombier }
228219b2ee8SDavid du Colombier 
229219b2ee8SDavid du Colombier int
getfiles(void)230219b2ee8SDavid du Colombier getfiles(void)
231219b2ee8SDavid du Colombier {
23280ee5cbfSDavid du Colombier 	unsigned char *ap;
233219b2ee8SDavid du Colombier 	int filecnt, bsize, rv;
234219b2ee8SDavid du Colombier 
235219b2ee8SDavid du Colombier 	filecnt = 0;
236219b2ee8SDavid du Colombier 	/* get a line, hopefully containing a ctrl char, size, and name */
237219b2ee8SDavid du Colombier 	for(;;) {
238219b2ee8SDavid du Colombier 		ap = lnbuf;
239219b2ee8SDavid du Colombier 		if ((rv=readline(0)) < 0) NAK();
2407dd7cddfSDavid du Colombier 		if (rv <= 0) {
2417dd7cddfSDavid du Colombier 			return(filecnt);
2427dd7cddfSDavid du Colombier 		}
243219b2ee8SDavid du Colombier 		switch(*ap++) {
244219b2ee8SDavid du Colombier 		case '\1':		/* cleanup - data sent was bad (whatever that means) */
245219b2ee8SDavid du Colombier 			break;
246219b2ee8SDavid du Colombier 		case '\2':		/* read control file */
24780ee5cbfSDavid du Colombier 			bsize = atoi((const char *)ap);
248219b2ee8SDavid du Colombier 			cntrlfd = tempfile();
249219b2ee8SDavid du Colombier 			if (readfile(cntrlfd, bsize) < 0) {
250219b2ee8SDavid du Colombier 				close(cntrlfd);
251219b2ee8SDavid du Colombier 				NAK();
252219b2ee8SDavid du Colombier 				return(0);
253219b2ee8SDavid du Colombier 			}
254219b2ee8SDavid du Colombier 			break;
255219b2ee8SDavid du Colombier 		case '\3':		/* read data file */
25680ee5cbfSDavid du Colombier 			bsize = atoi((const char *)ap);
257219b2ee8SDavid du Colombier 			datafd[filecnt] = tempfile();
258219b2ee8SDavid du Colombier 			if (readfile(datafd[filecnt], bsize) < 0) {
259219b2ee8SDavid du Colombier 				close(datafd[filecnt]);
260219b2ee8SDavid du Colombier 				NAK();
261219b2ee8SDavid du Colombier 				return(0);
262219b2ee8SDavid du Colombier 			}
263219b2ee8SDavid du Colombier 			filecnt++;
264219b2ee8SDavid du Colombier 			break;
265219b2ee8SDavid du Colombier 		default:
266219b2ee8SDavid du Colombier 			error("protocol error <%d>\n", *(ap-1));
267219b2ee8SDavid du Colombier 			NAK();
268219b2ee8SDavid du Colombier 		}
269219b2ee8SDavid du Colombier 	}
270219b2ee8SDavid du Colombier 	return(filecnt);
271219b2ee8SDavid du Colombier }
272219b2ee8SDavid du Colombier 
273219b2ee8SDavid du Colombier struct jobinfo *
getjobinfo(int fd)274219b2ee8SDavid du Colombier getjobinfo(int fd)
275219b2ee8SDavid du Colombier {
27680ee5cbfSDavid du Colombier 	unsigned char *ap;
277219b2ee8SDavid du Colombier 	int rv;
278219b2ee8SDavid du Colombier 	static struct jobinfo info;
279219b2ee8SDavid du Colombier 
2807dd7cddfSDavid du Colombier 	if (fd < 0) error("getjobinfo: bad file descriptor\n");
281219b2ee8SDavid du Colombier 	if (lseek(fd, 0L, 0) < 0) {
282219b2ee8SDavid du Colombier 		error("error seeking in temp file\n");
283219b2ee8SDavid du Colombier 		exit(7);
284219b2ee8SDavid du Colombier 	}
285219b2ee8SDavid du Colombier 	/* the following strings should be < NAMELEN or else they will not
286219b2ee8SDavid du Colombier 	 * be null terminated.
287219b2ee8SDavid du Colombier 	 */
288219b2ee8SDavid du Colombier 	strncpy(info.user, "daemon", NAMELEN);
289219b2ee8SDavid du Colombier 	strncpy(info.host, "nowhere", NAMELEN);
290219b2ee8SDavid du Colombier 	/* there may be a space after the name and host.  It will be filtered out
291219b2ee8SDavid du Colombier 	 * by CPYFIELD.
292219b2ee8SDavid du Colombier 	 */
293219b2ee8SDavid du Colombier 	while ((rv=readline(fd)) > 0) {
294219b2ee8SDavid du Colombier 		ap = lnbuf;
295219b2ee8SDavid du Colombier 		ap[rv-1] = '\0';	/* remove newline from string */
296219b2ee8SDavid du Colombier 		switch (*ap) {
297219b2ee8SDavid du Colombier 		case 'H':
298219b2ee8SDavid du Colombier 			if (ap[1] == '\0')
299219b2ee8SDavid du Colombier 				strncpy(info.host, "unknown", NAMELEN);
300219b2ee8SDavid du Colombier 			else
30180ee5cbfSDavid du Colombier 				strncpy(info.host, (const char *)&ap[1], NAMELEN);
302*ea9142f7SDavid du Colombier 			info.host[NAMELEN] = '\0';
303219b2ee8SDavid du Colombier 			break;
304219b2ee8SDavid du Colombier 		case 'P':
305219b2ee8SDavid du Colombier 			if (ap[1] == '\0')
306219b2ee8SDavid du Colombier 				strncpy(info.user, "unknown", NAMELEN);
307219b2ee8SDavid du Colombier 			else
30880ee5cbfSDavid du Colombier 				strncpy(info.user, (const char *)&ap[1], NAMELEN);
309*ea9142f7SDavid du Colombier 			info.user[NAMELEN] = '\0';
310219b2ee8SDavid du Colombier 			break;
311219b2ee8SDavid du Colombier 		}
312219b2ee8SDavid du Colombier 	}
313219b2ee8SDavid du Colombier 	return(&info);
314219b2ee8SDavid du Colombier }
315219b2ee8SDavid du Colombier 
316219b2ee8SDavid du Colombier void
alarmhandler(int sig)317219b2ee8SDavid du Colombier alarmhandler(int sig) {
318219b2ee8SDavid du Colombier 	signal(sig, alarmhandler);
319219b2ee8SDavid du Colombier 	error("alarm at %d - %s\n", dbgstate, dbgstrings[dbgstate]);
320219b2ee8SDavid du Colombier }
321219b2ee8SDavid du Colombier 
322027288c8SDavid du Colombier void
main()323219b2ee8SDavid du Colombier main()
324219b2ee8SDavid du Colombier {
32580ee5cbfSDavid du Colombier 	unsigned char *ap, *bp, *cp, *savbufpnt;
326219b2ee8SDavid du Colombier 	int i, blen, rv, saveflg, savargcnt;
327219b2ee8SDavid du Colombier 	struct jobinfo *jinfop;
328219b2ee8SDavid du Colombier 
32943af371bSDavid du Colombier 	signal(SIGHUP, SIG_IGN);
33043af371bSDavid du Colombier 	signal(SIGALRM, alarmhandler);
331219b2ee8SDavid du Colombier 	cp = argvstr;
332bd389b36SDavid du Colombier 	/* setup argv[0] for exec */
333219b2ee8SDavid du Colombier 	argvals[argcnt++] = cp;
33480ee5cbfSDavid du Colombier 	for (bp = (unsigned char *)LP, i = 0; (*bp != '\0') && (i < ARGSIZ-1); *cp++ = *bp++, i++);
335219b2ee8SDavid du Colombier 	*cp++ = '\0';
336219b2ee8SDavid du Colombier 	/* get the first line sent and parse it as arguments for lp */
337219b2ee8SDavid du Colombier 	if ((rv=readline(0)) < 0)
338219b2ee8SDavid du Colombier 		exit(1);
3393ff48bf5SDavid du Colombier 	bp = lnbuf;
340bd389b36SDavid du Colombier 	/* setup the remaining arguments */
341219b2ee8SDavid du Colombier 	/* check for BSD style request */
342219b2ee8SDavid du Colombier 	/* ^A, ^B, ^C, ^D, ^E (for BSD lpr) */
343219b2ee8SDavid du Colombier 	switch (*bp) {
344219b2ee8SDavid du Colombier 	case '\001':
345219b2ee8SDavid du Colombier 	case '\003':
346219b2ee8SDavid du Colombier 	case '\004':
347219b2ee8SDavid du Colombier 		bp++;	/* drop the ctrl character from the input */
348219b2ee8SDavid du Colombier 		argvals[argcnt++] = cp;
349219b2ee8SDavid du Colombier 		*cp++ = '-'; *cp++ = 'q'; *cp++ = '\0';		/* -q */
350219b2ee8SDavid du Colombier 		argvals[argcnt++] = cp;
351219b2ee8SDavid du Colombier 		*cp++ = '-'; *cp++ = 'd'; 			/* -d */
352219b2ee8SDavid du Colombier 		CPYFIELD(bp, cp);				/* printer */
353219b2ee8SDavid du Colombier 		*cp++ = '\0';
354219b2ee8SDavid du Colombier 		break;
355219b2ee8SDavid du Colombier 	case '\002':
356219b2ee8SDavid du Colombier 		bp++;	/* drop the ctrl character from the input */
357219b2ee8SDavid du Colombier 		argvals[argcnt++] = cp;
358219b2ee8SDavid du Colombier 		*cp++ = '-'; *cp++ = 'd'; 			/* -d */
359219b2ee8SDavid du Colombier 		CPYFIELD(bp, cp);				/* printer */
360219b2ee8SDavid du Colombier 		*cp++ = '\0';
361219b2ee8SDavid du Colombier 		ACK();
362219b2ee8SDavid du Colombier 		savargcnt = argcnt;
363219b2ee8SDavid du Colombier 		savbufpnt = cp;
364219b2ee8SDavid du Colombier 		while ((rv=getfiles())) {
365219b2ee8SDavid du Colombier 			jinfop = getjobinfo(cntrlfd);
366219b2ee8SDavid du Colombier 			close(cntrlfd);
367219b2ee8SDavid du Colombier 			argcnt = savargcnt;
368219b2ee8SDavid du Colombier 			cp = savbufpnt;
369219b2ee8SDavid du Colombier 			argvals[argcnt++] = cp;
370219b2ee8SDavid du Colombier 			*cp++ = '-'; *cp++ = 'M'; 			/* -M */
37180ee5cbfSDavid du Colombier 			bp = (unsigned char *)jinfop->host;
372219b2ee8SDavid du Colombier 			CPYFIELD(bp, cp);				/* host name */
373219b2ee8SDavid du Colombier 			*cp++ = '\0';
374219b2ee8SDavid du Colombier 			argvals[argcnt++] = cp;
375219b2ee8SDavid du Colombier 			*cp++ = '-'; *cp++ = 'u'; 			/* -u */
37680ee5cbfSDavid du Colombier 			bp = (unsigned char *)jinfop->user;
377219b2ee8SDavid du Colombier 			CPYFIELD(bp, cp);				/* user name */
378219b2ee8SDavid du Colombier 			*cp++ = '\0';
379219b2ee8SDavid du Colombier 			for(i=0;i<rv;i++)
380219b2ee8SDavid du Colombier 				forklp(datafd[i]);
381219b2ee8SDavid du Colombier 		}
382219b2ee8SDavid du Colombier 		exit(0);
383219b2ee8SDavid du Colombier 	case '\005':
384219b2ee8SDavid du Colombier 		bp++;	/* drop the ctrl character from the input */
385219b2ee8SDavid du Colombier 		argvals[argcnt++] = cp;
386219b2ee8SDavid du Colombier 		*cp++ = '-'; *cp++ = 'k'; *cp++ = '\0';		/* -k */
387219b2ee8SDavid du Colombier 		argvals[argcnt++] = cp;
388219b2ee8SDavid du Colombier 		*cp++ = '-'; *cp++ = 'd'; 			/* -d */
389219b2ee8SDavid du Colombier 		CPYFIELD(bp, cp);				/* printer */
390219b2ee8SDavid du Colombier 		*cp++ = '\0';
391219b2ee8SDavid du Colombier 		argvals[argcnt++] = cp;
3923ff48bf5SDavid du Colombier 		*cp++ = '-'; ap = cp; *cp++ = 'u'; 		/* -u */
393219b2ee8SDavid du Colombier 		CPYFIELD(bp, cp);				/* username */
3943ff48bf5SDavid du Colombier 
3953ff48bf5SDavid du Colombier 		/* deal with bug in lprng where the username is not supplied
3963ff48bf5SDavid du Colombier 		 */
3973ff48bf5SDavid du Colombier 		if (ap == (cp-1)) {
3983ff48bf5SDavid du Colombier 			ap = (unsigned char *)"none";
3993ff48bf5SDavid du Colombier 			CPYFIELD(ap, cp);
4003ff48bf5SDavid du Colombier 		}
4013ff48bf5SDavid du Colombier 
402219b2ee8SDavid du Colombier 		*cp++ = '\0';
403219b2ee8SDavid du Colombier 		datafd[0] = tempfile();
40480ee5cbfSDavid du Colombier 		blen = strlen((const char *)bp);
405219b2ee8SDavid du Colombier 		if (write(datafd[0], bp, blen) != blen) {
406219b2ee8SDavid du Colombier 			error("write error\n");
407219b2ee8SDavid du Colombier 			exit(6);
408219b2ee8SDavid du Colombier 		}
409219b2ee8SDavid du Colombier 		if (write(datafd[0], "\n", 1) != 1) {
410219b2ee8SDavid du Colombier 			error("write error\n");
411219b2ee8SDavid du Colombier 			exit(6);
412219b2ee8SDavid du Colombier 		}
413219b2ee8SDavid du Colombier 		break;
414219b2ee8SDavid du Colombier 	default:
415219b2ee8SDavid du Colombier 		/* otherwise get my lp arguments */
416bd389b36SDavid du Colombier 		do {
417bd389b36SDavid du Colombier 			/* move to next non-white space */
418219b2ee8SDavid du Colombier 			while (*bp==' '||*bp=='\t')
419bd389b36SDavid du Colombier 				++bp;
420219b2ee8SDavid du Colombier 			if (*bp=='\n') continue;
421bd389b36SDavid du Colombier 			/* only accept arguments beginning with -
422bd389b36SDavid du Colombier 			 * this is done to prevent the printing of
423bd389b36SDavid du Colombier 			 * local files from the destination host
424bd389b36SDavid du Colombier 			 */
425bd389b36SDavid du Colombier 			if (*bp=='-') {
426219b2ee8SDavid du Colombier 				argvals[argcnt++] = cp;
427bd389b36SDavid du Colombier 				saveflg = 1;
428bd389b36SDavid du Colombier 			} else
429bd389b36SDavid du Colombier 				saveflg = 0;
430bd389b36SDavid du Colombier 			/* move to next white space copying text to argument buffer */
431219b2ee8SDavid du Colombier 			while (*bp!=' ' && *bp!='\t' && *bp!='\n'
432bd389b36SDavid du Colombier 			    && *bp!='\0') {
433219b2ee8SDavid du Colombier 				*cp = *bp++;
434219b2ee8SDavid du Colombier 				cp += saveflg;
435bd389b36SDavid du Colombier 			}
436219b2ee8SDavid du Colombier 			*cp = '\0';
437219b2ee8SDavid du Colombier 			cp += saveflg;
4387dd7cddfSDavid du Colombier 		} while (*bp!='\n' && *bp!='\0');
4397dd7cddfSDavid du Colombier 		if (readline(0) < 0) exit(7);
440219b2ee8SDavid du Colombier 		datafd[0] = tempfile();
44180ee5cbfSDavid du Colombier 		if(readfile(datafd[0], atoi((const char *)lnbuf)) < 0) {
442219b2ee8SDavid du Colombier 			error("readfile failed\n");
443219b2ee8SDavid du Colombier 			exit(8);
444bd389b36SDavid du Colombier 		}
445bd389b36SDavid du Colombier 	}
446219b2ee8SDavid du Colombier 	forklp(datafd[0]);
447219b2ee8SDavid du Colombier 	exit(0);
448bd389b36SDavid du Colombier }
449