/* Print.c V1.0.0 27-Mar-88 ) Frangois Gagnon */ /* Copyright ) 1988 Frangois Gagnon, All Rights Reserved. The author does not make any warranty expressed or implied, or assumes any liability or responsiblity for the use of this software. Permission is hereby granted to copy, reproduce, redistribute or otherwise use this software as long as it is for non-profit. This notice and the above copyright notice must remain intact and appear on all copies. Permission is also granted to correct any problems with this software, but modifications and improvements are reserved by the author. */ #include #include #include #include #include #include #include #include #include #include "stdefs.h" #include "Print_Spool.h" /* Declarations of status messages */ local char FIND[] = "\nPrint: Unable to find Spool port.\n\n"; local char PROT[] = "\nPrint: Mismatched protocol versions.\n\n"; local char PORT[] = "\nPrint: Unable to create Print port.\n\n"; local char DATA[] = "\nPrint: Unable to allocate memory.\n\n"; local char EXEC[] = "\nPrint: Unknown or ambiguous command = %s.\n\n"; local char LOCK[] = "\nPrint: File not found = %s.\n\n"; local char TYPE[] = "\nPrint: Wrong file type = %s.\n\n"; local char SIZE[] = "\nPrint: File name too long = %s%s.\n\n"; /* Definition for Execution */ local struct Inform *Print_Data; local struct MsgPort *Spool_Port, *Print_Port; local struct FileInfoBlock *Print_Info; local File *Print_List = NULL, *Print_Last = NULL; local int Print_File = PS_Insert; local int Print_Opts = (Opts_Headers | Opts_Numbers); local int Print_Flag = 0; local int Print_Copy = 1; #define Options( Mask, Opts) (Print_Opts = (Print_Opts & ~Mask) + Opts) ^L /*****************************/ /* Define Available Commands */ /*****************************/ /* Add option commands */ #define PS_CPI10 30 #define PS_CPI12 31 #define PS_CPI17 32 #define PS_LPI6 33 #define PS_LPI8 34 #define PS_NARROW 35 #define PS_WIDE 36 #define PS_SHORT 37 #define PS_LONG 38 #define PS_HEADER 40 #define PS_NUMBER 41 #define PS_KEEP 42 #define PS_DELETE 43 #define PS_DRAFT 44 #define PS_LETTER 45 /* Define the data structure */ #define Print_Size 26 #define Print_Used 7 struct Print_Type { char Name[Print_Used]; byte Code; }; local struct Print_Type Print_Exec[Print_Size] = { { "CANCEL", PS_Cancel }, { "CHANGE", PS_Change }, { "CPI10", PS_CPI10 }, { "CPI12", PS_CPI12 }, { "CPI17", PS_CPI17 }, { "DELETE", PS_DELETE }, { "DRAFT", PS_DRAFT }, { "FINISH", PS_Finish }, { "FREEZE", PS_Freeze }, { "HEADER", PS_HEADER }, { "INSERT", PS_Insert }, { "KEEP", PS_KEEP }, { "LETTER", PS_LETTER }, { "LONG", PS_LONG }, { "LPI6", PS_LPI6 }, { "LPI8", PS_LPI8 }, { "NARROW", PS_NARROW }, { "NUMBER", PS_NUMBER }, { "REMOVE", PS_Remove }, { "REPORT", PS_Report }, { "RESET", PS_Resets }, { "RESUME", PS_Resume }, { "RETURN", PS_Return }, { "SHORT", PS_SHORT }, { "UPDATE", PS_Update }, { "WIDE", PS_WIDE }}; ^L /********************************/ /* Search Allowing Abbreviatoin */ /********************************/ local int Find_Command( Name) /*********************************/ register char Name[]; { register int Length, Result; auto int Test, Next; extern int strncmp(); for (Length = 0; Name[Length] != NUL; ++Length) Name[Length] = toupper( Name[Length]); Next = 1; Result = -1; do /* The name table must be sorted */ { Test = Next; if (++Result == Print_Size) { Next = -1; break; } Next = strncmp( Name, Print_Exec[Result].Name, Length); } while (Test > 0); if ((Test != 0) || (Next == 0)) return 0; return Print_Exec[Result - 1].Code; } ^L /******************************/ /* Initialization of Defaults */ /******************************/ #define INTUITIONNAME "intuition.library" public struct IntuitionBase *IntuitionBase; local void Default_Values() /******************************/ { auto struct Preferences PrefBuffer; auto int Temp; extern struct IntuitionBase *OpenLibrary(); extern struct Preferences *GetPrefs(); /* Fetch the information from the system */ IntuitionBase = OpenLibrary( INTUITIONNAME, 0L); if (IntuitionBase == NULL) return; GetPrefs( &PrefBuffer, (long) sizeof( struct Preferences)); CloseLibrary( IntuitionBase); /* Extract the information from the structure */ if (PrefBuffer.PrintPitch == ELITE) Print_Opts |= Line_12; else if (PrefBuffer.PrintPitch == FINE) Print_Opts |= Line_17; Temp = (PrefBuffer.PrintSpacing == EIGHT_LPI ? 8 : 6); if (PrefBuffer.PrintQuality == LETTER) Print_Flag |= Flag_Quality; if (PrefBuffer.PrintSpacing == EIGHT_LPI) Print_Opts |= Page_8; if (PrefBuffer.PaperSize == W_TRACTOR) Print_Opts |= Line_13; if (PrefBuffer.PaperLength / Temp == 11) Print_Opts |= Page_11; } /****************************/ /* Printing Utility Routine */ /****************************/ local char Value[3][3] = { "10", "12", "17" }; local void Show_File( Info_File) /***********************************/ register File *Info_File; { printf( "%3s%4s%4s%4s%3c%c%c%c%6d %6ld %s\n", Value[Info_File->File_Opts & Line_Density], (Info_File->File_Opts & Line_Formats ? "13" : "8"), (Info_File->File_Opts & Page_Density ? "8" : "6"), (Info_File->File_Opts & Page_Formats ? "11" : "8.5"), (Info_File->File_Opts & Opts_Headers ? 'T' : 'F'), (Info_File->File_Opts & Opts_Numbers ? 'T' : 'F'), (Info_File->File_Flag & Flag_Quality ? 'L' : 'D'), (Info_File->File_Flag & Flag_Deleted ? 'D' : 'K'), Info_File->File_Copy, Info_File->File_Size, Info_File->File_Name); } ^L /*********************************/ /* General Communication Routine */ /*********************************/ local int Request_Action( Action) /*************************************/ int Action; { extern struct MsgPort *FindPort(); extern struct Inform *GetMsg(); /* Prepare the message for sending */ Print_Data->Packet.mn_Node.ln_Type = NT_MESSAGE; Print_Data->Packet.mn_ReplyPort = Print_Port; Print_Data->Number = PROTOCOL; Print_Data->Action = Action; /* Send the request message across */ /* Making sure the port still exist */ Forbid(); if ((Spool_Port = FindPort( SPOOLNAME)) == NULL) { Permit(); fprintf( stderr, FIND); return TRUE; } PutMsg( Spool_Port, Print_Data); Permit(); /* Receive the result message */ do WaitPort( Print_Port); while ((Print_Data = GetMsg( Print_Port)) == NULL); /* Check the protocol version */ if (Print_Data->Number != PROTOCOL) { fprintf( stderr, PROT); return TRUE; } return FALSE; } ^L /*************************************/ /* Request the status of the Spooler */ /*************************************/ local char *State[] = { "\nSpool: Waiting for a file to print.\n", "\nSpool: Waiting for a change of paper.\n", "\nSpool: Waiting to access the printer.\n", "\nSpool: Printing a requested file.\n", "\nSpool: Printing but will pause after the file.\n", "\nSpool: Pausing between two files.\n", "\nSpool: Pausing in the middle of a file.\n" }; local void Request_Report() /******************************/ { register File *File_List, *File_Next; register byte Prog_Info; /* Request the wanted operation */ if (Request_Action( PS_Report)) return; /* Display the status information */ printf( State[Prog_Info = Print_Data->Detail.Status.Prog_State]); if (Print_Data->Detail.Status.Flag_State) printf( "Spool: Set to terminate its execution.\n"); if (Print_Data->Detail.Status.Opts_State & Flag_Partial) printf( "Spool: Partial list of files, unable to allocate memory.\n"); if ((Prog_Info == Exec_State) || (Prog_Info == File_State) || (Prog_Info == Stop_State) ) { printf( "Spool: Printing %ld chars ... %ld lines ... %ld pages.\n", Print_Data->Detail.Status.Char_Print, Print_Data->Detail.Status.Line_Print, Print_Data->Detail.Status.Page_Print); } /* Display the contents of the print queue */ if ((File_List = Print_Data->Detail.Status.File_Print) != NULL) { printf( "\ncpi ipl lpi ipp hnqd copy size report\n"); do { File_List = (File_Next = File_List)->File_Next; Show_File( File_Next); FreeMem( File_Next, (long) sizeof( File)); } while (File_List != NULL); } putchar( '\n'); } ^L /*************************************/ /* Request the removal of some files */ /*************************************/ local void Request_Remove( Name) /***********************************/ char Name[]; { register File *Temp_File, *Temp_Next; strncpy( Print_Data->Detail.Remove, Name, Name_Size); if (Request_Action( PS_Remove)) return; if ((Temp_File = Print_Data->Detail.Insert) != NULL) { printf( "\ncpi ipl lpi ipp hnqd copy size remove\n"); do { Temp_File = (Temp_Next = Temp_File)->File_Next; Show_File( Temp_Next); FreeMem( Temp_Next, (long) sizeof( File)); } while (Temp_File != NULL); } putchar( '\n'); } ^L /**************************************/ /* Perform the specified file request */ /**************************************/ local void Perform() /***********************/ { if (Print_List != NULL) { /* Execute the operation */ if (Print_File == PS_Insert) Print_Data->Detail.Insert = Print_List; if (Print_File == PS_Update) Print_Data->Detail.Update = Print_List; Print_Last->File_Next = NULL; if (Request_Action( Print_File)) { do { Print_List = (Print_Last = Print_List)->File_Next; FreeMem( Print_Last, (long) sizeof( File)); } while (Print_List != NULL); return; } if (Print_File == PS_Insert) Print_List = NULL; if (Print_File == PS_Update) { printf( "\ndone cpi ipl lpi ipp hnqd copy size update\n"); do { Print_List = (Print_Last = Print_List)->File_Next; printf( "%s", (Print_Last->File_Flag & Flag_Updated ? "TRUE " : "FALSE ")); Show_File( Print_Last); FreeMem( Print_Last, (long) sizeof( File)); } while (Print_List != NULL); putchar( '\n'); } } } ^L /*********************************/ /* File Search Utililty Routines */ /*********************************/ local int File_Match( Name, Data) /*************************************/ register char *Name, *Data; { auto char *Save_Name[10], *Save_Data[10]; register int Save; if ((*Data == NUL) || (*Name == NUL)) return FALSE; Save = -1; while ((*Data != NUL) || (*Name != NUL)) { if (*Data == '*') { if (*++Data == NUL) return TRUE; if ( ++Save == 10) return FALSE; Save_Name[Save] = Name; Save_Data[Save] = Data; continue; } if ( ((*Data == '?') && (*Name != NUL)) || (toupper(*Data) == toupper(*Name))) { ++Data; ++Name; continue; } if (*Name == NUL) --Save; if ( Save < 0) return FALSE; Name = ++Save_Name[Save]; Data = Save_Data[Save]; } return TRUE; } ^L local int File_Parent( File_Name, File_Path, File_Size, File_Info) /**********************************************************************/ char *File_Name, *File_Path; int File_Size; struct FileInfoBlock *File_Info; { extern struct FileLock *Lock(), *ParentDir(); auto struct FileLock *File_Lock, *File_Next; register int File_Save, File_Loop; if ((File_Lock = Lock( File_Name, SHARED_LOCK)) == NULL) return 0; File_Path[File_Loop = File_Size - 1] = NUL; do { if (!Examine( File_Lock, File_Info)) { UnLock( File_Lock); return 0; } File_Save = strlen( File_Info->fib_FileName) + 1; if ((File_Loop < File_Save) || (File_Loop < 4)) { UnLock( File_Lock); return -1; } if (File_Save == 1) strcpy( &File_Path[File_Loop - (File_Save = 4)], "RAM"); else strcpy( &File_Path[File_Loop - File_Save], File_Info->fib_FileName); File_Next = ParentDir( File_Lock); UnLock( File_Lock); File_Path[File_Loop - 1] = (File_Next == NULL ? ':' : '/'); File_Lock = File_Next; File_Loop -= File_Save; } while (File_Lock != NULL); if (File_Loop != 0) strcpy( File_Path, &File_Path[File_Loop]); return (File_Size - File_Loop); } ^L /**********************************/ /* Specific File Handling Routine */ /**********************************/ local int File_Insert() /***************************/ { extern void *AllocMem(); extern char *ctime(); register File *Temp_File; auto char *Temp_Date; auto time_t Temp_Time; Temp_File = AllocMem( (long) sizeof(File), MEMF_PUBLIC); if (Temp_File == NULL) { fprintf( stderr, DATA); return TRUE; } Temp_Time = Print_Info->fib_Date.ds_Days * 86400 + Print_Info->fib_Date.ds_Minute * 60 + Print_Info->fib_Date.ds_Tick / TICKS_PER_SECOND; Temp_Date = ctime( &Temp_Time); memcpy( Temp_File->File_Date, &Temp_Date[4], Date_Size); Temp_File->File_Opts = Print_Opts; Temp_File->File_Flag = Print_Flag; Temp_File->File_Copy = Print_Copy; Temp_File->File_Size = Print_Info->fib_Size; if (Print_List == NULL) Print_List = Temp_File; else Print_Last->File_Next = Temp_File; Print_Last = Temp_File; return FALSE; } ^L local void File_Search( Name) /********************************/ char *Name; { extern char *strchr(), *strrchr(); extern struct FileLock *Lock(); auto struct FileLock *File_Lock; auto int File_Size; auto char *File_Name, *File_Char; auto char File_Path[Name_Size]; if ((strchr( Name, '*') == NULL) && (strchr( Name, '?') == NULL)) { /* Take care of simple file name */ File_Size = File_Parent( Name, File_Path, Name_Size, Print_Info); if (File_Size <= 0) { if (File_Size == 0) fprintf( stderr, LOCK, Name); else fprintf( stderr, SIZE, Name, ""); return; } File_Path[File_Size - 2] = NUL; if ((File_Lock = Lock( File_Path, SHARED_LOCK)) == NULL) { fprintf( stderr, LOCK, Name); return; } if (!Examine( File_Lock, Print_Info)) fprintf( stderr, LOCK, Name); else if (Print_Info->fib_DirEntryType >= 0) fprintf( stderr, TYPE, Print_Info->fib_FileName); else if (!File_Insert()) strcpy( Print_Last->File_Name, File_Path); } else { /* Extract the directory part */ if (((File_Name = strrchr( Name, '/')) == NULL) && ((File_Name = strchr( Name, ':')) == NULL) ) File_Name = Name; else memcpy( File_Path, Name, ++File_Name - Name); File_Path[File_Name - Name] = NUL; /* Initialize the search */ File_Size = File_Parent( File_Path, File_Path, Name_Size, Print_Info); if (File_Size <= 0) { if (File_Size == 0) fprintf( stderr, LOCK, Name); else fprintf( stderr, SIZE, Name, ""); return; } if ((File_Lock = Lock( File_Path, SHARED_LOCK)) == NULL) { fprintf( stderr, LOCK, File_Path); return; } ^L if (!Examine( File_Lock, Print_Info)) fprintf( stderr, LOCK, File_Path); else if (Print_Info->fib_DirEntryType < 0) fprintf( stderr, TYPE, Print_Info->fib_FileName); else { /* Search for the matching files */ while (ExNext( File_Lock, Print_Info)) { if ((Print_Info->fib_DirEntryType < 0) && File_Match( Print_Info->fib_FileName, File_Name) ) { if (File_Size + strlen( Print_Info->fib_FileName) > Name_Size) fprintf( stderr, SIZE, File_Path, Print_Info->fib_FileName); else if (!File_Insert()) { strcpy( Print_Last->File_Name, File_Path); strcpy( &Print_Last->File_Name[File_Size - 1], Print_Info->fib_FileName); } } } } } UnLock( File_Lock); } ^L /************************/ /* Execute the Commands */ /************************/ local void Exec_Action( Exec) /********************************/ char Exec[]; { extern int atoi(); auto int Code; if (isdigit( *Exec)) Print_Copy = atoi( Exec); else switch( Code = Find_Command( Exec)) { /* Take care of the options */ case PS_CPI10 : Options( Line_Density, Line_10); break; case PS_CPI12 : Options( Line_Density, Line_12); break; case PS_CPI17 : Options( Line_Density, Line_17); break; case PS_LPI6 : Options( Page_Density, Page_6); break; case PS_LPI8 : Options( Page_Density, Page_8); break; case PS_NARROW : Options( Line_Formats, Line_8); break; case PS_WIDE : Options( Line_Formats, Line_13); break; case PS_SHORT : Options( Page_Formats, Page_85); break; case PS_LONG : Options( Page_Formats, Page_11); break; case PS_HEADER : Print_Opts ^= Opts_Headers; break; case PS_NUMBER : Print_Opts ^= Opts_Numbers; break; case PS_KEEP : Print_Flag &= ~Flag_Deleted; break; case PS_DELETE : Print_Flag |= Flag_Deleted; break; case PS_DRAFT : Print_Flag &= ~Flag_Quality; break; case PS_LETTER : Print_Flag |= Flag_Quality; break; /* Take care of the actions */ case PS_Insert : case PS_Update : case PS_Remove : if (Print_File != Code) Perform(); Print_File = Code; break; case PS_Report : Perform(); Request_Report(); break; case PS_Return : case PS_Change : case PS_Freeze : case PS_Finish : case PS_Resets : case PS_Cancel : case PS_Resume : Perform(); Request_Action( Code); break; /* Take care of unknown commands */ default : fprintf( stderr, EXEC, Exec); break; } } ^L /*****************************/ /* This is the Print program */ /*****************************/ public void main( argc, argv) /*******************************/ int argc; char *argv[]; { extern struct MsgPort *CreatePort(); extern void *AllocMem(); printf( "Print V1.0 27-Mar-88 ) Frangois Gagnon\n"); /* Allocate Initial Structure */ Print_Port = CreatePort( NULL, 0L); if (Print_Port == NULL) { fprintf( stderr, PORT); exit(1); } Print_Data = AllocMem( (long) sizeof(struct Inform), MEMF_PUBLIC); if (Print_Data == NULL) { fprintf( stderr, DATA); goto Abort1; } Print_Info = AllocMem( (long) sizeof(struct FileInfoBlock), MEMF_PUBLIC); if (Print_Info == NULL) { fprintf( stderr, DATA); goto Abort2; } Default_Values(); /* Analyze the given arguments */ if (argc == 1) Request_Report(); else { while (++argv, --argc) { if ((*argv)[0] == '-') Exec_Action( &(*argv)[1]); else if (Print_File == PS_Remove) Request_Remove( *argv); else File_Search( *argv); } if (Print_List != NULL) Perform(); } /* Deallocate Initial Structure */ Abort3: FreeMem( Print_Info, (long) sizeof(struct FileInfoBlock)); Abort2: FreeMem( Print_Data, (long) sizeof(struct Inform)); Abort1: DeletePort( Print_Port); }