/* PRTSPOOL.c - print SPOOLed file program */ /* ** Date written: 04/23/86 ** Author: Tim Holloway ** Compuserve: 73026,2026 ** Bix: tholloway ** Fido node: 112/1 (Casa Mi Amiga). ** ** Version: 1.1 - a true spooler version ** ** Copyright (C) 1986, by Tim Holloway. This program may be ** freely distributed for non-commercial use only. Use for commercial ** purposes without the express permission of the author is a violation ** of copyright law. ** ** Description: ** This program accepts a printer name (file name) as a parameter. ** It opens the file and requests the names of files to be printed ** by sending messages to the SPOOLER program, which fills in a ** file name and returns the message to PRTSPOOL ** ** Change History: ** ** 11/19/86, TFH. added logic to actually drive a printer. ** removed the tracing code, and changed the error message ** reporting to use my Gripe procedure so display a requester ** if the SPOOLED file could not be accessed. ** ** Usage: See below. ** ** Special notes: sorry, I mixed AmigaDOS file I/O and Unix-style ** I/O. In accordance with my policy of never programming unportable ** unless neccessary, I had intended to use all Unix-style I/O, but ** the Lattice version 3.03 and earlier systems buffer files that ** according to Unix should not be buffered. I could have used ** the set-non-buffered function, but two wrongs don't make a right! */ /* Basic Amiga system definitions */ #include #include #include #include #include #include struct Library *IntuitionBase, *OpenLibrary(); /* more mundane definitions */ #include "stdio.h" #include "spool.h" /* define login and logout stuff in the following #include: */ #include "login.cx" struct Process *myprocess, *FindTask(); struct FileHandle *outfile, *Open(); BOOL io_error = FALSE, aborting = FALSE; usage() { printf ("PRTSPOOL program v1.1 by Tim Holloway\n"); printf ("Usage: PRTSPOOL filename\n"); } SPOOLmsg packet = {{NULL, NULL, 0}, '?', ""}; error (msg) char *msg; { Gripe ("PRTSPOOL:", msg, ""); } /***************************************************************************/ static int linenum = 0; static char linebuffer[256]; FILE * infile; #define LINES_PER_PAGE 56 static int hour, minute, year, day, month; void getdate() { long dates[3]; int jday; (void) DateStamp(dates); hour = dates[1] / 60; minute = dates[1] % 60; year = (dates[0] * 4) / 1461; jday = dates[0] - (year*1461)/4; year += 1978; Julian_to_Gregorian (jday, &year, &month, &day); } void xputs(str) { register int i; i = strlen(str); if (Write (outfile, str, i) != i) io_error = TRUE; } spool_file(fname) /* print a file */ char *fname; { register int rc; /* Don't use Gripe, here! - it would halt PRTSPOOL until the user */ /* acknowledged. Better to waste a page and keep the printer running. */ if ((infile = fopen (fname, "r")) == 0) { xputs ("\f\n\n\n"); xputs ("*******************************************\n"); xputs ("**** ERROR ********************************\n"); xputs ("Could not open file to be printed:\n"); xputs (fname); xputs("\n"); xputs ("*******************************************\n"); return; } getdate(); /* get timestamp */ getheader(); /* setup page header */ putheader(); do { put_a_line(); } while (NOT io_error && get_a_line()); if (io_error) { io_error = FALSE; aborting = TRUE; Gripe ("PRTSPOOL Terminating:", "I/O error on printer file.", ""); } xputs ("\n"); xputs ("EOF\n"); rc = fclose (infile); /******** do NOT do the folowing under Lattice C version 3.03 and earlier. They didn't realize the the Amiga Close function does not return an error code. if (rc != 0) Gripe ("PRTSPOOL:", "Error closing file being printed", ""); *********/ } int get_a_line() { char *i; i = fgets(linebuffer, sizeof(linebuffer), infile); return (i != NULL); } put_a_line() { if (linenum++ > LINES_PER_PAGE) putheader(); xputs (linebuffer); } #define HBSIZE 32+8+2+6 static char headbuffer[HBSIZE+8]; /* two for ff, stretch, 32 for title, 8 for page#, 4 for shrink, 2*NL, NUL */ getheader() { int i; fgets (linebuffer, 255, infile); headbuffer[0] = 0x0c; /* ff */ headbuffer[1] = 0x0e; /* stretch */ for (i = 0; (i= ' '); i++) headbuffer[i+2] = linebuffer[i]; i+=2; headbuffer[i++]= 0x0f; headbuffer[i++]= '\n'; headbuffer[i++]= '\0'; } putheader() { char outfb[81]; xputs(headbuffer); sprintf (outfb, "As of: %02.2d/%02.2d/%4d, %02d:%02.2d\n\n", month, day, year, hour, minute); xputs(outfb); linenum = 0; } /***************************************************************************/ main (argc, argv) int argc; char *argv[]; { PORTPAIR ports; if ( (IntuitionBase = OpenLibrary("intuition.library", 0)) == NULL) { Alert (AT_Recovery + AG_OpenLib + AO_Intuition, NULL); exit(20); } if ((argc < 2) || (argv[1][1] == '?')) { usage(); goto abort; } if ( (outfile= Open(argv[1], MODE_OLDFILE)) == NULL) { Gripe ("PRTSPOOL:", "Couldn't open printer file:", argv[1]); goto abort; } if (NOT LogInPort (GIMME_A_FILE, &ports, &packet)) { error ("SPOOLER program is inactive"); goto abort; } /* printf ("message port for %s is at %lx\n", GIMME_A_FILE, ports[OUTPORT]); */ /* raise priority - this program is low-overhead (mostly Waiting) */ myprocess = FindTask(NULL); (void) SetTaskPri (myprocess, PRTSPOOL_PRIORITY); /* The following loop goes out and solicits for a filename. */ while (NOT aborting) { packet.filename[0] = NUL; /* be neat, null out file name */ packet.minfo.mn_ReplyPort = ports[INPORT]; /* return address */ /* printf ("send/w reply port at %lx\n", packet.minfo.mn_ReplyPort); */ packet.minfo.mn_Length = sizeof(packet.filename); /* printf ("===request to spool...\n"); */ PutMsg (ports[OUTPORT], &packet); WaitPort(ports[INPORT]); (VOID) GetMsg (ports[INPORT]); if (packet.log_status == LOG_OUT) break; spool_file(packet.filename); } Close(outfile); LogOutPort (&ports, &packet); abort: CloseLibrary(IntuitionBase); }