/*************************************************************************/ /* Name: TSPRWPR */ /* */ /* COPYRIGHT 5769-SS1 (C) IBM CORP. 1997, 1997 */ /* */ /* This material contains programming source code for your */ /* consideration. These examples have not been thoroughly */ /* tested under all conditions. IBM, therefore, cannot */ /* guarantee or imply reliability, serviceability, or function */ /* of these program. All programs contained herein are */ /* provided to you "AS IS". */ /* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS */ /* FOR A PARTICULAR PURPOSE ARE EXPRESSLY DISCLAIMED. */ /* IBM provides no program services for these programs and files. */ /* */ /* Type: External Program */ /* Called by: A remote writer, LPR, or SNDTCPSPLF */ /* Purpose: Provide page range support for *SCS and *AFPDS */ /* spooled files. Also an example of how a */ /* writer transform exit program might be written. */   /* This program is written to the Writer Transform Exit program interface as documented in the System API Reference manual. As such the incoming parameters are as follows:   1) Process Option - Binary(4)   10 Initialization: Set any initial information needed. Create needed work space and initialize host print transform.   20 Start File: A spooled file is available to print. Open the spooled file and get its attributes. Check to see if a page range is specified. If so, tell our caller that we will read the spooled file data.   30 Transform: Transform the data. If we are reading the data, find the data from the specified page range. Call the host print transform to transform the data to ASCII. When all pages in the page range have been transformed and sent back, tell the caller that we are done. If we aren't reading the data, just pass it to the host print transform |
and return the transformed data to the caller.   40 End File: Done with spooled file. Tell the host print transform we are done with the file and close the spooled file.   50 Terminate: Writer is ending. End the host print transform and delete the work space.   2) Option specific input information to exit. Information that writer passes to transform exit such as writer name, spooled file, number of pages, etc. Char(*)   3) Length of option specific input information. Binary(4)   4) Spooled file data buffer. The spooled file data to be transformed by the exit. Char(*)   5) Length of the spooled file data buffer. Binary(4).   6) Option specific output information. Area to be used by exit program to pass back information to writer such as return code, whether it can transform file, when it is done transforming, etc. Char(*)   7) Length of option specific output information. Size of area available for exit to send output information back to caller. Binary(4)   8) Length of option specific output information available from transform exit. Size of output information that exit program has to give back. Binary(4)   9) Transformed data buffer. Area to be used by exit to pass transformed data back to caller. Char(*)   10) Length of transformed data buffer. Size of area available for exit to send transformed data back to caller. Binary(4)   11) Length of transformed data available. Size of transformed data that exit program has to give back to caller. Binary(4)   */   /* Creation instructions: |
  See member TSPRWPRI in file QATTINFO, library QUSRTOOL.   */   /* Instructions on how to use:   For LPR or SNDTCPSPLF, specify this program name and library for the User Data Transform parameter on the command.   For Remote writers which have a connection type of *IP, specify this program name and library for the User Data Transform parameter of the CRTOUTQ or CHGOUTQ commands.   */     /* Change Activity: */ /* End Change Activity */   #include <stdio.h> #include <stddef.h> #include <stdlib.h> /* exit(), NULL, EXIT_FAILURE */ #include <string.h> /* memset, memcpy, memcmp */ #include <signal.h> /* signal handler functions and macros */ /* _GetExcData, signal */   #define _Remote_Writer_XFrm_Xt_main #include "qmhchgem.h" /* Change escape message */ #include "qmhsndpm.h" /* Send program message */ #include "quscrtus.h" /* Create user space API. */ #include "qusdltus.h" /* Delete user space API. */ #include "qusptrus.h" /* Get pointer to user space. */ #include "qusrspla.h" /* Retrieve spooled file attr. */ #include "qwpz.h" /* Host Print Transform header */ #include "qwpzhpt1.h" /* Host Print Transform Header */ #include "esptrnxt.h" /* Writer transform exit interface */ #include "qspopnsp.h" /* Open spooled file API */ #include "qspgetsp.h" /* Get spooled file data */ #include "qspclosp.h" /* Close spooled file API. */   /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ /* C MACROs. */ /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ |
/********************************************************************* * MACRO : Send a message from the exit program * * Syntax : Send_Pgm_Msg(char *, void *, char *, int, char *, * char *, void *); * * Parameters : 1) MsgId - charÝ7¨ * Character array containing the character ID * for the function to send. * 2) QualMsgF - void * * Qualified name of the message file. * 3) RplText - char * * Pointer to a character string which will * contain the replacement text for the message. * 4) RplTextLen - int * An integer length of the replacement text for the * message. * 5) MsgType - char * * Character array which will contain the type of * message to send. See MH API manual for more * information. * 6) MsgKey - char * * Character array which will contain the message key * of the message sent. * 7) ErrorStruct - void * * Pointer to the error structure. * * Description : This MACRO is used to send messages to * the job log of the writer. * ********************************************************************/   #define Send_Pgm_Msg(__MsgId, __QualMsgF, __RplText, __RplTextLen,\ __MsgType, __MsgKey, __ErrorStruct)\ QMHSNDPM (__MsgId, __QualMsgF, __RplText, __RplTextLen,\ __MsgType, (void *)PGMBDY, 0, __MsgKey, __ErrorStruct)   /***********************************************************/ /***********************************************************/ /** **/ /** Constants **/ /** **/ /***********************************************************/ /***********************************************************/ |
#define EXPECTEDPARMS 12   /* Process options: */ #define INITIALIZE 10 #define STARTFILE 20 #define TRANSFORM 30 #define ENDFILE 40 #define TERMINATE 50   /* Return code values: */ #define XFrm_SUCCESS 0 #define XFrm_ERR_TERM_IMMEDIATE 1 #define XFrm_ERR_Output_Spec 2 #define XFrm_ERR_Input_Spec 3 #define XFrm_ERR_Input_Bfr 4 #define XFrm_ERR_Output_Bfr 5   #define MaxXFrmBfrSize 4*1024*1024   /* Order of parameters passed into XFrm. */ #define XFrm_Option_Parm 1 #define XFrm_SpecIn_Parm 2 #define XFrm_SpecInLen_Parm 3 #define XFrm_InputDtaStreamBfr_Parm 4 #define XFrm_InputDtaStreamBfrLen_Parm 5 #define XFrm_SpecOut_Parm 6 #define XFrm_SpecOutLen_Parm 7 #define XFrm_SpecOutAvail_Parm 8 #define XFrm_OutputDtaStreamBfr_Parm 9 #define XFrm_OutputDtaStreamBfrLen_Parm 10 #define XFrm_OutputDtaStreamBfrAvail_Parm 11   #define MAX_INT 2147483647   #define MaxAreaForCRCmds 40 /* Maximum area allocated for */ /* Carriage Return commands */ /* returned by XFrm Pgm. */ #define MaxAreaForFFCmds 40 /* Maximum area allocated for */ /* Form Feed commands returned */ /* by XFrm Pgm. */   #define CRTLIB "QTEMP " /* Library to create US */ #define SPACESIZE 10   |
#define IMMED 1 #define FILEEND 8   /* Special Values for Splf Attr Start Page */ #define PRT_WHOLE_FILE 1 #define PRT_START_PG_1 0 #define USE_ENDPAGE_VAL -1   /* Special Values for Splf Attr End Page */ #define LAST_PAGE 0   /* Special Values for Splf Attr Restart Page */ #define USE_STRPAGE_VAL -1 #define USE_ENDPAGE -2 #define NEXTPAGE -3 #define NO_RESTART 0   /* Values to check to see how driver is ending. */ #define TERMINATE_CNTRLD 1 #define TERMINATE_IMMED 2 #define TERMINATE_ABNRL 3   /* Value of SPhandle when the spooled file has not been opened yet. */   #define SPLF_NOT_OPEN -1   /* Defines for transform exit termination type. */ #define NORMAL 1 #define IMMEDIATE 2 #define PAGEEND 3   /* Defines for Transform exit transform file. */ #define CANNOT_TRANSFORM '0' #define WILL_TRANSFORM '1' #define IN_FINAL_FORM '2'   #define PASS_SPLF_DATA '0' #define DONT_PASS_SPLF_DATA '1' #define DONT_SEND_SINGLE_COPY '0' #define WRITER_DECIDES '0' #define XFRM_DONE_WITH_FILE '1'   #define CALLER_PASSING_SPLF_DATA '0' |
#define CALLER_WANTS_ALIGN_DATA '1'   #define EMPTY_BUFFER -1   #define NEXT_BUFFER -1   #define FALSE 0 #define TRUE 1   /* Spooled file number special values. */ #define LAST -1 #define ONLY 0   /* Defines used to scan the SCS data stream for commands */ #define COMMAND_2B '\x2B' #define COMMAND_28 '\x28' #define COMMAND_03 '\x03' #define COMMAND_35 '\x35' #define COMMAND_34 '\x34' #define FORMFEED '\x0C' #define RQDFORMFEED '\x3A'   #define NON_NATIVE_AFP 0 #define NATIVE_AFP 1   /* Defines used to scan the AFP data stream for commands. */ #define ENDPAGE "\xD3\xA9\xAF"   static const char SCS??(??) = {"*SCS "}; static const char AFPDS??(??) = {"*AFPDS "}; static const char USERASCII??(??) = {"*USERASCII"}; static const char sIMMED??(??) = {"*IMMED "}; static const char NONE??(??) = {"*NONE "};   static const char SpoolSpace??(??) = {"XFRMGETSPLQTEMP "}; static const char XFrmXt_Work_Space??(??) = {"XFRMXT_SPAQTEMP "};   static const char INTJOBIDUSED??(??) = {"*INT "}; static const char INTSPLIDUSED??(??) = {"*INT "}; static const char EOFActWAIT??(??) = {"*WAIT "};   static const char SPFR0300??(??) = {"SPFR0300"}; static const char SPLA0200??(??) = {"SPLA0200"};   |
static const char SCSDtaStream??(??) = {"*SCS "}; static const char NoPrtDevice??(??) = {"*NONE "}; /**/   static const char QualQCPFMSGF??(??) = {"QCPFMSG QSYS "};   static char NO_MSG_KEY??(??) = {" "};   static const char MsgTypeESCP??(??) = {"*ESCAPE "}; static const char MsgTypeDIAG??(??) = {"*DIAG "}; static const char MsgTypeINFO??(??) = {"*INFO "}; static const char MsgTypeINQ??(??) = {"*INQ "}; static const char MsgTypeCOMP??(??) = {"*COMP "}; static const char MsgTypeNOTIFY??(??) = {"*NOTIFY "}; static const char MsgTypeREQUEST??(??) = {"*RQS "}; static const char MsgTypeSTATUS??(??) = {"*STATUS "};   static const char CPF9898??(7??) = {"CPF9898"};   /* Special constants for QMHSNDPM API in Send_Message().*/ static const char PGMBDY??(??) = {"*PGMBDY "};   /***********************************************************/ /***********************************************************/ /** **/ /** Structures **/ /** **/ /***********************************************************/ /***********************************************************/ /*-------------------------------------------------------------------- * AS/400 library qualified object name, this is used as the declare * to format the library/object format needed in APIs. *-------------------------------------------------------------------*/ typedef _Packed struct { char Object??(10??); char Library??(10??); } QNAME; /*-------------------------------------------------------------------- * AS/400 qualified job name structure, used to identify the * spooled file. *-------------------------------------------------------------------*/ typedef _Packed struct { char JOBNAME??(10??); char USRNAME??(10??); |
char JOBNUM??(6??); } QJOBNAM; /* Define the qualified job name structure */ /*-------------------------------------------------------------------- * Common structure used to return information from an API to the * calling program. *-------------------------------------------------------------------*/ typedef _Packed struct { int BytesPro; int BytesAvl; char ExcpID??(7??); char pad; char ExcpData??(512??); } ERRSTRUCTURE; /* Define the error return structure */ /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ | The following is a picture of what the XFrmXt Work user space | | contains: | |=====================================================================| | Ptr_SplfDtaUS Qsp_SPFRH_t * (16 bytes) | |---------------------------------------------------------------------| | Pointer to XFrm_SpecIn | | Pointer to XFrm_SpecOut | | Pointer to XFrm_ProcessOption | | Pointer to XFrm_SpecIn_Len | | Pointer to XFrm_Inp_Dta_Len | | Pointer to XFrm_SpecOut_Len | | Pointer to XFrm_SpecOut_Avail | | Pointer to XFrm_Out_Dta_Len | | Pointer to XFrm_Out_Dta_Avail | | Pointer to XFrm_Out_Dta | | Pointer to XFrm_In_Dta | |---------------------------------------------------------------------| | SplfAttr_t | | Char(sizeof(Qsp_SPLA0200_t) + 56) | |---------------------------------------------------------------------| | XFrm_Opt_SpecIn_t | | Char(sizeof(Qwpz_Hpt_Opt_SpecIn_t)) | |---------------------------------------------------------------------| | XFrm_Opt_SpecOut_t | | Char(sizeof(Qwpz_Hpt_Opt_SpecOut_t)) | | + MaxAreaForCRCmds + | | + MaxAreaForFFCmds | |---------------------------------------------------------------------| | Process_Option char(1) | | Length_of_SpecIn int | |
| Length_of_SplfDta_Bfr int | | Length_of_SpecOut int | | Length_of_SpecOut_Avail int | | Length_of_Xfrm_Dta_Bfr int | | Length_of_Xfrm_Dta_Avail int | |---------------------------------------------------------------------| | Writer_MsgQ char(20) - Name of the message queue for the writer. | |---------------------------------------------------------------------| | PreviousJob Char(26) - The JobName/User/JobNbr of the last job | | printed. | | JobName Char(10) | | User Char(10) | | JobNbr Char(6) | |---------------------------------------------------------------------| | Pass_Input_Data char | |---------------------------------------------------------------------| | Return_Alignment_Data short int | |---------------------------------------------------------------------| | EndOfSplf short int | |---------------------------------------------------------------------| | EndPage int | |---------------------------------------------------------------------| | StartPage int | |---------------------------------------------------------------------| | SPhandle int - Handle of spooled file that is currently open. | |---------------------------------------------------------------------| | Last_XFrm_Call_Opt int | |---------------------------------------------------------------------| | Off_Xfrm_Out_Bfr int | |---------------------------------------------------------------------| | Len_Xfrm_Out_Bfr int | |---------------------------------------------------------------------| | Xfrm_Output_Dta_Bfr char(*) | |---------------------------------------------------------------------| | Off_XFrm_Data_Left int | +====================================================================*/   typedef _Packed struct XFrmXt_Space_Fmt { Qsp_SPFRH_t *Ptr_SplfDtaUS; /* Pointer to the user space used to retrieve the spooled file data (via QSPGETSP API). */ Esp_Transform_Exit_I_t *XFrm_SpecIn; Esp_Transform_Exit_O_t *XFrm_SpecOut; int *XFrm_ProcessOption; |
int *XFrm_SpecIn_Len, *XFrm_Inp_Dta_Len, *XFrm_SpecOut_Len, *XFrm_SpecOut_Avail, *XFrm_Out_Dta_Len, *XFrm_Out_Dta_Avail; char *XFrm_Out_Dta; /* Pointer to transform output */ /* buffer. */ char *XFrm_In_Dta; /* Pointer to transform input */ /* buffer. */ Qus_SPLA0200_t SplFAInfo; /* Spooled file's attributes. */ char Reserved??(56??); /* Reserved area for user defined options for spooled file. */ char XFrm_Opt_SpecIn??(sizeof(Qwpz_HPT_Opt_SpecIn_t)??); char XFrm_Opt_SpecOut??(sizeof(Qwpz_HPT_Opt_SpecOut_t) + MaxAreaForCRCmds + MaxAreaForFFCmds??); int Process_Option; int Length_of_SpecIn; int Length_of_SplfDta_Bfr; int Length_of_SpecOut; int Length_of_SpecOut_Avail; int Length_of_XFrm_Dta_Bfr; int Length_of_XFrm_Dta_Avail; char Writer_MsgQ??(20??); /* The Writer's message queue. */ QJOBNAM Previous_Job; /* Qual Job of previous splf */ char Pass_Input_Data; short int Return_Alignment_Data; int EndOfSplf; /* End of spool file indicator */ int EndPage; /* Last page of the file to print. Special values for EndPage can be: LAST_PAGE - Print to the end of the file. NOTE: When set to LAST_PAGE, this can/is used to signal that we are NOT looking for an Ending page of a page range.*/ int StartPage; /* Starting page of file to print. Special values for StartPage can be: MAX_INT - Start on last page. |
PRT_WHOLE_FILE - Print whole file. NOTE: When set to PRT_WHOLE_FILE, this can/is used to signal that we are NOT processing a page range. */ int SPhandle; /* Handle of open spooled file. */ int StartFile; /* */ int ReadAgaininLoop; /* Set to true, if we need to */ /* read more data from spooled */ /* file and pass on to HPT. */ int Last_XFrm_Call_Opt; /* Last successful call to the */ /* transform program. */ int Off_XFrm_Out_Bfr; /* Offset from the beginning of */ /* the space where the */ /* transformed data output from */ /* the transform program is */ /* located. */ int Len_XFrm_Out_Bfr; /* Number of bytes of the */ /* user space that was allocated */ /* to contain the transformed */ /* output from the transform */ /* program. */ int Off_XFrm_Data_Left; int Nbr_Bytes_Left; } XFrmXt_Space_Fmt_t;   typedef _Packed struct { char Leading_Character; char Cmd_Len_03_35; char Cmd_Len_2B; } SCS_COMMAND;   typedef _Packed struct { short Afp_Length; char Afp_Cmd??(3??); } AFP_COMMAND;   typedef _Packed struct { int Original_Len; int Trim_Len; } AFP_Rcd_t;   |
typedef _Packed struct { int JOBIPL; int JOBOFF; char JOBTOD??(8??); } JOBID; /* Define the internal identifier structure */   typedef _Packed struct { int SPLFIPL; int SPLFOFF; char SPLFTOD??(8??); } SPLFID; /* Define internal spooled file identifier structure */   /***********************************************************/ /***********************************************************/ /** **/ /** Variables **/ /** **/ /***********************************************************/ /***********************************************************/     /***********************************************************/ /***********************************************************/ /** **/ /** ProtoTypes **/ /** **/ /***********************************************************/ /***********************************************************/ int Initialize_XFrm_Xt(XFrmXt_Space_Fmt_t *);   int Start_File(XFrmXt_Space_Fmt_t *);   int Transform(XFrmXt_Space_Fmt_t *, char *, int, char *, int, int *);   int End_File(XFrmXt_Space_Fmt_t *);   int Terminate_XFrmXt(XFrmXt_Space_Fmt_t *);   int Set_Parms(char *argv??(??), int *, |
Esp_Transform_Exit_I_t **, int *, char **, int *, Esp_Transform_Exit_O_t **, int *, int **, char **, int *, int **);   int Call_XFrmPgm(int, XFrmXt_Space_Fmt_t *); void CleanUp_XFrmXt(XFrmXt_Space_Fmt_t *); void Close_Spooled_File(int); int Create_User_Space(QNAME, long int); void DeleteUserSpace(QNAME); void Dump_Info_to_Splf(void); int Find_End_Page(int, Qsp_SPFRH_t *, Qus_SPLA0200_t *); int Find_Page_End(int, char *, int, Qus_SPLA0200_t *); int Find_Start_Page(int, int, QNAME, Qsp_SPFRH_t *, Qus_SPLA0200_t *); void Get_Page_Range(int *, int *, Qus_SPLA0200_t *); int Get_Spool_Data(int, QNAME, Qsp_SPFRH_t *, int, int *); char * Get_User_Space_Pointer(QNAME); int Open_Spooled_File(int *, JOBID *, SPLFID *, int); int Retrieve_Splf_Attr(Qus_SPLA0200_t *, QJOBNAM *, char *, int, JOBID *, SPLFID *); void signal_handler(int); static void XFrm_Xt_Hndlr(_INTRPT_Hndlr_Parms_T *);   /****************************************************************/ /****************************************************************/ /** Main Procedures **/ /****************************************************************/ /****************************************************************/   int Set_Parms(char *ParmValݨ, int *Option, Esp_Transform_Exit_I_t **InputSpecInfo, int *InputSpecInfoLen, char **InputDtaStreamBfr, int *InputDtaStreamBfrLen, Esp_Transform_Exit_O_t **OutputSpecInfo, int *OutputSpecLen, |
int **OutputSpecAvail, char **OutputDtaStreamBfr, int *OutputDtaStreamBfrLen, int **OutputDtaStreamBfrAvail) /********************************************************************* * Function : Set parameter values * * Syntax : Set_Parms(char *ParmValݨ, int *, * Esp_Tranform_Exit_I_t **, * int *, * char **, * int *, * Esp_Transform_Exit_O_t **, * int *, * int **, * char **, * int *, * int **) * * Parameters : 1) char ** - ParmVal * This is a character pointer to the parameter * values which are passed on the call to the * program. * * 2) int * - Option * Integer pointer to the one byte transform * option, (see prologue for more details). * * 3) Esp_Transform_Exit_I_t ** - InputSpecInfo * Pointer to Transform exit input specific information. * * 4) int * - InputSpecInfoLen * Integer pointer to the number of bytes passed to XFrmX * program to store the input specific information. * * 5) char ** - InputDtaStreamBfr * Character pointer to the spooled file data buffer. * * 6) int * - InputDtaStreamBfrLen * Integer pointer to the length of the spooled file data * buffer. * * 7) Esp_Transform_Exit_O_t ** - OutputSpecInfo * Pointer to Transform exit output specific information. |
* * 8) int * - OutputSpecLen * Integer pointer to the number of bytes passed to XFrmX * program to store the output specific information. * * 9) int ** - OutputSpecAvail * Integer pointer to the number of bytes transform exit * program used in the output specific information passed * * 10) char ** - OutputDtaStreamBfr * Character pointer to the transform data buffer provide * by the caller to hold the transformed data stream. * * 11) int * - OutputDtaStreamBfrLen * Integer pointer to the length of the transform data * buffer. * * 12) int ** - OutputDtaStreamBfrAvail * Integer pointer to the number of bytes of the transfor * data buffer used to return the transformed data. * * Description : Set_Parms is used to set mainline variables * from the parameters which are passed from the * calling program. * * Errors : * * Return value : 0 - No bad input parameters. * 1 - A bad input parameter was passed in. *********************************************************************/ { int RtnCde = 0;   /* Set the option for the driver */ *Option = *(int *)ParmVal??(XFrm_Option_Parm??);   /* Set the pointer to the input specific information */ *InputSpecInfo = (Esp_Transform_Exit_I_t *)ParmVal??(XFrm_SpecIn_Parm??);   *InputSpecInfoLen = *(int *)ParmVal??(XFrm_SpecInLen_Parm??);   *InputDtaStreamBfr = (char *)ParmVal??(XFrm_InputDtaStreamBfr_Parm??);   |
*InputDtaStreamBfrLen = *(int *)ParmVal??(XFrm_InputDtaStreamBfrLen_Parm??);   /* Set the pointer to the output specific information */ *OutputSpecInfo = (Esp_Transform_Exit_O_t *)ParmVal??(XFrm_SpecOut_Parm??);   *OutputSpecLen = *(int *)ParmVal??(XFrm_SpecOutLen_Parm??); *OutputSpecAvail = (int *)ParmVal??(XFrm_SpecOutAvail_Parm??); *OutputDtaStreamBfr = (char *)ParmVal??(XFrm_OutputDtaStreamBfr_Parm??); *OutputDtaStreamBfrLen = *(int *)ParmVal??(XFrm_OutputDtaStreamBfrLen_Parm??); *OutputDtaStreamBfrAvail = (int *)ParmVal??(XFrm_OutputDtaStreamBfrAvail_Parm??);   /* Validate input parameters */   if (*InputSpecInfo == NULL) { RtnCde = XFrm_ERR_Input_Spec; }/* End if input specific information not provided. */   if (*InputSpecInfoLen < 76) { RtnCde = XFrm_ERR_Input_Spec; }/* Not enough input specific information provided. */   if (*OutputSpecInfo == NULL) { RtnCde = XFrm_ERR_Output_Spec; }/* End if output specific information area not provided. */   if ((OutputSpecLen == NULL) || (*OutputSpecLen < 4)) { RtnCde = XFrm_ERR_Output_Spec; }/* No space provided for output specific information. */   if (OutputSpecAvail == NULL) { RtnCde = XFrm_ERR_Output_Spec; }/* No way to communicate the amount of output specific information provided. */   |
if (!(RtnCde)) { switch(*Option) { case(INITIALIZE): break; case(STARTFILE): if (*InputSpecInfoLen < 243) { RtnCde = XFrm_ERR_Input_Spec; }/* Not enough input specific information provided. */ if (*OutputSpecLen < 8) { RtnCde = XFrm_ERR_Output_Spec; }/* Not enough space provided for output specific information. */ if (*OutputDtaStreamBfr == NULL) { RtnCde = XFrm_ERR_Output_Spec; }/* No buffer to place open time commands. */ if ((OutputDtaStreamBfrLen == NULL) || (OutputDtaStreamBfrLen == 0)) { RtnCde = XFrm_ERR_Output_Bfr; }/* Output buffer length not specified, or too small. */ if (OutputDtaStreamBfrAvail == NULL) { RtnCde = XFrm_ERR_Output_Bfr; }/* No receiver variable for output buffer bytes available. */ break; case(TRANSFORM): if (*InputSpecInfoLen < 208) { RtnCde = XFrm_ERR_Input_Spec; }/* Not enough input specific information provided. */ if (*OutputSpecLen < 44) { RtnCde = XFrm_ERR_Output_Spec; }/* Not enough space provided for output specific information. */ if (*OutputDtaStreamBfr == NULL) { RtnCde = XFrm_ERR_Output_Bfr; |
}/* No buffer to place transformed data stream. */ if ((OutputDtaStreamBfrLen == NULL) || (OutputDtaStreamBfrLen == 0)) { RtnCde = XFrm_ERR_Output_Bfr; }/* Output buffer length not specified, or too small. */ if (OutputDtaStreamBfrAvail == NULL) { RtnCde = XFrm_ERR_Output_Bfr; }/* No receiver variable for output buffer bytes available. */ break; case(ENDFILE): if (*InputSpecInfoLen < 198) { RtnCde = XFrm_ERR_Input_Spec; }/* Not enough input specific information provided. */ if (*OutputDtaStreamBfr == NULL) { RtnCde = XFrm_ERR_Output_Bfr; }/* No buffer to place reset command(s). */ if ((OutputDtaStreamBfrLen == NULL) || (OutputDtaStreamBfrLen == 0 )) { RtnCde = XFrm_ERR_Output_Bfr; }/* Output buffer length not specified, or too small. */ if (OutputDtaStreamBfrAvail == NULL) { RtnCde = XFrm_ERR_Output_Bfr; }/* No receiver variable for output buffer bytes available. */ break; case(TERMINATE): if (*InputSpecInfoLen < 188) { RtnCde = XFrm_ERR_Input_Spec; }/* Not enough input specific information provided. */ break; default: break; }/* End of switch(*Option)*/ }/* End if RtnCde not 0.*/ return(RtnCde); } /* END -- Set_Parms */ |
  int Initialize_XFrm_Xt(XFrmXt_Space_Fmt_t *XFrmXtInfo) /********************************************************************* * Function : Initialize Transform Exit -- Option 10 * * Syntax : int Initialize_XFrm_Xt(XFrmXt_Space_Fmt_t *); * * Description : Initialize_XFrm_Xt initialize the host print * transform. * * Return value : *********************************************************************/ { int RtnCde = 0; /* Return code from call to XFrm. */ ERRSTRUCTURE ErrorStructure; char MsgKey??(4??);   /*------------------------------------------------------------ * Initialize local error structure for call to send program * message to the writer's joblog. *-----------------------------------------------------------*/ ErrorStructure.BytesPro = 0; /*--------------------------------------------------------------- * Copy the writer's message queue into the XFrmXt Work space. *--------------------------------------------------------------*/ memcpy(XFrmXtInfo->Writer_MsgQ, XFrmXtInfo->XFrm_SpecIn->Writer_Msgq_Name, sizeof(QNAME));   /*------------------------------------------------------------ * Initialize the spooled file handle to a special value, so * we won't try to close a spooled file that was never opened. *-----------------------------------------------------------*/ XFrmXtInfo->SPhandle = SPLF_NOT_OPEN;   /*------------------------------------------------------------- * Allocate space to hold the transformed data returned from * the Host print transform program. * NOTE: This is only done when transforming spooled files, * and must be taken in account when * calculating the offsets of the other * buffers/areas carved out of the user space. *------------------------------------------------------------*/   |
XFrmXtInfo->Off_XFrm_Out_Bfr = ((sizeof(XFrmXt_Space_Fmt_t) + 15)/16)*16;   XFrmXtInfo->Len_XFrm_Out_Bfr = MaxXFrmBfrSize;     /*---------------------------------------------------------------- * Initialize the transform. Note that pointer temp * is not needed to point to anything legitimate for the initialize * stage but simply needs to point to something. *----------------------------------------------------------------*/ RtnCde = Call_XFrmPgm(INITIALIZE, XFrmXtInfo); return(RtnCde);   } /* END -- Initialize_XFrm_Xt */   int Start_File(XFrmXt_Space_Fmt_t * XFrmXtInfo) /********************************************************************* * Function : Start file -- Option 20 * * Syntax : int Start_File(XFrmXt_Space_Fmt_t *); * * Description : Start_File will retrieve the spooled file * information and the spooled file data. The data * will then be transformed, if necessary. * * Return value : *********************************************************************/ { int ReadBuffers; /* The Read Buffer will indicate how many buffers to read from the spooled file. We will read 1 buffer for page range manipulation */ int Get_Buffer; /* Which buffer to get for the file */ QNAME GetSplfSpace; /* Qualified name of User Space used to retrieve spooled file data using API QSPGETSP. */ int RtnCde = 0; char TmpBfr??(40??); ERRSTRUCTURE ErrorStructure; char MsgKey??(4??);   /*------------------------------------------------------------ |
* Initialize local error structure for call to send program * message to the writer's joblog. *-----------------------------------------------------------*/ ErrorStructure.BytesPro = 0;   /*----------------------------------------------------------------- * Initialize name structure for the user space used to store the * spooled file data. *----------------------------------------------------------------*/ memcpy(GetSplfSpace.Object,SpoolSpace, sizeof(GetSplfSpace));   XFrmXtInfo->SPhandle = SPLF_NOT_OPEN;   /*------------------------------------------------------------------- * Call QUSRSPLA API to get information about the spooled file. * Also at this time, the attributes of the file will be checked * to make sure that we can print the file. The start and end * page will also be returned from the function. This information * is needed at this time since it will determine how the file * will be opened (the number of buffers to get). *-------------------------------------------------------------------*/ RtnCde = Retrieve_Splf_Attr(&XFrmXtInfo->SplFAInfo, (void *)XFrmXtInfo-> XFrm_SpecIn->Qualified_Job_Name, (void *)XFrmXtInfo-> XFrm_SpecIn->Spooled_File_Name, (int)XFrmXtInfo-> XFrm_SpecIn->Spooled_File_Number, (void *)XFrmXtInfo-> XFrm_SpecIn->Internal_Job_Id, (void *)XFrmXtInfo-> XFrm_SpecIn->Internal_Spool_Id);   if (RtnCde) /* Has a fatal error occurred? */   { XFrmXtInfo->XFrm_SpecOut->Transform_File = CANNOT_TRANSFORM; *XFrmXtInfo->XFrm_Out_Dta_Avail = 0; return(XFrm_SUCCESS); /* Can't transform */ } /* Bad return code from Retrieve_Splf_Attr. */   /*------------------------------------------------------------- * Call the transform with the STARTFILE option in order to get |
* the open time commands in ASCII for the spool file. *-------------------------------------------------------------*/ RtnCde = Call_XFrmPgm(STARTFILE, XFrmXtInfo); if (RtnCde) { CleanUp_XFrmXt(XFrmXtInfo); return(RtnCde); }/*---------------------------------------------- * Error trying to open the transform to process * the current spooled file. *---------------------------------------------*/ /*---------------------------------------------------------- * Check to see if the HPT can transform the * spooled file. *---------------------------------------------------------*/ if (XFrmXtInfo->XFrm_SpecOut->Transform_File == CANNOT_TRANSFORM) { CleanUp_XFrmXt(XFrmXtInfo); return(XFrm_SUCCESS); }/*------------------------------------------------------- * HPT cannot transform the current file. *------------------------------------------------------*/   /*--------------------------------------------------------------- * Check to see if the spooled file we are about to print (send) * has a page range specified, or a restart page specified. *--------------------------------------------------------------*/ Get_Page_Range(&XFrmXtInfo->StartPage, &XFrmXtInfo->EndPage, &XFrmXtInfo->SplFAInfo);   /*------------------------------------------------------------------ * Are we going to print a range of pages? *-----------------------------------------------------------------*/ if (XFrmXtInfo->StartPage != PRT_WHOLE_FILE) { /*-------------------------------------------------------------- * Set up to only read 1 buffer at a time. *-------------------------------------------------------------*/ ReadBuffers = 1;   RtnCde = Open_Spooled_File(&XFrmXtInfo->SPhandle, |
(void *)&XFrmXtInfo-> XFrm_SpecIn->Internal_Job_Id, (void *)&XFrmXtInfo-> XFrm_SpecIn->Internal_Spool_Id, ReadBuffers); /*----------------------------------------------------------- * If an error occurred, cleanup/hold spooled file/continue *----------------------------------------------------------*/ if (RtnCde) { CleanUp_XFrmXt(XFrmXtInfo); XFrmXtInfo->XFrm_SpecOut->Transform_File = CANNOT_TRANSFORM; *XFrmXtInfo->XFrm_Out_Dta_Avail = 0; return(XFrm_SUCCESS); } /* Fatal Error Occurred on Open_Spooled_File. */   if (XFrmXtInfo->Ptr_SplfDtaUS == NULL) { /*-------------------------------------------------------- * Set up spooled file data user space for the get spooled * file API. This user space will hold the data retrieved * from the spooled file. *------------------------------------------------------*/ Create_User_Space(GetSplfSpace, SPACESIZE); XFrmXtInfo->Ptr_SplfDtaUS = (Qsp_SPFRH_t *)Get_User_Space_Pointer(GetSplfSpace); } /* End if User space has not been created yet for QSPGETSP. */   /* * Update output specific information to tell caller: * 1) The transform exit will read the data from the splf. * 2) The transform exit will NOT deal with multiple copies. * 3) The transform exit will let the writer decide when * open time commands are sent to the printer device. *------------------------------------------------------------*/ XFrmXtInfo-> XFrm_SpecOut->Pass_Input_Data = DONT_PASS_SPLF_DATA; XFrmXtInfo-> XFrm_SpecOut->Send_Single_Copy = DONT_SEND_SINGLE_COPY; XFrmXtInfo-> XFrm_SpecOut->Send_Open_Time_Cmds = WRITER_DECIDES;   XFrmXtInfo->Off_XFrm_Data_Left = EMPTY_BUFFER; XFrmXtInfo->Nbr_Bytes_Left = 0; |
XFrmXtInfo->Pass_Input_Data = DONT_PASS_SPLF_DATA; XFrmXtInfo->EndOfSplf = FALSE; XFrmXtInfo->StartFile = TRUE;   }/* End if Page range is being processed. */ else { XFrmXtInfo->Pass_Input_Data = PASS_SPLF_DATA; }/* Transform will not be reading spooled file data. */   return(XFrm_SUCCESS); } /* END -- Start_File */   int Transform(XFrmXt_Space_Fmt_t *XFrmXtInfo, char *InputDataStreamBfr, int InputDataStreamBfrLen, char *OutputDataStreamBfr, int OutputDataStreamBfrLen, int *OutputDataStreamBfrAvail) /********************************************************************* * Function : Transform file from SCS or AFPDS to ASCII * * Syntax : int Transform(XFrmXt_Space_Fmt_t *XFrmXtInfo, * char *, * int, * char *, * int, * int *); * * Description : Transform the SCS or AFPDS spooled file data * into ASCII data using host print transform. * * Return value : *********************************************************************/ { QNAME GetSplfSpace; /* Qualified name of User Space used to retrieve spooled file data using API QSPGETSP. */ int len; /* Length of spool file data */ char *Send_Pointer; /* Pointer to the spool file data */ int Get_Buffer; /* Which buffer to get for the file */ char *temp; /* Generic temporary pointer */ int count; /* Generic counter variable */ int RtnCde = 0; |
char TmpBfr??(40??); ERRSTRUCTURE ErrorStructure; char MsgKey??(4??);   *OutputDataStreamBfrAvail = 0;   /*----------------------------------------------------------------- * Initialize name structure for the user space used to store the * spooled file data. *----------------------------------------------------------------*/ memcpy(GetSplfSpace.Object,SpoolSpace, sizeof(GetSplfSpace));   /* * If XFrmXt is reading the spooled file, read the spooled file * data and pass to HPT. *---------------------------------------------------------------*/ if (XFrmXtInfo->Pass_Input_Data == DONT_PASS_SPLF_DATA) { /* * Is there data from transform buffer that would not fit into * caller's output transform buffer? Only if XFrmXt reading * spooled file. *-------------------------------------------------------------*/ if (XFrmXtInfo->Off_XFrm_Data_Left == EMPTY_BUFFER) { if (XFrmXtInfo->StartFile == TRUE) { /*---------------------------------------------------------- * Find the starting page in the spooled file's data stream. * Find_Start_Page will modify the header information in the * user space for the spooled file data (pointed to by * Ptr_SplfDtaUS) such that the first buffer offset is * pointing to the starting page position in the buffer, and * the number of bytes to process has been updated to not * include the amount of data before the starting page. *---------------------------------------------------------*/ RtnCde = Find_Start_Page(XFrmXtInfo->StartPage, XFrmXtInfo->SPhandle, GetSplfSpace, XFrmXtInfo->Ptr_SplfDtaUS, &XFrmXtInfo->SplFAInfo); if (RtnCde) { CleanUp_XFrmXt(XFrmXtInfo); |
XFrmXtInfo->XFrm_SpecOut->Transform_File = CANNOT_TRANSFORM; *OutputDataStreamBfrAvail = 0; return(XFrm_SUCCESS); }/*--------------------------------------- * Error trying to find the starting page * of the spooled file. *--------------------------------------*/   XFrmXtInfo->StartFile = FALSE;   XFrmXtInfo->ReadAgaininLoop = FALSE;   }/* End -- if start of spooled file. */   /*--------------------------------------------------------- * Set pointer in XFrmXt Work space for the output data * buffer to the output buffer in the Work space. *---------------------------------------------------------*/ XFrmXtInfo->XFrm_Out_Dta = ((char *)XFrmXtInfo + XFrmXtInfo->Off_XFrm_Out_Bfr); XFrmXtInfo->XFrm_Out_Dta_Len = &XFrmXtInfo->Length_of_XFrm_Dta_Bfr; XFrmXtInfo->Length_of_XFrm_Dta_Bfr = XFrmXtInfo->Len_XFrm_Out_Bfr;   /*--------------------------------------------------------- * While there is no XFrm'd data from HPT. *---------------------------------------------------------*/ while (*OutputDataStreamBfrAvail == 0) { /* we need to conditionally get spooled file data so we can get out of the loop either by getting data back from HPT OR we hit end of the spooled file (or page range). */ if (XFrmXtInfo->ReadAgaininLoop) { /*------------------------------------------------------ * Call QSPGETSP API to get more data from the spool * file and put into a user space. *-----------------------------------------------------*/ RtnCde = Get_Spool_Data(XFrmXtInfo->SPhandle, GetSplfSpace, XFrmXtInfo->Ptr_SplfDtaUS, |
NEXT_BUFFER, &XFrmXtInfo->EndOfSplf); if (RtnCde) { CleanUp_XFrmXt(XFrmXtInfo); return(RtnCde); }/*------------------------------------- * Error trying to get the spooled file * data. *------------------------------------*/ }/* End if we need to read more data from spooled file.*/ /*------------------------------------------------------ * Add check here in case we got no end of file when * we went to read more data. This happens because * the routine Get_Spool_Data doesn't know its gotten * the last buffer until it tries to get another one * and it can't. We don't want to call HPT if there * is no data to transform. *-----------------------------------------------------*/ if (XFrmXtInfo->EndOfSplf == TRUE) break; /*------------------------------------------------------ * Check if there is a page range specified, and that the * current spool buffer of data contains the end page of * the page range, ONLY if the driver is reading the * spooled file data. *------------------------------------------------------*/ if (XFrmXtInfo->EndPage) { /*--------------------------------------------------- * Find the location of the ending page, adjust the * length of the spool buffer to the data location *--------------------------------------------------*/ XFrmXtInfo->EndOfSplf = Find_End_Page(XFrmXtInfo->EndPage + 1, XFrmXtInfo->Ptr_SplfDtaUS, &XFrmXtInfo->SplFAInfo); }/*------------------------------------ * End if A page range was specified. *-----------------------------------*/ XFrmXtInfo->XFrm_In_Dta = ((char *)XFrmXtInfo->Ptr_SplfDtaUS + XFrmXtInfo->Ptr_SplfDtaUS->Offset_First_Buffer);   RtnCde = Call_XFrmPgm(TRANSFORM, |
XFrmXtInfo); if (RtnCde) { CleanUp_XFrmXt(XFrmXtInfo); return(RtnCde); }/*------------------------------------- * Error trying to transform the spooled * file data. *------------------------------------*/   /*------------------------------------------------------ * If pagerange was specified, it is possible that all * the pages have been processed for the spooled file, * this is indicated by the EndOfSplf flag being set on * by the Find_End_Page function. *-----------------------------------------------------*/ XFrmXtInfo->ReadAgaininLoop = TRUE;   } /* End -- while(No XFrm'd data returned by HPT) */   XFrmXtInfo->Off_XFrm_Data_Left = XFrmXtInfo->Off_XFrm_Out_Bfr; XFrmXtInfo->Nbr_Bytes_Left = *OutputDataStreamBfrAvail;   }/* End --If no data left over in XFrmXt output buffer. */   /* * Transfer transformed data from XFrmXt output buffer to * the caller's output buffer. Only if XFrmXt reading * spooled file. *--------------------------------------------------------*/ if (OutputDataStreamBfrLen < XFrmXtInfo->Nbr_Bytes_Left) { memcpy(OutputDataStreamBfr, (char *)XFrmXtInfo->XFrm_Out_Dta, OutputDataStreamBfrLen); XFrmXtInfo->Nbr_Bytes_Left -= OutputDataStreamBfrLen; XFrmXtInfo->Off_XFrm_Data_Left += OutputDataStreamBfrLen; /* * Since we are done "using" the output buffer available * bytes parameter passed in by the caller, set it to * the amount of data we were able to send back to the * caller. *-----------------------------------------------------*/ |
*OutputDataStreamBfrAvail = OutputDataStreamBfrLen; }/* End if output buffer is smaller than internal bfr.*/ else { memcpy(OutputDataStreamBfr, (char *)XFrmXtInfo->XFrm_Out_Dta, *OutputDataStreamBfrAvail); XFrmXtInfo->Nbr_Bytes_Left = 0; XFrmXtInfo->Off_XFrm_Data_Left = EMPTY_BUFFER; }/* End else output bfr large enough to hold all XFrm'd data.*/   /*------------------------------------------------------------ * Check to see, if we are transforming, if the transform is * done transforming the file. *-----------------------------------------------------------*/ if ((XFrmXtInfo->Nbr_Bytes_Left == 0) && (XFrmXtInfo->EndOfSplf == TRUE)) { XFrmXtInfo->XFrm_SpecOut->Done_Transforming_File = XFRM_DONE_WITH_FILE; }/* End--if no more data left to transform. */   }/* End --If XFrmXt reading spooled file data. */ else { /* * Set up user space pointers to input and output data buffers. *-------------------------------------------------------------*/ XFrmXtInfo->Length_of_SplfDta_Bfr = InputDataStreamBfrLen;   XFrmXtInfo->XFrm_In_Dta = InputDataStreamBfr; XFrmXtInfo->XFrm_Inp_Dta_Len = &XFrmXtInfo->Length_of_SplfDta_Bfr; XFrmXtInfo->XFrm_Out_Dta = OutputDataStreamBfr; XFrmXtInfo->XFrm_Out_Dta_Len = &OutputDataStreamBfrLen; XFrmXtInfo->XFrm_Out_Dta_Avail = OutputDataStreamBfrAvail;   RtnCde = Call_XFrmPgm(TRANSFORM, XFrmXtInfo); if (RtnCde) { CleanUp_XFrmXt(XFrmXtInfo); |
return(RtnCde); }/*------------------------------------- * Error trying to transform the spooled * file data. *------------------------------------*/ }/* * Else just pass data from caller to HPT. *-----------------------------------------*/ return(XFrm_SUCCESS); } /* END -- Transform */   int EndFile(XFrmXt_Space_Fmt_t *XFrmXtInfo) /********************************************************************* * Function : End File * * Syntax : int EndFile(XFrmXt_Space_Fmt_t *XFrmXtInfo); * * Description : * * Return value : *********************************************************************/ { int RtnCde;   if ((XFrmXtInfo->Last_XFrm_Call_Opt == STARTFILE) || (XFrmXtInfo->Last_XFrm_Call_Opt == TRANSFORM)) { RtnCde = Call_XFrmPgm(ENDFILE, XFrmXtInfo); if (RtnCde) { CleanUp_XFrmXt(XFrmXtInfo); return(RtnCde); }/*------------------------------------- * Error trying to end the transform * for the current spooled file. *------------------------------------*/ }/* End if HPT was not called with ENDFILE (40) option yet. */   if (XFrmXtInfo->SPhandle != SPLF_NOT_OPEN) { /*---------------------------------------------------------------- * Close the spool file *----------------------------------------------------------------*/ |
Close_Spooled_File(XFrmXtInfo->SPhandle); XFrmXtInfo->SPhandle = SPLF_NOT_OPEN; } return(RtnCde); } /* END -- EndFile */   int Terminate_XFrmXt(XFrmXt_Space_Fmt_t *XFrmXtInfo) /********************************************************************* * Function : Terminate_XFrmXt * * Syntax : int Terminate_XFrmXt(XFrmXt_Space_Fmt_t *XFrmXtInfo); * * Description : * * Return value : *********************************************************************/ { QNAME GetSplfSpace; /* Qualified name of User Space used to retrieve spooled file data using API QSPGETSP. */ QNAME XFrmWrkSpace; /* Qualified name of User Space used as a work space for the XFrmXt program. */ int RtnCde = 0; ERRSTRUCTURE ErrorStructure; char MsgKey??(4??);   /*------------------------------------------------------------ * Initialize local error structure for call to send program * message to the writer's joblog. *-----------------------------------------------------------*/ ErrorStructure.BytesPro = 0;   /*----------------------------------------------------------------- * Initialize name structure for the user space used to store the * spooled file data. *----------------------------------------------------------------*/ memcpy(GetSplfSpace.Object, SpoolSpace, sizeof(GetSplfSpace));   memcpy(XFrmWrkSpace.Object, XFrmXt_Work_Space, sizeof(XFrmWrkSpace));   |
/*-------------------------------------------------------------------- * Was there a spooled file being processed when termination of * the XFrmXt was signalled? *------------------------------------------------------------------*/ if (XFrmXtInfo->SPhandle != SPLF_NOT_OPEN) Close_Spooled_File(XFrmXtInfo->SPhandle);   /*----------------------------------------------------------- * Were we transforming, and did we successfully initialize * the transform? *----------------------------------------------------------*/ if (XFrmXtInfo->Last_XFrm_Call_Opt >= INITIALIZE) /*----------------------------------------------------------- * Terminate the transform *----------------------------------------------------------*/ Call_XFrmPgm(TERMINATE, XFrmXtInfo);   if (XFrmXtInfo->Ptr_SplfDtaUS != NULL) { DeleteUserSpace(GetSplfSpace); XFrmXtInfo->Ptr_SplfDtaUS = NULL;   }/* End if user space created for reading spooled files. */ DeleteUserSpace(XFrmWrkSpace); XFrmXtInfo = NULL;   return(XFrm_SUCCESS); } /* END -- Terminate_XFrmXt */   int Call_XFrmPgm(int Process_Option, XFrmXt_Space_Fmt_t *XFrmXtInfo) /********************************************************************* * Function : Transform file from SCS or AFPDS to ASCII * * Syntax : int Call_XFrmPgm(int Process_Option, * XFrmXt_Space_Fmt_t *XFrmXtInfo); * * Description : Transform_Data will get the open time commands * and transform the SCS or AFPDS spooled file data * into ASCII data using host print transform or a * user supplied data transform program. * * Return value : |
*********************************************************************/ { /* CPF3CF2_INFO CPF3CF2RplTxt;*/ Qsp_SPFRH_t * US_HdrPtr; ERRSTRUCTURE ErrorStructure; char MsgKey??(4??);   volatile int iExceptionRC = 0; int length; int j; char Buf??(100??); ERRSTRUCTURE Error_Data;   /*------------------------------------------------------------ * Initialize local error structure for call to send program * message to the writer's joblog. *-----------------------------------------------------------*/ ErrorStructure.BytesPro = 0; Error_Data.BytesPro = sizeof(ERRSTRUCTURE); Error_Data.BytesAvl = 0;   /*------------------------------------------------------------------- * Save the process option value into the XFrm work space. *------------------------------------------------------------------*/ *(XFrmXtInfo->XFrm_ProcessOption) = Process_Option;   /*------------------------------------------------------------------ * Do any necessary preprocessing before a call to HPT. *-----------------------------------------------------------------*/ switch (Process_Option) { case INITIALIZE:   break;   case STARTFILE: /*------------------------------------------------------------ * Change the input specific information for qualified job * name and spooled file name to *INT. *-----------------------------------------------------------*/ memcpy(XFrmXtInfo->XFrm_SpecIn->Qualified_Job_Name, INTJOBIDUSED, sizeof(QJOBNAM)); memcpy(XFrmXtInfo->XFrm_SpecIn->Spooled_File_Name, INTSPLIDUSED, |
sizeof(XFrmXtInfo->XFrm_SpecIn->Spooled_File_Name)); /*------------------------------------------------------------ * Change the input specific information for manufacturer type * and model name if there is a printer device. *-----------------------------------------------------------*/ if (memcmp(XFrmXtInfo->XFrm_SpecIn->Printer_Device_Name, "*NONE ", sizeof(XFrmXtInfo->XFrm_SpecIn->Printer_Device_Name)) != 0) { memcpy(XFrmXtInfo->XFrm_SpecIn->Mfr_Type_Model, " ", sizeof(XFrmXtInfo->XFrm_SpecIn->Mfr_Type_Model)); memcpy(XFrmXtInfo->XFrm_SpecIn->Wkstn_Cust_Obj_Name, "*NONE ", sizeof(XFrmXtInfo->XFrm_SpecIn->Wkstn_Cust_Obj_Name)); } break; case TRANSFORM: if (XFrmXtInfo->Pass_Input_Data == DONT_PASS_SPLF_DATA) { XFrmXtInfo->Length_of_SplfDta_Bfr = XFrmXtInfo->Ptr_SplfDtaUS->Size_Print_Data300; XFrmXtInfo->XFrm_In_Dta = ((char *)XFrmXtInfo->Ptr_SplfDtaUS + XFrmXtInfo->Ptr_SplfDtaUS->Offset_First_Buffer); /*---------------------------------------------------------- * Set the number of pages to transform from the information * in the spool information. *---------------------------------------------------------*/ XFrmXtInfo->XFrm_SpecIn->Number_Of_Complete_Pages = XFrmXtInfo->Ptr_SplfDtaUS->Nbr_Comp_Pages;   /*--------------------------------------------------------- * Set the size of the output buffer to the length of the * output buffer in the XFrmXt Work user space. *--------------------------------------------------------*/ *XFrmXtInfo->XFrm_Out_Dta_Len = MaxXFrmBfrSize; }/*----------------------------------------------------- * Driver is reading in spooled file data and passing * to transform program. *----------------------------------------------------*/ break; case ENDFILE: case TERMINATE: break; |
default:; } /* End -- switch (Process_Option) */     /*------------------------------------------------------------- * Call the host print transform service program *------------------------------------------------------------*/ QwpzHostPrintTransform ( (int *)XFrmXtInfo->XFrm_ProcessOption, (char *)XFrmXtInfo->XFrm_SpecIn, (int *)XFrmXtInfo->XFrm_SpecIn_Len, XFrmXtInfo->XFrm_In_Dta, (int *)XFrmXtInfo->XFrm_Inp_Dta_Len, (char *)XFrmXtInfo->XFrm_SpecOut, (int *)XFrmXtInfo->XFrm_SpecOut_Len, (int *)XFrmXtInfo->XFrm_SpecOut_Avail, XFrmXtInfo->XFrm_Out_Dta, (int *)XFrmXtInfo->XFrm_Out_Dta_Len, (int *)XFrmXtInfo->XFrm_Out_Dta_Avail, (char *)&Error_Data );   if (Error_Data.BytesAvl > 0) { /*------------------------------------------------------- * There are cases where we will get CPF6DF5 when * a previous option failed to complete successfully. * We need some way to either eliminate that possibility, * or we need to have some way of accounting for it, and * not signal an error message. *------------------------------------------------------*/ Dump_Info_to_Splf(); Send_Pgm_Msg(Error_Data.ExcpID, (void *)QualQCPFMSGF, Error_Data.ExcpData, Error_Data.BytesAvl - 16, (char *)MsgTypeDIAG, MsgKey, &ErrorStructure); return(XFrm_ERR_TERM_IMMEDIATE); /* or controlled? */ }/* End if error calling HPT. */   /*------------------------------------------------- |
* Save the last successful transform call option. * This is needed later to do proper cleanup if an * exception occurs. *------------------------------------------------*/ XFrmXtInfo->Last_XFrm_Call_Opt = Process_Option;   /*------------------------------------------------------------------ * Do any necessary postprocessing after a call to HPT or the * Transform exit program. *-----------------------------------------------------------------*/ switch (Process_Option) { case INITIALIZE: if (*XFrmXtInfo->XFrm_SpecOut_Avail < 0) { /* * Need to issue a message and return. */   j = sprintf(Buf, "ERROR IN AMOUNT OF DATA RETURNED FROM\ CALL TO TRANSFORM PROGRAM");   Send_Pgm_Msg((char *)CPF9898, (void *)QualQCPFMSGF, Buf, j, (char *)MsgTypeDIAG, MsgKey, &ErrorStructure); return(XFrm_ERR_Output_Spec); }/*----------------------------------------------------------- * Transform program did not return enough data in the output * specific structure for the driver program to continue * using the transform program. *-----------------------------------------------------------*/ break; case STARTFILE: if (*XFrmXtInfo->XFrm_SpecOut_Avail < 6) { /* * Need to issue a message and return. */   j = sprintf(Buf, "ERROR IN AMOUNT OF DATA RETURNED FROM\ CALL TO TRANSFORM PROGRAM");   |
Send_Pgm_Msg((char *)CPF9898, (void *)QualQCPFMSGF, Buf, j, (char *)MsgTypeDIAG, MsgKey, &ErrorStructure); return(XFrm_ERR_Output_Spec); }/*----------------------------------------------------------- * Transform program did not return enough data in the output * specific structure for the driver program to continue * using the transform program. *-----------------------------------------------------------*/ break; case TRANSFORM: if (*XFrmXtInfo->XFrm_SpecOut_Avail < 44) { /* * Need to issue a message and return. */   j = sprintf(Buf, "ERROR IN AMOUNT OF DATA RETURNED FROM\ CALL TO TRANSFORM PROGRAM");   Send_Pgm_Msg((char *)CPF9898, (void *)QualQCPFMSGF, Buf, j, (char *)MsgTypeDIAG, MsgKey, &ErrorStructure); return(XFrm_ERR_Output_Spec); }/*----------------------------------------------------------- * Transform program did not return enough data in the output * specific structure for the driver program to continue * using the transform program. *-----------------------------------------------------------*/ break; case ENDFILE: if (*XFrmXtInfo->XFrm_SpecOut_Avail < 0) { /* * Need to issue a message and return. */   j = sprintf(Buf, "ERROR IN AMOUNT OF DATA RETURNED FROM\ |
CALL TO TRANSFORM PROGRAM");   Send_Pgm_Msg((char *)CPF9898, (void *)QualQCPFMSGF, Buf, j, (char *)MsgTypeDIAG, MsgKey, &ErrorStructure); return(XFrm_ERR_Output_Spec); }/*----------------------------------------------------------- * Transform program did not return enough data in the output * specific structure for the driver program to continue * using the transform program. *-----------------------------------------------------------*/ break; default: if (*XFrmXtInfo->XFrm_SpecOut_Avail < 0) { /* * Need to issue a message and return. */   j = sprintf(Buf, "ERROR IN AMOUNT OF DATA RETURNED FROM\ CALL TO TRANSFORM PROGRAM");   Send_Pgm_Msg((char *)CPF9898, (void *)QualQCPFMSGF, Buf, j, (char *)MsgTypeDIAG, MsgKey, &ErrorStructure); return(XFrm_ERR_Output_Spec); }/*----------------------------------------------------------- * Transform program did not return enough data in the output * specific structure for the driver program to continue * using the transform program. *-----------------------------------------------------------*/ }/*------------------------------------------------ * End of postprocessing for call to transform. *-----------------------------------------------*/   return(XFrm_SUCCESS);   |
} /* END -- Call_XFrmPgm */   void CleanUp_XFrmXt(XFrmXt_Space_Fmt_t *XFrmXtInfo) /********************************************************************* * Function : Clean up after an error occurred in XFrmXt. * * * Syntax : void CleanUp_XFrmXt(XFrmXt_Space_Fmt_t *); * * Description : * * Return value : No value returned. *********************************************************************/ { ERRSTRUCTURE ErrorStructure; char MsgKeyÝ4¨;   /*------------------------------------------------------------ * Initialize local error structure for call to send program * message to the writer's joblog. *-----------------------------------------------------------*/ ErrorStructure.BytesPro = 0; /*------------------------------------------------------ * Check to see if the transform needs to be ended for * the current file. *-----------------------------------------------------*/ if ((XFrmXtInfo->Last_XFrm_Call_Opt == STARTFILE) || (XFrmXtInfo->Last_XFrm_Call_Opt == TRANSFORM)) { Call_XFrmPgm(ENDFILE, XFrmXtInfo); }/*----------------------------------------------------- * End if the XFrm needs to be closed for the current * spooled file. *----------------------------------------------------*/   /*------------------------------------------------------- * Check to see if the spooled file needs to be closed. *------------------------------------------------------*/ if (XFrmXtInfo->SPhandle != SPLF_NOT_OPEN) { /*---------------------------------------------------- * Close the spool file *---------------------------------------------------*/ Close_Spooled_File(XFrmXtInfo->SPhandle); |
XFrmXtInfo->SPhandle = SPLF_NOT_OPEN; }/*-------------------------------------- * End if spooled file was left open. *-------------------------------------*/ }/* End of CleanUp_XFrmXt(). */   void Close_Spooled_File(int SPhandle) /********************************************************************* * Function : Close a spooled file * * Syntax : void Close_Spooled_File(int SPhandle); * * Description : Close_Spooled_File will close a spooled file that * was opened in the Open_Spooled_File function. * * Return value : No value is returned from this function *********************************************************************/ { ERRSTRUCTURE ErrorStructure; char MsgKeyÝ4¨; int SplfUnAvail = FALSE; ERRSTRUCTURE Error_Data;   /*------------------------------------------------------------ * Initialize local error structure for call to send program * message to the writer's joblog. *-----------------------------------------------------------*/ ErrorStructure.BytesPro = 0; Error_Data.BytesPro = sizeof(ERRSTRUCTURE); Error_Data.BytesAvl = 0;   do { /* Loop until spooled file is available */ /*------------------------------------------------------------------ * Call QSPCLOSP API to close the spooled file *-----------------------------------------------------------------*/ QSPCLOSP ( SPhandle, (char *)(&Error_Data) );   /*------------------------------------------------------------------ * Check if an error occured while closing the spooled file |
*-----------------------------------------------------------------*/ if (Error_Data.BytesAvl > 0) { /* Problems have been found when closing the spooled file */ /*--------------------------------------------------------- * Is it possible that the SCB could be locked by another * process when we want to close the spooled file? *--------------------------------------------------------*/ if (!(memcmp(Error_Data.ExcpID, "CPF3330", 7))) SplfUnAvail = TRUE; else { Dump_Info_to_Splf(); SplfUnAvail = FALSE; Send_Pgm_Msg(Error_Data.ExcpID, (void *)QualQCPFMSGF, Error_Data.ExcpData, Error_Data.BytesAvl - 16, (char *)MsgTypeDIAG, MsgKey, &ErrorStructure); }/*------------------------------------ * Else error closing spooled file, * and SCB was not locked(CPF3330). *-----------------------------------*/ }/* if error occurred closing spooled file. */ } while (SplfUnAvail); /* End of while spool file not available */   } /* END -- Close_Spooled_File */   int Create_User_Space(QNAME spacename, long int sizeofspace) /********************************************************************* * Function : Create a user space * * Syntax : void Create_User_Space(QNAME qname, long int size, * XFrmXt_Space_Fmt_t *) * * Parameters : 1) qname - QNAME * Qualified job name of the user space to * create. * 2) size - int * Size of the user space that will be created. * * Description : Create_User_Space will create a user space and * return a basing pointer to the caller. qname will |
* contain the qualified name of the space. size will * contain an integer value for the size of the space. * * Errors : A check will be made to make sure that the * user space API completed correct. * * Return value : XFrm_SUCCESS or *********************************************************************/ { ERRSTRUCTURE ErrorStructure; char MsgKeyÝ4¨; char authorityÝ10¨ = "*ALL ";/* Authority of the space */ char descriptionÝ50¨ = "Work space for XFrm exit program. \0"; char replaceÝ10¨ = "*YES ";/* Replace space if exists */ char initialvalue = '\0'; /* Initial value of the space */ char extattribÝ10¨ = "XFrmExit ";/* Attribute of the space */ ERRSTRUCTURE Error_Data;   /*------------------------------------------------------------ * Initialize local error structure for call to send program * message to the writer's joblog. *-----------------------------------------------------------*/ ErrorStructure.BytesPro = 0; Error_Data.BytesPro = sizeof(ERRSTRUCTURE); Error_Data.BytesAvl = 0;   /*------------------------------------------------------------------ * Create a user space *-----------------------------------------------------------------*/ QUSCRTUS ( &spacename, extattrib, sizeofspace, &initialvalue, authority, description, replace, (char *)(&Error_Data) );   if (Error_Data.BytesAvl > 0) { Dump_Info_to_Splf(); |
Send_Pgm_Msg(Error_Data.ExcpID, (void *)QualQCPFMSGF, Error_Data.ExcpData, Error_Data.BytesAvl - 16, (char *)MsgTypeDIAG, MsgKey, &ErrorStructure); return(XFrm_ERR_TERM_IMMEDIATE); }/* if error trying to create a user space. */   return(XFrm_SUCCESS); } /* END -- Create_User_Space */ /***********************************************/ /* function DeleteUserSpace */ /* */ /* Parameters: */ /* */ /* none */ /* */ /* Functions used: */ /* */ /* memcpy() */ /* QUSDLTUS */ /* */ /* Description: */ /* */ /* DeleteUserSpace will free a previously */ /* allocated user space. */ /***********************************************/ void DeleteUserSpace(QNAME qnUserSpace) { QNAME qnTempName; ERRSTRUCTURE Error_Data, esErrCode_sndpmsg; /* Used with Send_Pgm_Msg macro */   /*********************************/ /* Make copy of User Space Name. */ /*********************************/   memcpy(&qnTempName, &qnUserSpace, sizeof(QNAME));   /*********************************/ /* Setup error code structure */ /*********************************/ |
  /*--------------------------------------------------------- * Initialize the size of the error structure for the APIs *--------------------------------------------------------*/ Error_Data.BytesPro = sizeof(ERRSTRUCTURE); Error_Data.BytesAvl = 0;   /*********************************/ /* Delete a user space. */ /*********************************/ QUSDLTUS ((void *)&qnTempName, (void *)&Error_Data);     /**************************************************/ /* If there was an error, ignore it. */ /**************************************************/ if (Error_Data.BytesAvl > 0) {   Dump_Info_to_Splf();   esErrCode_sndpmsg.BytesPro=0L;/* Exception requested */ Send_Pgm_Msg( (char *)&(Error_Data.ExcpID), (void *)&QualQCPFMSGF, &(Error_Data.ExcpData), Error_Data.BytesAvl-16, (char *)&MsgTypeDIAG, (void *)NO_MSG_KEY, (void *)&esErrCode_sndpmsg); } } /* End -- DeleteUserSpace */   void Dump_Info_to_Splf() /********************************************************************* * Function : * * Syntax : void Dump_Info_to_Splf(); * * Description : * * Return value : No value is returned from this function |
*********************************************************************/ /************************************************************* * ************************************************************/ { char Cmd??(255??); /*---------------------------------------------------- * Dump the XFrmXt Work user space for debugging. *---------------------------------------------------*/ sprintf(Cmd,"DMPOBJ OBJ(%.10s) OBJTYPE(*USRSPC)", XFrmXt_Work_Space); system(Cmd); /*------------------------------------------------------ * Dump the user space containing the spooled file data * for debugging. *-----------------------------------------------------*/ sprintf(Cmd,"DMPOBJ OBJ(%.10s) OBJTYPE(*USRSPC)", SpoolSpace); system(Cmd);   }/* End -- Dump_Info_to_Splf */   int Find_End_Page(int Page_Nbr, Qsp_SPFRH_t *US_HdrPtr, Qus_SPLA0200_t * SplFAttr) /********************************************************************* * Function : Find the ending page of the spooled file buffer * * Syntax : int Find_End_Page(int Page_Nbr, char *Data_Input); * * Parameters : 1) Page_Nbr - int * The ending page number to look for in the * data passed in. * * 2) US_HdrPtr - Qsp_SPFRH_t * * Pointer to the spooled buffer information returned * by the API. * * 3) SplFAttr - Qus_SPLA0200_t * * Pointer to the spooled file attributes. * * Description : This routine is called to see if the last page * specified in the page range of the spooled file * is located in current buffer of data. * The buffer is passed in, with the (relative) page |
* being looked for. First a determination is made * to see if the page actually exists in the buffer, * if it does not exist, the routine simply returns * to the caller and processing continues. * If the ending page does exist in the buffer * a routine is called to locate the page. *---------------------------------------------------------------- * NOTE: The header information in the user space is * modified such that the number of complete pages * is set to the number of pages UP TO and including * the end page. The number of bytes of print data * is set to the number of bytes UP TO and including * the end page. *----------------------------------------------------------------- * An EOF indicator is returned to indicate that * there should be no more data processed for * the file. * * Return value : Returns end of file if the last page was found. ********************************************************************/ { char *DtaStream_ptr; /* Pointer to the splf data stream */ int DtaStream_Len; /* Length of the data stream */ int offset; /* The offset at which the end of the page was located */ int adj_page_count; /* The adjustment of the page count that takes into account the starting page in the buffer */   /*------------------------------------------------------------------- * Must check if there is the end of a page in the buffer before the * start of the first page. *------------------------------------------------------------------*/ if (US_HdrPtr->Offset_First_Page == 0) adj_page_count = 0; /* There is not a page in the buffer */ else adj_page_count = 1; /* There is a page in the buffer */   /*------------------------------------------------------------------- * Check if the page is in the buffer. Also handle the case where * the last page of the file is in the buffer. In that case, the * First_Page_Nbr could be zero (if it started in the prev buffer) * but Nbr_Comp_Pages wouldn't be zero. *------------------------------------------------------------------*/ |
if (((US_HdrPtr->First_Page_Nbr == 0) && (US_HdrPtr->Nbr_Comp_Pages == 0)) || ((US_HdrPtr->First_Page_Nbr != 0) && (US_HdrPtr->First_Page_Nbr + US_HdrPtr->Nbr_Comp_Pages - adj_page_count < Page_Nbr))) return FALSE; /* Return not end of file */ /*------------------------------------------------------------------- * Check if the starting page is the one being looked for. *------------------------------------------------------------------*/ if (US_HdrPtr->First_Page_Nbr == Page_Nbr) { US_HdrPtr->Size_Print_Data300 = US_HdrPtr->Offset_First_Page; US_HdrPtr->Nbr_Comp_Pages = adj_page_count; } else { /*----------------------------------------------------------------- * Call routine to find the end of the page for the file. *----------------------------------------------------------------*/ DtaStream_ptr = (char *)US_HdrPtr + US_HdrPtr->Offset_First_Buffer; DtaStream_Len = US_HdrPtr->Size_Print_Data300;   /*----------------------------------------------------------------- * If no page starts in this buffer, it must be the last buffer. *----------------------------------------------------------------*/ if (US_HdrPtr->First_Page_Nbr == 0) { offset = Find_Page_End(1, DtaStream_ptr + US_HdrPtr->Offset_First_Page, DtaStream_Len, SplFAttr); } else { offset = Find_Page_End(Page_Nbr - US_HdrPtr->First_Page_Nbr, DtaStream_ptr + US_HdrPtr->Offset_First_Page, DtaStream_Len, SplFAttr);   } /*----------------------------------------------------------------- * Adjust the size of the print data by the offset - 1, * (minus 1 since the start of the page is actually returned). |
*----------------------------------------------------------------*/ US_HdrPtr->Size_Print_Data300 = offset + US_HdrPtr->Offset_First_Page - 1; US_HdrPtr->Nbr_Comp_Pages = Page_Nbr - US_HdrPtr->First_Page_Nbr + adj_page_count; } /* End -- else */   return TRUE; /* Return the end of file found */   } /* END -- Find_End_Page */   int Find_Page_End(int page_number, char *DtaStream_data, int DtaStream_Len, Qus_SPLA0200_t * SplFAttr) /********************************************************************* * Function : Find the page end in the buffer * * Syntax : int Find_Page_End(int page_number, * char *DtaStream_data, * int DtaStream_Len); * * Parameters : 1) page_number - int * The number of complete pages located in the * buffer before the page we are looking for. * * 2) DtaStream_data - char * * Pointer to the starting page in the data stream. * * 3) DtaStream_Len - int * The amount of data to look for the page. * * 4) SplFAttr - Qus_SPLA0200_t * * Pointer to the attributes of the spooled file. * * Description : This routine is used to find the specified page * number in the spooled file. This is done by * starting to look for the data at the beginning * of the first page in the buffer. From there * the data stream is parsed, looking for a * command indicating end of page. When an end of * page is detected, the number of pages encountered * is increment, a check is made to see if we have |
* parsed through the correct number of pages. * If we have reached the desired page, 1 is added * to the index, since we are actually looking for * the start of the next page, not the end of the * current page. * This information is returned to the caller so * adjustments can be made. * WARNING!!! : It is assumed when this function is called, that * the page being looked for actually exists in the * buffer(s). If it is not found, -1 is returned. * * Return value : (int) - The location of the next page. ********************************************************************/ { SCS_COMMAND *SCS_Command; /* Pointer to the SCS command in buffer*/ int current_page = 0; /* The current page in the buffer, relative to the beginning of the buffer. */ int current_index = 0; /* The current location in the buffer */ int Advance; /* The amount of number of bytes to skip in the current command */ int bump = 0; AFP_COMMAND *AFP_Command; AFP_Rcd_t *AFP_Rcd; int Format;   if (memcmp(SplFAttr->Ptr_Dev_Type, AFPDS, sizeof(SplFAttr->Ptr_Dev_Type)) == 0) { /*------------------------------------------------------- * If there are '5A'Xs present, set bump counter to 1. * else don't need to compensate AFP command length, thus * set bump counter to 0. *------------------------------------------------------*/ if (SplFAttr->Flg_Pres5aÝ0¨ == 'Y') bump = 1; else bump = 0;   /*--------------------------------------------------------- * If the data stream contains original and trim lengths, * set the bump count to 8. Don't need to worry about * accounting for the 5A, as the trim length already |
* takes that in account. *--------------------------------------------------------*/ if (SplFAttr->Flg_LengthsÝ0¨ == 'Y') { bump = 8; Format = NON_NATIVE_AFP; }/*--------------------------------------------- * end if original and trim lengths specified. *--------------------------------------------*/ else Format = NATIVE_AFP;   AFP_Rcd = (AFP_Rcd_t *)DtaStream_data; AFP_Command = (AFP_COMMAND*)(DtaStream_data+bump);   while (current_page < page_number) { if (memcmp(AFP_Command->Afp_Cmd, ENDPAGE, 3) == 0) current_page ++;   if (Format == NATIVE_AFP) Advance = AFP_Command->Afp_Length+bump; else Advance = AFP_Rcd->Trim_Len + bump;   AFP_Rcd = (AFP_Rcd_t *)((char *)AFP_Rcd + Advance); AFP_Command = (AFP_COMMAND*)((char *)AFP_Command + Advance);   current_index += Advance;   /*---------------------------------------------------- * must decrement current_index because it includes * the next bump so could be 1 byte too far *---------------------------------------------------*/ if (current_index-bump > DtaStream_Len) return -1; }/* end while */ /*---------------------------------------------------- * must decrement current_index because it includes * the next bump so could be 1 byte too far *---------------------------------------------------*/ current_index -= bump; }/*----------------------------------------------------- * End if the data stream we are to check is *AFPDS. |
*----------------------------------------------------*/ else if (memcmp(SplFAttr->Ptr_Dev_Type, SCS, sizeof(SplFAttr->Ptr_Dev_Type)) == 0) { /*--------------------------------------------------------- * Set the command pointer into the data in the buffer. *--------------------------------------------------------*/ SCS_Command = (SCS_COMMAND *)DtaStream_data;   /*--------------------------------------------------------- * Loop through the data until the correct page is located. *--------------------------------------------------------*/ while (current_page < page_number) { /*-------------------------------------------------- * Check the leading character of the command * to see what it is. *-------------------------------------------------*/ switch (SCS_Command->Leading_Character) { case (COMMAND_2B) : /* Length is 2 bytes more than the length in the command */ Advance = SCS_Command->Cmd_Len_2B + 2; break; case (COMMAND_28) : Advance = 3; /* The length of a 28 command is 3 */ break; case (COMMAND_03) : /* ASCII transparency */ case (COMMAND_35) : /* Character transparency */ /* Length is 2 bytes more than the command length */ Advance = SCS_Command->Cmd_Len_03_35 + 2; break; case (COMMAND_34) : Advance = 3; /* Command length is 3 bytes */ break; case (FORMFEED) : case (RQDFORMFEED): current_page ++; /* Increment the number of pages found */ default : Advance = 1; /* The length of all |
other commands is 1*/ break; } /* End -- switch(... */   /*--------------------------------------------------------- * Set the pointer to the next command in the buffer. *--------------------------------------------------------*/ SCS_Command = (SCS_COMMAND *)((char *)SCS_Command + Advance); current_index += Advance;/* Increment the index */   /*------------------------------------------------------ * Check if there is more data to parse through. *-----------------------------------------------------*/ if (current_index > DtaStream_Len) return -1; /* Return an error if no data */ } /* End -- while(current_page < page_number) */ }/*---------------------------------------------------- * End else if data stream we are searching is *SCS. *---------------------------------------------------*/   return current_index + 1; /* Increment the index, since the page start is really the next byte in the buffer */   } /* END -- Find_Page_End */   int Find_Start_Page(int Page_Nbr, int SPHandle, QNAME Spool_API_Spc, Qsp_SPFRH_t *SplfDtaSpcPtr, Qus_SPLA0200_t *SplFAttr) /********************************************************************* * Function : Find the starting page in the buffer * * Syntax : int Find_Start_Page(int Page_Nbr, int SPHandle, * QNAME Spool_API_Spc, * Qsp_SPFRH_t *SplfDtaSpcPtr, * Qus_SPLA0200_t *SplFAttr); * * Parameters : 1) Page_Nbr - int * The starting page number to look for in the buffer. * * 2) SPHandle - int * Internal spool handle ID used identify the spooled |
* file which has been opened by the open spooled * file API. * * 3) Spool_API_Spc - QNAME * The qualified job name of the space that the spool * API will copy the buffer data into (For QSPGETSP). * * 4) SplfDtaSpcPtr - Qsp_SPFRH_t * * A pointer which points to the start of the API * space where the buffer data will be placed. * * Description : This routine is used to locate the starting page * number in the spooled file. If a page range is * specified, this routine will then be called to look * for the starting page. There are 2 code paths * here: * * 1) There are 6 or more buffers of data in the * spooled file a binary search of the data will be * done. Some special code is needed to handle * the case where there are no pages in the current * buffer being searched. In this case a backward * sequential search will need to be done until * a page number is located. * * 2) If there are less than 6 buffers of data, or * the spooled file is open (buffers == 0) a * sequential search of the data is done starting at * the first buffer. * NOTE: Currently, page ranges are not going to * be supported for spooled files that are * schedule *IMMED and still OPN. * * After the correct buffer has been located, a * check is made to see if the first page in the * buffer is actually the page which is being searched * for. If not another routine is called to seach * the buffer for the start of the page being looked * for. The location of the page is returned from * the functions. *------------------------------------------------------------------- * NOTE: This routine will MODIFY the header information * of the user space(containing the spooled file * data), adjusting the offset of the |
* data and the length of the data. *------------------------------------------------------------------- * The function then returns * to the caller, with the adjusted buffer. * Processing of the buffer can continue at that time. * * Possibly modified values in the user space header * are: * Description CLEINC field name * ------------------------- ------------------------ * Number of complete pages Nbr_Comp_Pages * Total number of bytes Size_Print_Data300 * Offset to the first buffer Offset_First_Buffer * Offset to the first page Offset_First_Page * First page number First_Page_Nbr * * Return value : XFrm_SUCCESS or ... ********************************************************************/ { int End_of_Data; /* Indicator for end of the spooled file */ char *DtaStream_ptr; /* Pointer to the SCS data */ int DtaStream_Len; /* Length of the SCS data stream */ int total_pages=0; /* Total number of pages which have been processed in the buffer so far */ int offset; /* The offset at which the end of the page was located */ int buffer_index; /* The buffer to get from the spooled file */ int find_index; /* An index which is used to retreive spooled buffers, if there is no page information in the one which was retreived */ int Change_pages; int adj_page_count; int hi, lo; int count_first_page; int adjust; int Get_Buffer = NEXT_BUFFER; int RtnCde = 0;   /*------------------------------------------------------------------ * Check if there are greater than 6 buffers of data, in that case * there is enough data to do a binary search of the buffers, AND |
* the first page we are looking for is not the last page. *-----------------------------------------------------------------*/ if ((SplFAttr->Number_Buffers > 6) & (Page_Nbr != MAX_INT)) { /*--------------------------------------------------------------- * Calculate the starting index by taking 1/2 of the total number * of buffers in the spooled file. *--------------------------------------------------------------*/ hi = SplFAttr->Number_Buffers; lo = 0; buffer_index = 0; while (TRUE) { if (hi-lo <= 1) buffer_index++; else buffer_index = (hi - lo) / 2 + lo;   /*----------------------------------------------------------- * Call routine to get the spooled buffer. *----------------------------------------------------------*/ RtnCde = Get_Spool_Data(SPHandle, Spool_API_Spc, SplfDtaSpcPtr, buffer_index, &End_of_Data);   if (RtnCde) return(RtnCde); /*----------------------------------------------------------- * In some cases there may not be any page information in the * buffer, for that case a backward sequential search of the * buffers will be done until some page information is found. *----------------------------------------------------------*/ find_index = buffer_index; /* Start at the current index */ while (SplfDtaSpcPtr->First_Page_Nbr == 0) { RtnCde = Get_Spool_Data(SPHandle, Spool_API_Spc, SplfDtaSpcPtr, --find_index, &End_of_Data); if (RtnCde) |
return(RtnCde); }/* End While a page doesn't start in a buffer. */   /*----------------------------------------------------------- * Must check if there is the end of page in the buffer * before the start of the first page. *----------------------------------------------------------*/ if (SplfDtaSpcPtr->Offset_First_Page == 0) adj_page_count = 0;/* There is not a page in the buffer */ else adj_page_count = 1;/* There is a page in the buffer */   /*----------------------------------------------------------- * Check if the start page number in the buffer is the page * which we are searching for. *----------------------------------------------------------*/ if (SplfDtaSpcPtr->First_Page_Nbr == Page_Nbr) break; /* The page which is the first one is the first page in the buffer */   /*----------------------------------------------------------- * Calculate the new index to use for the buffer *----------------------------------------------------------*/ if (Page_Nbr < SplfDtaSpcPtr->First_Page_Nbr) /*----------------------------------------------------- * Makes more sense here to use find_index rather than * buffer_index, as the while loop above has determined * that 0 or more buffers previous to buffer_index did * not have any pages in them. *-----------------------------------------------------*/ hi = find_index; else if (Page_Nbr > SplfDtaSpcPtr->First_Page_Nbr + SplfDtaSpcPtr->Nbr_Comp_Pages - adj_page_count) lo = buffer_index; else break; /* The page is located in the buffer */   } /* End -- while (TRUE) */ } /* End -- if (number_of_buffers > 6) */   /*----------------------------------------------------------------- * There are not enough buffer to justify a binary search, perform |
* a sequential search of the file. *----------------------------------------------------------------*/ else { /*--------------------------------------------------------- * Check to see if we are searching for the page from the * beginning of the spooled file, or if we are looking for * the start of the last page. *--------------------------------------------------------*/ if (Page_Nbr == MAX_INT) /*--------------------------- * Looking for last page. *--------------------------*/ Get_Buffer = SplFAttr->Number_Buffers; else /*----------------------------------- * Looking for a specific page from * the beginning of splf. *----------------------------------*/ Get_Buffer = 1; /*-------------------------------------------------------- * Loop until the buffer with the correct starting page * is found. In the case of the last page, we will start * looking at the last buffer and work our way toward the * first spooled file buffer until we find the start of * the last page. *--------------------------------------------------------*/ do { RtnCde = Get_Spool_Data(SPHandle, Spool_API_Spc, SplfDtaSpcPtr, Get_Buffer, &End_of_Data); if (RtnCde) return(RtnCde);   /*------------------------------------------------- * Set Get_Buffer to the right value to make sure * we get the previous buffer for the last page * search, and the next buffer for the sequential * page search. *------------------------------------------------*/ if (Page_Nbr == MAX_INT) |
Get_Buffer--; else Get_Buffer = NEXT_BUFFER;   /*---------------------------------------------------------- * Check if the end of the spooled file was reached before * that starting page was found. *---------------------------------------------------------*/ if (End_of_Data == TRUE) { /* This would be a case when we were processing a page range that was invalid. */   return(XFrm_ERR_TERM_IMMEDIATE); }   /*----------------------------------------------------------- * Must check if there is the end of page in the buffer * before the start of the first page. *----------------------------------------------------------*/ if (SplfDtaSpcPtr->Offset_First_Page == 0) adj_page_count = 0;/* There is not a page in the buffer */ else adj_page_count = 1;/* There is a page in the buffer */   } while (((SplfDtaSpcPtr->First_Page_Nbr + SplfDtaSpcPtr->Nbr_Comp_Pages - adj_page_count < Page_Nbr) && (Page_Nbr != MAX_INT)) || ((Page_Nbr == MAX_INT) && (SplfDtaSpcPtr->First_Page_Nbr == 0))); } /* End -- else if (number_of_buffers ... */   /*---------------------------------------------------------------- * Check if the starting page is the first page in the buffer. *---------------------------------------------------------------*/ if ((SplfDtaSpcPtr->First_Page_Nbr == Page_Nbr) || ((Page_Nbr == MAX_INT) && (SplfDtaSpcPtr->Nbr_Comp_Pages == 1))) { offset = 0; /* The first page is the one */ if (SplfDtaSpcPtr->Offset_First_Page == 0) /* no page information change needed */ Change_pages = 0; |
else /* Set the number of pages that will be modified */ Change_pages = 1; } /* End -- if (gen_header ... */ else { if (SplfDtaSpcPtr->Offset_First_Page == 0) count_first_page = 0; else count_first_page = 1; /* Set pointer to the start of the first page in the buffer */ DtaStream_ptr = (char *)SplfDtaSpcPtr + SplfDtaSpcPtr->Offset_First_Buffer + SplfDtaSpcPtr->Offset_First_Page; /* Set the length of the data in the buffer */ DtaStream_Len = SplfDtaSpcPtr->Size_Print_Data300 - SplfDtaSpcPtr->Offset_First_Page;   if (Page_Nbr == MAX_INT) { /*------------------------------------------------------------ * Call routine to look for the start of last page in * the buffer. *-----------------------------------------------------------*/ if (++Get_Buffer == SplFAttr->Number_Buffers) adjust = 1; else adjust = 0;   /*---------------------------------------------------------------- * WARNING: A -1 could be returned by Find_Page_End. * This should not happen, but it could if * the page information returned by API * QSPGETSP is incorrect. *---------------------------------------------------------------*/   offset = Find_Page_End(SplfDtaSpcPtr->Nbr_Comp_Pages - (adjust + count_first_page), DtaStream_ptr, DtaStream_Len, SplFAttr); if (offset == -1) return(XFrm_ERR_TERM_IMMEDIATE); |
  Change_pages = SplfDtaSpcPtr->Nbr_Comp_Pages - adjust + count_first_page; }/*-------------------------------- * End if looking for last page. *-------------------------------*/ else { /*------------------------------------------------------------ * Call routine to look for the starting page in the buffer. *-----------------------------------------------------------*/   /*---------------------------------------------------------------- * WARNING: A -1 could be returned by Find_Page_End. * This should not happen, but it could if * the page information returned by API * QSPGETSP is incorrect. *---------------------------------------------------------------*/ offset = Find_Page_End(Page_Nbr - SplfDtaSpcPtr->First_Page_Nbr, DtaStream_ptr, DtaStream_Len, SplFAttr); if (offset == -1) return(XFrm_ERR_TERM_IMMEDIATE);   Change_pages = Page_Nbr - SplfDtaSpcPtr->First_Page_Nbr + count_first_page; }/*--------------------------------- * End if looking for start page. *--------------------------------*/ } /* End -- else if (gen_header ... */   if (SplfDtaSpcPtr->Offset_First_Page + offset - 1 == SplfDtaSpcPtr->Size_Print_Data300) /*------------------------------------------------- * Decrement the size of the offset here, since * the start of the page that was returned is * actually in the next buffer. What will * happen is the buffer will not have any * data in it, therefore no processing * will be done, the next buffer will be * read by the mainline. |
*----------------------------------------------*/ offset --; /*----------------------------------------- * Change the starting offset to the * beginning of the starting page we were * looking for. *----------------------------------------*/ SplfDtaSpcPtr->Offset_First_Buffer += offset + SplfDtaSpcPtr->Offset_First_Page;   /*---------------------------------------------- * Change the amount of data in the buffer * to the number of bytes of data in buffer from * the beginning of the starting page we were * looking for to the end of the buffer. *----------------------------------------------*/ SplfDtaSpcPtr->Size_Print_Data300 -= offset + SplfDtaSpcPtr->Offset_First_Page;   /*----------------------------------------------- * Change the number of complete pages to the * number of complete pages after and including * the starting page we were looking for. *-----------------------------------------------*/ SplfDtaSpcPtr->Nbr_Comp_Pages -= Change_pages;   /*--------------------------------------------------- * Change Offset_First_Page to the offset to the * starting page we were looking for. *--------------------------------------------------*/ SplfDtaSpcPtr->Offset_First_Page = 0;   /*-------------------------------------- * Set the number of the first * page in the buffer information area * to the number of our starting page, * or our last page. *-------------------------------------*/ if (Page_Nbr == MAX_INT) SplfDtaSpcPtr->First_Page_Nbr += Change_pages; else SplfDtaSpcPtr->First_Page_Nbr = Page_Nbr;   return(XFrm_SUCCESS); |
} /* END -- Find_Start_Page */   void Get_Page_Range(int *StartPage, int *EndPage, Qus_SPLA0200_t *SplFAInfo) /********************************************************************* * Function : Returns the page range for the current spooled * file. * * Syntax : void Get_Page_Range(int * StartPage, * int * EndPage, * Qus_SPLA0200_t *); * * Description : Returns the starting and ending pages of the * currently spooled file. * NOTE : Special values are returned for StartPage and * EndPage. * * StartPage * --------- * PRT_WHOLE_FILE - The whole file is to be printed, * no page range processing should * occur. * MAX_INT - The starting page is the last * page of the spooled file. * page# - Number of the page to start * printing from. * * EndPage * --------- * LAST_PAGE - The ending page is the last * page of the spooled file. * page# - The page number of the last * page of the spooled file that * is to be printed. * Modified Values: StartPage - Set to the page to start printing * on. * EndPage - Set to the page to end printing * on. * * Return Value : No value is returned. ********************************************************************/ { /*--------------------------------------------------------------- |
* Is the printer device type of the spooled file not *SCS and * not *AFPDS OR is the spooled file schedule *IMMED and still * open? *--------------------------------------------------------------*/ if (((memcmp(SplFAInfo->Ptr_Dev_Type, SCS, sizeof(SplFAInfo->Ptr_Dev_Type)) != 0) && (memcmp(SplFAInfo->Ptr_Dev_Type, AFPDS, sizeof(SplFAInfo->Ptr_Dev_Type)) != 0)) || ((memcmp(SplFAInfo->File_Avail, sIMMED, sizeof(SplFAInfo->File_Avail)) == 0) && (SplFAInfo->Flg_File_OpenÝ0¨ == 'Y'))) { *StartPage = PRT_WHOLE_FILE; }/*------------------------------------------------------------ * Spooled file is not eligible for page range manipulation. *-----------------------------------------------------------*/ /*-------------------------------------------------------------- * Else look for page range to use *-------------------------------------------------------------*/ else { /*-------------------------------------------------------- * Select the starting page based on the restart page * first. It is assumed that in normal printing cases, * the value for restart page will be 0. In this case, * the starting page will be based on the value in the * start page in the spooled file attributes. *-------------------------------------------------------*/ switch(SplFAInfo->Rest_Page) { case(USE_ENDPAGE): switch(SplFAInfo->End_Page) { case(LAST_PAGE): case(MAX_INT): *StartPage = MAX_INT; /* Start on Last page */ break; default: /*----------------------------------------------- * Start on page specified in the spooled file * attributes end page value. |
*----------------------------------------------*/ *StartPage = SplFAInfo->End_Page; }/*-------------------------------------------- * End of switch on Splf Attr End Page value. *-------------------------------------------*/ break; case(NEXTPAGE): /*----------------------------------------------------- * Set start page to the last page that was printed * plus 1. *----------------------------------------------------*/ *StartPage = SplFAInfo->Last_Page_Print + 1; break; case(USE_STRPAGE_VAL): case(NO_RESTART): /*------------------------------------------------------- * This should be the most common path, where the start * page is determined by the starting page value in the * spooled file attributes. *------------------------------------------------------*/ switch(SplFAInfo->Start_Page) { case(USE_ENDPAGE_VAL): switch(SplFAInfo->End_Page) { case(LAST_PAGE): case(MAX_INT): *StartPage = MAX_INT; /* Start on Last page */ break; default: /*----------------------------------------------- * Start on page specified in the spooled file * attributes end page value. *----------------------------------------------*/ *StartPage = SplFAInfo->End_Page; }/*-------------------------------------------- * End of switch on Splf Attr End Page value. *-------------------------------------------*/ break; default: /*-------------------------------------------------- * Start on the page specified in the spooled file * attr start page. This may be the special value * indicating to print the whole file. |
*-------------------------------------------------*/ *StartPage = SplFAInfo->Start_Page; }/*----------------------------------------------- * End of switch on Splf Attr Start Page value. *----------------------------------------------*/ break; default: /*--------------------------------------------------- * Start page will be set to the restart page value * specified in the spooled file attributes. *--------------------------------------------------*/ *StartPage = SplFAInfo->Rest_Page; }/*------------------------------------------------------ * End switch on Splf Attr Reset Page value. *-----------------------------------------------------*/ /*--------------------------------------------------------------- * We now need to decide the endpage value. If we are not * printing to the end of the spooled file, the value for EndPage * will be nonzero. *--------------------------------------------------------------*/ if ((SplFAInfo->End_Page != MAX_INT) && (SplFAInfo->End_Page != 0)) /*---------------------------------------------------- * We may not be printing to the end of the spooled * file, set EndPage to the last page to print. *---------------------------------------------------*/ { if (SplFAInfo->End_Page == SplFAInfo->Total_Pages) *EndPage = LAST_PAGE; else *EndPage = SplFAInfo->End_Page; } else { /*------------------------------------------------- * If the page range starts on the first page, * and ends on the last page, set start page to * indicate that we are printing the whole file. *------------------------------------------------*/ if (*StartPage == 0) *StartPage = PRT_WHOLE_FILE; /*----------------------------------------------------- * We are printing to the end of the spooled file, set * EndPage to special value indicating all the way to * the end. |
*----------------------------------------------------*/ *EndPage = LAST_PAGE; }/* Printing to the last page of the file. */ }/*----------------------------------------------------------- * Spooled file IS eligible for page range manipulation. *----------------------------------------------------------*/ }/* End of Get_Page_Range().*/     int Get_Spool_Data(int GSPhandle, QNAME puthere, Qsp_SPFRH_t *splfh_ptr, int which_buffer, int *EOFFlag) /********************************************************************* * Function : Get spool data (buffers) * * Syntax : int Get_Spool_Data(int splfhandle, QNAME user_sp, * Qsp_SPFRH_t *splfh_ptr, int which_buffer, * int *EOFFlag); * * Description : Get_Spool_Data will retreive the spooled file data * and place the data into the specified user space. * The required user space point (I know this is * a duplicate parameter but it worked faster this way) * is used to access the user space to check if there * is any data returned from the GET api, or if we * have reached the end of file. * * Change value : *EOFFlag - Flag indicating whether we reached * the end of the spooled file or not. * * Return value : XFrm_SUCCESS *********************************************************************/ { ERRSTRUCTURE ErrorStructure; char MsgKeyÝ4¨; ERRSTRUCTURE Error_Data;   /*------------------------------------------------------------ * Initialize local error structure for call to send program * message to the writer's joblog. *-----------------------------------------------------------*/ ErrorStructure.BytesPro = 0; |
Error_Data.BytesPro = sizeof(ERRSTRUCTURE); Error_Data.BytesAvl = 0;   /*------------------------------------------------------------------ * Call Spool API to get the buffers for the specified spooled file *-----------------------------------------------------------------*/ QSPGETSP ( GSPhandle, (char *)&puthere, (char *)SPFR0300, which_buffer, (char *)EOFActWAIT, (char *)(&Error_Data) );   /*------------------------------------------------------------------ * Check if an error occured when getting data from the spooled file *-----------------------------------------------------------------*/ if (Error_Data.BytesAvl > 0) { /* Problems have been found when getting the spooled data */ if (memcmp(Error_Data.ExcpID, "CPF33D7", 7) == 0) { Error_Data.BytesAvl = 0; /* Reset the error structure */ *EOFFlag = TRUE; /* Indicate End of file reached. */ return(XFrm_SUCCESS); }/*---------------------------------------------------- * if error on getting spooled file data, BUT end of * spooled file was reached (CPF33D7). *---------------------------------------------------*/ else { Dump_Info_to_Splf(); Send_Pgm_Msg(Error_Data.ExcpID, (void *)QualQCPFMSGF, Error_Data.ExcpData, Error_Data.BytesAvl - 16, (char *)MsgTypeDIAG, MsgKey, &ErrorStructure); return(XFrm_ERR_TERM_IMMEDIATE); }/*--------------------------------------------------------- * Error trying to get spooled file data from user space, * and NOT end of spooled file (CPF33D7). |
*--------------------------------------------------------*/ } /*------------------------------------- * Error occurred on call to QSPGETSP. *------------------------------------*/   /*------------------------------------------------------------------ * Check to see if the end of the spooled file was reached *-----------------------------------------------------------------*/ if (( splfh_ptr->Buffers_Returned == 0) && (splfh_ptr->Info_Complete_IndÝ0¨ == 'C')) *EOFFlag = TRUE; /* Return -- End of file reached */ else *EOFFlag = FALSE; /* Return -- more data to read */   return(XFrm_SUCCESS); } /* END -- Get_Spool_Data */   char * Get_User_Space_Pointer(QNAME SpaceName) /********************************************************************* * Function : Get the user space pointer * * Syntax : Get_User_Space_Pointer(QNAME SpaceName); * * Parameters : 1) SpaceName - QNAME * Name of the user space to return the pointer * to. * * Description : This function will provide the user the * user the ability to get a pointer to the * start of the specified user space. The * pointer will be returned by the function. * * Errors : Check to make sure that the call to the user space * API completed correctly * * Return Value : A pointer to the start of the user space will be * returned. * * NOTE: THIS FUNCTION ASSUMES THAT THE SPACE DOES EXIST ********************************************************************/ { ERRSTRUCTURE ErrorStructure; char MsgKeyÝ4¨; char *Temp_Pointer; /* Pointer to the user space */ |
ERRSTRUCTURE Error_Data;   /*------------------------------------------------------------ * Initialize local error structure for call to send program * message to the writer's joblog. *-----------------------------------------------------------*/ ErrorStructure.BytesPro = 0; Error_Data.BytesPro = sizeof(ERRSTRUCTURE); Error_Data.BytesAvl = 0;   QUSPTRUS ( &SpaceName, &Temp_Pointer, (char *)&Error_Data );   if (Error_Data.BytesAvl > 0) { Dump_Info_to_Splf(); Send_Pgm_Msg(Error_Data.ExcpID, (void *)QualQCPFMSGF, Error_Data.ExcpData, Error_Data.BytesAvl - 16, (char *)MsgTypeDIAG, MsgKey, &ErrorStructure); return(NULL); }/* Error trying to get a pointer to a user space. */ return Temp_Pointer; } /* END -- Get_User_Space_Pointer */   int Open_Spooled_File(int *OSPhandle, JOBID *Ojobid, SPLFID *Osplfid, int ReadRecs) /********************************************************************* * Function : Open the spooled file using spool APIs * * Syntax : int Open_Spooled_File(int *,int *, * JOBID *, SPOFID *, int); * * Parameters : 1) OSPhandle - int * * The spool handle for the spooled file. |
* * 2) Ojobid - JOBID * * The internal job identifier. * * 3) Ospllfid - SPLFID * * Internal file identifier. * * Description : This function will open a spooled file using the * Open Spooled File API. This is needed to get * the spooled file handle needed in other APIs. * * Change value : OSPhandle is set to the spool handle * * Return Value : XFrm_SUCCESS or ... ********************************************************************/ { ERRSTRUCTURE ErrorStructure; char MsgKeyÝ4¨; int SplfUnAvail = FALSE; int Osplfnum = -1; ERRSTRUCTURE Error_Data;   /*------------------------------------------------------------ * Initialize local error structure for call to send program * message to the writer's joblog. *-----------------------------------------------------------*/ ErrorStructure.BytesPro = 0; Error_Data.BytesPro = sizeof(ERRSTRUCTURE); Error_Data.BytesAvl = 0;   do { /* Loop until spooled file is available */ /*--------------------------------------------------------------- * Call QSPOPNSP API to open the spooled file *--------------------------------------------------------------*/ QSPOPNSP ( OSPhandle, (char *)(INTJOBIDUSED), Ojobid, Osplfid, (char *)INTSPLIDUSED, Osplfnum, ReadRecs, |
(char *)(&Error_Data) );   /*---------------------------------------------------------------- * Check if an error occured when opening the spooled file *---------------------------------------------------------------*/ if (Error_Data.BytesAvl > 0) { /* Problems have been found when opening the spooled file */ if (!(memcmp(Error_Data.ExcpID, "CPF3330", 7))) SplfUnAvail = TRUE; else { Dump_Info_to_Splf(); SplfUnAvail = FALSE; Send_Pgm_Msg(Error_Data.ExcpID, (void *)QualQCPFMSGF, Error_Data.ExcpData, Error_Data.BytesAvl - 16, (char *)MsgTypeDIAG, MsgKey, &ErrorStructure); return(XFrm_ERR_TERM_IMMEDIATE); }/*-------------------------------------------------- * End else if SCB not locked (CPF3330) and error * opening spooled file. *-------------------------------------------------*/ }/* if error opening spooled file. */ } while (SplfUnAvail); /* End of while spool file not available */   return(XFrm_SUCCESS); } /* END -- Open_Spooled_File */   int Retrieve_Splf_Attr(Qus_SPLA0200_t *SplfAPtr, QJOBNAM *Qualified_Job_Name, char *Spooled_File_Name, int Spooled_File_Number, JOBID *Rjobid, SPLFID *Rsplfid) /********************************************************************* * Function : Retrieve the spooled file attributes * * Syntax : int Retrieve_Spool_Attr(Qus_SPLA0200_t *, * JOBID *, SPLFID *); * |
* Description : Retrieve the attributes of the spooled file. * * Return Value : Success or failure. ********************************************************************/ { ERRSTRUCTURE ErrorStructure; char MsgKeyÝ4¨; int len; /* Length of the attribute structure */ QJOBNAM LocalQJobName; char LocalSplfNameÝ10¨; int Rsplfnum; int SplfUnAvail = FALSE; int RtnINTJOBID = FALSE; int RtnINTSPLID = FALSE; ERRSTRUCTURE Error_Data;   /*------------------------------------------------------------ * Initialize local error structure for call to send program * message to the writer's joblog. *-----------------------------------------------------------*/ ErrorStructure.BytesPro = 0; Error_Data.BytesPro = sizeof(ERRSTRUCTURE); Error_Data.BytesAvl = 0;   /* Set the length of the structure */ len = sizeof(Qus_SPLA0200_t);   if (!(memcmp(Rjobid, " ", sizeof(Rjobid)))) { memcpy(&LocalQJobName,Qualified_Job_Name,sizeof(QJOBNAM)); RtnINTJOBID = TRUE; } else memcpy(&LocalQJobName,INTJOBIDUSED,sizeof(QJOBNAM));   if (!(memcmp(Rsplfid, " ", sizeof(Rsplfid)))) { memcpy(LocalSplfName,Spooled_File_Name,sizeof(LocalSplfName)); Rsplfnum = Spooled_File_Number; RtnINTSPLID = TRUE; |
}/* Actual spooled file name and number is to be used. */ else { memcpy(LocalSplfName,INTSPLIDUSED,sizeof(LocalSplfName)); Rsplfnum = ONLY; }/* Internal spool indentifier is to be used. */     do { /* Loop until spool file is available */ /*-------------------------------------------------------------- * Call the Spool API to retrieve the spooled file attributes *-------------------------------------------------------------*/ QUSRSPLA ( (char *)(SplfAPtr), len, (char *)SPLA0200, (void *)&LocalQJobName, Rjobid, Rsplfid, (char *)LocalSplfName, Rsplfnum, (char *)&Error_Data );   /*------------------------------------------------------------- * Check if an error occured when retrieving the file's * attributes. *------------------------------------------------------------*/ if (Error_Data.BytesAvl > 0) { /* Problems have been found when retreiving attributes */ if (!(memcmp(Error_Data.ExcpID, "CPF3330", 7))) SplfUnAvail = TRUE; else { Dump_Info_to_Splf(); Send_Pgm_Msg(Error_Data.ExcpID, (void *)QualQCPFMSGF, Error_Data.ExcpData, Error_Data.BytesAvl - 16, (char *)MsgTypeDIAG, MsgKey, &ErrorStructure); return(XFrm_ERR_TERM_IMMEDIATE); |
}/*----------------------------------------------------- * End else error retrieving spooled file attributes, * and the SCB was not locked (CPF3330). *----------------------------------------------------*/ } /* Error when calling QUSRSPLA API. */ } while (SplfUnAvail); /* End of while spool file not available */   if (RtnINTJOBID) memcpy(Rjobid,SplfAPtr->Int_Job_ID,sizeof(JOBID)); if (RtnINTSPLID) memcpy(Rsplfid,SplfAPtr->Int_Splf_ID,sizeof(SPLFID));   return(XFrm_SUCCESS); } /* END -- Retrieve_Spooled_File_Attr */   /***********************************************************************/ /* Name: signal_handler */ /* Type: Sub-routine */ /* Called by: OS/400 */ /* Purpose: Signal Handling Routine */ /* Description: */ /* */ /* All CPF signal messages come here. This sub-routine will be */ /* automatically call by the system if there is an error signaled (via */ /* the signal() function call). Note that the function __GetExcData */ /* this routine is OS/400 specific and allows us to obtain info about */ /* the signal from the ILE exception handler. */ /* */ /* The following structure exists in <except.h> : */ /* */ /* typedef struct _INTRPT_Hndlr_Parms_T */ /* { Exception Message Information */ /* char Msg_IdÝ7¨; Message Identifier */ /* int Msg_Ref_Key; Message Reference Key (CL Gude) */ /* } _INTRPT_Hndlr_Parms_T; */ /* */ /* */ /* All arrays in these structures are NOT C strings - they are system */ /* values and do not end in "\0". */ /* */ /***********************************************************************/ void signal_handler(int sig) { _INTRPT_Hndlr_Parms_T ExceptData; |
  _GetExcData(&ExceptData);   Dump_Info_to_Splf();   /* signal(SIGALL, &signal_handler); Reset the signal handler */ /* Resignal the error instead of abort. Resignalling escape will cause the driver to end (same as abort). */ abort(); }/* End of signal_handler. */   /************************************************************** * function XFrm_Xt_Hndlr(_INTRPT_Hndlr_Parms_T *) * * Parameters: * * * Functions used: * * * Description: * *************************************************************/ static void XFrm_Xt_Hndlr(_INTRPT_Hndlr_Parms_T *pExceptData) { ERRSTRUCTURE esErrStruct; int fRetCode = TRUE;   /* Check the message ID. */ esErrStruct.BytesPro = 8L; QMHCHGEM (&(pExceptData->Target), 0, &(pExceptData->Msg_Ref_Key), "*HANDLE ", "", 0, &esErrStruct);   Dump_Info_to_Splf();   /*--------------------------------------------------------- * At this point a global flag maybe needed to * indicate that there was a failure with the Transform * exit program. *--------------------------------------------------------*/ abort(); } /* End of XFrm_Xt_Hndlr. */   |
/***********************************************************/ /***********************************************************/ /** **/ /** Main **/ /** **/ /***********************************************************/ /***********************************************************/   int main (int argc, char *argvݨ) { Esp_Transform_Exit_I_t * Input_Spec_Info; /* Input interface pointer */ Esp_Transform_Exit_O_t * Output_Spec_Info; /* Output interface pointer */   char *Input_Data_Stream_Bfr, *Output_Data_Stream_Bfr;   int Input_Spec_Info_Len, Input_Data_Stream_Bfr_Len, Output_Spec_Info_Len, Output_Data_Stream_Bfr_Len;   int *Output_Spec_Info_Avail, *Output_Data_Stream_Bfr_Avail;   XFrmXt_Space_Fmt_t *XFrmXt_Info;   char tempÝ10¨; int Option; /* XFrmXt input option */ int RtnCde = 0; /* Return code value from a call to an internal function. */ int Space_Size; /* Size of XFrmXt work space */ QNAME XFrmXt_Space; /* Qualified name of the XFrmXt work space. */ ERRSTRUCTURE Error_Data;   /*------------------------------------------------------- * Setup an exception handler to capture control if an * unexpected error occurs, so we can copy user spaces |
* into QSPL if they exist. *------------------------------------------------------*/ signal(SIGALL, &signal_handler);   /*--------------------------------------------------------- * Initialize the size of the error structure for the APIs *--------------------------------------------------------*/ Error_Data.BytesPro = sizeof(ERRSTRUCTURE); Error_Data.BytesAvl = 0;   if (argc == EXPECTEDPARMS) { memcpy(XFrmXt_Space.Object, XFrmXt_Work_Space, sizeof(XFrmXt_Space));   /*--------------------------------------------------------- * Set the parameters into local storage *--------------------------------------------------------*/ RtnCde = Set_Parms(argv, &Option, &Input_Spec_Info, &Input_Spec_Info_Len, &Input_Data_Stream_Bfr, &Input_Data_Stream_Bfr_Len, &Output_Spec_Info, &Output_Spec_Info_Len, &Output_Spec_Info_Avail, &Output_Data_Stream_Bfr, &Output_Data_Stream_Bfr_Len, &Output_Data_Stream_Bfr_Avail);   /*--------------------------------------------------------- * Switch statement to determine what option the writer * called the transform with. *--------------------------------------------------------*/ if (!(RtnCde)) { switch (Option) { case(INITIALIZE): /*------------------------------------------------- * Set the initial size of the space to the * maximum number of bytes that we know we might * use. |
*------------------------------------------------*/ Space_Size = ((sizeof(XFrmXt_Space_Fmt_t) + MaxXFrmBfrSize + 15)/16 + 1)*16; /*----------------------------------------------------- * Create a user space for the data transform program *----------------------------------------------------*/ Create_User_Space(XFrmXt_Space, Space_Size); /*----------------------------------------------------- * Set pointer to the XFrm work space *----------------------------------------------------*/ XFrmXt_Info = (XFrmXt_Space_Fmt_t *) Get_User_Space_Pointer(XFrmXt_Space);   if (XFrmXt_Info) /* Not Null */ { /* * Set up pointers to input parameters in Work space *-------------------------------------------------*/ XFrmXt_Info->Length_of_SplfDta_Bfr = 0;   XFrmXt_Info->XFrm_ProcessOption = &Option; XFrmXt_Info->XFrm_SpecIn = Input_Spec_Info; XFrmXt_Info->XFrm_SpecIn_Len = &Input_Spec_Info_Len; XFrmXt_Info->XFrm_In_Dta = temp; XFrmXt_Info->XFrm_Inp_Dta_Len = &XFrmXt_Info->Length_of_SplfDta_Bfr; XFrmXt_Info->XFrm_SpecOut = Output_Spec_Info; XFrmXt_Info->XFrm_SpecOut_Len = &Output_Spec_Info_Len; XFrmXt_Info->XFrm_SpecOut_Avail = Output_Spec_Info_Avail; XFrmXt_Info->XFrm_Out_Dta = Output_Data_Stream_Bfr; XFrmXt_Info->XFrm_Out_Dta_Len = &Output_Data_Stream_Bfr_Len; XFrmXt_Info->XFrm_Out_Dta_Avail = Output_Data_Stream_Bfr_Avail; /*------------------------------------------------------ * Call initialization routine * to initialize the data transform program. *-----------------------------------------------------*/ RtnCde = Initialize_XFrm_Xt(XFrmXt_Info); }/* End -- if we have XFrmXt work space. */ else |
RtnCde = XFrm_ERR_TERM_IMMEDIATE; if (*XFrmXt_Info->XFrm_SpecOut_Avail < 4) *XFrmXt_Info->XFrm_SpecOut_Avail = 4; break;   case(STARTFILE): /*------------------------------------------------------- * Set pointer to the XFrm Work space *------------------------------------------------------*/ XFrmXt_Info = (XFrmXt_Space_Fmt_t *) Get_User_Space_Pointer(XFrmXt_Space); if (XFrmXt_Info) /* Not Null */ { /* * Set up pointers to input parameters in Work space *-------------------------------------------------*/ XFrmXt_Info->Length_of_SplfDta_Bfr = 0;   XFrmXt_Info->XFrm_ProcessOption = &Option; XFrmXt_Info->XFrm_SpecIn = Input_Spec_Info; XFrmXt_Info->XFrm_SpecIn_Len = &Input_Spec_Info_Len; XFrmXt_Info->XFrm_In_Dta = temp; XFrmXt_Info->XFrm_Inp_Dta_Len = &XFrmXt_Info->Length_of_SplfDta_Bfr; XFrmXt_Info->XFrm_SpecOut = Output_Spec_Info; XFrmXt_Info->XFrm_SpecOut_Len = &Output_Spec_Info_Len; XFrmXt_Info->XFrm_SpecOut_Avail = Output_Spec_Info_Avail; XFrmXt_Info->XFrm_Out_Dta = Output_Data_Stream_Bfr; XFrmXt_Info->XFrm_Out_Dta_Len = &Output_Data_Stream_Bfr_Len; XFrmXt_Info->XFrm_Out_Dta_Avail = Output_Data_Stream_Bfr_Avail; /*------------------------------------------------------- * Call routine to *------------------------------------------------------*/ RtnCde = Start_File(XFrmXt_Info); }/* End -- If there is a XFrmXt work space. */ else RtnCde = XFrm_ERR_TERM_IMMEDIATE; if (*XFrmXt_Info->XFrm_SpecOut_Avail < 8) *XFrmXt_Info->XFrm_SpecOut_Avail = 8; break; |
  case(TRANSFORM): /*-------------------------------------------------------- * Set pointer to the XFrm Work space *-------------------------------------------------------*/ XFrmXt_Info = (XFrmXt_Space_Fmt_t *) Get_User_Space_Pointer(XFrmXt_Space); if (XFrmXt_Info) /* Not Null */ /*--------------------------------------------------------- * Call routine *--------------------------------------------------------*/ { if ((Input_Data_Stream_Bfr == NULL) && (XFrmXt_Info->Pass_Input_Data == CALLER_PASSING_SPLF_DATA)) { RtnCde = XFrm_ERR_Input_Bfr; }/* No input buffer. */ if ((Input_Data_Stream_Bfr_Len == 0) && (XFrmXt_Info->Pass_Input_Data == CALLER_PASSING_SPLF_DATA)) { RtnCde = XFrm_ERR_Input_Bfr; }/* Input buffer length not specified, or to small. */ if ((Output_Spec_Info_Len < 124) && ((XFrmXt_Info->Return_Alignment_Data == 1) || (Input_Spec_Info->Return_Align_Data == CALLER_WANTS_ALIGN_DATA))) { RtnCde = XFrm_ERR_Output_Spec; }/* Not enough space provided for output specific information. */ if (!(RtnCde)) { /* * Set up pointers to input parameters in Work space *-------------------------------------------------*/ XFrmXt_Info->XFrm_ProcessOption = &Option; XFrmXt_Info->XFrm_SpecIn = Input_Spec_Info; XFrmXt_Info->XFrm_SpecIn_Len = &Input_Spec_Info_Len; XFrmXt_Info->XFrm_SpecOut = Output_Spec_Info; XFrmXt_Info->XFrm_SpecOut_Len = &Output_Spec_Info_Len; XFrmXt_Info->XFrm_SpecOut_Avail = |
Output_Spec_Info_Avail;   RtnCde = Transform(XFrmXt_Info, Input_Data_Stream_Bfr, Input_Data_Stream_Bfr_Len, Output_Data_Stream_Bfr, Output_Data_Stream_Bfr_Len, Output_Data_Stream_Bfr_Avail); }/* End -- If no parameter problems. */ } else RtnCde = XFrm_ERR_TERM_IMMEDIATE; if (*XFrmXt_Info->XFrm_SpecOut_Avail < 44) *XFrmXt_Info->XFrm_SpecOut_Avail = 44; break;   case(ENDFILE): /*-------------------------------------------------------- * Set pointer to the XFrm Work space *-------------------------------------------------------*/ XFrmXt_Info = (XFrmXt_Space_Fmt_t *) Get_User_Space_Pointer(XFrmXt_Space); if (XFrmXt_Info) /* Not Null */ { /* * Set up pointers to input parameters in Work space *-------------------------------------------------*/ XFrmXt_Info->Length_of_SplfDta_Bfr = 0;   XFrmXt_Info->XFrm_ProcessOption = &Option; XFrmXt_Info->XFrm_SpecIn = Input_Spec_Info; XFrmXt_Info->XFrm_SpecIn_Len = &Input_Spec_Info_Len; XFrmXt_Info->XFrm_In_Dta = temp; XFrmXt_Info->XFrm_Inp_Dta_Len = &XFrmXt_Info->Length_of_SplfDta_Bfr; XFrmXt_Info->XFrm_SpecOut = Output_Spec_Info; XFrmXt_Info->XFrm_SpecOut_Len = &Output_Spec_Info_Len; XFrmXt_Info->XFrm_SpecOut_Avail = Output_Spec_Info_Avail; XFrmXt_Info->XFrm_Out_Dta = Output_Data_Stream_Bfr; XFrmXt_Info->XFrm_Out_Dta_Len = &Output_Data_Stream_Bfr_Len; XFrmXt_Info->XFrm_Out_Dta_Avail = |
Output_Data_Stream_Bfr_Avail;   /*--------------------------------------------------------- * Call routine *--------------------------------------------------------*/ RtnCde = EndFile(XFrmXt_Info); } else RtnCde = XFrm_ERR_TERM_IMMEDIATE; if (*XFrmXt_Info->XFrm_SpecOut_Avail < 4) *XFrmXt_Info->XFrm_SpecOut_Avail = 4; break;   case(TERMINATE): /*--------------------------------------------------------- * Set pointer to the XFrm Work space *--------------------------------------------------------*/ XFrmXt_Info = (XFrmXt_Space_Fmt_t *) Get_User_Space_Pointer(XFrmXt_Space); if (XFrmXt_Info) /* Not Null */ { /* * Set up pointers to input parameters in Work space *-------------------------------------------------*/ XFrmXt_Info->Length_of_SplfDta_Bfr = 0;   XFrmXt_Info->XFrm_ProcessOption = &Option; XFrmXt_Info->XFrm_SpecIn = Input_Spec_Info; XFrmXt_Info->XFrm_SpecIn_Len = &Input_Spec_Info_Len; XFrmXt_Info->XFrm_In_Dta = temp; XFrmXt_Info->XFrm_Inp_Dta_Len = &XFrmXt_Info->Length_of_SplfDta_Bfr; XFrmXt_Info->XFrm_SpecOut = Output_Spec_Info; XFrmXt_Info->XFrm_SpecOut_Len = &Output_Spec_Info_Len; XFrmXt_Info->XFrm_SpecOut_Avail = Output_Spec_Info_Avail; XFrmXt_Info->XFrm_Out_Dta = Output_Data_Stream_Bfr; XFrmXt_Info->XFrm_Out_Dta_Len = &Output_Data_Stream_Bfr_Len; XFrmXt_Info->XFrm_Out_Dta_Avail = Output_Data_Stream_Bfr_Avail; /*---------------------------------------------------------- * Call routine to terminate the XFrm exit. |
*---------------------------------------------------------*/ RtnCde = Terminate_XFrmXt(XFrmXt_Info); } else RtnCde = XFrm_ERR_TERM_IMMEDIATE; if (*Output_Spec_Info_Avail < 4) *Output_Spec_Info_Avail = 4; break;   default : /*--------------------------------------------------------- * If the option is not known, no processing will be * done for it. Essentially this would be a NOP. *--------------------------------------------------------*/ break; } /* End -- switch (Option) */ }/* End if RtnCde not 0. */ } /* End -- Number of parameters received matches number expected.*/ else /* Error in call to driver. Correct number of parameters was not passed. */ abort();   /*--------------------------------------------------------------- * Set the return code here. This will always be the normal * exit point for this driver. *--------------------------------------------------------------*/ if (RtnCde != XFrm_ERR_Output_Spec) Output_Spec_Info->Return_Code = RtnCde; else abort(); /*--------------------------------------------------------------- * Return to the caller *--------------------------------------------------------------*/   return 0; }   |