Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

AS/400 Spool Files

7 views
Skip to first unread message

Lancer

unread,
Jan 24, 2001, 9:38:04 AM1/24/01
to
I'm a relative newcomer to the AS/400, so forgive the probably *Duh*
factor of my question! <grin>. We are currently using Client Access on
the pc side of our network. I have written several applications
to "automatically" download via the client access TTO files. However,
in order to get the list of files (whose names change with every run) I
have had to resort to using a macro, copying it to a txt file and
parsing it.. I realize this is an extremely rube goldberg approach,
however, I have been unable to get any of our organization
as/400 "gurus" to give me any idea how I could "grab" that file
information. Specifically, I am grabbing spool files, then
transforming them into physical files using keysends, etc. then
downloading those physical files. Any help or direction that could get
me away from this macro technique would be appreciated.

Thanks!

--
http://www.lancercountry.com


Sent via Deja.com
http://www.deja.com/

Thomas

unread,
Jan 24, 2001, 11:09:17 PM1/24/01
to
Lancer:

Can you elaborate on what file names (the temporary PFs? the
spoolfiles? ?) change each time and why they change?

Tom Liotta

In article <94mpcb$49a$1...@nnrp1.deja.com>,

--
Tom Liotta, AS/400 Systems Programmer
The PowerTech Group, Inc.; http://www.400security.com

Lancer

unread,
Jan 25, 2001, 11:27:05 AM1/25/01
to
These are actually print spool files that are created by a now-
unsupported package. I use the CPYSPLF to convert them over to
Physical Files for download and processing on a pc. But I have had
to "script" all this thru client access by sending keystrokes, running
a macro to capture the contents of the outq and parse it to populate
the cpysplf command(s). I guess because these files are simple print
spool files they are assigned a simple job number rather than a name.
There is no way in the software package to change the output (other
than directing it to a certain outq).. and I have absolutely no
cooperation from the AS/400 gurus.. (who feel that the as/400 should be
an independent platform). I've seen a client access dll that was
apparently not visual basic compatible (I downloaded and tried to
access it, and was unable to) this particular dll showed the code in
C++ to do exactly what I want to do.. I've got a solid handle on
everything on the PC side.. it's simply that getting information about
our AS/400 system (on which I have less than a years worth of user
experience on) takes an act of congress. I know there has to be a way
to talk to the as/400 (or even have it push the files to a pc network
directory) but I've been stonewalled by 2 very territorial and
uncooperative operators that continually tell my boss it cannot be done.

In article <94o8ta$hah$1...@nnrp1.deja.com>,

AerialCircle

unread,
Jan 25, 2001, 1:03:52 PM1/25/01
to
Hi,

have I captured it right: You want to download of a number of spool files
from your AS/400 the the PC.

So, first question, why don't you use Operations Navigator? With it, it's
easy to drag-and-drop the spool-files as ASCII-txt files to you PC.

Next question, are you using Client Access Express (V4R4)? If yes, you can
use the ActiveX controls from the Express toolkit. I've used them some time
ago, with Delphi, and it was pretty cool. You can show the same tree
structure like the OpsNav, but you can "filter" the output(e.g. to only show
PRINTERS or JOBS). You can also use the Java classes, if you are a Java
programmer.

Bye
Daniel


Lancer

unread,
Jan 25, 2001, 3:36:47 PM1/25/01
to
You've pretty well got it.. However, I have in place a pc of software
that will take the (literally hundreds) of daily downloads our
organization does from the AS/400 and process them without operator
intervention. Right now it automates 98% of the process.. but I still
have to have an operator kick it off at a certain time..and identify
the job numbers of the spool files and examine them for content. I
want to totally automate this process. The code is in place on the pc
side.. and totally functional for persistent files.. but for the
spooled output files that are named by job run.. I'm up against a
wall.. (other than running a macro in client access to capture the
data, pull from the clipboard into a file and then parse the file- a
rube goldberg approach at best)


In article <94pqaf$1aj$05$1...@news.t-online.com>,

--

Charles R. Pence

unread,
Jan 25, 2001, 4:17:24 PM1/25/01
to
Lancer wrote:
> These are actually print spool files that are created by a now-
> unsupported package. I use the CPYSPLF to convert them over to
> Physical Files for download and processing on a pc. But I have had
> to "script" all this thru client access by sending keystrokes, running
> a macro to capture the contents of the outq and parse it to populate
> the cpysplf command(s). I guess because these files are simple print
> spool files they are assigned a simple job number rather than a name.
> There is no way in the software package to change the output (other
> than directing it to a certain outq).. <<SNIP>>

