In the following text, I will assume that your printer itself is working properly. I.e., you are able to send data to the printer in such a way that it responds by - well, printing the text :)
How to ensure this is highly system-dependent and falls outside the scope of this document. However, here are some hints.
Gordon Haverland
<haverlan@agric.gov.ab.ca
> supplied this little script,
that will put you on the right track:
#!/bin/sh #set -v -x # uncomment for debugging PATH=/bin:/usr/bin printer= for $i in $*; do case $i in /dev/*) printer=$i ;; *) ;; esac done if test -z "$printer"; then echo USAGE: $0 device_name ; exit 1; fi; echo PRINTER TEST to $printer 1>&2 for i in 1 2 3 4 5 6 7 8 9; do echo $i > $printer; done echo -e \\r\\f > $printer exit 0;
If your printer is connected to the device name you provided, then you should get a page of something out. If the output suffers from the ``staircase'' effect, you will see the numbers ``marching'' across the page, otherwise the numbers will all be in a single column.
If your printer is attached by a serial line, then you may need to set the serial line characteristictics before sending the job to the printer. Here are a set of guidelines to following when attaching a serial port printer to a serial line.
1. Check to make sure that the line is not enabled for login.
Logins are usually managed by the
getty
(BSD)
or
ttymon
(Solaris, SystemV).
Check your system documentation and make sure that these daemons are not
managing the serial line.
2. Check the permissions and ownership of the serial line. For the most easy testing, set the permissions to 0666 (everybody can open for reading and writing). After you have made sure that you can send jobs to the printer, you might want to change the ownership of the serial line to the LPD server and change the permissions to 0600.
3. Make sure that you can print a test file on the printer via the serial port. This may require setting the line characteristictics and then sending a file to the printer. You should try to use 8 bit, no parity, with hardware flow control and no special character interpretation, and definitely no LF to CR/LF translation. The problem is that different versions of UNIX systems have different sets of stty(1) commands to do this. The following simple test script can help in this.
#!/bin/sh # 9600, no echo, no CR FLAGS= 9600 -raw -parenb cs8 crtscts DEV= /dev/tty01 (stty $FLAGS; stty 1>&2; cat $1 ) <$DEV >$DEV
This shows using stty to set the flags, then to print the current settings, and then using cat a file to the output. If you attach a dumb terminal to the serial port, you can even use this script to ensure that input from the device is echoed to the output with the correct speed, parity, etc.
fc,fs,xc,xs
To LPRng sy
Justin Mason
<jmason@iona.ie>
and Updated by Patrick Powell
<papowell@sdsu.edu>
:
One of the worst things about old LPDs is that they expected you
to give it line characteristictics as octal numbers, using the
fc,fs,xc,xs printcap parameters. There are a number of disadvantages
to this, compared to using the ty
parameter.
The sy format is portable, as it is supported on all UNIXes, rather
than simply BSD-derived ones; it's also much easier to understand
than the fc,fs,xc,xs
format -- compare the two:
# new format :sy=pass8 -parity tabs litout nl: # old format :fc#0000374:fs#0000003:xc#0:xs#0040040:
Note, also, that sy
uses the same symbolic names as the stty
command, which is (relatively) well documented.
Anyway, assuming you have a set of printcaps which use the fc
,fs
,xc
,xs
method, you can convert them to sy
strings using the following
table.
Each parameter is an octal number, composed by logical-or'ing the bits for the desired parameters together. The bit patterns below have been worked out from SunOS 4.1.2 /usr/include/sys/ttold.h. For example, the following fc,fs,xc,xs set:
:fc#0000374:fs#0000003:xc#0:xs#0040040:converts to the following sy string:
:sy=-parity -echo -crmod -raw -lcase tandem cbreak litout decctq:
Quite often, the resulting strings seem a little complicated, but
usually they can be broken down using combination modes. See the
printcap(5)
manual page for details of which combination modes
LPRng supports.
In order to help you, the 'xlate' program can be used to translate from the old to the new form. For example:
#> xlate ":fc#0000374:fs#0000003:xc#0:xs#0040040:" fc = 374 clear LCASE (simulate lower case) try '-lcase' clear ECHO (echo input) try '-echo' clear CRMOD (map \r to \r\n on output) try '-crmod' clear RAW (no i/o processing) try '-raw' clear ODDP (get/send odd parity) try '-oddp' clear EVENP (get/send even parity) try '-evenp' clear ANYP (get any parity/send none) try '-parity? anyp? pass8? (caution)' fs = 3 set TANDEM (send stopc on out q full) try 'tandem' set CBREAK (half-cooked mode) try 'cbreak' xc = 0 xs = 40040 set LITOUT (literal output) try 'litout' set DECCTQ (only ^Q starts after ^S) try 'decctlq'
Note that when you clear odd and even parity, then you get no parity or any parity. You should use -parity to be compatible. You might also want to add 'pass8' as well. Thus, using the xlate output, you would try:
:sy=-lcase -echo -crmod -raw -parity pass8 tandem cbreak litout decctlq:
Bits used in the fc, fs parameters:
TANDEM 00000001 /* send stopc on out q full */ CBREAK 00000002 /* half-cooked mode */ LCASE 00000004 /* simulate lower case */ ECHO 00000010 /* echo input */ CRMOD 00000020 /* map \r to \r\n on output */ RAW 00000040 /* no i/o processing */ ODDP 00000100 /* get/send odd parity */ EVENP 00000200 /* get/send even parity */ ANYP 00000300 /* get any parity/send none */ NLDELAY 00001400 /* \n delay */ NL0 00000000 NL1 00000400 /* tty 37 */ NL2 00001000 /* vt05 */ NL3 00001400 TBDELAY 00006000 /* horizontal tab delay */ TAB0 00000000 TAB1 00002000 /* tty 37 */ TAB2 00004000 XTABS 00006000 /* expand tabs on output */ CRDELAY 00030000 /* \r delay */ CR0 00000000 CR1 00010000 /* tn 300 */ CR2 00020000 /* tty 37 */ CR3 00030000 /* concept 100 */ VTDELAY 00040000 /* vertical tab delay */ FF0 00000000 FF1 00040000 /* tty 37 */ BSDELAY 00100000 /* \b delay */ BS0 00000000 BS1 00100000 ALLDELAY 00177400
Bits used in the xc, xs parameters:
CRTBS 00000001 /* do backspacing for crt */ PRTERA 00000002 /* \ ... / erase */ CRTERA 00000004 /* " \b " to wipe out char */ TILDE 00000010 /* hazeltine tilde kludge */ MDMBUF 00000020 /* start/stop output on carrier intr */ LITOUT 00000040 /* literal output */ TOSTOP 00000100 /* SIGSTOP on background output */ FLUSHO 00000200 /* flush output to terminal */ NOHANG 00000400 /* no SIGHUP on carrier drop */ CRTKIL 00002000 /* kill line with " \b " */ PASS8 00004000 /* pass 8 bits */ CTLECH 00010000 /* echo control chars as ^X */ PENDIN 00020000 /* tp->t_rawq needs reread */ DECCTQ 00040000 /* only ^Q starts after ^S */ NOFLSH 00100000 /* no output flush on signal */
The following program translates the various bits to stty
flags.
#include <stdio.h> #include <string.h> struct bits{ char *name; int bitfields; char *comment; char *try; int mask; }; /* f flags - used with the TIOCGET and the struct sgttyb.sg_flags field */ struct bits tiocget[] = { { "TANDEM",00000001, "send stopc on out q full", "tandem" }, { "CBREAK",00000002, "half-cooked mode", "cbreak" }, { "LCASE",00000004, "simulate lower case", "lcase" }, { "ECHO",00000010, "echo input", "echo" }, { "CRMOD",00000020, "map \\r to \\r\\n on output", "crmod" }, { "RAW",00000040, "no i/o processing", "raw" }, { "ODDP",00000100, "get/send odd parity", "oddp" }, { "EVENP",00000200, "get/send even parity", "evenp" }, { "ANYP",00000300, "get any parity/send none", "parity? anyp? pass8? (caution)" }, { "NL0",0000000, "new line delay", "nl??",00001400 }, { "NL1",00000400, "new line delay tty 37", "nl??",00001400 }, { "NL2",00001000, "new line delay vt05", "nl??",00001400 }, { "NL3",00001400, "new line delay", "nl??",00001400 }, { "TAB0",00000000, "tab expansion delay", "tab??",00006000 }, { "TAB1",00002000, "tab expansion delay tty 37", "tab??",00006000 }, { "TAB2",00004000, "tab expansion delay", "tab??",00006000 }, { "XTABS",00006000, "expand tabs on output", "tabs" }, { "CR0",00000000, "cr??", "",00030000 }, { "CR1",00010000, "tn 300", "cr??",00030000 }, { "CR2",00020000, "tty 37", "cr??",00030000 }, { "CR3",00030000, "concept 100", "cr??",00030000}, { "FF1",00040000, "form feed delay tty 37", "ff??" }, { "BS1",0010000, "backspace timing", "bs??" }, { 0 } }; /* x flags - used with the TIOCLGET and the struct sgttyb.sg_flags field */ struct bits tiolget[] = { { "CRTBS",00000001, "do backspacing for crt", "crterase" }, { "PRTERA",00000002, "\\ ... / erase", "prterase" }, { "CRTERA",00000004, "\"\\b\" to wipe out char", "crterase" }, { "TILDE",00000010, "hazeltine tilde kludge", "don't even think about this" }, { "MDMBUF",00000020, "start/stop output on carrier intr", "crtscts" }, { "LITOUT",00000040, "literal output", "litout" }, { "TOSTOP",00000100, "SIGSTOP on background output", "tostop" }, { "FLUSHO",00000200, "flush output to terminal", "noflsh?? (caution)" }, { "NOHANG",00000400, "no SIGHUP on carrier drop", "nohand" }, { "CRTKIL",00002000, "kill line with \"\\b\"", "crtkill" }, { "PASS8",00004000, "pass 8 bits", "pass8" }, { "CTLECH",00010000, "echo control chars as ^X", "echok" }, { "PENDIN",00020000, "tp->t_rawq needs reread", "don't even think about this" }, { "DECCTQ",00040000, "only ^Q starts after ^S", "decctlq? -ixany? (caution)" }, { "NOFLSH",00100000, "no output flush on signal", "noflsh" }, { 0 } }; char *msg[] = { "xlate optionstrings", " Example", " xlate \":fc#0000374:fs#0000003:xc#0:xs#0040040:\"", 0 }; usage() { char **m; for( m = msg; *m; ++m ){ fprintf( stderr, "%s\n", *m ); } exit( 1 ); } main( argc, argv ) int argc; char *argv[]; { char *s, *end, *value; int c, v, set; struct bits *table; if( argc != 2 ) usage(); for( s = argv[1]; s && *s; s = end ){ end = strchr( s, ':' ); if( end ){ *end++ = 0; } while( (c = *s) && isspace( c ) ) ++s; if( c == 0 ) continue; /* now translate option */ value = strchr( s, '#' ); if( value == 0 ) usage(); *value++ = 0; v = strtol( value, (char **)0, 0 ); printf( "%s = %o\n", s, v); switch( s[0] ){ case 'f': table = tiocget; break; case 'x': table = tiolget; break; default: usage(); } switch( s[1] ){ case 's': set = 1; break; case 'c': set = 0; break; default: usage(); } /* now we scan down the values */ for(; table->name; ++table ){ if( (table->bitfields & v) && ( ((table->bitfields & v) ^ table->bitfields) & (table->mask?table->mask:~0) ) == 0 ){ printf( " %s %s (%s) try '%s%s'\n", set?"set":"clear", table->name, table->comment, set? "":"-", table->try ); } } } }
If you have a network printer, then you may have several options. First, your printer may have built-in LPD server support. However, this may not function as expected. It has been observed that most of these builtin servers do not correctly handle large jobs or jobs with complex PJL, PCL, or PostScript with binary information.
On the other hand,
your printer may have a TCP/IP port that connects directly to the
print engine.
For example,
on the HP JetDirect cards, sending a print file to port 9100 will cause
the print engine to process and print it.
In addition,
this channel may provide status and other information during the printing
process.
You can use the
netcat
utility by Hobbit <Hobbit@avian.org>
to send files directly to the printer.
The simplest and easiest way to print a file to a network printer appears
to be: nc printer.ip.addr 9100 < file
.