From: miki@dune.tmr.co.jp (AKAMA miki)
Newsgroups: alt.test
Subject: rec program
Date: 14 Aug 92 02:42:08 GMT
Reply-To: miki@dune.tmr.co.jp (AKAMA miki)
Organization: Technical Marketing Reserch Inc., TOKYO JAPAN

/*
 * FILE NAME:  rec.c
 *
 * Based upon bsd/prosbsd.c from the AX-5, vers 2.02
 *
 * (C) Copyright 1992, Axis Communications AB, LUND, SWEDEN.
 *
 * This program is modified by Martin Gren, Tokyo Aug 14, 1992
 * in order to provde communication from the AX-5 to the host.
 *
 * The program wil open a connection, and immediately close it.
 * This gets the AX-5 to send back the status to the host.
 *
 * Since the program is looping all the time it is recommended
 * that parameter 27, READTIM2 is set to as high value as possible,
 * preferrably 255.
 *
 * What to do with the return data is up to the application. Simply
 * search for the FEEDBACK define, and do what action is desired!
 *
 * Note: this program does not terminate - it runs forever. To stop
 * it from the Unix prompt, do "ctrl+Z" and "kill %1".
 *
 * Version 1.00 Aug 14, 1992 MG
 */
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <fcntl.h>
#include <stdio.h>
#include <errno.h>
#include <ctype.h>
#include <string.h>
#include <sys/wait.h>
#include <signal.h>


#define PROS_PORT       35
#define MAX_LOOPS       200
#define MAX_OUTBUF      4096
#define MAX_STATBUF     4096

/* PROS protocol 2.0 */

/* server -> host error messages */

#define PROSERR_HDR    0  /* header error */
#define PROSERR_MEM    1  /* out of memory */
#define PROSERR_NOA    2  /* No access */
#define PROSERR_POC    3  /* Printer occupied */
#define PROSERR_BAN    4  /* Bad printer name */
#define PROSERR_OLD    5  /* Old protocol */
#define PROSERR_NOI    6  /* Printer not installed */
#define PROSERR_OFL    7  /* Printer off line */
#define PROSERR_EOP    8  /* Printer out of paper */
#define PROSERR_BSY    9  /* Printer busy */
#define PROSERR_PRO   10  /* Protocol error */
#define PROSERR_UND   11  /* Undefined error */

/* host -> server informational messages */

#define PROSMSG_EOF   32   /* End-of-file: no more print data */
#define PROSMSG_UID   33   /* user name */
#define PROSMSG_HST   34   /* host name */
#define PROSMSG_PRN   35   /* printer name */
#define PROSMSG_PAS   36   /* password */
#define PROSMSG_DTP   37   /* data to printer */

/* server -> host informational messages */

#define PROSMSG_JOK   48   /* Job ended ok */
#define PROSMSG_JST   49   /* Job started */
#define PROSMSG_ACC   50   /* accounting data */
#define PROSMSG_DFP   51   /* data from printer */

/* status byte bits */

#define PROSBIT_FATAL  0x40   /* fatal error bit */
#define PROSBIT_DATA   0x80   /* data record follows */

int sock;
char outdata[MAX_OUTBUF];
unsigned char statbuf[MAX_STATBUF];

int DEBUG = (0 == 1);
int MSG   = (0 == 1);


cancel()
{
  int status;
  wait(&status);
  close(sock);
  exit(status >> 8);
}

main(argc, argv)
int argc;
char *argv[];
{
  while(1 == 1)
    secondmain(argc, argv);
}


