/*
 * 5799-WZQ (C) COPYRIGHT IBM CORPORATION 1988
 * LICENSED MATERIALS - PROPERTY OF IBM
 * REFER TO COPYRIGHT INSTRUCTIONS FORM NUMBER G120-2083
 */
/* $Header:bits4216.c 12.3$ */
/* $ACIS:bits4216.c 12.3$ */
/* $Source: /ibm/acis/usr/src/ibm/lpfilter/pp4216/RCS/bits4216.c,v $ */

#ifndef lint
static char *rcsid = "$Header:bits4216.c 12.3$";
#endif




#include <sys/wait.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <stdio.h>
#include <sys/psioctl.h>
#include <signal.h>
#include "fcntl.h"

struct noname
        {
        char            dfimag00[8];
        unsigned short  n_rows;
        unsigned short  n_cols;
        char            image_type;
        long            framelen;
        char            spare[12];
        } header, *headptr;


static char bbcmd[] = "\
\
/sh 11 72 mul def /sw 8.5 72 mul def \
 /width 480 8 div cvi def \
 /height 640 def \
 \
 /vscale height sh div def\
 /hscale width 8 mul sw div def \
 /out (%stdout) (w) file def \
 \
 /mtx [  \
        hscale      0 \
        0           vscale  neg \
        0           height ] def \
\
 /bitsback { \
   16#8012 statusdict begin sendmarkerpacket end \
   0 0 width height (%stdout) (w) file statusdict begin readframe end \
   flush \
 } def \
\
mtx width height /bitsback load framedevice \
currentscreen /p exch def \
pop pop 27 45 /p load setscreen\
\
\
/terminate {\
   16#8002 statusdict begin sendmarkerpacket end flush \
} def ";

static int   DEBUG = 0; 
static char  psbuf[1024];
static char *psdevname = "/dev/ps0";
static int   pid;

main(int argc, char **argv)
    

{ int f, outfile, psfile, stat, psbuflen, index, error, amount, written;
  char buf[1028];
  unsigned short packetlen, packettype, swapbytes();

   index = 1;
   if ((argc > 1) && (argv[index][0] == '-')) {
       if (argv[index][1] == 'f') {
           psdevname = &argv[index][2];
           index++;
       }
       else {
           fprintf(stderr, "usage: bits4216 [-fpsdevname] psfile [bitfile]\n");
           exit(1);
       }
    }

   if (index+2 == argc) {
       outfile = open(argv[argc-1], O_CREAT | O_TRUNC | O_WRONLY, 0666);
       if (outfile < 0)  {
           fprintf(stderr, "could not open %s\n",argv[argc-1]);
           exit(1);
       }
   }
   else if (index+1 == argc) {
       outfile = 1;
   }
   else {
       fprintf(stderr, "usage: bits4216 [-fpsdevname] psfile [bitfile]\n");
       exit(1);
   }

   header.n_rows = swapbytes((unsigned short)640);
   header.n_cols = swapbytes((unsigned short)480);
   header.framelen = 640*480/8;

   amount = 0;
   while ((written = write(outfile, &header+amount, sizeof header - amount)) <
                                               sizeof header - amount) {
       if ( written < 0 ) {
           perror("bits4216");
           exit(1);
       }
       else {
           amount += written;
       }
    }

   f = open(psdevname, O_RDWR, 0);
   if (f < 0) {
        fprintf(stderr, "could not open %s\n",psdevname);
        exit(1);
   }
   if (DEBUG) printf("after the open f = %d\n", f);

   error = ioctl(f, PSREADPACKET, 0);
   if (error < 0) {
       fprintf(stderr, "%s ioctl failed: PSREADPACKET\n", psdevname);
       exit(1);
   }

   /* flush the link, unfortunately a program running on the printer */
   /* may put stuff onto it afterwords                               */

   error = write(f, " flush\n ", strlen(" flush\n "));
   if (error < 0) {
       perror("bits4216");
       exit(1);
   }
   sleep(2); 
   while (read(f, buf, 1028) > 0) {
       packettype = swapbytes(((unsigned short *)buf)[1]);
       if (packettype == 0x8000) {
           write(2, buf+4, (int) packetlen);
       }
   }

   if (DEBUG) printf("write bb\n");
   amount = 0;
   while ((written = write(f, bbcmd+amount, strlen(bbcmd) - amount)) < 
						strlen(bbcmd) - amount ) {
       if (DEBUG) fprintf(stderr,"written %d bytes of %d\n",written,amount);
       if ( written < 0 ) {
           perror("bits4216");
           exit(1);
       }
       else {
           amount += written;
       }
   }

   if (!strcmp(argv[index], "-")) {
       psfile = 0;
   }
   else {
       psfile = open(argv[index], O_RDONLY, 0);
       if (psfile < 0)  {
           fprintf(stderr, "ps file %s not opened\n", argv[index]);
           exit(1);
       }
   }
  
   if ( ! (pid = fork()) ) {

       /* child process to write the file to /dev/ps */

       psbuflen = read(psfile, psbuf, 1024);
       if (psbuflen < 0) {
           perror("bits4216");
           kill(getppid(), SIGKILL);
           exit(1);
       }
       while (psbuflen > 0) {
           if (DEBUG) fprintf(stderr,"write %s\n", argv[index]);
           amount = 0;
           while ((written = write(f, psbuf + amount, (int) psbuflen - amount))
						< (int) psbuflen - amount ) {
           if (DEBUG) fprintf(stderr,"written %d bytes of %d\n",written,amount);
               if ( written < 0 ) {
                   perror("bits4216");
                   kill(getppid(), SIGKILL);
                   exit(1);
               }
               else {
	           amount += written;
               }
           }
           psbuflen = read(psfile, psbuf, 1024);
           if (psbuflen < 0) {
               perror("bits4216");
               kill(getppid(), SIGKILL);
               exit(1);
           }
      }
      
      error = write(f, " terminate ", 11);
      if (error < 0) {
           perror("bits4216");
           kill(getppid(), SIGKILL);
           exit(1);
      }
      close(psfile);
      exit(0);   
   }

   if (pid < 0) {
       perror("bits4216");
       exit(1);
   }

   stat = 0;
   while (!stat) {
       stat = getpage(f, outfile, buf);
       if (DEBUG) printf("after, stat = %d\n", stat);
   }
   close(outfile);
   if (DEBUG) printf("survived the close\n", close(f)); 

}






