/*
 *	Copyright (C) 1992	TGV, Incorporated
 *
 *	Message Printing commands
 */
#include "comnd.h"
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <sjcdef.h>
#include "vax-mm.h"

static Get_Print_Options_And_Msg_Seq();
extern char *GetSetupModules();

#define MAX_PRINT_SWITCHES	19

/* field definitions */

#define	AFTER_SWITCH	0
#define	ALL_SWITCH	1
#define	BURST_SWITCH	2
#define	CANCEL_SWITCH	3
#define COPIES_SWITCH	4
#define	FEED_SWITCH	5
#define	FLAG_SWITCH	6
#define	FORM_SWITCH	7
#define HEADERS_ONLY_SWITCH	8
#define	HOLD_SWITCH	9
#define	IMMEDIATE_SWITCH	10
#define	NAME_SWITCH	11
#define	NOTIFY_SWITCH	12
#define	PARAMETERS_SWITCH	13
#define	QUEUE_SWITCH	14
#define SEPARATE_PAGES_SWITCH	15
#define SPACE_SWITCH	16
#define	TRAILER_SWITCH	17
#define SETUP_SWITCH	18

/*
 *	UpperCasing Macro
 */
#define	UPPERCASE(word)	{char *cp;				\
			 cp = word;				\
			 while(*cp) {				\
				if (islower(*cp))		\
					*cp = toupper(*cp);	\
				cp++;				\
			} }

/*
 *	Print Command Options
 */
static int Messages_To_Print = 0;
static int Print_Sequence = 0;
static int Immediately;
static int Init_Variables = 1;
static char After_Time[64];
static char After_Time_Quad[8];	/* contains the VMS time quadword */
static int All_Messages;
static int Burst_Page;
static int Cancel_Messages;
static int Number_Of_Copies;
static int Feed_Page;
static int Flag_Page;
static char Queue_Form[64];
static int Headers_Only;
static int Hold_Job;
static char Job_Name[64];
static int Notify;
static int  Number_Of_Job_Params;
static char **Job_Parameters;
static char *Setup_Modules;
static char Queue_Name[64];
static int Separate_Pages;
static int Job_Spacing;
static int Trailer_Page;

/*
 *	This is located in VAX-MM.TOPS
 */
static char Atom_Buffer[128];

/*
 *	Establish the break mask to delimit fields based
 *	on " ", "/", "?" and "DEL".
 */
static 	unsigned long int Field_Break_Mask[4] =
		{0x0,0x80008001,0x0,0x80000000}
;

static struct {
	int current_entries;
	int maximum_entries;
	struct tbluk_keyword keywords[19];
	} Options = {
	19,19,
	{{0,	"after",	(int)AFTER_SWITCH},
	 {0,	"all",	(int)ALL_SWITCH},
	 {0,	"burst",	(int)BURST_SWITCH},
	 {0,	"cancel",	(int)CANCEL_SWITCH},
	 {0,	"copies",	(int)COPIES_SWITCH},
	 {0,	"feed",	(int)FEED_SWITCH},
	 {0,	"flag",	(int)FLAG_SWITCH},
	 {0,	"form",	(int)FORM_SWITCH},
	 {0,	"headers-only",	(int)HEADERS_ONLY_SWITCH},
	 {0,	"hold",	(int)HOLD_SWITCH},
	 {0,	"immediate",	(int)IMMEDIATE_SWITCH},
	 {0,	"name",	(int)NAME_SWITCH},
	 {0,	"notify",	(int)NOTIFY_SWITCH},
	 {0,	"parameters",	(int)PARAMETERS_SWITCH},
	 {0,	"queue",	(int)QUEUE_SWITCH},
	 {0,	"separate-pages",	(int)SEPARATE_PAGES_SWITCH},
	 {0,	"setup",	(int)SETUP_SWITCH},
	 {0,	"space",	(int)SPACE_SWITCH},
	 {0,	"trailer",	(int)TRAILER_SWITCH}}};