The other night, for lack of the CPYOUTQ tool I might have used
otherwise, I wrote my own in REXX. For your consumption <be sure
to read and heed my signature-line>; review variable ctlchar please:

/* Restriction: // Using OS/400 NLV2924 V4RxMx // */
/* Restriction: TheOutQ is assumed to be in *LIBL */
/* If spooling for QPRTSPLQ goes to TheOutQ, you get two copies in PRT133 */
parse arg TheOutQ .
address "*COMMAND"
"CRTPF QTEMP/PRT133 RCDLEN(133) MBR(*NONE) MAXMBRS(*NOMAX) SIZE(*NOMAX)"
if rc<>0 then do;
"RMVM QTEMP/PRT133 MBR(*ALL)"
end;
signal on error
"OVRPRTF QPRTSPLQ PRTTXT(*BLANK)"
"WRKOUTQ *LIBL/"TheOutQ "OUTPUT(*PRINT)"
"CPYSPLF QPRTSPLQ TOFILE(QTEMP/PRT133) TOMBR(QPRTSPLQ) CTLCHAR(*NONE) ",
"SPLNBR(*LAST) JOB(*) MBROPT(*REPLACE) "
"ovrdbf stdin tofile(qtemp/prt133) mbr(qprtsplq)"
mbrnbr=0
rexrcvf:
/* Copy a bunch of records */
parse pull line
if length(line) > 0 then do;
do while length(line) > 0
cmd="CPYSPLF"
splf=WORD(line,1)
If splf<>'File' & splf<>'5769SS1' & splf<>'*' & splf<>'(no' then do;
mbrnbr=mbrnbr+1
tofile= "TOFILE(QTEMP/PRT133)"
tombr= "TOMBR(SPL"||right(mbrnbr,5,'0')||")"
usr=WORD(line,2)
rest=right(line,65)
jobnbr=WORD(rest,3)
splnbr="SPLNBR(" WORD(rest,1) ")"
jobnam=WORD(rest,2)
job="JOB("jobnbr"/"usr"/"jobnam")"
ctlchar="CTLCHAR(*FCFC)"
address command cmd splf splnbr tofile tombr job ctlchar
end;
parse pull line
end
cpyrc=0;
end
else cpyrc=97
return cpyrc

error:
exit 99

The above REXX could have a command created; eg. CPYOUTQ OUTQINLIBL()
Refer to CRTCMD for REXX source members.
p.s. Normally I'd not suggest using a spooled interface for this; that
instead APIs should be used... but I figure it might be preferred
to some screen scraping macros.

Regards, Chuck
All comments provided "as is" with no warranties of any kind whatsoever.

Thomas

unread,
Jan 25, 2001, 11:32:08 PM1/25/01
to
Lancer:

Two general ways to go depending on your authorities on the AS/400, your
programming abilities and the means of identifying the appropriate
spoolfiles.

You apparently have enough authority to execute certain commands such as
CPYSPLF and CRTPF from a command line otherwise your macro wouldn't
work. Do you have the authority to create programs as well? Would you be
willing to create some basic AS/400 programs?

You have Client Access on your PC, so you have at least some of the
Client Access APIs available to you. Are you willing to write VB or C on
the PC to call these APIs?

Your script apparently gets the appropriate spoolfiles, so there must be
spoolfile attributes that identify which spoolfiles. Do you simply grab
all spoolfiles in a particulat *outq? Do you grab all spoolfiles from a
particular job? That is, how does your script/macro know WHICH
spoolfiles?

I'd start by suggesting you review the Client Access APIs available,
perhaps starting with the example in the Client Access for Windows 95/NT
API and Technical Reference, topic 2.14.3 in the Version 3 manual (all
I have handy right now), labelled "Example of AS/400 Object API Usage,
where the example is for "List all spooled files for the current user
and display them to the user".

The CA Express versions of the manuals are on the web and the same topic
can be seen at:

http://publib.boulder.ibm.com/pubs/html/as400/v4r4/ic2924/info/RZAIKOBJA
PIEX.HTM#HDROBJAPIEX
(copy/paste as needed)

The lead-in to the CA Express APIs is at:

http://publib.boulder.ibm.com/pubs/html/as400/v4r4/ic2924/info/rzaikidx.
htm

If this looks comfortable, then a more or less completely PC approach
seems best. Otherwise, some AS/400 CL or REXX programming is more
likely. In either case, if your macro can do it, a program is certainly
possible and reasonable.

Tom Liotta

In article <94pk4b$k9t$1...@nnrp1.deja.com>,

oleg_ch...@my-deja.com