int getpage(psdev, outfile, buf)
    int psdev, outfile;
    char *buf;

{ unsigned short packetlen, packettype;
           int   error, written, amount;
  

   packetlen   = 0;
   packettype  = 0;
   while (packetlen != 1024) {
       if (DEBUG) printf("waiting.\n");
       error = read(psdev, buf, 1028);
       if (error < 0) {
           perror("bits4216");
           kill(pid, SIGKILL);
           exit(1);
       }
       packetlen = swapbytes(*((unsigned short *)buf));
       packettype = swapbytes(((unsigned short *)buf)[1]);
       if (packettype == 0x8002) return 1;
       if (DEBUG) printf("read : len = %d type = %04x string: %s\n", packetlen,
                                                          packettype, buf+4);
       sleep(2);
   }
   while (packettype == 0x8000) {
       amount = 0;
       while ((written = write(outfile, buf+4+amount, (int) packetlen - amount))
                                                  < (int) packetlen - amount) {
       if (DEBUG) fprintf(stderr,"written %d bytes of %d\n",written,amount);
           if ( written < 0 ) {
               perror("bits4216");
               kill(pid, SIGKILL);
               exit(1);
           }
           else {
               amount += written;
           }
       }
       bzero(buf, 1028);
       error = read(psdev, buf, 1028);
       if (error < 0) {
           perror("bits4216");
           kill(pid, SIGKILL);
           exit(1);
       }
       packetlen = swapbytes(*(unsigned short *)buf);
       packettype = swapbytes(((unsigned short *)buf)[1]);
       if (DEBUG) printf("read : len = %d type = %04x string: %s\n", packetlen,
                                                          packettype, buf+4);
   }
   if (packettype == 0x8002) return 1;
   return 0;
}



unsigned short swapbytes(i)
      unsigned short i;

{
    char t;
    char *ip;

    ip = (char *)(&i);
    t = *ip;
    *ip = ip[1];
    ip[1] = t;
    return i;
}