static struct comnd_function P_Confirm = {
	COMND_CONFIRM,
	(COMND_HELP_VALID | COMND_SUPPRESS_DEFAULT_HELP),
	0,
	(int)0,
	0,
	0,
	0};

static struct comnd_function Switch = {
	COMND_SWITCH,
	COMND_HELP_VALID,
	&P_Confirm,
	(int)&Options,
	0,
	0,
	0};

static struct comnd_function Field_LOCAL_1 = {
	COMND_FIELD,
	(COMND_HELP_VALID | COMND_SUPPRESS_DEFAULT_HELP | COMND_BREAK),
	0,
	(int)0,
	0,
	0,
	Field_Break_Mask};

static struct comnd_function Field = {
	COMND_QUOTED_STRING,
	(COMND_HELP_VALID | COMND_SUPPRESS_DEFAULT_HELP),
	&Field_LOCAL_1,
	(int)0,
	0,
	0,
	0};

/*
 *	JBC control block for printing job submissions
 */

static int Print_Switch_Index = 0;

/*
 *	JBC Item list, this is an array with
 *	MAX_PRINT_SWITCHES along with
 *		File Specification
 *		Delete File
 *		Returned Entry Number
 *		Zero out terminator
 */
struct ITMLST {
	unsigned short Length;
	unsigned short Code;
	char *Buf;
	unsigned short *RetLen;
} JBC_ItemList_Block[MAX_PRINT_SWITCHES+4];	/* all the switches + other things */


/*
 *	Print messages to a queued printer
 */
