home *** CD-ROM | disk | FTP | other *** search
/ Super Net 1 / SUPERNET_1.iso / PC / OTROS / MSDOS / WATTCP / NEWWATCP.ZIP / APPS / LPR.C < prev    next >
Encoding:
C/C++ Source or Header  |  1993-11-19  |  11.7 KB  |  419 lines

  1. /*
  2.  * LPR - dump job to printer
  3.  *
  4.  *
  5.  *   Copyright (C) 1991, University of Waterloo
  6.  *
  7.  *   Portions Copyright (C) 1990, National Center for Supercomputer Applications
  8.  *   and portions copyright (c) 1990, Clarkson University
  9.  *
  10.  *   This program is free software; you can redistribute it and/or modify
  11.  *   it, but you may not sell it.
  12.  *
  13.  *   This program is distributed in the hope that it will be useful,
  14.  *   but without any warranty; without even the implied warranty of
  15.  *   merchantability or fitness for a particular purpose.
  16.  *
  17.  *       Erick Engelke                   or via E-Mail
  18.  *       Faculty of Engineering
  19.  *       University of Waterloo          Erick@development.watstar.uwaterloo.ca
  20.  *       200 University Ave.,
  21.  *       Waterloo, Ont., Canada
  22.  *       N2L 3G1
  23.  *
  24.  *
  25.  * The following notes on control and data files were obtained from Clarkson's
  26.  * CUTE project.
  27.  *
  28.  *
  29.  * Control File: format is the first character in the line is a command,
  30.  * the rest of the line is the argument.  Also note lowercase letters
  31.  * denote the data file names (of various types).
  32.  *
  33.  * currently valid commands are:
  34.  *
  35.  *     J -- "job name" on banner page
  36.  *     C -- "class name" on banner page
  37.  *     L -- "literal" user's name to print on banner
  38.  *     T -- "title" for pr
  39.  *     H -- "host name" of machine where lpr was done
  40.  *     P -- "person" user's login name
  41.  *     I -- "indent" amount to indent output
  42.  *     f -- "file name" name of text file to print
  43.  *     l -- "file name" text file with control chars
  44.  *     p -- "file name" text file to print with pr(1)
  45.  *     t -- "file name" troff(1) file to print
  46.  *     n -- "file name" ditroff(1) file to print
  47.  *     d -- "file name" dvi file to print
  48.  *     g -- "file name" plot(1G) file to print
  49.  *     v -- "file name" plain raster file to print (impress)
  50.  *     c -- "file name" cifplot file to print
  51.  *     1 -- "R font file" for troff
  52.  *     2 -- "I font file" for troff
  53.  *     3 -- "B font file" for troff
  54.  *     4 -- "S font file" for troff
  55.  *     N -- "name" of file (used by lpq)
  56.  *     U -- "unlink" name of file to remove
  57.  *           (after we print it. (Pass 2 only)).
  58.  *     M -- "mail" to user when done printing
  59.  *
  60.  * Currently it looks like only a lowercase filename and U command are
  61.  * necessary.  However one should also include J, L, H, and P.
  62.  *
  63.  * In general the lpd program doesn't care what the data file looks like.
  64.  * It should however be of the type specified in the control file
  65.  * otherwise it will probably print incorrectly.
  66.  *
  67.  * The format is ?fA<number><hostname>.  ? is either c for control or d
  68.  * for data files.  Number is a 3 digit number (0 padded) used for job
  69.  * number information.  Hostname is the name of the originating host and
  70.  * had best be equal to whatever shows up in the from field when a
  71.  * connection is opened (ie probably should be the "real" hostname).
  72.  * Currently all of these must be used as the program has them compiled in
  73.  * (by stupid use of pointers).  I may change this in time but currently
  74.  * it is the law if you want everything to work (some things will work
  75.  * just fine without it, queueing a file just wants names, showing the
  76.  * queue expects a number to start in the fourth position, deleting a file
  77.  * expects the hostname to start in the 7th position and go to the end of
  78.  * the filename.
  79.  *
  80.  * default userid = server = "UNKNOWN";
  81.  *
  82.  * get's sequence file from getenv( "SEQUENCE" )
  83.  * else "SEQUENCE.LPR"
  84.  *
  85.  * if ( ( title = getenv( "TITLE" )) ==  NULL )
  86.  *      title = "stdprn";
  87.  * if ( ( jobname = getenv( "JOBNAME" )) == NULL )
  88.  *       jobname = "job_name";
  89.  * if ( (  class = getenv("CLASS")) == NULL )
  90.  *       class = server
  91.  */
  92.  
  93.  
  94. #include <stdio.h>
  95. #include <io.h>
  96. #include <tcp.h>
  97.  
  98. #define SHORT_LIST 3
  99. #define LONG_LIST  4
  100. #define MFCF_COUNT 5
  101. char *mfcf[MFCF_COUNT];
  102.  
  103.  
  104. #define LPQ_PORT 515
  105. #define LOCAL_PORT 722
  106.  
  107. #define SEQFILE "SEQUENCE.LPR"
  108. char *seqwhere;
  109.  
  110. word getsequence()
  111. {
  112.     static word oldseq = 0;
  113.     FILE *f;
  114.  
  115.     if ( ! oldseq ) {
  116.         /* must look to disk for an old sequence number */
  117.         if ( f = fopen( seqwhere, "rt" )) {
  118.             fscanf( f, "%u", &oldseq );
  119.             fclose( f );
  120.         }
  121.     }
  122.  
  123.     oldseq = ( oldseq + 1 ) % 1000;
  124.  
  125.     if ( f = fopen( seqwhere, "wt" )) {
  126.         fprintf( f, "%u", oldseq );
  127.         fclose( f );
  128.     }
  129.     return( oldseq );
  130. }
  131.  
  132. lpr( localhostname, printer, rhostname, filename, title, jobname,
  133.     class, username, servername )
  134. char *localhostname;
  135. char *printer;
  136. char *rhostname;
  137. char *filename;
  138. char *title;
  139. char *jobname;
  140. char *class;
  141. char *username;
  142. char *servername;
  143. {
  144.     static tcp_Socket socketdata;
  145.     tcp_Socket *s;
  146.     longword filesize;
  147.     longword host;
  148.     int status = 0;
  149.     int connected = 0;
  150.     int completed = 0;
  151.     int localport;
  152.     word seqnum, i;
  153.  
  154.     static char buffer[ 1024 ];
  155.     char *b2;
  156.     char remotename[ 80 ];
  157.     static char cmdfile[ 1024 ];
  158.     longword remaining;
  159.     word found;
  160.     FILE *f;
  161.  
  162.     if (( *class == 0 ) || (*class == ' ')) class = NULL;
  163.  
  164.     for ( i = 0; i < MFCF_COUNT ; ++i ) {
  165.         if ( mfcf[ i ] )
  166.             printf("Extra option: %s\n", mfcf[i] );
  167.     }
  168.  
  169.     if (!(f = fopen( filename, "rb"))) {
  170.     printf("Unable to open file '%s'\n", filename );
  171.     return( 3 );
  172.     }
  173.  
  174.     sock_init();
  175.     s = &socketdata;
  176.     if (!(host = resolve( rhostname ))) {
  177.         printf( "lpq: unknown host %s\n",rhostname);
  178.         return(1);
  179.     }
  180.  
  181.     localport = 255 + (MsecClock() & 255);
  182.     if ( !tcp_open( s, localport, host, LPQ_PORT, NULL)) {
  183.       printf("Unable to open socket.");
  184.       tcp_shutdown();
  185.       return(1);
  186.    }
  187.  
  188.    printf( "connecting...\r");
  189.    sock_wait_established( s, sock_delay, NULL, &status );
  190.    connected = 1;
  191.    printf("connection established\n");
  192.  
  193.    /* is there an opening message - non-standard but possible */
  194.  
  195.    if (sock_dataready( s )) {
  196.        sock_fastread( s, buffer, sizeof( buffer ));
  197.        sock_tick( s, &status );    /* in case above message closed port */
  198.    }
  199.  
  200.    /* use ipnumber/time  */
  201.    seqnum = getsequence();
  202.    sprintf(remotename,"fA%03u%s", seqnum, localhostname );
  203.    
  204.    /* we are connected */
  205.    sprintf( buffer, "\2%s\n", printer );    /* select a printer */
  206.    sock_puts( s, buffer );
  207.  
  208.    /* state #2 */
  209.  
  210.    sock_wait_input( s, sock_delay, NULL, &status );
  211.  
  212.    sock_fastread( s, buffer, sizeof( buffer ));
  213.  
  214.    switch (*buffer) {
  215.        case 0 : break;
  216.        case 1 : printf("Printer '%s' is not available\n", printer);
  217.         goto close_it;
  218.        default: rip( buffer );
  219.                 printf("ERROR: %s\n", buffer);
  220.         goto close_it;
  221.    }
  222.  
  223.    /* printer is accepted, printing file */
  224.    filesize = filelength( fileno( f ));
  225.  
  226.  
  227.    sprintf( buffer, "\3%ld d%s\n", filesize, remotename );
  228.    sock_puts( s , buffer );
  229.    sock_wait_input( s, sock_delay, NULL, &status );
  230.  
  231.    /* state 3, reply from filename */
  232.    sock_fastread( s, buffer, sizeof( buffer ));
  233.  
  234.    switch (*buffer) {
  235.     case 0: break;
  236.         case 1: printf("remote host complains of bad connection");
  237.         goto close_it;
  238.     case 2: puts("remote host out of storage space");
  239.         goto close_it;
  240.     }
  241.  
  242.     /* dump file */
  243.  
  244.     remaining = filesize;
  245.     do {
  246.         cprintf("Transferred: %lu %c  \r",
  247.             ((filesize - remaining + 1L)*100L)/(filesize+1), 37 );
  248.         backgroundon();
  249.         if ( (found = fread( buffer, 1, sizeof(buffer), f)) == 0 )
  250.         break;
  251.         backgroundoff();
  252.  
  253.         sock_write( s, buffer, found );
  254.     sock_tick( s , &status );
  255.     if (sock_dataready( s )) {
  256.         puts("LPR: interrupted on transfer...");
  257.         goto close_it;
  258.     }
  259.     } while ( (remaining -= (longword)found) > 0 );
  260.  
  261.     sock_putc( s, 0 );
  262.  
  263.     /* check on status of this file */
  264.  
  265.     sock_wait_input( s, sock_delay, NULL, &status );
  266.     sock_fastread( s, buffer, sizeof(buffer));
  267.  
  268.     switch (*buffer) {
  269.     case 0: break;
  270.     default:puts("file was rejected");
  271.         goto close_it;        /* could retry */
  272.     }
  273.  
  274.     sprintf( cmdfile,   "H%s\n"  "P%s\n" "C%s\n" "L%s\n",
  275.         servername,     /* eg "development" */
  276.     username,    /* eg "erick", */
  277.         class ? class : servername, /* eg "NDSW or development", */
  278.  
  279.         username );     /* eg  "erick"       for on banner */
  280.  
  281.     for ( i = 0 ; i < MFCF_COUNT ; ++i ) {
  282.         if ( mfcf[i] ) {
  283.             strcat( cmdfile, mfcf[i] );
  284.             strcat( cmdfile, "\n" );
  285.         }
  286.     }
  287.     b2 = strchr( cmdfile, 0 );
  288.     sprintf( b2, "T%s\n" "fd%s\n" "N%s\n" "Ud%s\n" "J%s\n",
  289.         title,          /* title */
  290.     remotename,    /* file processor */
  291.         title,          /* name */
  292.     remotename,
  293.         jobname
  294.     );
  295.     printf("Options:\n%s\n", cmdfile );
  296.  
  297.     sprintf( buffer, "\2%d c%s\n", strlen( cmdfile ), remotename );
  298.  
  299.     sock_puts( s , buffer );
  300.     sock_flush( s );
  301.  
  302.     sock_wait_input( s, sock_delay, NULL, &status );
  303.     sock_fastread( s, buffer, sizeof( buffer ));
  304.  
  305.     switch (*buffer) {
  306.     case 0: break;
  307.         case 1: puts("Bad connection");
  308.         goto close_it;
  309.         case 2: puts("Out of space on host");
  310.                 goto close_it;
  311.         default:puts("Unknown error");
  312.                 goto close_it;
  313.     }
  314.  
  315.     sock_puts( s, cmdfile );
  316.     sock_putc( s, 0 );
  317.     sock_flush( s );
  318.  
  319.     sock_wait_input( s, sock_delay, NULL, &status );
  320.     sock_fastread( s, buffer, sizeof( buffer ));
  321.  
  322.     switch (*buffer) {
  323.         case 0: puts("Completed - job accepted");
  324.                 completed = 1;
  325.         sock_putc( s, 0 );
  326.         sock_flush( s );
  327.         break;
  328.         default:puts("Control file rejected");
  329.                 status = 3;
  330.                 break;
  331.     }
  332.  
  333.     /* all roads come here */
  334. close_it:
  335.     sock_tick( s, &status);    /* in case they sent reset */
  336.     sock_close( s );
  337.     sock_wait_closed( s, sock_delay, NULL, &status );
  338.  
  339. sock_err:
  340.     switch( status ) {
  341.     case 1: break;
  342.         case-1: printf("Remote host reset connection\n\r");
  343.         status = 3;
  344.         break;
  345.     }
  346.     if (!connected)
  347.        printf( "\n\rCould not get connected.  Perhaps you were not in the /etc/hosts.lpd file!\n\r");
  348.  
  349.     return( !completed );
  350. }
  351.  
  352.  
  353. main(argc, argv)
  354. int argc;
  355. char **argv;
  356. {
  357.     char remotename[128];
  358.     char *hostname;
  359.     char *filename;
  360.     char *printer;
  361.     char *userid, *server;
  362.     char *title, *jobname;
  363.     char *rhostname;
  364.     char *class;
  365.     int status, i;
  366.  
  367.     for ( i = 0 ; i < MFCF_COUNT ; ++i ) {
  368.         sprintf( remotename, "MFCF%u", i );
  369.         mfcf[i] = getenv( remotename );
  370.         if ( *mfcf[i] == 0 ) mfcf[i] = NULL;
  371.     }
  372.  
  373.  
  374.     userid = server = "UNKNOWN";
  375.     if ((seqwhere = getenv( "SEQUENCE" )) == NULL )
  376.         seqwhere = SEQFILE;
  377.     if ( ( title = getenv( "TITLE" )) ==  NULL )
  378.         title = "stdprn";
  379.     if ( ( jobname = getenv( "JOBNAME" )) == NULL )
  380.         jobname = "job_name";
  381.     class = getenv("CLASS");
  382.  
  383.     puts("LPR using Waterloo TCP");
  384.     switch (argc) {
  385.     case 3:
  386.         /* no printername */
  387.         rhostname = argv[1];
  388.         filename = argv[2];
  389.         printer = "lp";
  390.         break;
  391.     case 6:
  392.         /* whole thing */
  393.         userid = argv[4];
  394.         server = argv[5];        /* and continue on below */
  395.     case 4:
  396.         /* Hostname and printer */
  397.         printer = argv[1];
  398.         rhostname = argv[2];
  399.         filename = argv[3];
  400.         break;
  401.     default:
  402.               printf( "Usage: LPR [printer] host filename [userid server]");
  403.           exit(1);
  404.    }
  405.     hostname = gethostname( NULL, 0 );
  406.     if ( !hostname || !*hostname ) {
  407.         puts("You must define your hostname in the WATTCP.CFG file!");
  408.         exit( 3 );
  409.     }
  410.  
  411.     strlwr( hostname );
  412.     strlwr( userid );
  413.     strlwr( server );
  414.     status = lpr( hostname, printer, rhostname, filename, title, jobname,
  415.         class, userid, server, MFCF_COUNT, mfcf );
  416.  
  417.     return( status ? 3 : 0 );
  418. }
  419.