Initial lp.
This commit is contained in:
parent
2863ba101f
commit
262ecfed9f
8 changed files with 1647 additions and 0 deletions
57
src/cmd/lp/LOCK.c
Normal file
57
src/cmd/lp/LOCK.c
Normal file
|
|
@ -0,0 +1,57 @@
|
||||||
|
#include <u.h>
|
||||||
|
#include <libc.h>
|
||||||
|
|
||||||
|
/* MAXHOSTNAMELEN is in sys/param.h */
|
||||||
|
#define MAXHOSTNAMELEN 64
|
||||||
|
|
||||||
|
char lockstring[MAXHOSTNAMELEN+8];
|
||||||
|
|
||||||
|
void
|
||||||
|
main(int argc, char *argv[]) {
|
||||||
|
char *lockfile;
|
||||||
|
int fd, ppid, ssize;
|
||||||
|
struct Dir *statbuf;
|
||||||
|
|
||||||
|
if (argc != 4) {
|
||||||
|
fprint(2, "usage: LOCK lockfile hostname ppid\n");
|
||||||
|
exits("lock failed on usage");
|
||||||
|
}
|
||||||
|
lockfile = argv[1];
|
||||||
|
if ((fd=create(lockfile, OLOCK|ORDWR, 0666)) < 0) {
|
||||||
|
exits("lock failed on create");
|
||||||
|
}
|
||||||
|
ppid = atoi(argv[3]);
|
||||||
|
ssize = sprint(lockstring, "%s %s\n", argv[2], argv[3]);
|
||||||
|
if (write(fd, lockstring, ssize) != ssize) {
|
||||||
|
fprint(2, "LOCK:write(): %r\n");
|
||||||
|
exits("lock failed on write to lockfile");
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(fork()) {
|
||||||
|
default:
|
||||||
|
exits("");
|
||||||
|
case 0:
|
||||||
|
break;
|
||||||
|
case -1:
|
||||||
|
fprint(2, "LOCK:fork(): %r\n");
|
||||||
|
exits("lock failed on fork");
|
||||||
|
}
|
||||||
|
|
||||||
|
for(;;) {
|
||||||
|
statbuf = dirfstat(fd);
|
||||||
|
if(statbuf == nil)
|
||||||
|
break;
|
||||||
|
if (statbuf->length == 0){
|
||||||
|
free(statbuf);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
free(statbuf);
|
||||||
|
if (write(fd, "", 0) < 0)
|
||||||
|
break;
|
||||||
|
sleep(3000);
|
||||||
|
}
|
||||||
|
|
||||||
|
close(fd);
|
||||||
|
postnote(PNGROUP, ppid, "kill");
|
||||||
|
exits("");
|
||||||
|
}
|
||||||
92
src/cmd/lp/ipcopen.c
Normal file
92
src/cmd/lp/ipcopen.c
Normal file
|
|
@ -0,0 +1,92 @@
|
||||||
|
#include <u.h>
|
||||||
|
#include <libc.h>
|
||||||
|
|
||||||
|
int ppid;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* predefined
|
||||||
|
*/
|
||||||
|
void pass(int from, int to);
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Connect to given datakit port
|
||||||
|
*/
|
||||||
|
main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
int fd0, fd1;
|
||||||
|
int cpid;
|
||||||
|
char c;
|
||||||
|
char *cp, *devdir, *buf;
|
||||||
|
|
||||||
|
if (argc != 4) {
|
||||||
|
fprint(2, "usage: %s destination network service\n", argv[0]);
|
||||||
|
exits("incorrect number of arguments");
|
||||||
|
}
|
||||||
|
if(!(cp = malloc((long)(strlen(argv[1])+strlen(argv[2])+strlen(argv[3])+8)))) {
|
||||||
|
perror("malloc");
|
||||||
|
exits("malloc failed");
|
||||||
|
}
|
||||||
|
sprint(cp, "%s!%s!%s", argv[2], argv[1], argv[3]);
|
||||||
|
if (dial(cp, &devdir, 0) < 0) {
|
||||||
|
fprint(2, "dialing %s\n", cp);
|
||||||
|
perror("dial");
|
||||||
|
exits("can't dial");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialize the input fd, and copy bytes.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if(!(buf = malloc((long)(strlen(devdir)+6)))) {
|
||||||
|
perror("malloc");
|
||||||
|
exits("malloc failed");
|
||||||
|
}
|
||||||
|
sprint(buf, "%s/data", devdir);
|
||||||
|
fd0=open(buf, OREAD);
|
||||||
|
fd1=open(buf, OWRITE);
|
||||||
|
if(fd0<0 || fd1<0) {
|
||||||
|
print("can't open", buf);
|
||||||
|
exits("can't open port");
|
||||||
|
}
|
||||||
|
ppid = getpid();
|
||||||
|
switch(cpid = fork()){
|
||||||
|
case -1:
|
||||||
|
perror("fork failed");
|
||||||
|
exits("fork failed");
|
||||||
|
case 0:
|
||||||
|
close(0);
|
||||||
|
close(fd1);
|
||||||
|
pass(fd0, 1); /* from remote */
|
||||||
|
hangup(fd0);
|
||||||
|
close(1);
|
||||||
|
close(fd0);
|
||||||
|
exits("");
|
||||||
|
default:
|
||||||
|
close(1);
|
||||||
|
close(fd0);
|
||||||
|
pass(0, fd1); /* to remote */
|
||||||
|
hangup(fd1);
|
||||||
|
close(0);
|
||||||
|
close(fd1);
|
||||||
|
exits("");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
pass(int from, int to)
|
||||||
|
{
|
||||||
|
char buf[1024];
|
||||||
|
int ppid, cpid;
|
||||||
|
int n, tot = 0;
|
||||||
|
|
||||||
|
while ((n=read(from, buf, sizeof(buf))) > 0) {
|
||||||
|
if (n==1 && tot==0 && *buf=='\0')
|
||||||
|
break;
|
||||||
|
tot += n;
|
||||||
|
if (write(to, buf, n)!=n) {
|
||||||
|
perror("pass write error");
|
||||||
|
exits("pass write error");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
224
src/cmd/lp/lp.rc
Executable file
224
src/cmd/lp/lp.rc
Executable file
|
|
@ -0,0 +1,224 @@
|
||||||
|
#!/usr/local/plan9/bin/rc
|
||||||
|
# This program enqueues the file to be printed and starts the daemon, when necessary.
|
||||||
|
# Make changes to /sys/src/cmd/lp/lp.rc. Changes made directly to /rc/bin/lp will be lost.
|
||||||
|
|
||||||
|
# rfork en # so that environment and name space are not polluted
|
||||||
|
#
|
||||||
|
# put 'fn sigexit { rm /tmp/lpcrap; exit interrupted }' into processes that create /tmp/lpcrap.
|
||||||
|
|
||||||
|
ifs='
|
||||||
|
' # set ifs in case it is munged in user's environment
|
||||||
|
|
||||||
|
LPLIB=$PLAN9/lp # lp scripts directories and configuration file are here
|
||||||
|
LPBIN=$PLAN9/bin/lpbin # lp specific binaries are here
|
||||||
|
LPSPOOL=$LPLIB/queue # lp queues
|
||||||
|
LPLOGDIR=$LPLIB/log # lp logs
|
||||||
|
|
||||||
|
# $LPLIB/bin/lpscratch || exit $status
|
||||||
|
LPTMP=/var/tmp
|
||||||
|
|
||||||
|
path=($PLAN9/bin /usr/local/bin /usr/bin /bin $LPLIB/bin $LPBIN)
|
||||||
|
|
||||||
|
USAGE='usage: lp [-d printer] [-p process] [options] [files]
|
||||||
|
lp [-d printer] -q
|
||||||
|
lp [-d printer] -k jobnos
|
||||||
|
|
||||||
|
options include:
|
||||||
|
-H no header
|
||||||
|
-L landscape mode
|
||||||
|
-c<n> make <n> copies
|
||||||
|
-f<font.size> specify font and size
|
||||||
|
-i<src> take media from <src> input bin
|
||||||
|
-l<n> print <n> lines per logical page
|
||||||
|
-m<n> magnify <n> times
|
||||||
|
-n<n> print <n> logical pages per physical page
|
||||||
|
-o<i-j,k> print only pages i-j and k
|
||||||
|
-r reverse pages
|
||||||
|
-x<n> x page offset in inches
|
||||||
|
-y<n> y page offset in inches'
|
||||||
|
|
||||||
|
umask 000 # this doesn't work in plan 9
|
||||||
|
THIS_HOST=$sysname
|
||||||
|
if(~ $#THIS_HOST 0)
|
||||||
|
THIS_HOST=`{hostname | sed 's/\..*//'}
|
||||||
|
if(~ $#THIS_HOST 0)
|
||||||
|
THIS_HOST=gnot
|
||||||
|
|
||||||
|
# Helpers for scripts
|
||||||
|
|
||||||
|
# Run a program from a /sys/lib/lp subdirectory.
|
||||||
|
fn lpsub {
|
||||||
|
_LPSUB=$1
|
||||||
|
shift
|
||||||
|
_LPCMD=$1
|
||||||
|
shift
|
||||||
|
@{path=($LPLIB/$_LPSUB $path); $LPLIB/$_LPSUB/$_LPCMD $*}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Run a command with standard input from file $1.
|
||||||
|
# If $1 is '', use the current standard input.
|
||||||
|
fn lpinput {
|
||||||
|
_LPFILE=$1
|
||||||
|
shift
|
||||||
|
if(~ $_LPFILE '') $*
|
||||||
|
if not $* < $_LPFILE
|
||||||
|
}
|
||||||
|
|
||||||
|
LPMACHID=$THIS_HOST
|
||||||
|
THIS_USERID=$user
|
||||||
|
LPUSERID=$THIS_USERID
|
||||||
|
LPLOC=''
|
||||||
|
|
||||||
|
# Set default printer to be output device
|
||||||
|
if (~ $#LPDEST 0 && test -f $LPLIB/default)
|
||||||
|
LPDEST=`{cat $LPLIB/default}
|
||||||
|
|
||||||
|
# Parse option parameters
|
||||||
|
|
||||||
|
XOFF=''
|
||||||
|
YOFF=''
|
||||||
|
POINT=''
|
||||||
|
FONT=''
|
||||||
|
LINES=''
|
||||||
|
LAND=''
|
||||||
|
COPIES=''
|
||||||
|
MAG=''
|
||||||
|
NPAG=''
|
||||||
|
OLIST=''
|
||||||
|
IBIN=''
|
||||||
|
REVERSE=''
|
||||||
|
NOHEAD=''
|
||||||
|
TRAY=''
|
||||||
|
# remove FLAGS from environment
|
||||||
|
FLAGD=();FLAGH=();FLAGL=();FLAGM=();FLAGQ=();FLAGc=();FLAGd=();FLAGf=()
|
||||||
|
FLAGi=();FLAGk=();FLAGl=();FLAGm=();FLAGn=();FLAGo=();FLAGp=();FLAGq=()
|
||||||
|
FLAGr=();FLAGt=();FLAGu=();FLAGx=();FLAGy=()
|
||||||
|
# Process options
|
||||||
|
eval `{getflags DHLM:1QRc:1d:1f:1i:1kl:1m:1n:1o:1p:1qrt:1u:1x:1y:1 $*}
|
||||||
|
if (! ~ $status '') exit $status
|
||||||
|
if (! ~ $#FLAGD 0) { DEBUG=1; flag x + }; if not { DEBUG=''; flag x - }
|
||||||
|
if (! ~ $#FLAGH 0) NOHEAD=1; if not NOHEAD=''
|
||||||
|
if (! ~ $#FLAGL 0) LAND=1; if not LAND=''
|
||||||
|
# originating machine id (for information only)
|
||||||
|
if (! ~ $#FLAGM 0 && ~ $LPUSERID daemon) LPMACHID=$FLAGM
|
||||||
|
if (! ~ $#FLAGQ 0) QONLY=1; if not QONLY=''
|
||||||
|
if (! ~ $#FLAGR 0) RESET=1; if not RESET=''
|
||||||
|
if (! ~ $#FLAGc 0) COPIES=$FLAGc; if not COPIES=1
|
||||||
|
if (! ~ $#FLAGd 0) {
|
||||||
|
switch ($FLAGd) {
|
||||||
|
case '?'; exec awk 'BEGIN{printf "device location host class\n"}
|
||||||
|
/^[^#]/ {printf "%-12s %-9s %-20s %s\n", $1, $2, $3, $6 }' $LPLIB/devices
|
||||||
|
case *; LPDEST=$FLAGd
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (! ~ $#FLAGf 0) eval `{echo $FLAGf | sed -e 's/([^.]*)\.([0-9.]*)/FONT=\1;POINT=\2;/'}
|
||||||
|
if (! ~ $#FLAGi 0) IBIN=$FLAGi
|
||||||
|
if (! ~ $#FLAGk 0) KILLFLAG=1; if not KILLFLAG=0
|
||||||
|
if (! ~ $#FLAGl 0) LINES=$FLAGl
|
||||||
|
if (! ~ $#FLAGm 0) MAG=$FLAGm
|
||||||
|
if (! ~ $#FLAGn 0) NPAG=$FLAGn
|
||||||
|
if (! ~ $#FLAGo 0) OLIST=-o$FLAGo
|
||||||
|
if (! ~ $#FLAGp 0) {
|
||||||
|
switch (FLAGp) {
|
||||||
|
case '?';exec ls $LPLIB/process
|
||||||
|
case *; LPPROC=$FLAGp
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (! ~ $#FLAGq 0) LPQ=1; if not LPQ=0
|
||||||
|
if (! ~ $#FLAGr 0) {
|
||||||
|
switch ($REVERSE) {
|
||||||
|
case '';REVERSE=1
|
||||||
|
case 1; REVERSE=''
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (! ~ $#FLAGt 0) TRAY=$FLAGt
|
||||||
|
# originating user id
|
||||||
|
if (! ~ $#FLAGu 0) LPUSERID=$FLAGu
|
||||||
|
if (! ~ $#FLAGx 0) XOFF=$FLAGx
|
||||||
|
if (! ~ $#FLAGy 0) YOFF=$FLAGy
|
||||||
|
|
||||||
|
if (~ $#LPDEST 0) {
|
||||||
|
echo 'Set environment variable LPDEST or use the
|
||||||
|
''-d printer'' option to set the destination.' >[1=2]
|
||||||
|
exit 'LPDEST not set'
|
||||||
|
}
|
||||||
|
if (~ $LPDEST */*) { # handles MHCC destinations like mh/lino
|
||||||
|
LPLOC=`{echo $LPDEST|sed 's/^(.*)\/(.*)/\1/'}
|
||||||
|
LPDEST=`{echo $LPDEST|sed 's/^(.*)\/(.*)/\2/'}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Fetch device info from devices file.
|
||||||
|
|
||||||
|
LPDLINE=`{grep '^'$LPDEST'[ ]' $LPLIB/devices}
|
||||||
|
if (! ~ $status '') {
|
||||||
|
echo 'device '$LPDEST' is not in '$LPLIB'/devices' >[1=2]
|
||||||
|
exit 'LPDEST is bad'
|
||||||
|
}
|
||||||
|
LOC=$LPDLINE(2)
|
||||||
|
DEST_HOST=$LPDLINE(3)
|
||||||
|
OUTDEV=$LPDLINE(4)
|
||||||
|
SPEED=$LPDLINE(5)
|
||||||
|
LPCLASS=$LPDLINE(6)
|
||||||
|
if (~ $#LPPROC 0) LPPROC=$LPDLINE(7)
|
||||||
|
SPOOLER=$LPDLINE(8)
|
||||||
|
STAT=$LPDLINE(9)
|
||||||
|
KILL=$LPDLINE(10)
|
||||||
|
DAEMON=$LPDLINE(11)
|
||||||
|
SCHED=$LPDLINE(12)
|
||||||
|
|
||||||
|
# On to the actual command-line processing.
|
||||||
|
|
||||||
|
# lp -k
|
||||||
|
if (~ $KILLFLAG 1)
|
||||||
|
switch ($KILL) {
|
||||||
|
case -
|
||||||
|
echo kill option not available on $LPDEST >[1=2]
|
||||||
|
exit 'kill n/a'
|
||||||
|
case *
|
||||||
|
lpsub kill $KILL $*
|
||||||
|
exit $status
|
||||||
|
}
|
||||||
|
|
||||||
|
# lp -q
|
||||||
|
if (~ $LPQ 1)
|
||||||
|
switch ($STAT) {
|
||||||
|
case -
|
||||||
|
echo queue status option not available on $LPDEST >[1=2]
|
||||||
|
exit 'stat option not available'
|
||||||
|
case *
|
||||||
|
lpsub stat $STAT $* </dev/null
|
||||||
|
exit $status
|
||||||
|
}
|
||||||
|
|
||||||
|
# lp
|
||||||
|
DATE=`{date}
|
||||||
|
LPLOG=$LPLOGDIR/$LPDEST
|
||||||
|
if (! test -e $LPLOG) {
|
||||||
|
>$LPLOG
|
||||||
|
chmod +rwa $LPLOG >[2]/dev/null
|
||||||
|
}
|
||||||
|
|
||||||
|
if (~ $RESET '') { # lp file
|
||||||
|
switch ($SPOOLER) {
|
||||||
|
case -; echo spooler does not exist for $LPDEST >[1=2]
|
||||||
|
exit 'no spooler'
|
||||||
|
case *; path=($LPLIB/spooler $path)
|
||||||
|
if (~ $#* 0) $SPOOLER
|
||||||
|
if not $SPOOLER $*
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if not { # lp -R
|
||||||
|
echo restarting daemon for printer $LPDEST >[1=2]
|
||||||
|
echo `{date} restarting daemon >>$LPLOG
|
||||||
|
UNLOCK $LPSPOOL/$LPDEST
|
||||||
|
sleep 5
|
||||||
|
}
|
||||||
|
|
||||||
|
# run daemon
|
||||||
|
if (~ $QONLY '') { # not lp -Q
|
||||||
|
if (! ~ $DAEMON -) {
|
||||||
|
lpsub daemon $DAEMON $* >>$LPLOG >[2=1] &
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exit ''
|
||||||
457
src/cmd/lp/lpdaemon.c
Normal file
457
src/cmd/lp/lpdaemon.c
Normal file
|
|
@ -0,0 +1,457 @@
|
||||||
|
#include <u.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <libc.h>
|
||||||
|
|
||||||
|
#undef ctime
|
||||||
|
#undef wait
|
||||||
|
|
||||||
|
/* for Plan 9 */
|
||||||
|
#ifdef PLAN9
|
||||||
|
#define LP "/bin/lp"
|
||||||
|
#define TMPDIR "/var/tmp"
|
||||||
|
#define LPDAEMONLOG unsharp("#9/lp/log/lpdaemonl")
|
||||||
|
#endif
|
||||||
|
/* for Tenth Edition systems */
|
||||||
|
#ifdef V10
|
||||||
|
#define LP "/usr/bin/lp"
|
||||||
|
#define TMPDIR "/tmp"
|
||||||
|
#define LPDAEMONLOG "/tmp/lpdaemonl"
|
||||||
|
#endif
|
||||||
|
/* for System V or BSD systems */
|
||||||
|
#if defined(SYSV) || defined(BSD)
|
||||||
|
#define LP "/v/bin/lp"
|
||||||
|
#define TMPDIR "/tmp"
|
||||||
|
#define LPDAEMONLOG "/tmp/lpdaemonl"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define ARGSIZ 4096
|
||||||
|
#define NAMELEN 30
|
||||||
|
|
||||||
|
unsigned char argvstr[ARGSIZ]; /* arguments after parsing */
|
||||||
|
unsigned char *argvals[ARGSIZ/2+1]; /* pointers to arguments after parsing */
|
||||||
|
int ascnt = 0, argcnt = 0; /* number of arguments parsed */
|
||||||
|
/* for 'stuff' gleened from lpr cntrl file */
|
||||||
|
struct jobinfo {
|
||||||
|
char user[NAMELEN+1];
|
||||||
|
char host[NAMELEN+1];
|
||||||
|
} *getjobinfo();
|
||||||
|
|
||||||
|
#define MIN(a,b) ((a<b)?a:b)
|
||||||
|
|
||||||
|
#define CPYFIELD(src, dst) { while (*(src)!=' ' && *(src)!='\t' && *(src)!='\r' && *(src)!='\n' && *(src)!='\0') *(dst)++ = *(src)++; }
|
||||||
|
|
||||||
|
#define ACK() write(1, "", 1)
|
||||||
|
#define NAK() write(1, "\001", 1)
|
||||||
|
|
||||||
|
#define LNBFSZ 4096
|
||||||
|
unsigned char lnbuf[LNBFSZ];
|
||||||
|
|
||||||
|
#define RDSIZE 512
|
||||||
|
unsigned char jobbuf[RDSIZE];
|
||||||
|
|
||||||
|
int datafd[400], cntrlfd = -1;
|
||||||
|
|
||||||
|
int dbgstate = 0;
|
||||||
|
char *dbgstrings[] = {
|
||||||
|
"",
|
||||||
|
"sendack1",
|
||||||
|
"send",
|
||||||
|
"rcvack",
|
||||||
|
"sendack2",
|
||||||
|
"done"
|
||||||
|
};
|
||||||
|
|
||||||
|
void
|
||||||
|
error(char *s1, ...)
|
||||||
|
{
|
||||||
|
FILE *fp;
|
||||||
|
long thetime;
|
||||||
|
char *chartime;
|
||||||
|
va_list ap;
|
||||||
|
char *args[8];
|
||||||
|
int argno = 0;
|
||||||
|
|
||||||
|
if((fp=fopen(LPDAEMONLOG, "a"))==NULL) {
|
||||||
|
fprintf(stderr, "cannot open %s in append mode\n", LPDAEMONLOG);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
time(&thetime);
|
||||||
|
chartime = ctime(&thetime);
|
||||||
|
fprintf(fp, "%.15s [%5.5d] ", &(chartime[4]), getpid());
|
||||||
|
va_start(ap, s1);
|
||||||
|
while((args[argno++] = va_arg(ap, char*)) && argno<8);
|
||||||
|
va_end(ap);
|
||||||
|
fprintf(fp, s1, args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]);
|
||||||
|
fflush(fp);
|
||||||
|
fclose(fp);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
forklp(int inputfd)
|
||||||
|
{
|
||||||
|
int i, cpid;
|
||||||
|
unsigned char *bp, *cp;
|
||||||
|
unsigned char logent[LNBFSZ];
|
||||||
|
|
||||||
|
/* log this call to lp */
|
||||||
|
cp = logent;
|
||||||
|
for (i=1; i<argcnt; i++) {
|
||||||
|
bp = argvals[i];
|
||||||
|
if (cp+strlen((const char *)bp)+1 < logent+LNBFSZ-1) {
|
||||||
|
CPYFIELD(bp, cp);
|
||||||
|
*cp++ = ' ';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*--cp = '\n';
|
||||||
|
*++cp = '\0';
|
||||||
|
error(logent);
|
||||||
|
switch((cpid=fork())){
|
||||||
|
case -1:
|
||||||
|
error("fork error\n");
|
||||||
|
exit(2);
|
||||||
|
case 0:
|
||||||
|
if (inputfd != 0)
|
||||||
|
dup2(inputfd, 0);
|
||||||
|
dup2(1, 2);
|
||||||
|
lseek(0, 0L, 0);
|
||||||
|
execvp(LP, (char**)argvals);
|
||||||
|
error("exec failed\n");
|
||||||
|
exit(3);
|
||||||
|
default:
|
||||||
|
while(wait((int *)0) != cpid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
tempfile(void)
|
||||||
|
{
|
||||||
|
int tindx = 0;
|
||||||
|
char tmpf[sizeof(TMPDIR)+64];
|
||||||
|
int crtfd, tmpfd;
|
||||||
|
|
||||||
|
sprintf(tmpf, "%s/lp%d.%d", TMPDIR, getpid(), tindx++);
|
||||||
|
if((crtfd=creat(tmpf, 0666)) < 0) {
|
||||||
|
error("cannot create temp file %s\n", tmpf);
|
||||||
|
NAK();
|
||||||
|
exit(3);
|
||||||
|
}
|
||||||
|
if((tmpfd=open(tmpf, 2)) < 0) {
|
||||||
|
error("cannot open temp file %s\n", tmpf);
|
||||||
|
NAK();
|
||||||
|
exit(3);
|
||||||
|
}
|
||||||
|
close(crtfd);
|
||||||
|
unlink(tmpf); /* comment out for debugging */
|
||||||
|
return(tmpfd);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
readfile(int outfd, int bsize)
|
||||||
|
{
|
||||||
|
int rv;
|
||||||
|
|
||||||
|
dbgstate = 1;
|
||||||
|
alarm(60);
|
||||||
|
ACK();
|
||||||
|
dbgstate = 2;
|
||||||
|
for(; bsize > 0; bsize -= rv) {
|
||||||
|
alarm(60);
|
||||||
|
if((rv=read(0, jobbuf, MIN(bsize,RDSIZE))) < 0) {
|
||||||
|
error("error reading input, %d unread\n", bsize);
|
||||||
|
exit(4);
|
||||||
|
} else if (rv == 0) {
|
||||||
|
error("connection closed prematurely\n");
|
||||||
|
exit(4);
|
||||||
|
} else if((write(outfd, jobbuf, rv)) != rv) {
|
||||||
|
error("error writing temp file, %d unread\n", bsize);
|
||||||
|
exit(5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dbgstate = 3;
|
||||||
|
alarm(60);
|
||||||
|
if (((rv=read(0, jobbuf, 1))==1) && (*jobbuf=='\0')) {
|
||||||
|
alarm(60);
|
||||||
|
ACK();
|
||||||
|
dbgstate = 4;
|
||||||
|
alarm(0);
|
||||||
|
return(outfd);
|
||||||
|
}
|
||||||
|
alarm(0);
|
||||||
|
error("received bad status <%d> from sender\n", *jobbuf);
|
||||||
|
error("rv=%d\n", rv);
|
||||||
|
NAK();
|
||||||
|
return(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* reads a line from the input into lnbuf
|
||||||
|
* if there is no error, it returns
|
||||||
|
* the number of characters in the buffer
|
||||||
|
* if there is an error and there where characters
|
||||||
|
* read, it returns the negative value of the
|
||||||
|
* number of characters read
|
||||||
|
* if there is an error and no characters were read,
|
||||||
|
* it returns the negative value of 1 greater than
|
||||||
|
* the size of the line buffer
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
readline(int inpfd)
|
||||||
|
{
|
||||||
|
unsigned char *ap;
|
||||||
|
int i, rv;
|
||||||
|
|
||||||
|
ap = lnbuf;
|
||||||
|
lnbuf[0] = '\0';
|
||||||
|
i = 0;
|
||||||
|
alarm(60);
|
||||||
|
do {
|
||||||
|
rv = read(inpfd, ap, 1);
|
||||||
|
} while (rv==1 && ++i && *ap != '\n' && ap++ && (i < LNBFSZ - 2));
|
||||||
|
alarm(0);
|
||||||
|
if (i != 0 && *ap != '\n') {
|
||||||
|
*++ap = '\n';
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
*++ap = '\0';
|
||||||
|
if (rv < 0) {
|
||||||
|
error("read error; lost connection\n");
|
||||||
|
if (i==0) i = -(LNBFSZ+1);
|
||||||
|
else i = -i;
|
||||||
|
}
|
||||||
|
return(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
getfiles(void)
|
||||||
|
{
|
||||||
|
unsigned char *ap;
|
||||||
|
int filecnt, bsize, rv;
|
||||||
|
|
||||||
|
filecnt = 0;
|
||||||
|
/* get a line, hopefully containing a ctrl char, size, and name */
|
||||||
|
for(;;) {
|
||||||
|
ap = lnbuf;
|
||||||
|
if ((rv=readline(0)) < 0) NAK();
|
||||||
|
if (rv <= 0) {
|
||||||
|
return(filecnt);
|
||||||
|
}
|
||||||
|
switch(*ap++) {
|
||||||
|
case '\1': /* cleanup - data sent was bad (whatever that means) */
|
||||||
|
break;
|
||||||
|
case '\2': /* read control file */
|
||||||
|
bsize = atoi(ap);
|
||||||
|
cntrlfd = tempfile();
|
||||||
|
if (readfile(cntrlfd, bsize) < 0) {
|
||||||
|
close(cntrlfd);
|
||||||
|
NAK();
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case '\3': /* read data file */
|
||||||
|
bsize = atoi(ap);
|
||||||
|
datafd[filecnt] = tempfile();
|
||||||
|
if (readfile(datafd[filecnt], bsize) < 0) {
|
||||||
|
close(datafd[filecnt]);
|
||||||
|
NAK();
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
filecnt++;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
error("protocol error <%d>\n", *(ap-1));
|
||||||
|
NAK();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return(filecnt);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct jobinfo *
|
||||||
|
getjobinfo(int fd)
|
||||||
|
{
|
||||||
|
unsigned char *ap;
|
||||||
|
int rv;
|
||||||
|
static struct jobinfo info;
|
||||||
|
|
||||||
|
if (fd < 0) error("getjobinfo: bad file descriptor\n");
|
||||||
|
if (lseek(fd, 0L, 0) < 0) {
|
||||||
|
error("error seeking in temp file\n");
|
||||||
|
exit(7);
|
||||||
|
}
|
||||||
|
/* the following strings should be < NAMELEN or else they will not
|
||||||
|
* be null terminated.
|
||||||
|
*/
|
||||||
|
strncpy(info.user, "daemon", NAMELEN);
|
||||||
|
strncpy(info.host, "nowhere", NAMELEN);
|
||||||
|
/* there may be a space after the name and host. It will be filtered out
|
||||||
|
* by CPYFIELD.
|
||||||
|
*/
|
||||||
|
while ((rv=readline(fd)) > 0) {
|
||||||
|
ap = lnbuf;
|
||||||
|
ap[rv-1] = '\0'; /* remove newline from string */
|
||||||
|
switch (*ap) {
|
||||||
|
case 'H':
|
||||||
|
if (ap[1] == '\0')
|
||||||
|
strncpy(info.host, "unknown", NAMELEN);
|
||||||
|
else
|
||||||
|
strncpy(info.host, (const char *)&ap[1], NAMELEN);
|
||||||
|
info.host[strlen(info.host)] = '\0';
|
||||||
|
break;
|
||||||
|
case 'P':
|
||||||
|
if (ap[1] == '\0')
|
||||||
|
strncpy(info.user, "unknown", NAMELEN);
|
||||||
|
else
|
||||||
|
strncpy(info.user, (const char *)&ap[1], NAMELEN);
|
||||||
|
info.user[strlen(info.user)] = '\0';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return(&info);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
alarmhandler(int sig) {
|
||||||
|
signal(sig, alarmhandler);
|
||||||
|
error("alarm at %d - %s\n", dbgstate, dbgstrings[dbgstate]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
unsigned char *ap, *bp, *cp, *savbufpnt;
|
||||||
|
int i, blen, rv, saveflg, savargcnt;
|
||||||
|
struct jobinfo *jinfop;
|
||||||
|
|
||||||
|
USED(argc);
|
||||||
|
USED(argv);
|
||||||
|
|
||||||
|
signal(SIGHUP, SIG_IGN);
|
||||||
|
signal(SIGALRM, alarmhandler);
|
||||||
|
cp = argvstr;
|
||||||
|
/* setup argv[0] for exec */
|
||||||
|
argvals[argcnt++] = cp;
|
||||||
|
for (bp = (unsigned char *)LP, i = 0; (*bp != '\0') && (i < ARGSIZ-1); *cp++ = *bp++, i++);
|
||||||
|
*cp++ = '\0';
|
||||||
|
/* get the first line sent and parse it as arguments for lp */
|
||||||
|
if ((rv=readline(0)) < 0)
|
||||||
|
exit(1);
|
||||||
|
bp = lnbuf;
|
||||||
|
/* setup the remaining arguments */
|
||||||
|
/* check for BSD style request */
|
||||||
|
/* ^A, ^B, ^C, ^D, ^E (for BSD lpr) */
|
||||||
|
switch (*bp) {
|
||||||
|
case '\001':
|
||||||
|
case '\003':
|
||||||
|
case '\004':
|
||||||
|
bp++; /* drop the ctrl character from the input */
|
||||||
|
argvals[argcnt++] = cp;
|
||||||
|
*cp++ = '-'; *cp++ = 'q'; *cp++ = '\0'; /* -q */
|
||||||
|
argvals[argcnt++] = cp;
|
||||||
|
*cp++ = '-'; *cp++ = 'd'; /* -d */
|
||||||
|
CPYFIELD(bp, cp); /* printer */
|
||||||
|
*cp++ = '\0';
|
||||||
|
break;
|
||||||
|
case '\002':
|
||||||
|
bp++; /* drop the ctrl character from the input */
|
||||||
|
argvals[argcnt++] = cp;
|
||||||
|
*cp++ = '-'; *cp++ = 'd'; /* -d */
|
||||||
|
CPYFIELD(bp, cp); /* printer */
|
||||||
|
*cp++ = '\0';
|
||||||
|
ACK();
|
||||||
|
savargcnt = argcnt;
|
||||||
|
savbufpnt = cp;
|
||||||
|
while ((rv=getfiles())) {
|
||||||
|
jinfop = getjobinfo(cntrlfd);
|
||||||
|
close(cntrlfd);
|
||||||
|
argcnt = savargcnt;
|
||||||
|
cp = savbufpnt;
|
||||||
|
argvals[argcnt++] = cp;
|
||||||
|
*cp++ = '-'; *cp++ = 'M'; /* -M */
|
||||||
|
bp = (unsigned char *)jinfop->host;
|
||||||
|
CPYFIELD(bp, cp); /* host name */
|
||||||
|
*cp++ = '\0';
|
||||||
|
argvals[argcnt++] = cp;
|
||||||
|
*cp++ = '-'; *cp++ = 'u'; /* -u */
|
||||||
|
bp = (unsigned char *)jinfop->user;
|
||||||
|
CPYFIELD(bp, cp); /* user name */
|
||||||
|
*cp++ = '\0';
|
||||||
|
for(i=0;i<rv;i++)
|
||||||
|
forklp(datafd[i]);
|
||||||
|
}
|
||||||
|
exit(0);
|
||||||
|
case '\005':
|
||||||
|
bp++; /* drop the ctrl character from the input */
|
||||||
|
argvals[argcnt++] = cp;
|
||||||
|
*cp++ = '-'; *cp++ = 'k'; *cp++ = '\0'; /* -k */
|
||||||
|
argvals[argcnt++] = cp;
|
||||||
|
*cp++ = '-'; *cp++ = 'd'; /* -d */
|
||||||
|
CPYFIELD(bp, cp); /* printer */
|
||||||
|
*cp++ = '\0';
|
||||||
|
argvals[argcnt++] = cp;
|
||||||
|
*cp++ = '-'; ap = cp; *cp++ = 'u'; /* -u */
|
||||||
|
CPYFIELD(bp, cp); /* username */
|
||||||
|
|
||||||
|
/* deal with bug in lprng where the username is not supplied
|
||||||
|
*/
|
||||||
|
if (ap == (cp-1)) {
|
||||||
|
ap = (unsigned char *)"none";
|
||||||
|
CPYFIELD(ap, cp);
|
||||||
|
}
|
||||||
|
|
||||||
|
*cp++ = '\0';
|
||||||
|
datafd[0] = tempfile();
|
||||||
|
blen = strlen((const char *)bp);
|
||||||
|
if (write(datafd[0], bp, blen) != blen) {
|
||||||
|
error("write error\n");
|
||||||
|
exit(6);
|
||||||
|
}
|
||||||
|
if (write(datafd[0], "\n", 1) != 1) {
|
||||||
|
error("write error\n");
|
||||||
|
exit(6);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/* otherwise get my lp arguments */
|
||||||
|
do {
|
||||||
|
/* move to next non-white space */
|
||||||
|
while (*bp==' '||*bp=='\t')
|
||||||
|
++bp;
|
||||||
|
if (*bp=='\n') continue;
|
||||||
|
/* only accept arguments beginning with -
|
||||||
|
* this is done to prevent the printing of
|
||||||
|
* local files from the destination host
|
||||||
|
*/
|
||||||
|
if (*bp=='-') {
|
||||||
|
argvals[argcnt++] = cp;
|
||||||
|
saveflg = 1;
|
||||||
|
} else
|
||||||
|
saveflg = 0;
|
||||||
|
/* move to next white space copying text to argument buffer */
|
||||||
|
while (*bp!=' ' && *bp!='\t' && *bp!='\n'
|
||||||
|
&& *bp!='\0') {
|
||||||
|
*cp = *bp++;
|
||||||
|
cp += saveflg;
|
||||||
|
}
|
||||||
|
*cp = '\0';
|
||||||
|
cp += saveflg;
|
||||||
|
} while (*bp!='\n' && *bp!='\0');
|
||||||
|
if (readline(0) < 0) exit(7);
|
||||||
|
datafd[0] = tempfile();
|
||||||
|
if(readfile(datafd[0], atoi((char *)lnbuf)) < 0) {
|
||||||
|
error("readfile failed\n");
|
||||||
|
exit(8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
forklp(datafd[0]);
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
428
src/cmd/lp/lpdsend.c
Normal file
428
src/cmd/lp/lpdsend.c
Normal file
|
|
@ -0,0 +1,428 @@
|
||||||
|
#include <u.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/param.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <libc.h>
|
||||||
|
|
||||||
|
#define REDIALTIMEOUT 15
|
||||||
|
#define TIMEOUT 600
|
||||||
|
|
||||||
|
char tmpfilename[L_tmpnam+1];
|
||||||
|
int alarmstate = 0;
|
||||||
|
int debugflag = 0;
|
||||||
|
int killflag = 0;
|
||||||
|
int statflag = 0;
|
||||||
|
|
||||||
|
void
|
||||||
|
cleanup(void) {
|
||||||
|
unlink(tmpfilename);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define SBSIZE 8192
|
||||||
|
unsigned char sendbuf[SBSIZE];
|
||||||
|
|
||||||
|
void
|
||||||
|
debug(char *str) {
|
||||||
|
if (debugflag)
|
||||||
|
fprintf(stderr, "%s", str);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
alarmhandler(int sig) {
|
||||||
|
fprintf(stderr, "timeout occurred, check printer.\n");
|
||||||
|
exit(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* send a message after each WARNPC percent of data sent */
|
||||||
|
#define WARNPC 5
|
||||||
|
|
||||||
|
int
|
||||||
|
copyfile(int in, int out, long tosend) {
|
||||||
|
int n;
|
||||||
|
int sent = 0;
|
||||||
|
int percent = 0;
|
||||||
|
|
||||||
|
if (debugflag)
|
||||||
|
fprintf(stderr, "lpdsend: copyfile(%d,%d,%ld)\n",
|
||||||
|
in, out, tosend);
|
||||||
|
while ((n=read(in, sendbuf, SBSIZE)) > 0) {
|
||||||
|
if (debugflag)
|
||||||
|
fprintf(stderr, "lpdsend: copyfile read %d bytes from %d\n",
|
||||||
|
n, in);
|
||||||
|
alarm(TIMEOUT); alarmstate = 1;
|
||||||
|
if (write(out, sendbuf, n) != n) {
|
||||||
|
alarm(0);
|
||||||
|
fprintf(stderr, "write to fd %d failed\n", out);
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
alarm(0);
|
||||||
|
if (debugflag)
|
||||||
|
fprintf(stderr, "lpdsend: copyfile wrote %d bytes to %d\n",
|
||||||
|
n, out);
|
||||||
|
sent += n;
|
||||||
|
if (tosend && ((sent*100/tosend)>=(percent+WARNPC))) {
|
||||||
|
percent += WARNPC;
|
||||||
|
fprintf(stderr, ": %5.2f%% sent\n", sent*100.0/tosend);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (debugflag)
|
||||||
|
fprintf(stderr, "lpdsend: copyfile read %d bytes from %d\n",
|
||||||
|
n, in);
|
||||||
|
return(!n);
|
||||||
|
}
|
||||||
|
|
||||||
|
char strbuf[120];
|
||||||
|
char hostname[MAXHOSTNAMELEN], *username, *printername, *killarg;
|
||||||
|
char *inputname;
|
||||||
|
char filetype = 'o'; /* 'o' is for PostScript */
|
||||||
|
int seqno = 0;
|
||||||
|
char *seqfilename;
|
||||||
|
|
||||||
|
void
|
||||||
|
killjob(int printerfd) {
|
||||||
|
int strlength;
|
||||||
|
if (printername==0) {
|
||||||
|
fprintf(stderr, "no printer name\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
if (username==0) {
|
||||||
|
fprintf(stderr, "no user name given\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
if (killarg==0) {
|
||||||
|
fprintf(stderr, "no job to kill\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
sprintf(strbuf, "%c%s %s %s\n", '\5', printername, username, killarg);
|
||||||
|
strlength = strlen(strbuf);
|
||||||
|
if (write(printerfd, strbuf, strlength) != strlength) {
|
||||||
|
fprintf(stderr, "write(printer) error\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
copyfile(printerfd, 2, 0L);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
checkqueue(int printerfd) {
|
||||||
|
int strlength;
|
||||||
|
|
||||||
|
sprintf(strbuf, "%c%s\n", '\4', printername);
|
||||||
|
strlength = strlen(strbuf);
|
||||||
|
if (write(printerfd, strbuf, strlength) != strlength) {
|
||||||
|
fprintf(stderr, "write(printer) error\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
copyfile(printerfd, 2, 0L);
|
||||||
|
/*
|
||||||
|
{ int n;
|
||||||
|
unsigned char sendbuf[1];
|
||||||
|
while ((n=read(printerfd, sendbuf, 1)) > 0) {
|
||||||
|
write(2, sendbuf, n);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
getack(int printerfd, int as) {
|
||||||
|
char resp;
|
||||||
|
int rv;
|
||||||
|
|
||||||
|
alarm(TIMEOUT); alarmstate = as;
|
||||||
|
if ((rv=read(printerfd, &resp, 1)) != 1 || resp != '\0') {
|
||||||
|
fprintf(stderr, "getack failed: read returned %d, read value (if any) %d, alarmstate=%d\n",
|
||||||
|
rv, resp, alarmstate);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
alarm(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* send control file */
|
||||||
|
void
|
||||||
|
sendctrl(int printerfd) {
|
||||||
|
char cntrlstrbuf[256];
|
||||||
|
int strlength, cntrlen;
|
||||||
|
|
||||||
|
sprintf(cntrlstrbuf, "H%s\nP%s\n%cdfA%3.3d%s\n", hostname, username, filetype, seqno, hostname);
|
||||||
|
cntrlen = strlen(cntrlstrbuf);
|
||||||
|
sprintf(strbuf, "%c%d cfA%3.3d%s\n", '\2', cntrlen, seqno, hostname);
|
||||||
|
strlength = strlen(strbuf);
|
||||||
|
if (write(printerfd, strbuf, strlength) != strlength) {
|
||||||
|
fprintf(stderr, "write(printer) error\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
getack(printerfd, 3);
|
||||||
|
if (write(printerfd, cntrlstrbuf, cntrlen) != cntrlen) {
|
||||||
|
fprintf(stderr, "write(printer) error\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
if (write(printerfd, "\0", 1) != 1) {
|
||||||
|
fprintf(stderr, "write(printer) error\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
getack(printerfd, 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* send data file */
|
||||||
|
void
|
||||||
|
senddata(int inputfd, int printerfd, long size) {
|
||||||
|
int strlength;
|
||||||
|
|
||||||
|
sprintf(strbuf, "%c%ld dfA%3.3d%s\n", '\3', size, seqno, hostname);
|
||||||
|
strlength = strlen(strbuf);
|
||||||
|
if (write(printerfd, strbuf, strlength) != strlength) {
|
||||||
|
fprintf(stderr, "write(printer) error\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
getack(printerfd, 5);
|
||||||
|
if (!copyfile(inputfd, printerfd, size)) {
|
||||||
|
fprintf(stderr, "failed to send file to printer\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
if (write(printerfd, "\0", 1) != 1) {
|
||||||
|
fprintf(stderr, "write(printer) error\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
fprintf(stderr, "%ld bytes sent, status: waiting for end of job\n", size);
|
||||||
|
getack(printerfd, 6);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
sendjob(int inputfd, int printerfd) {
|
||||||
|
struct stat statbuf;
|
||||||
|
int strlength;
|
||||||
|
|
||||||
|
if (fstat(inputfd, &statbuf) < 0) {
|
||||||
|
fprintf(stderr, "fstat(%s) failed\n", inputname);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
sprintf(strbuf, "%c%s\n", '\2', printername);
|
||||||
|
strlength = strlen(strbuf);
|
||||||
|
if (write(printerfd, strbuf, strlength) != strlength) {
|
||||||
|
fprintf(stderr, "write(printer) error\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
getack(printerfd, 2);
|
||||||
|
debug("send data\n");
|
||||||
|
senddata(inputfd, printerfd, statbuf.st_size);
|
||||||
|
debug("send control info\n");
|
||||||
|
sendctrl(printerfd);
|
||||||
|
fprintf(stderr, "%ld bytes sent, status: end of job\n", (long)statbuf.st_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* make an address, add the defaults
|
||||||
|
*/
|
||||||
|
char *
|
||||||
|
netmkaddr(char *linear, char *defnet, char *defsrv)
|
||||||
|
{
|
||||||
|
static char addr[512];
|
||||||
|
char *cp;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* dump network name
|
||||||
|
*/
|
||||||
|
cp = strchr(linear, '!');
|
||||||
|
if(cp == 0){
|
||||||
|
if(defnet==0){
|
||||||
|
if(defsrv)
|
||||||
|
sprintf(addr, "net!%s!%s", linear, defsrv);
|
||||||
|
else
|
||||||
|
sprintf(addr, "net!%s", linear);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if(defsrv)
|
||||||
|
sprintf(addr, "%s!%s!%s", defnet, linear, defsrv);
|
||||||
|
else
|
||||||
|
sprintf(addr, "%s!%s", defnet, linear);
|
||||||
|
}
|
||||||
|
return addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* if there is already a service, use it
|
||||||
|
*/
|
||||||
|
cp = strchr(cp+1, '!');
|
||||||
|
if(cp)
|
||||||
|
return linear;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* add default service
|
||||||
|
*/
|
||||||
|
if(defsrv == 0)
|
||||||
|
return linear;
|
||||||
|
sprintf(addr, "%s!%s", linear, defsrv);
|
||||||
|
|
||||||
|
return addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
main(int argc, char *argv[]) {
|
||||||
|
int c, usgflg = 0;
|
||||||
|
char *desthostname;
|
||||||
|
int printerfd;
|
||||||
|
int inputfd;
|
||||||
|
int sendport;
|
||||||
|
char portstr[4];
|
||||||
|
|
||||||
|
desthostname = nil;
|
||||||
|
if (signal(SIGALRM, alarmhandler) == SIG_ERR) {
|
||||||
|
fprintf(stderr, "failed to set alarm handler\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
while ((c = getopt(argc, argv, "Dd:k:qs:t:H:P:")) != -1)
|
||||||
|
switch (c) {
|
||||||
|
case 'D':
|
||||||
|
debugflag = 1;
|
||||||
|
debug("debugging on\n");
|
||||||
|
break;
|
||||||
|
case 'd':
|
||||||
|
printername = optarg;
|
||||||
|
break;
|
||||||
|
case 'k':
|
||||||
|
if (statflag) {
|
||||||
|
fprintf(stderr, "cannot have both -k and -q flags\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
killflag = 1;
|
||||||
|
killarg = optarg;
|
||||||
|
break;
|
||||||
|
case 'q':
|
||||||
|
if (killflag) {
|
||||||
|
fprintf(stderr, "cannot have both -q and -k flags\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
statflag = 1;
|
||||||
|
break;
|
||||||
|
case 's':
|
||||||
|
seqno = strtol(optarg, NULL, 10);
|
||||||
|
if (seqno < 0 || seqno > 999)
|
||||||
|
seqno = 0;
|
||||||
|
break;
|
||||||
|
case 't':
|
||||||
|
switch (filetype) {
|
||||||
|
case 'c':
|
||||||
|
case 'd':
|
||||||
|
case 'f':
|
||||||
|
case 'g':
|
||||||
|
case 'l':
|
||||||
|
case 'n':
|
||||||
|
case 'o':
|
||||||
|
case 'p':
|
||||||
|
case 'r':
|
||||||
|
case 't':
|
||||||
|
case 'v':
|
||||||
|
case 'z':
|
||||||
|
filetype = optarg[0];
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
usgflg++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'H':
|
||||||
|
strncpy(hostname, optarg, MAXHOSTNAMELEN);
|
||||||
|
break;
|
||||||
|
case 'P':
|
||||||
|
username = optarg;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
case '?':
|
||||||
|
fprintf(stderr, "unknown option %c\n", c);
|
||||||
|
usgflg++;
|
||||||
|
}
|
||||||
|
if (argc < 2) usgflg++;
|
||||||
|
if (optind < argc) {
|
||||||
|
desthostname = argv[optind++];
|
||||||
|
} else
|
||||||
|
usgflg++;
|
||||||
|
if (usgflg) {
|
||||||
|
fprintf(stderr, "usage: to send a job - %s -d printer -H hostname -P username [-s seqno] [-t[cdfgklnoprtvz]] desthost [filename]\n", argv[0]);
|
||||||
|
fprintf(stderr, " to check status - %s -d printer -q desthost\n", argv[0]);
|
||||||
|
fprintf(stderr, " to kill a job - %s -d printer -P username -k jobname desthost\n", argv[0]);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* make sure the file to send is here and ready
|
||||||
|
* otherwise the TCP connection times out.
|
||||||
|
*/
|
||||||
|
inputfd = -1;
|
||||||
|
if (!statflag && !killflag) {
|
||||||
|
if (optind < argc) {
|
||||||
|
inputname = argv[optind++];
|
||||||
|
debug("open("); debug(inputname); debug(")\n");
|
||||||
|
inputfd = open(inputname, O_RDONLY);
|
||||||
|
if (inputfd < 0) {
|
||||||
|
fprintf(stderr, "open(%s) failed\n", inputname);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
inputname = "stdin";
|
||||||
|
tmpnam(tmpfilename);
|
||||||
|
debug("using stdin\n");
|
||||||
|
if ((inputfd = create(tmpfilename, ORDWR, 0600)) < 0) {
|
||||||
|
fprintf(stderr, "open(%s) failed\n", tmpfilename);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
atexit(cleanup);
|
||||||
|
debug("copy input to temp file ");
|
||||||
|
debug(tmpfilename);
|
||||||
|
debug("\n");
|
||||||
|
if (!copyfile(0, inputfd, 0L)) {
|
||||||
|
fprintf(stderr, "failed to copy file to temporary file\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
if (lseek(inputfd, 0L, 0) < 0) {
|
||||||
|
fprintf(stderr, "failed to seek back to the beginning of the temporary file\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sprintf(strbuf, "%s", netmkaddr(desthostname, "tcp", "printer"));
|
||||||
|
fprintf(stderr, "connecting to %s\n", strbuf);
|
||||||
|
for (sendport=721; sendport<=731; sendport++) {
|
||||||
|
sprintf(portstr, "%3.3d", sendport);
|
||||||
|
fprintf(stderr, " trying from port %s...", portstr);
|
||||||
|
debug(" dial("); debug(strbuf); debug(", "); debug(portstr); debug(", 0, 0) ...");
|
||||||
|
printerfd = dial(strbuf, portstr, 0, 0);
|
||||||
|
if (printerfd >= 0) {
|
||||||
|
fprintf(stderr, "connected\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
fprintf(stderr, "failed\n");
|
||||||
|
sleep(REDIALTIMEOUT);
|
||||||
|
}
|
||||||
|
if (printerfd < 0) {
|
||||||
|
fprintf(stderr, "Cannot open a valid port!\n");
|
||||||
|
fprintf(stderr, "- All source ports [721-731] may be busy.\n");
|
||||||
|
fprintf(stderr, "- Is recipient ready and online?\n");
|
||||||
|
fprintf(stderr, "- If all else fails, cycle the power!\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
/* hostname[8] = '\0'; */
|
||||||
|
#ifndef PLAN9
|
||||||
|
if (gethostname(hostname, sizeof(hostname)) < 0) {
|
||||||
|
perror("gethostname");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
/* char *hnend;
|
||||||
|
if ((hnend = strchr(hostname, '.')) != NULL)
|
||||||
|
*hnend = '\0';
|
||||||
|
*/
|
||||||
|
if (statflag) {
|
||||||
|
checkqueue(printerfd);
|
||||||
|
} else if (killflag) {
|
||||||
|
killjob(printerfd);
|
||||||
|
} else {
|
||||||
|
sendjob(inputfd, printerfd);
|
||||||
|
}
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
341
src/cmd/lp/lpsend.c
Normal file
341
src/cmd/lp/lpsend.c
Normal file
|
|
@ -0,0 +1,341 @@
|
||||||
|
#ifdef plan9
|
||||||
|
|
||||||
|
#include <u.h>
|
||||||
|
#include <libc.h>
|
||||||
|
#define stderr 2
|
||||||
|
|
||||||
|
#define RDNETIMEOUT 60000
|
||||||
|
#define WRNETIMEOUT 60000
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
/* not for plan 9 */
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <signal.h>
|
||||||
|
|
||||||
|
#define create creat
|
||||||
|
#define seek lseek
|
||||||
|
#define fprint fprintf
|
||||||
|
#define sprint sprintf
|
||||||
|
#define exits exit
|
||||||
|
|
||||||
|
#define ORDWR O_RDWR
|
||||||
|
#define OTRUNC O_TRUNC
|
||||||
|
#define ORCLOSE 0
|
||||||
|
|
||||||
|
#define RDNETIMEOUT 60
|
||||||
|
#define WRNETIMEOUT 60
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define MIN(a,b) ((a<b)?a:b)
|
||||||
|
|
||||||
|
#define ACK(a) write(a, "", 1)
|
||||||
|
#define NAK(a) write(a, "\001", 1)
|
||||||
|
|
||||||
|
#define LPDAEMONLOG "/tmp/lpdaemonl"
|
||||||
|
|
||||||
|
#define LNBFSZ 4096
|
||||||
|
char lnbuf[LNBFSZ];
|
||||||
|
int dbgstate = 0;
|
||||||
|
char *dbgstrings[] = {
|
||||||
|
"",
|
||||||
|
"rcvack1",
|
||||||
|
"send",
|
||||||
|
"rcvack2",
|
||||||
|
"response",
|
||||||
|
"done"
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef plan9
|
||||||
|
|
||||||
|
void
|
||||||
|
error(int level, char *s1, ...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
long thetime;
|
||||||
|
char *chartime;
|
||||||
|
char *args[8];
|
||||||
|
int argno = 0;
|
||||||
|
|
||||||
|
if (level == 0) {
|
||||||
|
time(&thetime);
|
||||||
|
chartime = ctime(thetime);
|
||||||
|
fprint(stderr, "%.15s ", &(chartime[4]));
|
||||||
|
}
|
||||||
|
va_start(ap, s1);
|
||||||
|
while(args[argno++] = va_arg(ap, char*));
|
||||||
|
va_end(ap);
|
||||||
|
fprint(stderr, s1, *args);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
alarmhandler(void *foo, char *note) {
|
||||||
|
USED(foo);
|
||||||
|
if(strcmp(note, "alarm")==0) {
|
||||||
|
fprint(stderr, "alarm at %d - %s\n", dbgstate, dbgstrings[dbgstate]);
|
||||||
|
return(1);
|
||||||
|
} else return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
void
|
||||||
|
error(int level, char *s1, ...)
|
||||||
|
{
|
||||||
|
time_t thetime;
|
||||||
|
char *chartime;
|
||||||
|
|
||||||
|
if (level == 0) {
|
||||||
|
time(&thetime);
|
||||||
|
chartime = ctime(&thetime);
|
||||||
|
fprintf(stderr, "%.15s ", &(chartime[4]));
|
||||||
|
}
|
||||||
|
fprintf(stderr, s1, (&s1+1));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
alarmhandler() {
|
||||||
|
fprintf(stderr, "alarm at %d - %s\n", dbgstate, dbgstrings[dbgstate]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* get a line from inpfd using nonbuffered input. The line is truncated if it is too
|
||||||
|
* long for the buffer. The result is left in lnbuf and the number of characters
|
||||||
|
* read in is returned.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
readline(int inpfd)
|
||||||
|
{
|
||||||
|
register char *ap;
|
||||||
|
register int i;
|
||||||
|
|
||||||
|
ap = lnbuf;
|
||||||
|
i = 0;
|
||||||
|
do {
|
||||||
|
if (read(inpfd, ap, 1) != 1) {
|
||||||
|
error(0, "read error in readline, fd=%d\n", inpfd);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} while ((++i < LNBFSZ - 2) && *ap++ != '\n');
|
||||||
|
if (i == LNBFSZ - 2) {
|
||||||
|
*ap = '\n';
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
*ap = '\0';
|
||||||
|
return(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define RDSIZE 512
|
||||||
|
char jobbuf[RDSIZE];
|
||||||
|
|
||||||
|
int
|
||||||
|
pass(int inpfd, int outfd, int bsize)
|
||||||
|
{
|
||||||
|
int bcnt = 0;
|
||||||
|
int rv = 0;
|
||||||
|
|
||||||
|
for(bcnt=bsize; bcnt > 0; bcnt -= rv) {
|
||||||
|
alarm(WRNETIMEOUT); /* to break hanging */
|
||||||
|
if((rv=read(inpfd, jobbuf, MIN(bcnt,RDSIZE))) < 0) {
|
||||||
|
error(0, "read error during pass, %d remaining\n", bcnt);
|
||||||
|
break;
|
||||||
|
} else if((write(outfd, jobbuf, rv)) != rv) {
|
||||||
|
error(0, "write error during pass, %d remaining\n", bcnt);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
alarm(0);
|
||||||
|
return(bcnt);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* get whatever stdin has and put it into the temporary file.
|
||||||
|
* return the file size.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
prereadfile(int inpfd)
|
||||||
|
{
|
||||||
|
int rv, bsize;
|
||||||
|
|
||||||
|
bsize = 0;
|
||||||
|
do {
|
||||||
|
if((rv=read(0, jobbuf, RDSIZE))<0) {
|
||||||
|
error(0, "read error while making temp file\n");
|
||||||
|
exits("read error while making temp file");
|
||||||
|
} else if((write(inpfd, jobbuf, rv)) != rv) {
|
||||||
|
error(0, "write error while making temp file\n");
|
||||||
|
exits("write error while making temp file");
|
||||||
|
}
|
||||||
|
bsize += rv;
|
||||||
|
} while (rv!=0);
|
||||||
|
return(bsize);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
tempfile(void)
|
||||||
|
{
|
||||||
|
static int tindx = 0;
|
||||||
|
char tmpf[20];
|
||||||
|
int tmpfd;
|
||||||
|
|
||||||
|
sprint(tmpf, "/var/tmp/lp%d.%d", getpid(), tindx++);
|
||||||
|
if((tmpfd=create(tmpf,
|
||||||
|
|
||||||
|
#ifdef plan9
|
||||||
|
|
||||||
|
ORDWR|OTRUNC,
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
0666)) < 0) {
|
||||||
|
error(0, "cannot create temp file %s\n", tmpf);
|
||||||
|
exits("cannot create temp file");
|
||||||
|
}
|
||||||
|
close(tmpfd);
|
||||||
|
if((tmpfd=open(tmpf, ORDWR
|
||||||
|
|
||||||
|
#ifdef plan9
|
||||||
|
|
||||||
|
|ORCLOSE|OTRUNC
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
)) < 0) {
|
||||||
|
error(0, "cannot open temp file %s\n", tmpf);
|
||||||
|
exits("cannot open temp file");
|
||||||
|
}
|
||||||
|
return(tmpfd);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
recvACK(int netfd)
|
||||||
|
{
|
||||||
|
int rv;
|
||||||
|
|
||||||
|
*jobbuf = '\0';
|
||||||
|
alarm(RDNETIMEOUT);
|
||||||
|
if (read(netfd, jobbuf, 1)!=1 || *jobbuf!='\0') {
|
||||||
|
error(0, "failed to receive ACK, ");
|
||||||
|
if (*jobbuf == '\0')
|
||||||
|
error(1, "read failed\n");
|
||||||
|
else
|
||||||
|
error(1, "received <0x%x> instead\n", *jobbuf);
|
||||||
|
rv = 0;
|
||||||
|
} else rv = 1;
|
||||||
|
alarm(0);
|
||||||
|
return(rv);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
char *devdir;
|
||||||
|
int i, rv, netfd, bsize;
|
||||||
|
int datafd;
|
||||||
|
|
||||||
|
#ifndef plan9
|
||||||
|
|
||||||
|
void (*oldhandler)();
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
devdir = nil;
|
||||||
|
/* make connection */
|
||||||
|
if (argc != 2) {
|
||||||
|
fprint(stderr, "usage: %s network!destination!service\n", argv[0]);
|
||||||
|
exits("incorrect number of arguments");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* read options line from stdin into lnbuf */
|
||||||
|
i = readline(0);
|
||||||
|
|
||||||
|
/* read stdin into tempfile to get size */
|
||||||
|
datafd = tempfile();
|
||||||
|
bsize = prereadfile(datafd);
|
||||||
|
|
||||||
|
/* network connection is opened after data is in to avoid timeout */
|
||||||
|
if ((netfd=dial(argv[1], 0, 0, 0)) < 0) {
|
||||||
|
fprint(stderr, "dialing %s\n", devdir);
|
||||||
|
perror("dial");
|
||||||
|
exits("can't dial");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* write out the options we read above */
|
||||||
|
if (write(netfd, lnbuf, i) != i) {
|
||||||
|
error(0, "write error while sending options\n");
|
||||||
|
exits("write error while sending options");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* send the size of the file to be sent */
|
||||||
|
sprint(lnbuf, "%d\n", bsize);
|
||||||
|
i = strlen(lnbuf);
|
||||||
|
if ((rv=write(netfd, lnbuf, i)) != i) {
|
||||||
|
perror("write error while sending size");
|
||||||
|
error(0, "write returned %d\n", rv);
|
||||||
|
exits("write error while sending size");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (seek(datafd, 0L, 0) < 0) {
|
||||||
|
error(0, "error seeking temp file\n");
|
||||||
|
exits("seek error");
|
||||||
|
}
|
||||||
|
/* mirror performance in readfile() in lpdaemon */
|
||||||
|
|
||||||
|
#ifdef plan9
|
||||||
|
|
||||||
|
atnotify(alarmhandler, 1);
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
oldhandler = signal(SIGALRM, alarmhandler);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
dbgstate = 1;
|
||||||
|
if(!recvACK(netfd)) {
|
||||||
|
error(0, "failed to receive ACK before sending data\n");
|
||||||
|
exits("recv ack1 failed");
|
||||||
|
}
|
||||||
|
dbgstate = 2;
|
||||||
|
if ((i=pass(datafd, netfd, bsize)) != 0) {
|
||||||
|
NAK(netfd);
|
||||||
|
error(0, "failed to send %d bytes\n", i);
|
||||||
|
exits("send data failed");
|
||||||
|
}
|
||||||
|
ACK(netfd);
|
||||||
|
dbgstate = 3;
|
||||||
|
if(!recvACK(netfd)) {
|
||||||
|
error(0, "failed to receive ACK after sending data\n");
|
||||||
|
exits("recv ack2 failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* get response, as from lp -q */
|
||||||
|
dbgstate = 4;
|
||||||
|
while((rv=read(netfd, jobbuf, RDSIZE)) > 0) {
|
||||||
|
if((write(1, jobbuf, rv)) != rv) {
|
||||||
|
error(0, "write error while sending to stdout\n");
|
||||||
|
exits("write error while sending to stdout");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dbgstate = 5;
|
||||||
|
|
||||||
|
#ifdef plan9
|
||||||
|
|
||||||
|
atnotify(alarmhandler, 0);
|
||||||
|
/* close down network connections and go away */
|
||||||
|
exits("");
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
signal(SIGALRM, oldhandler);
|
||||||
|
exit(0);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
}
|
||||||
18
src/cmd/lp/lpsend.rc
Executable file
18
src/cmd/lp/lpsend.rc
Executable file
|
|
@ -0,0 +1,18 @@
|
||||||
|
#!/bin/rc
|
||||||
|
if (! ~ $DEBUG '') { flag x + }
|
||||||
|
if (test -e /net/tcp/clone) {
|
||||||
|
dialstring=`{ndb/query sys $1 dom}
|
||||||
|
network=tcp
|
||||||
|
if (~ $#dialstring 0 || ! ~ $dialstring '') {
|
||||||
|
dialstring=$1
|
||||||
|
}
|
||||||
|
if(lpsend $network^!^$dialstring^!printer) exit ''
|
||||||
|
rv='tcp failed'
|
||||||
|
}
|
||||||
|
if not rv='no tcp'
|
||||||
|
|
||||||
|
|
||||||
|
if (! ~ $dialstring '')
|
||||||
|
exit 'lpsend: no dialstring'
|
||||||
|
if not
|
||||||
|
exit 'lpsend: '^$rv
|
||||||
30
src/cmd/lp/mkfile
Normal file
30
src/cmd/lp/mkfile
Normal file
|
|
@ -0,0 +1,30 @@
|
||||||
|
<$PLAN9/src/mkhdr
|
||||||
|
|
||||||
|
TARG=\
|
||||||
|
lpdsend \
|
||||||
|
lpsend \
|
||||||
|
LOCK \
|
||||||
|
lpdaemon
|
||||||
|
|
||||||
|
OFILES=
|
||||||
|
|
||||||
|
HFILES=
|
||||||
|
|
||||||
|
BIN=$PLAN9/lp/bin
|
||||||
|
<$PLAN9/src/mkmany
|
||||||
|
CFLAGS=-Dplan9
|
||||||
|
|
||||||
|
install:V: $PLAN9/lp/bin/lpsend.rc $PLAN9/bin/lp
|
||||||
|
|
||||||
|
$PLAN9/lp/bin/lpsend.rc: lpsend.rc
|
||||||
|
cp $prereq $target
|
||||||
|
|
||||||
|
lpdsend.$O: lpdsend.c
|
||||||
|
$CC $CFLAGS -D_POSIX_SOURCE -D_BSD_EXTENSION -D_NET_EXTENSION -DPLAN9 -'DMAXHOSTNAMELEN=64' lpdsend.c
|
||||||
|
|
||||||
|
lpdaemon.$O: lpdaemon.c
|
||||||
|
$CC $CFLAGS -D_POSIX_SOURCE -DPLAN9 lpdaemon.c
|
||||||
|
|
||||||
|
$PLAN9/bin/lp: lp.rc
|
||||||
|
cp $prereq $target
|
||||||
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue