9fans archive / 1996 / 01 / 14 /    prev next

From: G. David Butler gdb@dbS...
Subject: Setting up lp for PC
Date: Mon, 8 Jan 1996 09:31:37 -0500

This is how I added a postscript printer on serial port
eia1 on a PC cpu server named cpu1.

To drive a printer on the parallel port, a different
approach is required since tcpostio requires feedback
from the printer and the parallel interface is one way.
Basically a lptsrv needs to be written that opens
/dev/lpt1data write only and emulates the responses
from tcpostio.  A simpler approach would be to change
the daemon side alltogether so it doesn't chat with
the printer.

Since I have a file server that does *NOT* have a WORM,
I have all the cpus and terminals share the /sys/lib/lp
directory and use the queue and tmp directories there.
(In other words, no bootes "other" file system.)

After these changes, one can print from the cpu console
and any terminal or cpu window.

I would like to have some feedback to the code in eiasrv.c.
Did I do all the "proper" Plan 9 things?

Enjoy.

David Butler
gdb@dbS...


==================================================
add to /sys/lib/lp/devices: (line broken for readability)
ps	Office	cpu1	/srv/eia1	512	post+nohead	generic
generic	generic	generic	tcppost	FIFO

==================================================
/sys/lib/lp/bin/lpsend.rc (/sys/src/cmd/lp/lpsend.rc):
diff -e lpsend.rc.cdrom lpsend.rc
24,32c
#if (test -e /net/dk/clone || import helix /net/dk) {
# 	dialstring=`{ndb/query sys $1 dk}
#	network=dk
#	if (! ~ $dialstring '') {
#		if(lpsend $dialstring $network printer) exit ''
#	}
#	rv=$rv^', dk failed'
#}
#if not rv=$rv^', no dk'
.
5c
if (test -e /net/tcp/clone || import cpu1 /net/tcp) {
.

==================================================
/rc/bin/lp (/sys/src/cmd/lp/lp.rc):
diff -e lp.rc.cdrom lp.rc
17,21c
#if (! test -r /srv/bootes) srv -m bootes
#if (! mount -c /srv/bootes /n/bootesother other || ! bind -a /n/bootesother/lp /sys/lib/lp) {
#	echo 'could not properly setup LPSPOOL' >[1=2]
#	exit 'LPSPOOL setup'
#}
.

==================================================
/386/bin/aux/lpdaemon (/sys/src/cmd/lp/lpdaemon.c):
diff -e lpdaemon.c.cdrom lpdaemon.c
423a
		ACK();
.
153c
	return(fd);
.
151d
146c
	close(fd);
	if((fd=open(tmpf, 2)) < 0) {
.
141c
	if((fd=creat(tmpf, 0666)) < 0) {
.
137,138c
	char tmpf[100];
	int fd;
.
92a
#else
	fputs(s1, fp);
#endif
.
91a
#ifndef PLAN9
.
90a
#else
	vfprintf(fp, s1, ap);
#endif
.
89a
#ifndef PLAN9
.
79a
#endif
.
77a
#ifndef PLAN9
.

==================================================
/386/bin/aux/tcpostio (/sys/src/cmd/postscript/tcpostio.l):
diff -e tcpostio.l.cdrom tcpostio.l
412c
				fprint(2, ". %5.2f%% sent, %.100s\n", bytes_sent*100.0/bytes_to_send, statusbuf);
.
283c
				blocksize = atoi(av);
.
197c
byte statusbuf[PRBUFSIZ];
.
177c
			if (write(printerfd, "\004", 1) != 1) {
.
162c
					if (write(printerfd, "\004", 1) != 1) {
.
149c
			if (write(printerfd, "\024", 1) != 1) {
.
123,124c
				if (*(ke = find(ks, ":")) == '\0') {
					return(PR_UNKNOWN);
				}
				kl = ke - ks;
.
120a
				return(statuslist[i].val);
.
117,118c
						break;
.
103c
			vl = ve - vs;
.
91,92c
		if (*(ke = find(ks, ":")) == '\0') {
			return(PR_UNKNOWN);
		}
		kl = ke - ks;
.
59c
	{ nil, PR_UNKNOWN }
.

==================================================
/386/bin/aux/eiasrv (/sys/src/cmd/aux/eiasrv.c):
cat eiasrv.c
/*
 * Copyright (c) 1996 G. David Butler
 * All Rights Reserved.
 *
 * Unrestricted use of this source is granted as long as
 * the above copyright remains.
 */

#include <u.h>
#include <libc.h>

#define PRBUFSIZ 8192	/* from /sys/src/cmd/postscript/tcpostio/tcpostio.h */

char Srvfilename[256];
int Childpid;

/* remove the /srv entry and kill the child at exit */
void
cleanup(void)
{
	remove(Srvfilename);
	postnote(PNPROC, Childpid, "kill");
}

/* on interrupt, if in the child writing to pipe, OK */
/* else, cleanup and exit */
int
notehandler(void *, char *note) {
	static char *pipenote = "sys: write on closed pipe";

	if (strncmp(note, pipenote, sizeof(pipenote) - 1) == 0) {
		return 1;
	}
	cleanup();
	return 0;
}

void
main(int argc, char *argv[])
{
	int blocksize;	/* see tcpostio.l about this */
	int baud;		/* rate of the serial device */
	int outputfd;	/* fd to serial device */
	int inputfd;	/* fd from pipe on /srv */
	int pipefd[2];
	char buf[PRBUFSIZ];

	blocksize = PRBUFSIZ;
	baud = 9600;	/* default rate */

	ARGBEGIN {
	case 'B':
		blocksize = atoi(ARGF());
		break;
	case 'b':
		baud = atoi(ARGF());
		break;
	default:
		fprint(2, "%s: badflag('%c')\n", argv0, ARGC());
		break;
	} ARGEND

	if (argc != 1 || baud == 0) {
		fprint(2, "Usage: %s [-B blocksize] [-b baud] device\n", argv0);
		exits("fatal");
	}

	if (blocksize < 1 || blocksize > PRBUFSIZ) {
		blocksize = PRBUFSIZ;
	}

	if ((outputfd = open(*argv, ORDWR)) < 0) {
		fprint(2, "%s: open of (%s) failed: %r\n", argv0, *argv);
		exits("fatal");
	}

	/* set the port up correctly for I/O */
	sprint(Srvfilename, "%sctl", *argv);
	if ((inputfd = open(Srvfilename, OWRITE)) < 0) {
		fprint(2, "%s: open of (%s) failed: %r\n", argv0, Srvfilename);
		exits("fatal");
	}

	sprint(buf, "b%d", baud);
	if (write(inputfd, buf, strlen(buf)) < 0 ||
	    write(inputfd, "d1", 2) < 0 ||
	    write(inputfd, "r1", 2) < 0 ||
	    write(inputfd, "m1", 2) < 0 ||
	    write(inputfd, "pn", 2) < 0 ||
	    write(inputfd, "s1", 2) < 0 ||
	    write(inputfd, "l8", 2) < 0) {
		fprint(2, "%s: write to (%s) failed: %r\n", argv0, Srvfilename);
		exits("fatal");
	}
	close(inputfd);

	/* this is the name of our "named pipe" */
	sprint(Srvfilename, "/srv%s", strrchr(*argv, '/'));
	if ((inputfd = create(Srvfilename, OWRITE, 0666)) < 0) {
		fprint(2, "%s: create of (%s) failed: %r\n", argv0, Srvfilename);
		exits("fatal");
	}

	atexit(cleanup);

	if (pipe(pipefd) < 0) {
		fprint(2, "%s: pipe failed: %r\n", argv0);
		exits("fatal");
	}

	sprint(buf, "%d", pipefd[0]);
	if (write (inputfd, buf, strlen(buf)) < 0) {
		fprint(2, "%s: write to (%s) failed: %r\n", argv0, Srvfilename);
		exits("fatal");
	}

	close(inputfd);
	close(pipefd[0]);
	inputfd = pipefd[1];

	atnotify(notehandler, 1);

	/* the parent and child can share */
	if (Childpid = rfork(RFPROC)) {

		while ((pipefd[0] = read(inputfd, buf, blocksize)) >= 0) {
			pipefd[1] = 0;
			while (pipefd[1] < pipefd[0]) {
				if ((baud = write(outputfd, buf, pipefd[0])) < 0) {
					fprint(2, "%s: parent write failed: %r\n", argv0);
					exits("fatal");
				}
				pipefd[1] += baud;
			}
		}

		if (pipefd[0] < 0) {
			fprint(2, "%s: parent read failed: %r\n", argv0);
			exits("fatal");
		} else {
			exits("");
		}

	} else {

		while ((pipefd[0] = read(outputfd, buf, blocksize)) >= 0) {
			pipefd[1] = 0;
			while (pipefd[1] < pipefd[0]) {
				if ((baud = write(inputfd, buf, pipefd[0])) < 0) {
					buf[0] = '\0';
					errstr(buf);
					if (strcmp(buf, "interrupted") == 0) {
						pipefd[1] = pipefd[0];
						continue;
					} else {
						fprint(2, "%s: child write failed: %s\n", argv0, buf);
						exits("fatal");
					}
				}
				pipefd[1] += baud;
			}
		}

		if (pipefd[0] < 0) {
			fprint(2, "%s: child read failed: %r\n", argv0);
			exits("fatal");
		} else {
			exits("");
		}
	}
}


==================================================
/sys/src/cmd/aux/mkfile:
diff -e mkfile.cdrom mkfile
10a
	eiasrv\
.


==================================================
/rc/bin/cpurc:
	add a line to your cpu server bootup like:
		aux/eiasrv -b 38400 /dev/eia1 &