CMD_Print()
{
	int i;


	Noise("print options");
	/*
	 *	Get user options and message sequence
	 */
	Get_Print_Options_And_Msg_Seq();
	/*
	 *	Mark those jobs as Pending Print
	 */
	Mark_Print_Jobs();
	/*
	 *	If /ALL is specified, mark all messages for printing
	 */
	if (All_Messages) Mark_All_Print_Jobs();
	/*
	 *	Build the JBC Item List for submission
	 */
	Print_Switch_Index = 0;
	/*
	 *	Do we have a after time?
	 */
	if (After_Time[0] != 0) {
		JBC_ItemList_Block[Print_Switch_Index].Length = 8;
		JBC_ItemList_Block[Print_Switch_Index].Code = SJC$_AFTER_TIME;
		JBC_ItemList_Block[Print_Switch_Index].Buf = After_Time_Quad;
		JBC_ItemList_Block[Print_Switch_Index++].RetLen = 0;
	};
	/*
	 *	Handle the burst page
	 */
	if (Burst_Page == 1)	{
		JBC_ItemList_Block[Print_Switch_Index].Length = 4;
		JBC_ItemList_Block[Print_Switch_Index].Code = SJC$_FILE_BURST_ONE;
		JBC_ItemList_Block[Print_Switch_Index].Buf = NULL;
		JBC_ItemList_Block[Print_Switch_Index++].RetLen = 0;
	} else if (Burst_Page == 2) {
		JBC_ItemList_Block[Print_Switch_Index].Length = 4;
		JBC_ItemList_Block[Print_Switch_Index].Code = SJC$_FILE_BURST;
		JBC_ItemList_Block[Print_Switch_Index].Buf = NULL;
		JBC_ItemList_Block[Print_Switch_Index++].RetLen = 0;
	}
	/*
	 *	Handle the # copies
	 */
	if (Number_Of_Copies > 1) {
		JBC_ItemList_Block[Print_Switch_Index].Length = 4;
		JBC_ItemList_Block[Print_Switch_Index].Code = SJC$_FILE_COPIES;
		JBC_ItemList_Block[Print_Switch_Index].Buf = (char *)&Number_Of_Copies;
		JBC_ItemList_Block[Print_Switch_Index++].RetLen = 0;
	}
	/*
	 *	Handle the feed qualifier
	 */
	if (Feed_Page) {
		JBC_ItemList_Block[Print_Switch_Index].Length = 4;
		JBC_ItemList_Block[Print_Switch_Index].Code = SJC$_PAGINATE;
		JBC_ItemList_Block[Print_Switch_Index].Buf = (char *)0;
		JBC_ItemList_Block[Print_Switch_Index++].RetLen = 0;
	}
	/*
	 *	Handle the flag page
	 */
	if (Flag_Page == 1)	{
		JBC_ItemList_Block[Print_Switch_Index].Length = 4;
		JBC_ItemList_Block[Print_Switch_Index].Code = SJC$_FILE_FLAG_ONE;
		JBC_ItemList_Block[Print_Switch_Index].Buf = NULL;
		JBC_ItemList_Block[Print_Switch_Index++].RetLen = 0;
	} else if (Flag_Page == 2) {
		JBC_ItemList_Block[Print_Switch_Index].Length = 4;
		JBC_ItemList_Block[Print_Switch_Index].Code = SJC$_FILE_FLAG;
		JBC_ItemList_Block[Print_Switch_Index].Buf = NULL;
		JBC_ItemList_Block[Print_Switch_Index++].RetLen = 0;
	}
	/*
	 *	Handle the form qualifier
	 */
	if (Queue_Form[0] != 0) {
		JBC_ItemList_Block[Print_Switch_Index].Length = strlen(Queue_Form);
		JBC_ItemList_Block[Print_Switch_Index].Code = SJC$_FORM_NAME;
		JBC_ItemList_Block[Print_Switch_Index].Buf = Queue_Form;
		JBC_ItemList_Block[Print_Switch_Index++].RetLen = 0;
	}
	/*
	 *	Handle the hold qualifier
	 */
	if (Hold_Job) {
		JBC_ItemList_Block[Print_Switch_Index].Length = 4;
		JBC_ItemList_Block[Print_Switch_Index].Code = SJC$_HOLD;
		JBC_ItemList_Block[Print_Switch_Index].Buf = (char *)0;
		JBC_ItemList_Block[Print_Switch_Index++].RetLen = 0;
	}
	/*
	 *	Handle the name qualifier
	 */
	if (Job_Name[0] != 0) {
		JBC_ItemList_Block[Print_Switch_Index].Length = strlen(Job_Name);
		JBC_ItemList_Block[Print_Switch_Index].Code = SJC$_JOB_NAME;
		JBC_ItemList_Block[Print_Switch_Index].Buf = Job_Name;
		JBC_ItemList_Block[Print_Switch_Index++].RetLen = 0;
	} else {
		strcpy(Job_Name, "MM");
		JBC_ItemList_Block[Print_Switch_Index].Length = strlen(Job_Name);
		JBC_ItemList_Block[Print_Switch_Index].Code = SJC$_JOB_NAME;
		JBC_ItemList_Block[Print_Switch_Index].Buf = Job_Name;
		JBC_ItemList_Block[Print_Switch_Index++].RetLen = 0;
	}
	/*
	 *	Handle the notify qualifier
	 */
	if (Notify) {
		JBC_ItemList_Block[Print_Switch_Index].Length = 4;
		JBC_ItemList_Block[Print_Switch_Index].Code = SJC$_NOTIFY;
		JBC_ItemList_Block[Print_Switch_Index].Buf = (char *)0;
		JBC_ItemList_Block[Print_Switch_Index++].RetLen = 0;
	}
	/*
	 *	Handle the parameters qualifier
	 */
	if (Number_Of_Job_Params) {
		for (i = 0; i < Number_Of_Job_Params; i++) {
			JBC_ItemList_Block[Print_Switch_Index].Length = strlen(Job_Parameters[i]);
			JBC_ItemList_Block[Print_Switch_Index].Code = (SJC$_PARAMETER_1 + i);
			JBC_ItemList_Block[Print_Switch_Index].Buf = Job_Parameters[i];
			JBC_ItemList_Block[Print_Switch_Index++].RetLen = 0;
		}
	}
	/*
	 *	Handle the queuing the setup modules
	 */
	if (Setup_Modules && Setup_Modules[0] != 0) {
		JBC_ItemList_Block[Print_Switch_Index].Length = strlen(Setup_Modules);
		JBC_ItemList_Block[Print_Switch_Index].Code = SJC$_FILE_SETUP_MODULES;
		JBC_ItemList_Block[Print_Switch_Index].Buf = Setup_Modules;
		JBC_ItemList_Block[Print_Switch_Index++].RetLen = 0;
	}
	/*
	 *	Handle the queue name
	 */
	if (Queue_Name[0] == 0) strcpy(Queue_Name, "SYS$PRINT");
	JBC_ItemList_Block[Print_Switch_Index].Length = strlen(Queue_Name);
	JBC_ItemList_Block[Print_Switch_Index].Code = SJC$_QUEUE;
	JBC_ItemList_Block[Print_Switch_Index].Buf = Queue_Name;
	JBC_ItemList_Block[Print_Switch_Index++].RetLen = 0;
	/*
	 *	Handle printer spacing
	 */
	if (Job_Spacing) {
		JBC_ItemList_Block[Print_Switch_Index].Length = 4;
		JBC_ItemList_Block[Print_Switch_Index].Code = SJC$_DOUBLE_SPACE;
		JBC_ItemList_Block[Print_Switch_Index].Buf = (char *)0;
		JBC_ItemList_Block[Print_Switch_Index++].RetLen = 0;
	}
	/*
	 *	Handle the trailer
	 */
	if (Trailer_Page == 1)	{
		JBC_ItemList_Block[Print_Switch_Index].Length = 4;
		JBC_ItemList_Block[Print_Switch_Index].Code = SJC$_FILE_TRAILER_ONE;
		JBC_ItemList_Block[Print_Switch_Index].Buf = NULL;
		JBC_ItemList_Block[Print_Switch_Index++].RetLen = 0;
	} else if (Trailer_Page == 2) {
		JBC_ItemList_Block[Print_Switch_Index].Length = 4;
		JBC_ItemList_Block[Print_Switch_Index].Code = SJC$_FILE_TRAILER;
		JBC_ItemList_Block[Print_Switch_Index].Buf = NULL;
		JBC_ItemList_Block[Print_Switch_Index++].RetLen = 0;
	}
	/*
	 *	Check to see if the user specified IMMEDIATE
	 *	if so, submit the print job, NOW
	 */
	if (Immediately) Print(0);
}


/*
 *	UnPrint (same as PRINT/CANCEL)
 */
CMD_Unprint()
{
	if (!Read_Mode) {
		/*
		 *	Set the help message
		 */
		Noise("Message Sequence");

		/*
		 *	Get the message sequence
		 */
		Parse_Message_List("CURRENT");
	}
	else
		Confirm();
	/*
	 *	Set the cancel flag
	 */
	Cancel_Messages = 1;

	/*
	 *	Mark (actually unmark) jobs for printing
	 */
	Mark_Print_Jobs();

	/*
	 *	Reset the cancel flag
	 */
	Cancel_Messages = 0;
}


/*
 *	Parse out the command string
 */
Get_Print_Options_And_Msg_Seq()
{
	int Number_Of_Options;
	int Clear_Atom_Buffer;
	char tmpbuf[1024];
	register char *cp;
	struct comnd_function *f;
	struct tbluk_keyword *t;
	int Status;

	/*
	 *	Initialize the defaults
	 */
	Clear_Atom_Buffer = 0;
	Cancel_Messages = 0;	/* always reset this value */
	Immediately = Print_Jobs_Immediately; /* and this one as well */
	if (Init_Variables) {
		After_Time[0] = 0;
		All_Messages = 0;
		Burst_Page = 0;
		Number_Of_Copies = 0;
		Feed_Page = 0;
		Flag_Page = 0;
		strcpy(Queue_Form, Print_Form);
		Headers_Only = 0;
		Hold_Job = 0;
		Job_Name[0] = 0;
		Notify = 0;
		Number_Of_Job_Params = 0;
		Job_Parameters = NULL;
		Setup_Modules = NULL;
		strcpy(Queue_Name, Print_Queue);
		Separate_Pages = List_On_Separate_Pages;
		Job_Spacing = 0;
		Trailer_Page = 0;
		Init_Variables = 0;	/* don't do this init again */
	}
	Number_Of_Options = 0;
	Print_Switch_Index = 0;
	/*
	 *	add an atom buffer if not there
	 */
	if (!Command_State.atom_buffer) {
		Clear_Atom_Buffer = 1;
		Command_State.atom_buffer = Atom_Buffer;
		Command_State.atom_buffer_size = sizeof(Atom_Buffer);
	}
	/*
	 *	If read mode, change the help string
	 */
	if (!Read_Mode)
		Switch.help_string = "message sequence\n  or optional PRINT qualifier, ";
	else
		Switch.help_string = "optional PRINT qualifier, ";

	/*
	 *	Try to get user options
	 */
	while(1) {
		/*
		 *	Get the option, turn off the error handling
		 *	available with TOPS-20, so that we can deal
		 *	with it ourselves.
		 */
		Command_State.flags &= ~COMND_HANDLE_ERRORS;
		if (COMND(&Command_State,&Switch,&t,&f)
 < 0) break;
		/*
		 *	Everything is okay so far, continue
		 *	parsing
		 */
		if (!Read_Mode) Command_State.flags |= COMND_HANDLE_ERRORS;
		/*
		 *	If it is a confirm (<RET>) break;
		 */
		if (f->code == COMND_CONFIRM) break;
		/*
		 *	If it is just a switch then set the
		 *	flag and continue
		 */
		if (t->user_data == ALL_SWITCH) {	/* print all messages */
			All_Messages = 1;
			continue;
		}
		else if (t->user_data == CANCEL_SWITCH) { /* cancel all messages */
			Cancel_Messages = 1;
			continue;
		}
		else if (t->user_data == FEED_SWITCH) { /* print a <ff> after every message */
			Feed_Page = 1;
			continue;
		}
		else if (t->user_data == HEADERS_ONLY_SWITCH) { /* only print the headers */
			Headers_Only = 1;
			continue;
		}
		else if (t->user_data == HOLD_SWITCH) { /* hold this job until released */
			Hold_Job = 1;
			continue;
		}
		else if (t->user_data == IMMEDIATE_SWITCH) { /* print this job *NOW* */
			Immediately = 1;
			continue;
		}
		else if (t->user_data == NOTIFY_SWITCH) { /* notify when print is done */
			Notify = 1;
			continue;
		}
		else if (t->user_data == SEPARATE_PAGES_SWITCH) { /* print messages on seperate pages */
			Separate_Pages = 1;
			continue;
		}
		else if (t->user_data == SPACE_SWITCH) { /* print double spaced */
			Job_Spacing = 1;
			continue;
		}
		/*
		 *	Process the switches that require input
		 */
		Number_Of_Options++;
		if (COMND(&Command_State,&Field,0,0)
 < 0) return;
		/*
		 *	Deal with the switches
		 */
		cp = Atom_Buffer;
		while (*cp == '=') cp++;	/* got to eat "=" since TOPS-20 doesn't */
		switch(t->user_data) {
			case AFTER_SWITCH:	/* print job after the specified time */
				strcpy(After_Time,cp);
				UPPERCASE(After_Time);
				/*
				 *	Convert the time into VMS binary time
				 */
				ConvertTime(After_Time, After_Time_Quad);
				break;
			case BURST_SWITCH:	/* print a burst page */
				strcpy(tmpbuf,cp);
				UPPERCASE(tmpbuf);
				if (strcmp(tmpbuf, "ALL") == 0)
					Burst_Page = 2;
				else 
					Burst_Page = 1;
				break;
			case COPIES_SWITCH:	/* # of copies to print */
				Number_Of_Copies = atoi(cp);
				break;
			case FLAG_SWITCH:	/* print a flag page */
				strcpy(tmpbuf, cp);
				UPPERCASE(tmpbuf);
				if (strcmp(tmpbuf, "ALL") == 0)
					Flag_Page = 2;
				else
					Flag_Page = 1;
				break;
			case FORM_SWITCH:	/* Queue form to use */
				strcpy(Queue_Form, cp);
				UPPERCASE(Queue_Form);
				break;
			case NAME_SWITCH:	/* Job name to use */
				strcpy(Job_Name, cp);	
				break;
			case PARAMETERS_SWITCH:	/* JBC parameters */
				GetParams (cp, &Number_Of_Job_Params, Job_Parameters);
				break;
			case QUEUE_SWITCH:	/* Queue to submit to */
				strcpy(Queue_Name, cp);
				UPPERCASE(Queue_Name);
				break;
			case TRAILER_SWITCH:	/* print a trailer page */
				strcpy(tmpbuf, cp);
				UPPERCASE(tmpbuf);
				if (strcmp(tmpbuf, "ALL") == 0)
					Trailer_Page = 2;
				else
					Trailer_Page = 1;
				break;
			case SETUP_SWITCH:	/* get the setup modules */
				Setup_Modules = GetSetupModules(cp);
				break;
		}
	}
	/*
	 *	Parse message list, make sure that the error
	 *	handling is re-enabled.
	 */
	if (!Read_Mode) {
		Command_State.flags |= COMND_HANDLE_ERRORS;
		Parse_Message_List("CURRENT");
	}
	/*
	 *	Confirm
	 */
	Confirm();
	/*
	 *	Remove the temp Atom Buffer if necessacary
	 */
	if (Clear_Atom_Buffer) {
		Command_State.atom_buffer = 0;
		Command_State.atom_buffer_size = 0;
	}
}


/*
 *	Mark Print Jobs for Printing
 */
Mark_Print_Jobs()
{
	int Message;
	int Number_Of_Messages = 0;

	/*
	 *	Mark 'em.  If in read mode, only do the current message
	 */
	if (Read_Mode) {
		/*
		 *	If already mark, don't remark it
		 */
		if (Cancel_Messages) {
			Messages[Current_Message-1].Flags &= ~MSG_NEEDS_PRINTING;
			Messages_To_Print--;
		}
		else {
			Messages[Current_Message-1].Flags |= MSG_NEEDS_PRINTING;
			Messages_To_Print++;
		}
	} else {
		while (1) {
			Message = Next_Message(1);
			if (Message <= 0) break;
			Current_Message = Message;
			/*
			 *	If already mark, don't remark it
			 */
			if (Cancel_Messages) {
				Messages[Message-1].Flags &= ~MSG_NEEDS_PRINTING;
				Messages_To_Print--;
			}
			else {
				Messages[Message-1].Flags |= MSG_NEEDS_PRINTING;
				Messages_To_Print++;
			}
			Update_Message(Message);
			Number_Of_Messages++;
		}
	}
	if (Number_Of_Messages) printf("\n");
}


/*
 *	Mark all messages for printing
 */
Mark_All_Print_Jobs()
{
	int Message;

	/*
	 *	Mark 'em
	 */
	for (Message = 1; Message <= Last_Message; Message++) {
		if (Cancel_Messages) {
			Messages[Message-1].Flags &= ~MSG_NEEDS_PRINTING;
			Messages_To_Print--;
		}
		else {
			Messages[Message-1].Flags |= MSG_NEEDS_PRINTING;
			Messages_To_Print++;
		}
		Update_Message(Message);
	}
}


/*
 *	Clear all marked for printing
 *	WARNING: This is designed to only be called from Print()
 *	during user confirmation.
 */
Clear_Print_Messages()
{
	int Message;

	/*
	 *	Loop through and update
	 */
	for (Message = 1; Message <= Last_Message; Message++) {
		if (Messages[Message-1].Flags & MSG_NEEDS_PRINTING) {
			Messages[Message-1].Flags &= ~MSG_NEEDS_PRINTING;
			Update_Message(Message);
		}
	}
	Messages_To_Print = 0;
	Init_Variables = 1;
}


/*
 *	Print all marked messages
 */
Print(Please_Ask)
int Please_Ask;
{
	struct {
		int current_entries;
		int maximum_entries;
		struct tbluk_keyword keywords[2];
		} Table = {
		2,
		2,
		{{0,	"no",	0},
		 {0,	"yes",	1}}};
	struct comnd_function Responses = 
		{COMND_KEYWORD,
		 COMND_HELP_VALID|COMND_SUPPRESS_DEFAULT_HELP,
		 0,
		 (int)&Table,
		 "YES or NO"};
	struct tbluk_keyword *t;
	char Prompt[280];
	int i, Entry_Number;
	unsigned long status, vaxerr;
	int Number_Of_Messages;
	unsigned short iosb[4];
	char file_spec[256];
	char Buffer[128], sjc_status[512];
	short sjc_status_len;
	FILE *Stream;
	register struct Msg *Msg;

	/*
	 *	Should we ask the user to print these files?
	 */
	if (Please_Ask && (Messages_To_Print > 0)) {
		/*
		 *	Make the user confirm
		 */
		sprintf(Prompt,
			"Print Jobs pending.  Submit to Queue? (YES/NO) ");
		Command_State.prompt = Prompt;
		while (1) {
			COMND_INIT(&Command_State);
			status = COMND(&Command_State, &Responses, &t, 0);
			if (status >= 0) break;
		}
		Confirm();
		if (t->user_data == 0) {
			Clear_Print_Messages();
			return;
		}
	} else if (Messages_To_Print <= 0) return;

	/*
	 *	Create the output file
	 */
	Print_Sequence++;
	sprintf (file_spec, "SYS$SCRATCH:MM_0x%x_%s_%d.prt", getpid(), getenv("USER"),
				Print_Sequence);
	Stream = fopen(file_spec, "w", "rfm=var", "rat=cr");
	Number_Of_Messages = 0;

	/*
	 *	If in Read_Mode, just print out the current message
	 */

	if (Read_Mode) {
		Number_Of_Messages = 1;
		Msg = &Messages[Current_Message-1];
		fprintf(Stream,"Message %d -- ************************\n",
							Current_Message);
		write(fileno(Stream),
		      MESSAGE_HEADER(Current_Message),
		      Msg->Real_Size);
		fprintf(Stream,"\n");
		if (Separate_Pages) fprintf(Stream,"\n");
		Messages[Current_Message-1].Flags &= ~MSG_NEEDS_PRINTING;
	}
	/*
	 *	else print the selected messages
	 */
	else {
		/*
		 *	Generate the header
		 */
		Get_DayTime(Buffer);
		fprintf(Stream,"-- Message from file: %s --\n", Current_Mail_File);
		fprintf(Stream,"   %s %s\n\n", Buffer, Timezone_String(0));
		/*
		 *	Generate the message headers if asked
		 */
		if (List_Include_Headers || Headers_Only) {
			for (i = 1; i <= Last_Message; i++) {
				if (Messages[i-1].Flags & MSG_NEEDS_PRINTING) {
					Print_Header(Stream,&Messages[i-1],i);
				}
			}
			fprintf(Stream, "\n");
		}
		if (Headers_Only) Number_Of_Messages++;
		/*
		 *	Print out the messages
		 */
		if (!Headers_Only) {
			for (i = 1; i <= Last_Message; i++) {
				if (Messages[i-1].Flags & MSG_NEEDS_PRINTING) {
					Number_Of_Messages++;
					if (Separate_Pages) fprintf (Stream, "\n");
					Msg = &Messages[i-1];
					fprintf(Stream, "Message %d -- ************************\n",i);
					write(fileno(Stream),MESSAGE_HEADER(i),Msg->Real_Size);
					fprintf(Stream,"\n");
				}
			}
		}
	}
	fclose(Stream);
	/*
	 *	Done, submit job to the printer, make sure the printer
	 *	knows to delete the job and retrieve back the entry
	 *	number message.
	 */
	if (Queue_Name[0] == 0) {
		strcpy (Queue_Name, "SYS$PRINT");
		JBC_ItemList_Block[Print_Switch_Index].Length = strlen(Queue_Name);
		JBC_ItemList_Block[Print_Switch_Index].Code   = SJC$_QUEUE;
		JBC_ItemList_Block[Print_Switch_Index].Buf    = Queue_Name;
		JBC_ItemList_Block[Print_Switch_Index++].RetLen = 0;
	}

	JBC_ItemList_Block[Print_Switch_Index].Length = 4;
	JBC_ItemList_Block[Print_Switch_Index].Code   = SJC$_DELETE_FILE;
	JBC_ItemList_Block[Print_Switch_Index].Buf    = (char *)0;
	JBC_ItemList_Block[Print_Switch_Index++].RetLen = 0;
	
	JBC_ItemList_Block[Print_Switch_Index].Length = 4;
	JBC_ItemList_Block[Print_Switch_Index].Code   = SJC$_ENTRY_NUMBER_OUTPUT;
	JBC_ItemList_Block[Print_Switch_Index].Buf    = (char *)&Entry_Number;
	JBC_ItemList_Block[Print_Switch_Index++].RetLen = 0;

	JBC_ItemList_Block[Print_Switch_Index].Length = strlen(file_spec);
	JBC_ItemList_Block[Print_Switch_Index].Code   = SJC$_FILE_SPECIFICATION;
	JBC_ItemList_Block[Print_Switch_Index].Buf    = file_spec;
	JBC_ItemList_Block[Print_Switch_Index++].RetLen = 0;

	JBC_ItemList_Block[Print_Switch_Index].Length = sizeof(sjc_status) - 1;
	JBC_ItemList_Block[Print_Switch_Index].Code   = SJC$_JOB_STATUS_OUTPUT;
	JBC_ItemList_Block[Print_Switch_Index].Buf    = sjc_status;
	JBC_ItemList_Block[Print_Switch_Index++].RetLen = (unsigned short *)&sjc_status_len;

	JBC_ItemList_Block[Print_Switch_Index].Length = 0;
	JBC_ItemList_Block[Print_Switch_Index].Code   = 0;
	JBC_ItemList_Block[Print_Switch_Index].Buf    = 0;
	JBC_ItemList_Block[Print_Switch_Index++].RetLen = 0;

	/*
	 *	Submit the job to the Queue, if there really is something to
	 *	print.  Otherwise, delete the file and clear the print count.
	 */
	if (Number_Of_Messages == 0) {
		delete(file_spec);
		Clear_Print_Messages();
		return;
	}

	status = sys$sndjbcw(0, SJC$_ENTER_FILE, 0, JBC_ItemList_Block,
			     iosb, 0, 0);
	if (status & 1) status = iosb[0];
	if ( !(status & 1) ) {
		/* OR in the JBC facility code to the error */
		vaxerr = ((status & 0xffff8000) == 0x8000) ? status | 0x40000 : status;
		printf("?Print job failed: %s\n", (char *)getvaxerr(vaxerr));
		delete(file_spec);
		return;
	}
	else {
		char *ep;
		ep = (char *)strchr(file_spec, '.');
		if (ep != NULL) *ep = '\0';
		sjc_status[sjc_status_len] = '\0';
		printf("%s\n", sjc_status);
		Clear_Print_Messages();
		return;
	}
}