secondmain(argc, argv)
int argc;
char *argv[];
{
  int ok, loops;
  int stat_len;
  struct sockaddr_in server;
  struct hostent *hp, *gethostbyname();
  char *outdata_data;
  int daughter, status, mothid;
  int bytes, c, i;
  char *accounting_file, *hostname, *userid;
  unsigned char status_code;
  char eof_marker = PROSMSG_EOF;
  int feedback = 0;
  int outfile;

#ifdef FEEDBACK
  outfile = open( FEEDBACK, O_WRONLY | O_CREAT | O_APPEND, 0666);
  if (outfile < 0)
  {
    fprintf(stderr, "Error trying to open feedback file %s! errno is %d\n",
		    FEEDBACK, errno);
    exit(1);
  }
#endif

  accounting_file = NULL; /* default no accounting */
#ifdef HOSTNAME
  hostname = HOSTNAME;
#else
  hostname = "some host";
#endif
  userid = "PROS";
  for (i = 1; i < argc; i++)
  {
    if (argv[i][0] == '-')
      switch (toupper(argv[i][1]))
      {
        case 'M' :
          MSG = (1 == 1);
          break;
        case 'D' :
          DEBUG = (1 == 1);
          break;
        case 'N' :
          userid = argv[++i];
          break;
        case 'H' :
          hostname = argv[++i];
          break;
      }
    else
      accounting_file = argv[i];
  }
  if (MSG)
    fprintf(stderr, "\nTrying to start new job on %s:%s initiated by %s@%s\n",
          BOXNAME, PRINTERNAME, userid, hostname);
  server.sin_family = AF_INET;
  hp = gethostbyname(BOXNAME);
  if (hp == 0)
  {
    fprintf(stderr, "%s: unknown host\n", BOXNAME);
    exit(2);
  }
  memcpy((char *) &server.sin_addr, (char *) hp->h_addr, hp->h_length);
  server.sin_port = htons(PROS_PORT);
  ok = 0;
  loops = 0;
  do
  {
    sock = socket(AF_INET, SOCK_STREAM, 0);
    if (sock < 0)
    {
      fprintf(stderr, "Error creating socket\n");
      exit(1);
    }
    if (connect(sock, (struct sockaddr *) & server, sizeof server) < 0)
    {
      loops++;
      if (errno != ECONNREFUSED)
      {
	fprintf(stderr, "The AX-5 seems to be off line; Unix errno is %d\n", 
                errno);
	exit(2);
      }
      else
      {
	close(sock);
	sleep(10);
	fprintf(stderr, "AX-5 busy; retrying...\n");
      }
    }
    else
      ok++;
  } while (!ok && loops < MAX_LOOPS);
  if (!ok)
  {
    fprintf(stderr, "Connection refused; AX-5 might be hung\n");
    exit(1);
  }
  mothid = getpid();
  daughter = fork();
  if (daughter != 0)
  {
    (void) signal(SIGINT, cancel);
    send_hdr(sock, PROSMSG_HST, hostname);
    send_hdr(sock, PROSMSG_UID, userid);
    send_hdr(sock, PROSMSG_PRN, PRINTERNAME);
    send_hdr(sock, PROSMSG_PAS, "netprinter");

    /*
     * Do not print anything - simply open and close the conection !
     */
      
    if (write(sock, &eof_marker, 1) < 0)
    {
      fprintf(stderr, "Error writing eof to socket\n");
      exit(1);
    }
    if (MSG)
      fprintf(stderr, "Sent EOF to AX-5\n");
    wait(&status);
    close(sock);
    return(status >> 8);
  }
  else
  {
    while (1)
    {
      get_stat(&status_code, 1);
      if (status_code & PROSBIT_DATA)
      {
        get_stat(statbuf, 2);
        stat_len = (statbuf[0] << 8) + statbuf[1];
        get_stat(statbuf, stat_len);
        statbuf[stat_len] = 0;
      }
      else
      {
        strcpy(statbuf, "<no message>");
        stat_len = 0;
      }

      if ( status_code == (PROSMSG_DFP | PROSBIT_DATA) )
      {
        if( feedback == 0 )
        {
          if (MSG)
             fprintf(stderr, "Received printer feedback!\n");
          feedback = 1;
        }

#ifdef FEEDBACK
        write(outfile, (void *)statbuf, strlen(statbuf) );
#else
        fprintf(stderr, "%s", statbuf);
#endif
      }
      else
      {
        if ( feedback != 0 )
          feedback = 0;

        if (MSG)
          fprintf(stderr, "AX-5: (%d, l=%d) %s%s\n",
                status_code, stat_len, statbuf,
                (status_code & PROSBIT_FATAL) ? " (FATAL)" : "");
      }

      if ((status_code & 0x3f) == PROSMSG_JOK)
	exit(0);
      if (status_code & PROSBIT_FATAL)
      {
	kill(mothid, SIGINT);
	exit(2);
      }
    }
  }
}

send_hdr(sock, msg_code, msg_data)
int sock;
int msg_code;
char *msg_data;
{
  int str_len;

  str_len = strlen(msg_data);
  outdata[0] = msg_code | PROSBIT_DATA;
  outdata[1] = str_len >> 8;
  outdata[2] = str_len & 255;
  strcpy(&outdata[3], msg_data);

  if (write(sock, outdata, str_len + 3) < 0)
  {
    fprintf(stderr, "Error writing header to socket\n");
    exit(1);
  }
}

get_stat(buffer, len)
char *buffer;
int len;
{
  int rval;

  if (DEBUG) printf("Calling get_stat len = %d...\n", len);
  do
  {
    if ((rval = read(sock, buffer, len)) < 0)
    {
      fprintf(stderr, "Error reading from AX-5\n");
      exit(2);
    }
    else if (rval == 0)
    {
      fprintf(stderr, "Unexpected close by AX-5\n");
      exit(2);
    }
    len -= rval;
    buffer += rval;
  } while (len > 0);
}
Newsgroups: alt.test