Subject: PAP interim release
From: wes.craig@umich.edu
Date: Tue Sep 08 1992 - 17:25:59 EDT
The following shar file contains the version of pap which will likely
be included in the 1.3 release. It expects to be installed in bin/pap.
To unshar it, cd to your source area's bin directory, and run the file
below through sh.
wes
------ cut ------
#! /bin/sh
# This is a shell archive. Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file". To overwrite existing
# files, type "sh file -c". You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g.. If this archive is complete, you
# will see the following message at the end:
# "End of shell archive."
# Contents: pap pap/README pap/Makefile pap/pap.c pap/papstatus.c
# Wrapped by wes@psycho.rs.itd.umich.edu on Tue Sep 8 17:20:46 1992
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test ! -d 'pap' ; then
echo shar: Creating directory \"'pap'\"
mkdir 'pap'
fi
if test -f 'pap/README' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'pap/README'\"
else
echo shar: Extracting \"'pap/README'\" \(1596 characters\)
sed "s/^X//" >'pap/README' <<'END_OF_FILE'
XThis is an interim release of pap (between the official release of
X1.2.1 and 1.3). It is a complete rewrite of the pap found in 1.2.1. It
Xexpects to be installed in the source bin directory, not in the source
Xetc/papd directory. There are two changes you might want to make to
Xthe CFLAGS variable in the Makefile:
X
X -DPRAGMATIC
X This causes several bit of work-around code to be included.
X Currently, there are three work-arounds:
X
X HP LJIIISI w/ BridgePort LocalTalk card sends zero
X instead of the connection ID in ATP Response packets.
X The work-around is to not check that the connection ID
X is correct.
X
X The Apple LaserWriter IIf doesn't send EOF under
X certain circumstance. There are probably several other
X implementations which have this bug. The symptom is
X that the job prints but leaves the job in the queue.
X As a temporary fix, we don't wait for the printer's EOF
X before sending our next file or closing. A better
X solution would be to determine that the other side
X wasn't going to send us EOF before giving up.
X
X The LaserWriter IINTX puts the current connection ID in
X status response packets. The offending field should be
X 0. The work around is to not check this field on status
X response packets.
X
X A general comment: there are lots of stinky PAP implementations
X out there. It's not clear if this is because PAP is a stinky
X protocol (it is), or there are a lot of stinky programmers
X (there are).
X
X -DEBUG
X This causes various bits of debugging to be printed on stdout.
X This is especially useful in conjunction with the debugging
X version of ATP.
END_OF_FILE
if test 1596 -ne `wc -c <'pap/README'`; then
echo shar: \"'pap/README'\" unpacked with wrong size!
fi
# end of 'pap/README'
fi
if test -f 'pap/Makefile' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'pap/Makefile'\"
else
echo shar: Extracting \"'pap/Makefile'\" \(1343 characters\)
sed "s/^X//" >'pap/Makefile' <<'END_OF_FILE'
XTARGETS= pap papstatus
XSRC = pap.c papstatus.c
X
XINCPATH= -I../../include
XCFLAGS= ${DEFS} ${OPTOPTS} ${INCPATH} -DPRAGMATIC
XLIBS= ${ADDLIBS} -latalk
XTAGSFILE= tags
XCC= cc
XINSTALL= install
XLIBDIRS= -L../../libatalk
X
Xall : ${TARGETS}
X
Xpap : pap.o ../../libatalk/libatalk.a
X ${CC} ${CFLAGS} -o pap pap.o ${LIBDIRS} ${LIBS}
X
Xpapstatus : papstatus.o ../../libatalk/libatalk.a
X ${CC} ${CFLAGS} -o papstatus papstatus.o ${LIBDIRS} ${LIBS}
X
Xinstall : all
X for i in ${TARGETS}; do ${INSTALL} -c $$i ${DESTDIR}/bin; done
X
Xclean :
X rm -f a.out core* *.o *.bak *[Ee]rrs tags
X rm -f ${TARGETS}
X
Xtags : ${SRC}
X cwd=`pwd`; \
X for i in ${SRC}; do \
X ctags -t -a -f ${TAGSFILE} $$cwd/$$i; \
X done
X
Xdepend :
X for i in ${SRC} ; do \
X ${CC} -M ${DEFS} ${INCPATH} $$i | \
X awk ' { if ($$1 != prev) { print rec; rec = $$0; prev = $$1; } \
X else { if (length(rec $$2) > 78) { print rec; rec = $$0; } \
X else rec = rec " " $$2 } } \
X END { print rec } ' >> makedep; done
X sed -n '1,/^# DO NOT DELETE THIS LINE/p' Makefile > Makefile.tmp
X cat makedep >> Makefile.tmp
X rm makedep
X echo '# DEPENDENCIES MUST END AT END OF FILE' >> Makefile.tmp
X echo '# IF YOU PUT STUFF HERE IT WILL GO AWAY' >> Makefile.tmp
X echo '# see make depend above' >> Makefile.tmp
X rm -f Makefile.bak
X cp Makefile Makefile.bak
X mv Makefile.tmp Makefile
X
X# DO NOT DELETE THIS LINE
X
END_OF_FILE
if test 1343 -ne `wc -c <'pap/Makefile'`; then
echo shar: \"'pap/Makefile'\" unpacked with wrong size!
fi
# end of 'pap/Makefile'
fi
if test -f 'pap/pap.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'pap/pap.c'\"
else
echo shar: Extracting \"'pap/pap.c'\" \(15953 characters\)
sed "s/^X//" >'pap/pap.c' <<'END_OF_FILE'
X/*
X * Copyright (c) 1990,1991 Regents of The University of Michigan.
X * All Rights Reserved.
X *
X * Permission to use, copy, modify, and distribute this software and
X * its documentation for any purpose and without fee is hereby granted,
X * provided that the above copyright notice appears in all copies and
X * that both that copyright notice and this permission notice appear
X * in supporting documentation, and that the name of The University
X * of Michigan not be used in advertising or publicity pertaining to
X * distribution of the software without specific, written prior
X * permission. This software is supplied as is without expressed or
X * implied warranties of any kind.
X *
X * Research Systems Unix Group
X * The University of Michigan
X * c/o Mike Clark
X * 535 W. William Street
X * Ann Arbor, Michigan
X * +1-313-763-0525
X * netatalk@itd.umich.edu
X */
X
X#include <sys/types.h>
X#include <sys/time.h>
X#include <sys/uio.h>
X#include <sys/file.h>
X#include <netatalk/endian.h>
X#include <netatalk/at.h>
X#include <atalk/atp.h>
X#include <atalk/pap.h>
X#include <atalk/nbp.h>
X#include <stdio.h>
X#include <strings.h>
X
X#define _PATH_PAPRC ".paprc"
X
Xusage( path )
X char *path;
X{
X char *p;
X
X if (( p = rindex( path, '/' )) == NULL ) {
X p = path;
X } else {
X p++;
X }
X fprintf( stderr,
X "Usage:\t%s [ -p printername ] [ -s statusfile ] [ file ] ...\n", p );
X exit( 1 );
X}
X
Xchar *
Xpaprc()
X{
X static char s[ 32 + 1 + 32 + 1 + 32 ];
X char *name = NULL;
X FILE *f;
X
X if (( f = fopen( _PATH_PAPRC, "r" )) == NULL ) {
X return( NULL );
X }
X while ( fgets( s, sizeof( s ), f ) != NULL ) {
X s[ strlen( s ) - 1 ] = '\0'; /* remove trailing newline */
X if ( *s == '#' ) {
X continue;
X }
X name = s;
X break;
X }
X fclose( f );
X return( name );
X}
X
Xchar *printer = NULL;
Xchar *status = NULL;
X
Xunsigned char connid, quantum, oquantum = PAP_MAXQUANTUM;
Xstruct sockaddr_at sat;
X
Xchar cbuf[ 8 ];
Xstruct nbpnve nn;
XATP satp;
X
Xmain( ac, av )
X int ac;
X char **av;
X{
X ATP atp;
X struct atp_block atpb;
X int c, err = 0, fd;
X char *obj = NULL, *type = "LaserWriter", *zone = "*";
X struct timeval stv, tv;
X char rbuf[ ATP_MAXDATA ];
X struct iovec iov;
X unsigned short waiting, result;
X extern char *optarg;
X extern int optind;
X
X while (( c = getopt( ac, av, "ep:s:" )) != EOF ) {
X switch ( c ) {
X case 'e' : /* send stdout to stderr */
X dup2( 2, 1 );
X break;
X
X case 'p' :
X printer = optarg;
X break;
X
X case 's' :
X status = optarg;
X break;
X
X default :
X fprintf( stderr, "Unknown option: '%c'\n", c );
X err++;
X }
X }
X if ( err ) {
X usage( *av );
X }
X if ( printer == NULL && (( printer = paprc()) == NULL )) {
X usage( *av );
X }
X
X /*
X * Open connection.
X */
X if ( nbp_name( printer, &obj, &type, &zone ) < 0 ) {
X fprintf( stderr, "%s: Bad name\n", printer );
X exit( 1 );
X }
X if ( obj == NULL ) {
X fprintf( stderr, "%s: Bad name\n", printer );
X exit( 1 );
X }
X if ( nbp_lookup( obj, type, zone, &nn, 1 ) <= 0 ) {
X perror( "nbp_lookup" );
X exit( 1 );
X }
X if ( isatty( 0 )) {
X printf( "Trying %u.%d:%d ...\n", ntohs( nn.nn_sat.sat_addr.s_net ),
X nn.nn_sat.sat_addr.s_node, nn.nn_sat.sat_port );
X }
X
X if (( atp = atp_open( 0 )) == NULL ) {
X perror( "atp_open" );
X exit( 1 );
X }
X if (( satp = atp_open( 0 )) == NULL ) {
X perror( "atp_open" );
X exit( 1 );
X }
X
X cbuf[ 0 ] = connid = getpid() & 0xff;
X cbuf[ 1 ] = PAP_OPEN;
X cbuf[ 2 ] = cbuf[ 3 ] = 0;
X cbuf[ 4 ] = atp_sockaddr( atp )->sat_port;
X cbuf[ 5 ] = oquantum; /* flow quantum */
X if ( gettimeofday( &stv, 0 ) < 0 ) {
X perror( "gettimeofday" );
X exit( 1 );
X }
X for (;;) {
X if ( gettimeofday( &tv, 0 ) < 0 ) {
X perror( "gettimeofday" );
X exit( 1 );
X }
X waiting = htons( tv.tv_sec - stv.tv_sec );
X bcopy( &waiting, &cbuf[ 6 ], sizeof( waiting ));
X
X atpb.atp_saddr = &nn.nn_sat;
X atpb.atp_sreqdata = cbuf;
X atpb.atp_sreqdlen = 8; /* bytes in OpenConn request */
X atpb.atp_sreqto = 2; /* retry timer */
X atpb.atp_sreqtries = 5; /* retry count */
X if ( atp_sreq( atp, &atpb, 1, ATP_XO ) < 0 ) {
X perror( "atp_sreq" );
X exit( 1 );
X }
X#ifdef EBUG
Xprintf( "> OPEN\n" );
X#endif EBUG
X
X iov.iov_base = rbuf;
X iov.iov_len = sizeof( rbuf );
X atpb.atp_rresiov = &iov;
X atpb.atp_rresiovcnt = 1;
X if ( atp_rresp( atp, &atpb ) < 0 ) {
X perror( "atp_rresp" );
X exit( 1 );
X }
X
X /* sanity */
X if ( iov.iov_len < 8 || (unsigned char)rbuf[ 0 ] != connid ||
X rbuf[ 1 ] != PAP_OPENREPLY ) {
X fprintf( stderr, "Bad response!\n" );
X continue; /* This is weird, since TIDs must match... */
X }
X#ifdef EBUG
Xprintf( "< OPENREPLY\n" );
X#endif EBUG
X
X if ( isatty( 1 )) {
X printf( "%.*s\n", iov.iov_len - 9, iov.iov_base + 9 );
X }
X updatestatus( iov.iov_base + 9, iov.iov_len - 9 );
X
X bcopy( &rbuf[ 6 ], &result, sizeof( result ));
X if ( result != 0 ) {
X sleep( 2 );
X } else {
X bcopy( &nn.nn_sat, &sat, sizeof( struct sockaddr_at ));
X sat.sat_port = rbuf[ 4 ];
X quantum = rbuf[ 5 ];
X break;
X }
X }
X
X if ( isatty( 1 )) {
X printf( "Connected to %.*s:%.*s@%.*s.\n",
X nn.nn_objlen, nn.nn_obj,
X nn.nn_typelen, nn.nn_type,
X nn.nn_zonelen, nn.nn_zone );
X }
X
X if ( optind == ac ) {
X sendfile( 0, atp );
X } else {
X for (; optind < ac; optind++ ) {
X if ( strcmp( av[ optind ], "-" ) == 0 ) {
X fd = 0;
X } else if (( fd = open( av[ optind ], O_RDONLY )) < 0 ) {
X perror( av[ optind ] );
X continue;
X }
X sendfile( fd, atp );
X if ( fd != 0 ) {
X close( fd );
X }
X }
X }
X
X /*
X * Close connection.
X */
X cbuf[ 0 ] = connid;
X cbuf[ 1 ] = PAP_CLOSE;
X cbuf[ 2 ] = cbuf[ 3 ] = 0;
X
X atpb.atp_saddr = &sat;
X atpb.atp_sreqdata = cbuf;
X atpb.atp_sreqdlen = 4; /* bytes in CloseConn request */
X atpb.atp_sreqto = 2; /* retry timer */
X atpb.atp_sreqtries = 5; /* retry count */
X if ( atp_sreq( atp, &atpb, 1, ATP_XO ) < 0 ) {
X perror( "atp_sreq" );
X exit( 1 );
X }
X#ifdef EBUG
Xprintf( "> CLOSE\n" );
X#endif EBUG
X
X iov.iov_base = rbuf;
X iov.iov_len = sizeof( rbuf );
X atpb.atp_rresiov = &iov;
X atpb.atp_rresiovcnt = 1;
X if ( atp_rresp( atp, &atpb ) < 0 ) {
X perror( "atp_rresp" );
X exit( 1 );
X }
X
X /* sanity */
X if ( iov.iov_len != 4 || (unsigned char)rbuf[ 0 ] != connid ||
X rbuf[ 1 ] != PAP_CLOSEREPLY ) {
X fprintf( stderr, "Bad response!\n" );
X exit( 1 ); /* This is weird, since TIDs must match... */
X }
X#ifdef EBUG
Xprintf( "< CLOSEREPLY\n" );
X#endif EBUG
X if ( isatty( 1 )) {
X printf( "Connection closed.\n" );
X }
X exit( 0 );
X}
X
Xchar fbuf[ PAP_MAXQUANTUM ][ 4 + PAP_MAXDATA ];
Xstruct iovec rfiov[ PAP_MAXQUANTUM ] = {
X { fbuf[ 0 ] + 4, 0 },
X { fbuf[ 1 ] + 4, 0 },
X { fbuf[ 2 ] + 4, 0 },
X { fbuf[ 3 ] + 4, 0 },
X { fbuf[ 4 ] + 4, 0 },
X { fbuf[ 5 ] + 4, 0 },
X { fbuf[ 6 ] + 4, 0 },
X { fbuf[ 7 ] + 4, 0 },
X};
Xstruct iovec sniov[ PAP_MAXQUANTUM ] = {
X { fbuf[ 0 ], 0 },
X { fbuf[ 1 ], 0 },
X { fbuf[ 2 ], 0 },
X { fbuf[ 3 ], 0 },
X { fbuf[ 4 ], 0 },
X { fbuf[ 5 ], 0 },
X { fbuf[ 6 ], 0 },
X { fbuf[ 7 ], 0 },
X};
X
Xchar nbuf[ PAP_MAXQUANTUM ][ 4 + PAP_MAXDATA ];
Xstruct iovec rniov[ PAP_MAXQUANTUM ] = {
X { nbuf[ 0 ], 0 },
X { nbuf[ 1 ], 0 },
X { nbuf[ 2 ], 0 },
X { nbuf[ 3 ], 0 },
X { nbuf[ 4 ], 0 },
X { nbuf[ 5 ], 0 },
X { nbuf[ 6 ], 0 },
X { nbuf[ 7 ], 0 },
X};
Xstruct iovec sfiov[ PAP_MAXQUANTUM ] = {
X { nbuf[ 0 ] + 4, 0 },
X { nbuf[ 1 ] + 4, 0 },
X { nbuf[ 2 ] + 4, 0 },
X { nbuf[ 3 ] + 4, 0 },
X { nbuf[ 4 ] + 4, 0 },
X { nbuf[ 5 ] + 4, 0 },
X { nbuf[ 6 ] + 4, 0 },
X { nbuf[ 7 ] + 4, 0 },
X};
X
Xint data = 0;
Xunsigned char port;
Xunsigned short seq = 0;
X
Xsendfile( fd, atp )
X int fd;
X ATP atp;
X{
X struct timeval tv;
X struct sockaddr_at ssat;
X struct atp_block atpb;
X fd_set fds;
X int fiovcnt = 0, niovcnt = 0, eof = 0, senteof = 0, to = 0;
X int cc, i;
X
X tv.tv_sec = 60;
X tv.tv_usec = 0;
X
X /*
X * Ask for more data.
X */
X cbuf[ 0 ] = connid;
X cbuf[ 1 ] = PAP_READ;
X if ( ++seq == 0xffff ) seq = 1;
X bcopy( &seq, &cbuf[ 2 ], sizeof( seq ));
X atpb.atp_saddr = &sat;
X atpb.atp_sreqdata = cbuf;
X atpb.atp_sreqdlen = 4; /* bytes in SendData request */
X atpb.atp_sreqto = 15; /* retry timer */
X atpb.atp_sreqtries = -1; /* retry count */
X if ( atp_sreq( atp, &atpb, oquantum, ATP_XO ) < 0 ) {
X perror( "atp_sreq" );
X exit( 1 );
X }
X#ifdef EBUG
Xprintf( "> READ %d\n", seq );
X#endif EBUG
X
X for (;;) {
X FD_ZERO( &fds );
X if ( !eof && fiovcnt == 0 ) {
X FD_SET( fd, &fds );
X }
X FD_SET( atp_fileno( atp ), &fds );
X
X if (( cc = select( FD_SETSIZE, &fds, 0, 0, &tv )) < 0 ) {
X perror( "select" );
X exit( 1 );
X }
X
X /*
X * A timeout has occured. Keep track of it, and go ahead and
X * send a tickle.
X */
X if ( cc == 0 ) {
X if ( to++ > 2 ) {
X fprintf( stderr, "Connection timed out.\n" );
X exit( 1 );
X }
X
X /*
X * Send a tickle.
X */
X cbuf[ 0 ] = connid;
X cbuf[ 1 ] = PAP_TICKLE;
X cbuf[ 2 ] = cbuf[ 3 ] = 0;
X atpb.atp_saddr = &sat;
X atpb.atp_sreqdata = cbuf;
X atpb.atp_sreqdlen = 4; /* bytes in Tickle request */
X atpb.atp_sreqto = 0; /* retry timer */
X atpb.atp_sreqtries = 1; /* retry count */
X if ( atp_sreq( satp, &atpb, 0, 0 ) < 0 ) {
X perror( "atp_sreq" );
X exit( 1 );
X }
X#ifdef EBUG
Xprintf( "> TICKLE\n" );
X#endif EBUG
X } else {
X to = 0;
X }
X
X /*
X * Read data.
X */
X if ( !fiovcnt && FD_ISSET( fd, &fds )) {
X for ( i = 0; i < quantum; i++ ) {
X rfiov[ i ].iov_len = PAP_MAXDATA;
X }
X if (( cc = readv( fd, rfiov, quantum )) < 0 ) {
X perror( "readv" );
X exit( 1 );
X }
X if ( cc == 0 ) {
X eof = 1;
X }
X fiovcnt = cc / PAP_MAXDATA + ( cc % PAP_MAXDATA > 0 );
X for ( i = 0; cc > 0; i++ ) {
X rfiov[ i ].iov_len = ( cc > PAP_MAXDATA ) ? PAP_MAXDATA : cc;
X cc -= ( cc > PAP_MAXDATA ) ? PAP_MAXDATA : cc;
X }
X }
X
X if ( FD_ISSET( atp_fileno( atp ), &fds )) {
X ssat = sat;
X ssat.sat_port = ATADDR_ANYPORT;
X switch( atp_rsel( atp, &ssat, ATP_TRESP | ATP_TREQ )) {
X case ATP_TREQ :
X atpb.atp_saddr = &ssat;
X atpb.atp_rreqdata = cbuf;
X atpb.atp_rreqdlen = sizeof( cbuf );
X if ( atp_rreq( atp, &atpb ) < 0 ) {
X perror( "atp_rreq" );
X exit( 1 );
X }
X /* sanity */
X if ( (unsigned char)cbuf[ 0 ] != connid ) {
X fprintf( stderr, "Bad ATP request!\n" );
X exit( 1 );
X }
X
X switch ( cbuf[ 1 ] ) {
X case PAP_READ :
X#ifdef EBUG
Xprintf( "< READ\n" );
X#endif EBUG
X data = 1;
X port = ssat.sat_port;
X break;
X
X case PAP_CLOSE :
X#ifdef EBUG
Xprintf( "< CLOSE\n" );
X#endif EBUG
X /*
X * Respond to the close request, and fail.
X */
X sniov[ 0 ].iov_len = 4;
X sniov[ 0 ].iov_base[ 0 ] = connid;
X sniov[ 0 ].iov_base[ 1 ] = PAP_CLOSEREPLY;
X sniov[ 0 ].iov_base[ 2 ] = sniov[ 0 ].iov_base[ 3 ] = 0;
X atpb.atp_sresiov = sniov;
X atpb.atp_sresiovcnt = 1;
X if ( atp_sresp( atp, &atpb ) < 0 ) {
X perror( "atp_sresp" );
X exit( 1 );
X }
X#ifdef EBUG
Xprintf( "> CLOSEREPLY\n" );
X#endif EBUG
X fprintf( stderr, "Connection closed by foreign host.\n" );
X exit( 1 );
X
X case PAP_TICKLE :
X#ifdef EBUG
Xprintf( "< TICKLE\n" );
X#endif EBUG
X break;
X default :
X fprintf( stderr, "Bad PAP request!\n" );
X exit( 1 );
X }
X break;
X
X case ATP_TRESP :
X atpb.atp_saddr = &ssat;
X for ( i = 0; i < oquantum; i++ ) {
X rniov[ i ].iov_len = PAP_MAXDATA + 4;
X }
X atpb.atp_rresiov = rniov;
X atpb.atp_rresiovcnt = oquantum;
X if ( atp_rresp( atp, &atpb ) < 0 ) {
X perror( "atp_rresp" );
X exit( 1 );
X }
X
X#ifndef PRAGMATIC
X /*
X * The HP LJIIISI w/ BridgePort LocalTalk card sends
X * zero instead of the connid.
X */
X if ( (unsigned char)rniov[ 0 ].iov_base[ 0 ] != connid ) {
X fprintf( stderr, "Bad data response!\n" );
X exit( 1 );
X }
X#endif PRAGMATIC
X if ( rniov[ 0 ].iov_base[ 1 ] != PAP_DATA ) {
X fprintf( stderr, "Bad data response!\n" );
X exit( 1 );
X }
X#ifdef EBUG
Xprintf( "< DATA\n" );
X#endif EBUG
X
X /* eof */
X if ( rniov[ 0 ].iov_base[ 2 ] ) {
X return( 0 );
X }
X
X for ( cc = 0, i = 0; i < atpb.atp_rresiovcnt; i++ ) {
X cc += sfiov[ i ].iov_len = rniov[ i ].iov_len - 4;
X }
X if ( writev( 1, sfiov, atpb.atp_rresiovcnt ) < cc ) {
X perror( "writev" );
X exit( 1 );
X }
X
X /*
X * Ask for more data.
X */
X cbuf[ 0 ] = connid;
X cbuf[ 1 ] = PAP_READ;
X if ( ++seq == 0xffff ) seq = 1;
X bcopy( &seq, &cbuf[ 2 ], sizeof( seq ));
X atpb.atp_saddr = &sat;
X atpb.atp_sreqdata = cbuf;
X atpb.atp_sreqdlen = 4; /* bytes in SendData request */
X atpb.atp_sreqto = 15; /* retry timer */
X atpb.atp_sreqtries = -1; /* retry count */
X if ( atp_sreq( atp, &atpb, oquantum, ATP_XO ) < 0 ) {
X perror( "atp_sreq" );
X exit( 1 );
X }
X#ifdef EBUG
Xprintf( "> READ %d\n", seq );
X#endif EBUG
X break;
X
X default:
X perror( "atp_rsel" );
X exit( 1 );
X }
X }
X
X /*
X * Send whatever is pending.
X */
X if ( !senteof && data && ( fiovcnt || eof )) {
X ssat.sat_port = port;
X atpb.atp_saddr = &ssat;
X if ( fiovcnt ) {
X for ( i = 0; i < fiovcnt; i++ ) {
X sniov[ i ].iov_len = rfiov[ i ].iov_len + 4;
X sniov[ i ].iov_base[ 0 ] = connid;
X sniov[ i ].iov_base[ 1 ] = PAP_DATA;
X senteof = sniov[ i ].iov_base[ 2 ] = eof;
X sniov[ i ].iov_base[ 3 ] = 0;
X }
X } else {
X sniov[ 0 ].iov_len = 4;
X sniov[ 0 ].iov_base[ 0 ] = connid;
X sniov[ 0 ].iov_base[ 1 ] = PAP_DATA;
X senteof = sniov[ 0 ].iov_base[ 2 ] = eof;
X sniov[ 0 ].iov_base[ 3 ] = 0;
X }
X atpb.atp_sresiov = sniov;
X atpb.atp_sresiovcnt = fiovcnt ? fiovcnt : 1;
X if ( atp_sresp( atp, &atpb ) < 0 ) {
X perror( "atp_sresp" );
X exit( 1 );
X }
X#ifdef EBUG
Xif ( eof ) {
Xprintf( "> DATA (eof)\n" );
X} else {
Xprintf( "> DATA\n" );
X}
X#endif EBUG
X data = fiovcnt = 0;
X#ifdef PRAGMATIC
X /*
X * The Apple LaserWriter IIf (and perhaps g) doesn't seem to
X * send us an EOF. To work around this heinous protocol
X * violation, we won't wait for their EOF before sending our
X * next file or closing.
X */
X if ( eof ) {
X return( 0 );
X }
X#endif PRAGMATIC
X
X } else {
X /*
X * If we can't send data right now, go ahead and get the
X * status. This is cool, because we get here reliable
X * if there is a problem.
X */
X cbuf[ 0 ] = 0;
X cbuf[ 1 ] = PAP_SENDSTATUS;
X cbuf[ 2 ] = cbuf[ 3 ] = 0;
X atpb.atp_saddr = &nn.nn_sat;
X atpb.atp_sreqdata = cbuf;
X atpb.atp_sreqdlen = 4; /* bytes in SendStatus request */
X atpb.atp_sreqto = 2; /* retry timer */
X atpb.atp_sreqtries = 5; /* retry count */
X if ( atp_sreq( satp, &atpb, 1, 0 ) < 0 ) {
X perror( "atp_sreq" );
X exit( 1 );
X }
X#ifdef EBUG
Xprintf( "> SENDSTATUS\n" );
X#endif EBUG
X
X atpb.atp_saddr = &nn.nn_sat;
X rniov[ 0 ].iov_len = PAP_MAXDATA + 4;
X atpb.atp_rresiov = rniov;
X atpb.atp_rresiovcnt = 1;
X if ( atp_rresp( satp, &atpb ) < 0 ) {
X perror( "atp_rresp" );
X continue;
X }
X
X#ifndef PRAGMATIC
X /*
X * The stinking LaserWriter IINTX puts crap in this
X * field.
X */
X if ( rniov[ 0 ].iov_base[ 0 ] != 0 ) {
X fprintf( stderr, "Bad status response!\n" );
X exit( 1 );
X }
X#endif PRAGMATIC
X
X if ( rniov[ 0 ].iov_base[ 1 ] != PAP_STATUS ||
X atpb.atp_rresiovcnt != 1 ) {
X fprintf( stderr, "Bad status response!\n" );
X exit( 1 );
X }
X#ifdef EBUG
Xprintf( "< STATUS\n" );
X#endif EBUG
X updatestatus( rniov[ 0 ].iov_base + 9,
X rniov[ 0 ].iov_base[ 8 ] );
X }
X }
X}
X
Xupdatestatus( s, len )
X char *s;
X int len;
X{
X int fd;
X struct iovec iov[ 2 ];
X
X if ( !status ) {
X return;
X }
X
X if (( fd = open( status, O_WRONLY|O_TRUNC )) < 0 ) {
X perror( status );
X status = NULL;
X return;
X }
X iov[ 0 ].iov_base = s;
X iov[ 0 ].iov_len = len;
X iov[ 1 ].iov_base = "\n";
X iov[ 1 ].iov_len = 1;
X writev( fd, iov, 2 );
X close( fd );
X}
END_OF_FILE
if test 15953 -ne `wc -c <'pap/pap.c'`; then
echo shar: \"'pap/pap.c'\" unpacked with wrong size!
fi
# end of 'pap/pap.c'
fi
if test -f 'pap/papstatus.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'pap/papstatus.c'\"
else
echo shar: Extracting \"'pap/papstatus.c'\" \(3965 characters\)
sed "s/^X//" >'pap/papstatus.c' <<'END_OF_FILE'
X/*
X * Copyright (c) 1990,1991 Regents of The University of Michigan.
X * All Rights Reserved.
X *
X * Permission to use, copy, modify, and distribute this software and
X * its documentation for any purpose and without fee is hereby granted,
X * provided that the above copyright notice appears in all copies and
X * that both that copyright notice and this permission notice appear
X * in supporting documentation, and that the name of The University
X * of Michigan not be used in advertising or publicity pertaining to
X * distribution of the software without specific, written prior
X * permission. This software is supplied as is without expressed or
X * implied warranties of any kind.
X *
X * Research Systems Unix Group
X * The University of Michigan
X * c/o Mike Clark
X * 535 W. William Street
X * Ann Arbor, Michigan
X * +1-313-763-0525
X * netatalk@itd.umich.edu
X */
X
X#include <sys/types.h>
X#include <sys/time.h>
X#include <sys/uio.h>
X#include <sys/file.h>
X#include <netatalk/endian.h>
X#include <netatalk/at.h>
X#include <atalk/atp.h>
X#include <atalk/pap.h>
X#include <atalk/nbp.h>
X#include <stdio.h>
X#include <strings.h>
X
X#define _PATH_PAPRC ".paprc"
X
Xusage( path )
X char *path;
X{
X char *p;
X
X if (( p = rindex( path, '/' )) == NULL ) {
X p = path;
X } else {
X p++;
X }
X fprintf( stderr,
X "Usage:\t%s [ -p printername ]\n", p );
X exit( 1 );
X}
X
Xchar *
Xpaprc()
X{
X static char s[ 32 + 1 + 32 + 1 + 32 ];
X char *name = NULL;
X FILE *f;
X
X if (( f = fopen( _PATH_PAPRC, "r" )) == NULL ) {
X return( NULL );
X }
X while ( fgets( s, sizeof( s ), f ) != NULL ) {
X s[ strlen( s ) - 1 ] = '\0'; /* remove trailing newline */
X if ( *s == '#' ) {
X continue;
X }
X name = s;
X break;
X }
X fclose( f );
X return( name );
X}
X
Xchar *printer = NULL;
X
Xchar cbuf[ 8 ];
Xstruct nbpnve nn;
X
Xmain( ac, av )
X int ac;
X char **av;
X{
X ATP atp;
X int wait, c, err = 0;
X char *obj = NULL, *type = "LaserWriter", *zone = "*";
X extern char *optarg;
X extern int optind;
X
X while (( c = getopt( ac, av, "p:s:" )) != EOF ) {
X switch ( c ) {
X case 'p' :
X printer = optarg;
X break;
X
X default :
X fprintf( stderr, "Unknown option: '%c'\n", c );
X err++;
X }
X }
X if ( err ) {
X usage( *av );
X }
X if ( printer == NULL && (( printer = paprc()) == NULL )) {
X usage( *av );
X }
X
X /*
X * Open connection.
X */
X if ( nbp_name( printer, &obj, &type, &zone ) < 0 ) {
X fprintf( stderr, "%s: Bad name\n", printer );
X exit( 1 );
X }
X if ( obj == NULL ) {
X fprintf( stderr, "%s: Bad name\n", printer );
X exit( 1 );
X }
X if ( nbp_lookup( obj, type, zone, &nn, 1 ) <= 0 ) {
X perror( "nbp_lookup" );
X exit( 1 );
X }
X
X if (( atp = atp_open( 0 )) == NULL ) {
X perror( "atp_open" );
X exit( 1 );
X }
X
X if ( optind == ac ) {
X getstatus( atp, &nn.nn_sat );
X exit( 0 );
X }
X if ( optind - ac > 1 ) {
X usage( *av );
X }
X wait = atoi( av[ optind ] );
X for (;;) {
X getstatus( atp, &nn.nn_sat );
X sleep( wait );
X }
X}
X
Xgetstatus( atp, sat )
X ATP atp;
X struct sockaddr_at *sat;
X{
X struct iovec iov;
X struct atp_block atpb;
X char rbuf[ ATP_MAXDATA ];
X
X cbuf[ 0 ] = 0;
X cbuf[ 1 ] = PAP_SENDSTATUS;
X cbuf[ 2 ] = cbuf[ 3 ] = 0;
X
X atpb.atp_saddr = sat;
X atpb.atp_sreqdata = cbuf;
X atpb.atp_sreqdlen = 4; /* bytes in SendStatus request */
X atpb.atp_sreqto = 2; /* retry timer */
X atpb.atp_sreqtries = 5; /* retry count */
X if ( atp_sreq( atp, &atpb, 1, ATP_XO ) < 0 ) {
X perror( "atp_sreq" );
X exit( 1 );
X }
X
X iov.iov_base = rbuf;
X iov.iov_len = sizeof( rbuf );
X atpb.atp_rresiov = &iov;
X atpb.atp_rresiovcnt = 1;
X if ( atp_rresp( atp, &atpb ) < 0 ) {
X perror( "atp_rresp" );
X exit( 1 );
X }
X
X /* sanity */
X if ( iov.iov_len < 8 ||
X rbuf[ 1 ] != PAP_STATUS ) {
X fprintf( stderr, "Bad response!\n" );
X return; /* This is weird, since TIDs must match... */
X }
X
X printf( "%.*s\n", iov.iov_len - 9, iov.iov_base + 9 );
X}
END_OF_FILE
if test 3965 -ne `wc -c <'pap/papstatus.c'`; then
echo shar: \"'pap/papstatus.c'\" unpacked with wrong size!
fi
# end of 'pap/papstatus.c'
fi
echo shar: End of shell archive.
exit 0
This archive was generated by hypermail 2b28 : Sat Dec 18 1999 - 16:09:02 EST