unread,
Jan 26, 2001, 3:40:59 AM1/26/01
to
Well, i suppose your question is one of most frequntly asked question
on this forum.

See java source below, it can be easily modified to your need.
This utility program takes given
OUTQ library,
OUTQ,
PRINTER,
FILTERFILE, and optionally
SYSTEM NAME,
USER NAME,
PASSWORD
and perform following actions:
takes list of splf in given outq,
parse filter file for splf templates,
for any matched splf it write to output file command to send it in
another outq (usually printer outq).
format of filter file:
'symbol ' used as single line comments
'there maximum 3 comma-separated values
'1: splfname template(wildcards allowed (*,?), same as in DOS)
'2: userdata template
'3: string to be found in splf text (only SCS splf supported)
'string below specify search for QPRINT splf with '001-' string in it
QPRINT,*,001-

Hope it helps,
Oleg
be it can be compiled and used you must have AS/400 toolbox for java
there must be jt400.jar in your class path variable
example: set CLASSPATH=.;jt400.jar
jt400.jar can be retrieved from http://www.iseries.ibm.com/toolbox/ for
free.
if you want compiled class file just send me a note.

java source begin
*************************
import java.util.*;
import java.io.*;
//import StringComparator;
import com.ibm.as400.access.*;

public class PrintManager
{
private final static char chStar = '*',chQuesMark = '?';

private final int SPLF_NAME = 0;
private final int SPLF_NUM = 1;
private final int SPLF_JOBNAME = 2;
private final int SPLF_JOBUSER = 3;
private final int SPLF_JOBNUM = 4;
private final int SPLF_USERDATA = 5;


private AS400 system_;

private String outputQueueLib;
private String outputQueue;
private String printer;

private String filterfile;

private String listsplf[][];
private int numberofsplfs;

public PrintManager(AS400 system,String outqlib_arg,
String outq_arg, String printer_arg, String
filterfile_arg)
{
system_ = system;
outputQueueLib = outqlib_arg;
outputQueue = outq_arg;
printer = printer_arg;
filterfile = filterfile_arg;
}

public void FillSplfList()
{
int i;
try
{
String sSpooledFileName,sSpooledFileUserData;

//System.out.println(" Now receiving all
spooled files Synchronously");
SpooledFileList splfList = new SpooledFileList(
system_ );

splfList.setUserFilter("*ALL");
splfList.setQueueFilter("/QSYS.LIB/" +
outputQueueLib + ".LIB/" + outputQueue +".OUTQ");

//Trace.setTraceOn(true);
splfList.openSynchronously();
//Trace.setTraceOn(false);

numberofsplfs = splfList.size();
listsplf = new String[numberofsplfs][6];
System.out.println("numberofsplfs=" +
numberofsplfs);

Enumeration enum = splfList.getObjects();

for(i=0; enum.hasMoreElements(); i++)
{
SpooledFile splf = (SpooledFile)
enum.nextElement();
if ( splf != null )
{
listsplf[i][SPLF_NAME] =
splf.getName();
listsplf[i][SPLF_NUM] = "" +
splf.getNumber();
listsplf[i][SPLF_JOBNAME] =
splf.getJobName();
listsplf[i][SPLF_JOBUSER] =
splf.getJobUser();
listsplf[i][SPLF_JOBNUM] =
splf.getJobNumber();
listsplf[i][SPLF_USERDATA] =
splf.getStringAttribute(SpooledFile.ATTR_USERDATA);
//System.out.println("splf
name:" +listsplf[i][SPLF_NAME] + ", " + splf.getName());
} else System.out.println("null splf
object");

}
// clean up after we are done with the list

splfList.close();
//System.out.println(" Done receiving all
spooled files Synchronously");
}
catch( Exception e )
{
e.printStackTrace();
}
}

public int FindSplf(String splfname_template,int index)
{
System.out.println("Finding splf for '" +
splfname_template + "'");
int i;
for(i=index; i<numberofsplfs; i++)
{
//System.out.println("Checking " + listsplf[i]
[SPLF_NAME]);
if( CompareMask(listsplf[i]
[SPLF_NAME],splfname_template) ) return i;
}
return -1;
}

public int FindSplf(String splfname_template,String
splfuserdate_template,int index)
{
System.out.println("Finding splf for '" +
splfname_template + "','" + splfuserdate_template + "'");
int i;
for(i=index; i<numberofsplfs; i++)
{
i = FindSplf(splfname_template,i);
if( i < 0 ) return i;
if( CompareMask(listsplf[i]
[SPLF_USERDATA],splfuserdate_template) ) return i;
}
return -1;
}

public int FindSplf(String splfname_template,String
splfuserdate_template,String splfdata, int index)
{
System.out.println("Finding splf for '" +
splfname_template + "','" + splfuserdate_template + "','" + splfdata
+ "'");

int i;
for(i=index; i<numberofsplfs; i++)
{
i = FindSplf
(splfname_template,splfuserdate_template,i);
if( i < 0 ) return i;
if( SplfContainsString(i,splfdata) ) return i;
}
return -1;
}
public boolean SplfContainsString(int index, String s)
{
String stemp;
byte[] buf = new byte[512];
boolean b = false;
PrintParameterList printParms = new PrintParameterList
();
Integer i = new Integer(listsplf[index][SPLF_NUM]);
try
{
SpooledFile splf = new SpooledFile( system_,
// AS400
listsplf[index][SPLF_NAME],
i.intValue(),
listsplf[index][SPLF_JOBNAME],
listsplf[index][SPLF_JOBUSER],
listsplf[index][SPLF_JOBNUM]);

printParms.setParameter(

PrintObject.ATTR_WORKSTATION_CUST_OBJECT,
"/QSYS.LIB/RBATOOL.LIB/NULL.WSCST");

printParms.setParameter(
PrintObject.ATTR_MFGTYPE,
"*WSCST");

//System.out.print("Checking splf file " +
SplfCommandString(index) + " for occurence of '" + s +"'...");

InputStream in = splf.getTransformedInputStream
(printParms); //splf.getInputStream();
in.read( buf );
stemp = new String(buf);
//System.out.println("Received data: '" + stemp
+ "'");
if( stemp.indexOf(s) > 0 )
b = true;
else
b = false;
in.close();
} //TRY BLOCK
//com.ibm.as400.access.AS400SecurityException
//com.ibm.as400.access.AS400Exception
catch (Exception e)
{
//
e.printStackTrace();
}
if (b) System.out.println(" found!");
else System.out.println(" not found");

