home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ftp.wwiv.com
/
ftp.wwiv.com.zip
/
ftp.wwiv.com
/
pub
/
PPPBCKP
/
SRC
/
SRC15B91.ZIP
/
WATTSRC.ZIP
/
APPS
/
LPR.C
< prev
next >
Wrap
Text File
|
1994-11-28
|
12KB
|
412 lines
/*
* LPR - dump job to printer
*
*
* Copyright (C) 1991, University of Waterloo
*
* Portions Copyright (C) 1990, National Center for Supercomputer Applications
* and portions copyright (c) 1990, Clarkson University
*
* This program is free software; you can redistribute it and/or modify
* it, but you may not sell it.
*
* This program is distributed in the hope that it will be useful,
* but without any warranty; without even the implied warranty of
* merchantability or fitness for a particular purpose.
*
* Erick Engelke or via E-Mail
* Faculty of Engineering
* University of Waterloo Erick@development.watstar.uwaterloo.ca
* 200 University Ave.,
* Waterloo, Ont., Canada
* N2L 3G1
*
*
* The following notes on control and data files were obtained from Clarkson's
* CUTE project.
*
*
* Control File: format is the first character in the line is a command,
* the rest of the line is the argument. Also note lowercase letters
* denote the data file names (of various types).
*
* currently valid commands are:
*
* J -- "job name" on banner page
* C -- "class name" on banner page
* L -- "literal" user's name to print on banner
* T -- "title" for pr
* H -- "host name" of machine where lpr was done
* P -- "person" user's login name
* I -- "indent" amount to indent output
* f -- "file name" name of text file to print
* l -- "file name" text file with control chars
* p -- "file name" text file to print with pr(1)
* t -- "file name" troff(1) file to print
* n -- "file name" ditroff(1) file to print
* d -- "file name" dvi file to print
* g -- "file name" plot(1G) file to print
* v -- "file name" plain raster file to print (impress)
* c -- "file name" cifplot file to print
* 1 -- "R font file" for troff
* 2 -- "I font file" for troff
* 3 -- "B font file" for troff
* 4 -- "S font file" for troff
* N -- "name" of file (used by lpq)
* U -- "unlink" name of file to remove
* (after we print it. (Pass 2 only)).
* M -- "mail" to user when done printing
*
* Currently it looks like only a lowercase filename and U command are
* necessary. However one should also include J, L, H, and P.
*
* In general the lpd program doesn't care what the data file looks like.
* It should however be of the type specified in the control file
* otherwise it will probably print incorrectly.
*
* The format is ?fA<number><hostname>. ? is either c for control or d
* for data files. Number is a 3 digit number (0 padded) used for job
* number information. Hostname is the name of the originating host and
* had best be equal to whatever shows up in the from field when a
* connection is opened (ie probably should be the "real" hostname).
* Currently all of these must be used as the program has them compiled in
* (by stupid use of pointers). I may change this in time but currently
* it is the law if you want everything to work (some things will work
* just fine without it, queueing a file just wants names, showing the
* queue expects a number to start in the fourth position, deleting a file
* expects the hostname to start in the 7th position and go to the end of
* the filename.
*
* default userid = server = "UNKNOWN";
*
* get's sequence file from getenv( "SEQUENCE" )
* else "SEQUENCE.LPR"
*
* if ( ( title = getenv( "TITLE" )) == NULL )
* title = "stdprn";
* if ( ( jobname = getenv( "JOBNAME" )) == NULL )
* jobname = "job_name";
* if ( ( class = getenv("CLASS")) == NULL )
* class = server
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h>
#include <io.h>
#include <tcp.h>
#define SHORT_LIST 3
#define LONG_LIST 4
#define MFCF_COUNT 5
char *mfcf[MFCF_COUNT];
#define LPQ_PORT 515
#define LOCAL_PORT 722
#define SEQFILE "SEQUENCE.LPR"
char *seqwhere;
word getsequence( void )
{
static word oldseq = 0;
FILE *f;
if ( ! oldseq ) {
/* must look to disk for an old sequence number */
if ( (f = fopen( seqwhere, "rt" )) != NULL ) {
fscanf( f, "%u", &oldseq );
fclose( f );
}
}
oldseq = ( oldseq + 1 ) % 1000;
if ( (f = fopen( seqwhere, "wt" )) != NULL ) {
fprintf( f, "%u", oldseq );
fclose( f );
}
return( oldseq );
}
int lpr( char *localhostname, char *printer, char *rhostname, char *filename,
char *title, char *jobname, char *class, char *username, char *servername )
{
static tcp_Socket socketdata;
tcp_Socket *s;
longword filesize;
longword host;
int status = 0;
int connected = 0;
int completed = 0;
int localport;
word seqnum, i;
static char buffer[ 1024 ];
char *b2;
char remotename[ 80 ];
static char cmdfile[ 1024 ];
longword remaining;
word found;
FILE *f;
if (( *class == 0 ) || (*class == ' ')) class = NULL;
for ( i = 0; i < MFCF_COUNT ; ++i ) {
if ( mfcf[ i ] )
printf("Extra option: %s\n", mfcf[i] );
}
if ( (f = fopen( filename, "rb")) == NULL ) {
printf("Unable to open file '%s'\n", filename );
return( 3 );
}
sock_init();
s = &socketdata;
if (!(host = resolve( rhostname ))) {
printf( "lpq: unknown host %s\n",rhostname);
return(1);
}
localport = 255 + (MsecClock() & 255);
if ( !tcp_open( s, localport, host, LPQ_PORT, NULL)) {
printf("Unable to open socket.");
tcp_shutdown();
return(1);
}
printf( "connecting...\r");
sock_wait_established( s, sock_delay, NULL, &status );
connected = 1;
printf("connection established\n");
/* is there an opening message - non-standard but possible */
if (sock_dataready( s )) {
sock_fastread( s, buffer, sizeof( buffer ));
sock_tick( s, &status ); /* in case above message closed port */
}
/* use ipnumber/time */
seqnum = getsequence();
sprintf(remotename,"fA%03u%s", seqnum, localhostname );
/* we are connected */
sprintf( buffer, "\2%s\n", printer ); /* select a printer */
sock_puts( s, buffer );
/* state #2 */
sock_wait_input( s, sock_delay, NULL, &status );
sock_fastread( s, buffer, sizeof( buffer ));
switch (*buffer) {
case 0 : break;
case 1 : printf("Printer '%s' is not available\n", printer);
goto close_it;
default: rip( buffer );
printf("ERROR: %s\n", buffer);
goto close_it;
}
/* printer is accepted, printing file */
filesize = filelength( fileno( f ));
sprintf( buffer, "\3%ld d%s\n", filesize, remotename );
sock_puts( s , buffer );
sock_wait_input( s, sock_delay, NULL, &status );
/* state 3, reply from filename */
sock_fastread( s, buffer, sizeof( buffer ));
switch (*buffer) {
case 0: break;
case 1: printf("remote host complains of bad connection");
goto close_it;
case 2: puts("remote host out of storage space");
goto close_it;
}
/* dump file */
remaining = filesize;
do {
cprintf("Transferred: %lu %c \r",
((filesize - remaining + 1L)*100L)/(filesize+1), 37 );
backgroundon();
if ( (found = fread( buffer, 1, sizeof(buffer), f)) == 0 )
break;
backgroundoff();
sock_write( s, buffer, found );
sock_tick( s , &status );
if (sock_dataready( s )) {
puts("LPR: interrupted on transfer...");
goto close_it;
}
} while ( (remaining -= (longword)found) > 0 );
sock_putc( s, 0 );
/* check on status of this file */
sock_wait_input( s, sock_delay, NULL, &status );
sock_fastread( s, buffer, sizeof(buffer));
switch (*buffer) {
case 0: break;
default:puts("file was rejected");
goto close_it; /* could retry */
}
sprintf( cmdfile, "H%s\n" "P%s\n" "C%s\n" "L%s\n",
servername, /* eg "development" */
username, /* eg "erick", */
class ? class : servername, /* eg "NDSW or development", */
username ); /* eg "erick" for on banner */
for ( i = 0 ; i < MFCF_COUNT ; ++i ) {
if ( mfcf[i] ) {
strcat( cmdfile, mfcf[i] );
strcat( cmdfile, "\n" );
}
}
b2 = strchr( cmdfile, 0 );
sprintf( b2, "T%s\n" "fd%s\n" "N%s\n" "Ud%s\n" "J%s\n",
title, /* title */
remotename, /* file processor */
title, /* name */
remotename,
jobname
);
printf("\nOptions:\n%s\n", cmdfile );
sprintf( buffer, "\2%d c%s\n", strlen( cmdfile ), remotename );
sock_puts( s , buffer );
sock_flush( s );
sock_wait_input( s, sock_delay, NULL, &status );
sock_fastread( s, buffer, sizeof( buffer ));
switch (*buffer) {
case 0: break;
case 1: puts("Bad connection");
goto close_it;
case 2: puts("Out of space on host");
goto close_it;
default:puts("Unknown error");
goto close_it;
}
sock_puts( s, cmdfile );
sock_putc( s, 0 );
sock_flush( s );
sock_wait_input( s, sock_delay, NULL, &status );
sock_fastread( s, buffer, sizeof( buffer ));
switch (*buffer) {
case 0: puts("Completed - job accepted");
completed = 1;
sock_putc( s, 0 );
sock_flush( s );
break;
default:puts("Control file rejected");
status = 3;
break;
}
/* all roads come here */
close_it:
sock_tick( s, &status); /* in case they sent reset */
sock_close( s );
sock_wait_closed( s, sock_delay, NULL, &status );
sock_err:
switch( status ) {
case 1: break;
case-1: printf("Remote host reset connection\n\r");
status = 3;
break;
}
if (!connected)
printf( "\n\rCould not get connected. Perhaps you were not in the /etc/hosts.lpd file!\n\r");
return( !completed );
}
int main( int argc, char **argv )
{
char remotename[128];
char *hostname;
char *filename;
char *printer;
char *userid, *server;
char *title, *jobname;
char *rhostname;
char *class;
int status, i;
for ( i = 0 ; i < MFCF_COUNT ; ++i ) {
sprintf( remotename, "MFCF%u", i );
mfcf[i] = getenv( remotename );
if ( *mfcf[i] == 0 ) mfcf[i] = NULL;
}
userid = server = "UNKNOWN";
if ((seqwhere = getenv( "SEQUENCE" )) == NULL )
seqwhere = SEQFILE;
if ( ( title = getenv( "TITLE" )) == NULL )
title = "stdprn";
if ( ( jobname = getenv( "JOBNAME" )) == NULL )
jobname = "job_name";
class = getenv("CLASS");
puts("LPR using Waterloo TCP");
switch (argc) {
case 3:
/* no printername */
rhostname = argv[1];
filename = argv[2];
printer = "lp";
break;
case 6:
/* whole thing */
userid = argv[4];
server = argv[5]; /* and continue on below */
case 4:
/* Hostname and printer */
printer = argv[1];
rhostname = argv[2];
filename = argv[3];
break;
default:
printf( "Usage: LPR [printer] host filename [userid server]");
exit(1);
}
hostname = gethostname( NULL, 0 );
if ( !hostname || !*hostname ) {
puts("You must define your hostname in the WATTCP.CFG file!");
exit( 3 );
}
strlwr( hostname );
strlwr( userid );
strlwr( server );
/* 94.11.19 -- removed extra parms */
status = lpr( hostname, printer, rhostname, filename, title, jobname,
class, userid, server /*, MFCF_COUNT, mfcf*/ );
return( status ? 3 : 0 );
}