[comp.laser-printers] Accounting for Imagen 3320

dougf.UUCP@dartvax.UUCP (Doug Fraser) (07/27/87)

$!
$! -----------------------------  Cut here ----------------------------
$!
$ write sys$output "Creating: IMAGEN_ACCT.C"
$ create IMAGEN_ACCT.C
$ deck /dollars
/*
 *  IMAGEN_ACCT.C
 *
 *  Reads accounting packets sent by the Imagen 3320 laser printer via
 *  TCP/IP and writes relevant information into a DCL compatible 
 *  ASCII (one line per print job) accounting file.
 *
 *  System requirements: VMS 4.5 and WIN/TCP 3.0
 *
 *  For use on VAX/VMS with the Wallongong TCP/IP package V. 3.0.
 *  For this to work correctly, the string "User" in the default
 *  IMPRINT.FMT supplied with the Kellerman & Smith VMS/Imagen spooler
 *  package will have to be changed to "Owner".  This will allow this 
 *  accounting to also work with files spooled from UNIX machines using 
 *  the Imagen spooling software.  This clearly a kludge.  It would be
 *  preferable if K&S would get together with Imagen and agree on a
 *  header prefix format containing username, filename, etc.
 *
 *  24-Jul-1987
 *
 *                             Doug Fraser   
 *  Thayer School of Engineering, Dartmouth College, Hanover, NH. 03755
 *                      dougf%thayer@dartmouth.EDU
 */

#include dvidef
#include <sys/types.h>
#include <sys/netdb.h>
#include <iodef.h>
#include <stdio.h>
#include <sys/socket.h>
#include <time>

#define PORT_IMAGEN_ACCT        36
#define INADDR_ANY              (u_long)0x00000000
#define DATA_FILE_NAME          "DUA0:[SYS0.SYSMGR.BILLING]imagen_acct.dat"

int chan;

main (argc, argv)
int argc;
char *argv[];
{                        
    int status, i, len, time_val;

    char *ptr, *tmp_ptr, printer[32], source[32], user[32];

    FILE *data_file;

    struct tm *time_structure;
    struct hostent *host_ptr;     /* hostname lookup */

    struct acct_header {          /* Imagen accounting header */
        unsigned long noonce;     /* Job ID */
        unsigned long source;     /* Source */
        unsigned long npages;     /* Number of pages */
        unsigned char data[256];  /* ASCII Header contents */
    }  acct_data, *pkt_ptr;

    struct sockaddr_in {
        short          sin_family;
        unsigned short sin_port;
        unsigned long  sin_addr;
        char           sin_zero[8];
    } sin, remote;

    static char *month[12] = 
      {"JAN","FEB","MAR","APR","MAY","JUN","JUL","AUG","SEP","OCT","NOV","DEC"};

/* Start here */

    sin.sin_port = htons(PORT_IMAGEN_ACCT);
    sin.sin_addr = INADDR_ANY;
    sin.sin_family = AF_INET;

/* Connect to the network */

    chan = socket(AF_INET, SOCK_DGRAM, 0);
    if (chan == -1){
        printf ("Imagen_acct: Socket connect failed");
        exit(1);
    }
        
    status = bind(chan, &sin, sizeof(sin));
    if (status == -1)
        errormsg("Imagen_acct: Bind failed");

/*
 *   Do the following forever.
 */
    while(1) {
                                           
        len = sizeof(remote);

        pkt_ptr = (struct acct_hdr *)&acct_data;

/* Get packet */

        status = recvfrom(chan, pkt_ptr, sizeof(*pkt_ptr),0, 
            (struct sock_addr *)&remote, &len);
        if (status == -1)                 
            errormsg ("Imagen_acct: Receive failed");

/* Get time */

        time (&time_val);
        time_structure = localtime(&time_val);

/* Get printer name */

        if ((host_ptr = gethostbyaddr(&remote.sin_addr,  
                        sizeof(remote.sin_addr), AF_INET)) == NULL)
            strcpy(printer, "<unknown>");
        else
            strcpy(printer, host_ptr->h_name);

/* Get host name */

        if ((host_ptr = gethostbyaddr(&acct_data.source,  
                        sizeof(acct_data.source), AF_INET)) == NULL)
            strcpy(source, "<unknown>");
        else
            strcpy(source, host_ptr->h_name);

/* Get user name */

        ptr = &acct_data.data[0];
        i = sizeof (acct_data.data);                                  

/*   Look for the string "Owner" in the ASCII header sent from the Imagen.  
 *   Note that this will probably have to changed from "User" in the file 
 *   "sys$manager:IMPRINT.FMT"
 */
        while ((--i >= 0) && (strncmp (ptr, "Owner", 5) != NULL))
            ptr++;

        while ((--i >= 0) && (*ptr != '"'))
            ptr++;

        ptr++;
        tmp_ptr = (char *)ptr;

        while (( --i >= 0) && (*ptr != ' '))
            ptr++;          

        *ptr = 0x00;
        if (i < 0)
            strcpy(user, "<unknown>");
        else
            strcpy (user, tmp_ptr);    

/* Write it all into the accounting file */

        if ((data_file = fopen(DATA_FILE_NAME, "a")) == NULL)
            errormsg ("Imagen_acct: File open failed");
                
        fprintf (data_file,
            "%02d-%s-19%02d %02d:%02d:%02d   %-15.14s%-13.12s%-13.12s %4d\n",
            time_structure->tm_mday,
            month[time_structure->tm_mon],
            time_structure->tm_year,
            time_structure->tm_hour,
            time_structure->tm_min,
            time_structure->tm_sec,     /* Time in DCL format */
            printer,                    /* Printer name */
            source,                     /* Source of print job */
            user,                       /* User name */
            ntohl(acct_data.npages)-1); /* Subtract 1 for the header page.   */
                                        /*    Another bogus maneuver since   */
                                        /*    there could be several or none.*/
 
/*   The following writes the entire ASCII header into the data file
 *   for diagnostic purposes.
 *
 *      ptr = &acct_data.data[0];
 *
 *      fwrite (ptr, status-24, 1, data_file);                               
 *      fputs ("\n --------------- \n", data_file);
 */

        fclose(data_file);
    }
                             
    netclose(chan);
    exit (0);
}

errormsg(msg)
char *msg;
{
    printf("%s\n", msg);
    netclose (chan);
    exit (1);
}
$ EOD
$!
$ write sys$output "Creating: BUILD.COM"
$ create BUILD.COM
$ deck/dollars
$!
$!  BUILD.COM
$!
$ set verify
$!
$ define /job lnk$library sys$library:vaxcrtl.olb
$!
$!   Define the locations of the Wallongong TCP include files below
$!
$ define /job sys dua0:[netdist.include.sys]
$ define /job netinet dua0:[netdist.include.netinet]
$!
$ cc /list imagen_acct
$!
$ link imagen_acct,dua0:[netdist.lib]libnet/lib,libnetacc/lib,libnet/lib
$!
$ copy imagen_acct.exe sys$manager:*
$!
$! The following should go in your sys$manager:systartup.com
$!   after TCP/IP and IMPRINT have been started
$!
$! run/det/proc=imagen_acct/uic=[1,4]/prio=6 sys$manager:imagen_acct
$!
$ set noverify
$ EOD
$ write sys$output "Done..."
$ write sys$output "Modify the system dependent sections of both files,"
$ write sys$output "and execute BUILD.COM."
$ exit
$!-----------------------------------------------------------------------