return b;
}


public void ProcessSplfList() throws java.io.IOException
{
System.out.println("Entered ProcessSplfList");
InputStream is;
//try to open config file
try
{
is = new FileInputStream(filterfile);
}
catch(FileNotFoundException fnfe)
{
System.out.println("FileNotFound");
return;
}

OutputStream os = new FileOutputStream("commands.out");
PrintWriter por = new PrintWriter(os);

//chgusrprf prtuser outq(*libl/edp)
por.println("chgusrprf prtuser outq(*libl/" + printer
+ ")");

BufferedReader bir = new BufferedReader(new
InputStreamReader(is));
StringTokenizer st;

String s;
String token,token2,token3;
boolean b;
int i;
while( true )
{
s = bir.readLine();
if( s == null) break;//eof
s.trim();
switch (s.charAt(0))
{
case '\'':
//comment line, just skip to
the next line
continue;
case '~':
//new department section
por.println(
"STRREXPRC SRCMBR(DEP_HEADER)
SRCFILE(EODLIB/QREXSRC) PARM('" +
s.substring(1) + " " +
printer + "')");
continue;
}
//System.out.println(s);
st = new StringTokenizer(s,",");

switch (st.countTokens())
{
case 1:
token = st.nextToken();
for(i=0; i>=0; i++)
{
i = FindSplf(token,i);
if ( i >= 0)
{
PrintSplfCommandString
(i,por);
System.out.println
("Found splf for '" + s + "': '" + SplfCommandString(i));
}
else break;
}
break;
case 2:
token = st.nextToken();
token2 = st.nextToken();
for(i=0; i>=0; i++)
{
i = FindSplf(token,token2,i);
if ( i >= 0)
{
PrintSplfCommandString
(i,por);
System.out.println
("Found splf for '" + s + "': '" + SplfCommandString(i));
}
else break;
}
break;
case 3:
token = st.nextToken();
token2 = st.nextToken();
token3 = st.nextToken();
for(i=0; i>=0; i++)
{
i = FindSplf
(token,token2,token3,i);
if ( i >= 0)
{
PrintSplfCommandString
(i,por);
System.out.println
("Found splf for '" + s + "': '" + SplfCommandString(i));
}
else break;
}
break;
}
}
bir.close();
is.close();
por.close();
}

private void PrintSplfCommandString(int i, PrintWriter pr)
{
pr.println("RLSSPLF " + SplfCommandString(i));
pr.println("SNDNETSPLF TOUSRID(PRTUSER " +
system_.getSystemName() + ") DTAFMT(*ALLDATA) "
+ SplfCommandString(i));
}
private String SplfCommandString(int i)
{
return "FILE (" + listsplf[i][SPLF_NAME] +
") JOB(" + listsplf[i][SPLF_JOBNUM] + "/" +
listsplf[i][SPLF_JOBUSER] + "/" + listsplf[i][SPLF_JOBNAME] +
") SPLNBR(" + listsplf[i][SPLF_NUM] + ")";
}

public boolean CompareMask(String string, String mask)
{
int i,j,c;
string = string.toUpperCase();

StringTokenizer st = new StringTokenizer
(mask.toUpperCase(),"*?",true);

int tokenlen;
int counttoken = st.countTokens();

String tokenarr[] = new String[counttoken];

i=0;
while (st.hasMoreTokens()) tokenarr[i++] = st.nextToken
();


i=0; c=0;
while (c < counttoken )
{
switch (tokenarr[c].charAt(0))
{
case chStar:
if( c < counttoken-1 )
{
i = string.indexOf(tokenarr
[c+1],i);
if( i < 0 ) return false;
i--;
}
else
return true;
break;
case chQuesMark:
break;
default:
if ( !string.regionMatches(i,tokenarr
[c],0,tokenarr[c].length()))
return false;
break;
}
i += tokenarr[c].length();
c++;
}
return true;
}


public static void main( String args[] )
{
System.out.println("args.length=" + args.length);
if( args.length < 4)
{
System.out.println("Invalid command options");
System.out.println("Usage:");
System.out.println(" outqlib outq printer
filterfile <system> <user> <password>");
System.exit(0);
}

AS400 system = new AS400(); //(args[0],args[1],args[2]);
try
{
if (args.length>4) system.setSystemName(args
[4]);
if (args.length>5) system.setUserId(args[5]);
if (args.length>6) system.setPassword(args[6]);
}
catch (Exception e)
{
e.printStackTrace();
}
PrintManager pm = new PrintManager(system,args[0],args
[1],args[2],args[3]);

try
{
//Trace.setTraceDiagnosticOn(true);
//Trace.setTraceInformationOn(true);
//Trace.setTraceWarningOn(true);
//Trace.setTraceAllOn(true);
//Trace.setFileName("trace.log");
system.connectService(AS400.PRINT);
pm.FillSplfList(); System.out.println
("FillSplfList complete.");
pm.ProcessSplfList(); System.out.println
("ProcessSplfList complete.");
system.disconnectService(AS400.PRINT);
}
catch (Exception e)
{
e.printStackTrace();
}
System.exit(1);
}

}
********************
java source end

oleg_ch...@my-deja.com

unread,
Jan 26, 2001, 8:25:18 AM1/26/01
to
If you dont like Java i have similar utility written
in c++ using Client Access Express API,
it's dspoutq.exe and it's output is exactly as from wrkoutq
Just send me a note if interested.
Regards,
Oleg

Daniel Gross

unread,
Jan 26, 2001, 5:51:03 PM1/26/01
to
Hi,

> the job numbers of the spool files and examine them for content. I
> want to totally automate this process. The code is in place on the pc

I just got another "cool" idea, but I don't know if it will help you. If you
can direct all spool files to one outq, you can setup this outq to send the
spool files via LPR to an LPD daemon on your network. With linux on the LPD
side, it's easy to setup a "virtual" printer, which will catch all spools.
This solution will work absolutly "operatorless".

Bye
Daniel

alba...@my-deja.com

unread,
Jan 29, 2001, 6:18:59 PM1/29/01
to
Lancer,
I had a similar problem with having to automate downloading of files
from the AS/400 to the PC. I ended up using C API's to write the PF's
to the Integrated File System(IFS) which is like a PC side of the 400.
The code is relatively simple. All you have to do is read a record,
write a record out to a stream file(ASCII text file on PC).

If you want the code let me know and I will post it, otherwise I wont
go to the work of documenting my program so I can stick it on the
internet;-).
Aaron Bartell

Michae...@isiinternet.com

unread,
Jan 29, 2001, 7:38:07 PM1/29/01
to
You also could try e-mailing the spool files using the CPYSPLF and SNDDST
commands. I'm trying to set up something similar. If I figure out my
problems, I could let you know.

alba...@my-deja.com

unread,
Jan 31, 2001, 6:17:05 PM1/31/01
to
Just download SPLTOOL from www.bvstools.com. It is about $200 dollars
and is more than worth that. There are packages that do similar things
out there that cost $5000!

SPLTOOL can email(as HTML,PDF,DOC,TXT etc), FTP, Copy to a stream file,
Copy to a file, . . . you name it, it can do it.

Aaron Bartell

0 new messages