I am trying to gather information on particular jobs that are
running, but want to do this dynamically. We have a third party setup
(JHS), but have never been able to find an interface that would allow me
to enter job(s) and return the status on them dynamically..
So is it possible to pull the start/end/status of a job that has
or has not run(obviously if not run, then not found) today??
If you have any questions and/or problems, please let me know.
Thanks.
Wags ;)
David R. Wagner
Senior Programmer Analyst
FedEx Services
1.719.484.2097 Tel
1.719.484.2419 Fax
1.408.623.5963 Cell
http://Fedex.com/us
----------------------------------------------------------------------
For TSO-REXX subscribe / signoff / archive access instructions,
send email to LIST...@VM.MARIST.EDU with the message: INFO TSO-REXX
But don't lose hope just yet.
If you run some console automation software (e.g. AF Operator), it could watch for job end messages and save the date/time/maxCC in a variable, which you could query later via TSO REXX. The specifics of this approach vary based on which console automation software you run (BMC AutoOPERATOR, CA OPS-MVS, SA z/OS, AF Operator, etc.). Write back with that info for additional details.
If this is a production batch job submitted by a job scheduler, you can use the scheduler's REXX API to look up job history. Not every job scheduler has a REXX API, so again, post back with details on what job scheduler you use, if any.
You can also use the REXX API to SDSF, CA SysView, or IOF (and probably others) to examine either the job output, or the syslog, via REXX. As long as the syslog wasn't written out, or the job output purged, you could find the job there.
Regards,
Bob Stark
ProTech - When you're serious about Systems Management
Consulting, Software, and Training for z/OS, UNIX and Internet
www.protechtraining.com 800-373-9188 x151 Cell: 412-445-8072
--
If this email is spam, report it here:
http://www.onlymyemail.com/view/?action=reportSpam&Id=Mzg3MzE6MTEyODE3NDU5MTpic3RhcmtAcHJvdGVjaHB0cy5jb206ZGVsaXZlcmVk
You can actually run SDSF as a batch job (EXEC PGM=SFSF), and there's a manual that describes how to set up the input commands (sorry, I don't have the reference handy right now). It's a little tricky, and took me a fair amount of experimentation to get the right commands for what I wanted to do. It's not intuitively obvious, even if you know SDSF fairly well.
So basically anything you can see using SDSF, you can get by running a batch job.
So from there, it's only a small step to creating a REXX exec that sets up the needed commands, allocates the input and output files, and then invokes "SDSF": ADDRESS LINKMVS "SDSF SDSFPARM" (in my case SDSFPARM was null, and all the logic was in the input commands).
You can run a REXX Exec online that does this, but I even got it working so that I could submit a batch job, which was a REXX program running under batch ISPF, that could query its own status.
Again, the way I got this all working was by experimenting over and over with a batch job that just executed SDSF directly (EXEC PGM=SDSF), and then once I got the right set of commands for what I needed, I incorporated them into the REXX Exec.
Again, sorry this is so sketchy -- let me know if you need more info.
Jeff
-----Original Message-----
From: TSO REXX Discussion List [mailto:TSO-...@VM.MARIST.EDU] On Behalf Of Wagner, David --- Senior Programmer Analyst --- CFS
Sent: Monday, July 26, 2010 1:58 PM
To: TSO-...@VM.MARIST.EDU
Subject: Ability to pull job information from MVS environment
Well, can't you OUTTRAP the results of STATUS and OUTPUT commands
and parse the result? Seems like it would be a low overhead approach.
ST
ST jobname
ST jobname(Jjobid)
return one of:
NO JOBS FOUND
JOB NOT FOUND
JOB WAITING EXECUTION
JOB EXECUTING
JOB ON OUTPUT QUEUE
then if the job is on the output queue, issue
OUTPUT (jobname[Jjobid]) PRINT({*|dsname})
where the * option will put output to the terminal, and dsname
will put the output to <hlq>.<dsname>.OUTLIST where you can then
process it.
--
Kind regards,
-Steve Comstock
The Trainer's Friend, Inc.
303-393-8716
http://www.trainersfriend.com
* To get a good Return on your Investment, first make an investment!
+ Training your people is an excellent investment
As they say, I have a enough knowledge to be dangerous, but not enough to possibly get the job done.
That is what is going on in a nutshell. I was thinking it should not be that big a thing, but obviously it is and can be.
I appreciate the insight and the time..
Thanks.
Wags ;)
David R. Wagner
Senior Programmer Analyst
FedEx Services
1.719.484.2097 Tel
1.719.484.2419 Fax
1.408.623.5963 Cell
http://Fedex.com/us
>
If the job is not a scheduled job, your best bet is probably looking at the
spool for SYSOUT from the job. using the SDSF/REXX API is probably your
best bet here.
In a message dated 7/26/2010 10:59:49 A.M. US Mountain Standard Time,
david....@FEDEX.COM writes:
Another question is can I use Rexx to get information concerning
a particular job and know if it has run today and/or whether it was
successful or not..
I am trying to gather information on particular jobs that are
running, but want to do this dynamically. We have a third party setup
(JHS), but have never been able to find an interface that would allow me
to enter job(s) and return the status on them dynamically..
So is it possible to pull the start/end/status of a job that has
or has not run(obviously if not run, then not found) today??
If you have any questions and/or problems, please let me know.
Thanks.
Wags ;)
David R. Wagner
Senior Programmer Analyst
FedEx Services
1.719.484.2097 Tel
1.719.484.2419 Fax
1.408.623.5963 Cell
http://Fedex.com/us
You might check out the JHS Utilities manual for the print utility program (JHSPRINT). The drawback (at least in the JHS we run here) is that you have to know the job number as well as the job name, but if you have another way to determine what the job number is, then you can "print" DSID(2) for that job name and number, which is the DSID for the JESMSGLG output collected by JHS. Write the output to a file and then you could read the file using REXX and extract all the information you have requested.
Here is a simple example that I can share; replace the <...> bracketed information with your installation and job names/numbers:
//GETSYSLG EXEC PGM=JHSPRINT
//STEPLIB DD DSN=<your-JHS-library-HLQ>.JHSLIB,DISP=SHR
//SYSPRINT DD SYSOUT=*
//OUTFILE DD DISP=(NEW,CATLG,CATLG),DSN=&SYSUID..<jobname>.JESMSGLG,
// UNIT=SYSDA,SPACE=(TRK,(15,15),RLSE),
// DSORG=PS,RECFM=VBA,LRECL=259,BLKSIZE=0
//SYSIN DD *
OPTIONS OUTFILE(OUTFILE)
LOGON SYSTEM(<systemname of your JHS>) FROMSYS(<jobname of your JHS>)
TEXT
TEXT
PRINT JOB(<yourjobname>) JOBNUMBER(<yourjobnumber>) DSID(00002)
//*
HTH
Peter
This message and any attachments are intended only for the use of the addressee and
may contain information that is privileged and confidential. If the reader of the
message is not the intended recipient or an authorized representative of the
intended recipient, you are hereby notified that any dissemination of this
communication is strictly prohibited. If you have received this communication in
error, please notify us immediately by e-mail and delete the message and any
attachments from your system.
If the job is not scheduled, here is some quick and dirty REXX using the
SDSF/REXX API to list all the jobs matching your provided jobname in the
HOLD queue and an attempt to look for them currently running.
Not perfect, but a start...
000001 /* rexx */
000002 arg jobname .
000003 if isfcalls('ON') <> 0 then exit 99
000004 isfprefix = jobname
000005 isfsort = 'dsdate d'
000006 address SDSF "ISFEXEC H"
000007 say isfrows 'Held Jobs matching' jobname',RC='RC
000008 say
000009 say 'JOBNAME JOBNUM DATE TIME RECORDS MAX-RC'
000010 say '---------------------------------------------------------'
000011 do h=1 to isfrows
000012 say left(jname.h,8) jobid.h dsdate.h right(reccnt.h,10)
retcode.h
000013 end
000014 say
000015 drop isfsort
000016 address SDSF "ISFEXEC DA"
000017 say isfrows 'Active Jobs matching' jobname',RC='RC
000018 say
000019 say 'JOBNAME JOBNUM'
000020 say '-----------------'
000021 do a=1 to isfrows
000022 say left(jname.a,8) jobid.a
000023 end
000024 call isfcalls 'OFF'
Rob
In a message dated 7/26/2010 10:59:49 A.M. US Mountain Standard Time,
david....@FEDEX.COM writes:
Another question is can I use Rexx to get information concerning
a particular job and know if it has run today and/or whether it was
successful or not..
I am trying to gather information on particular jobs that are
running, but want to do this dynamically. We have a third party setup
(JHS), but have never been able to find an interface that would allow me
to enter job(s) and return the status on them dynamically..
So is it possible to pull the start/end/status of a job that has
or has not run(obviously if not run, then not found) today??
If you have any questions and/or problems, please let me know.
Thanks.
Wags ;)
David R. Wagner
Senior Programmer Analyst
FedEx Services
1.719.484.2097 Tel
1.719.484.2419 Fax
1.408.623.5963 Cell
http://Fedex.com/us
Rob
In a message dated 7/26/2010 1:52:20 P.M. US Mountain Standard Time,
david....@FEDEX.COM writes:
>-----Original Message-----
>From: TSO REXX Discussion List [mailto:TSO-...@vm.marist.edu] On Behalf
Of
>Steve Comstock
>Sent: Monday, July 26, 2010 14:37
>To: TSO-...@vm.marist.edu
>Subject: Re: [TSO-REXX] Ability to pull job information from MVS
>environment
>
>Wagner, David --- Senior Programmer Analyst --- CFS wrote:
>> Another question is can I use Rexx to get information concerning
>> a particular job and know if it has run today and/or whether it was
>> successful or not..
>>
>> I am trying to gather information on particular jobs that are
>> running, but want to do this dynamically. We have a third party setup
>> (JHS), but have never been able to find an interface that would allow me
>> to enter job(s) and return the status on them dynamically..
>>
>> So is it possible to pull the start/end/status of a job that has
>> or has not run(obviously if not run, then not found) today??
>>
>> If you have any questions and/or problems, please let me know.
>> Thanks.
>>
>> Wags ;)
>> David R. Wagner
>> Senior Programmer Analyst
>> FedEx Services
>> 1.719.484.2097 Tel
>> 1.719.484.2419 Fax
>> 1.408.623.5963 Cell
>> http://Fedex.com/us
>
>Well, can't you OUTTRAP the results of STATUS and OUTPUT commands
>and parse the result? Seems like it would be a low overhead approach.
>
>ST
>ST jobname
>ST jobname(Jjobid)
>
>return one of:
>
>NO JOBS FOUND
>JOB NOT FOUND
>JOB WAITING EXECUTION
>JOB EXECUTING
>JOB ON OUTPUT QUEUE
>
>then if the job is on the output queue, issue
>
>OUTPUT (jobname[Jjobid]) PRINT({*|dsname})
>
>where the * option will put output to the terminal, and dsname
>will put the output to <hlq>.<dsname>.OUTLIST where you can then
>process it.
>
>
>
That is the problem in that the output is saved immediately at the
completion of the job into the world as it is known by JHS ( JCL Output Archiver
). I am not a REXX programmer, but one who gathers existing reports, works
with the reports and generates internal emails for our organization. I
currently have an unique trigger dsn created which is then processed by other
programs from another site. Instead of the trigger dsn, I was attempting to
come up with a simple approach looking at my current list of say 30-45 jobs,
gather the start, stop and condition code of the processing. Check if
today and have not processed yet, then generate the process to do the work on
email A. Then loop on this data until complete, starting other processes as
needed, write out the jobs that were worked on with the date/time/condtion,
so I know whether to do the work or not. They for the most part run once a
day spread out over the day.
The current setup has been working well, but running into some other
issues and was looking to see if there was alternative to what I am doing...
As they say, I have a enough knowledge to be dangerous, but not enough to
possibly get the job done.
That is what is going on in a nutshell. I was thinking it should not be
that big a thing, but obviously it is and can be.
I appreciate the insight and the time..
Thanks.
Wags ;)
David R. Wagner
Senior Programmer Analyst
FedEx Services
1.719.484.2097 Tel
1.719.484.2419 Fax
1.408.623.5963 Cell
http://Fedex.com/us
>
>--
>
>Kind regards,
>
>-Steve Comstock
>The Trainer's Friend, Inc.
>
>303-393-8716
>http://www.trainersfriend.com
>
>* To get a good Return on your Investment, first make an investment!
> + Training your people is an excellent investment
>
Anyway, find those datasets, change "<JOBNAM>" in the SYSIN card to a JOB name you want information for and run this and see if it produces something useful for what you're trying to do.
Thanks,
Dave K.
P.S. The comments at the end of this explain what the control card fields are in case you want to query for this JOB within specific run times or ranges or whatever.
//REPORT EXEC PGM=SASSHIS8,PARM='O,100000'
//*
//SYSLIST DD SYSOUT=*
//SYSOUT DD SYSOUT=*
//SYSUDUMP DD SYSOUT=*
//SORTWK01 DD UNIT=SYSDA,SPACE=(CYL,8)
//SORTWK02 DD UNIT=SYSDA,SPACE=(CYL,8)
//SORTWK03 DD UNIT=SYSDA,SPACE=(CYL,8)
//SORTWK04 DD UNIT=SYSDA,SPACE=(CYL,8)
//SORTWK05 DD UNIT=SYSDA,SPACE=(CYL,8)
//SORTWK06 DD UNIT=SYSDA,SPACE=(CYL,8)
//CNTLREPT DD SYSOUT=*,DCB=BLKSIZE=133
//UCC7HIST DD DUMMY, DSN=CA7.LOG.DATASET.NAME,
// DISP=SHR
//*
//UCC7ARCH DD DSN=CA7.ARCHIVE.DATASET.NAME,
// DISP=SHR
//SYSIN DD *
06HIST RPT <JOBNAM> 123INDEX
/* |_______||_______|
//* POS 1 - 2 REPORT ID = 06
//* POS 3 - 10 REQUEST ID LITERAL (BANNER DATA)
//* POS 11 - 15 FROM DATE
//* POS 16 - 19 FROM TIME
//* POS 20 - 24 TO DATE
//* POS 25 - 28 TO TIME
//* POS 29 - 36 JOBNAME
//* POS 37 - 38 RESERVED
//* POS 39 - 41 SORT ORDER
//* 1 = DATE/TIME THE LOG RECORD WAS WRITTEN
//* 2 = JOB NAME
//* 3 = SYSTEM ID
//* POS 42 - 46 LITERAL "INDEX" - ONE LINE INDEX ENTRY PER JOB IS PRINTED
//* POS 47 - 50 SMFID TO REPORT ON
//* POS 51 - 80 USER COMMENTS
//*
>
>
We are running under CA7 Scheduler (at least that is the terminology used by Computer Operations) and as stated in the initial email, the data is not around at the completion of a 'production job', but moved in 99% of the processing, so the jcl history can be reviewed by JHS software ( SystemWare ).
------------------------------------------------------------------------------
This e-mail transmission may contain information that is proprietary, privileged and/or confidential and is intended exclusively for the person(s) to whom it is addressed. Any use, copying, retention or disclosure by any person other than the intended recipient or the intended recipient's designees is strictly prohibited. If you are not the intended recipient or their designee, please notify the sender immediately by return e-mail and delete all copies. OppenheimerFunds may, at its sole discretion, monitor, review, retain and/or disclose the content of all email communications.
==============================================================================
From my experience you have a couple options (maybe already touched on
here),
1. If the JCL is up for change, add a control step to the end of the job to
update a database file of some sort with the relevant information (Jobname,
Run Times, High CC, etc.). This has applicability beyond just this need.
2. If you have an automation tool, have it capture the relevant messages
(Submitted/Started, Step CC, Max CC, etc.) and update a DB file in the same
manner.
3. Is there a Jes Exit that can be used to filter on jobname and to fire on
your selected jobs to retrieve the data for you and store it?
Options 2 and 3 are the least likely to bypass the process, as the
programmer could easily remove the recording step when running the job
manually. However, if you are dependent on the jobname as the filter,
changing that will bypass the process, too.
These are a couple ideas to mix in the pot of stew offered by lots of others
so far...
*dj*
> //UCC7HIST DD DUMMY, DSN=CA7.LOG.DATASET.NAME<http://ca7.log.dataset.name/>
> ,
> // DISP=SHR
> //*
> //UCC7ARCH DD DSN=CA7.ARCHIVE.DATASET.NAME<http://ca7.archive.dataset.name/>
Mickey
--------------------------------------------------
From: "Robert Zenuk" <Robz...@AOL.COM>
Sent: Monday, July 26, 2010 5:25 PM
To: <TSO-...@VM.MARIST.EDU>
Subject: Re: [TSO-REXX] Ability to pull job information from MVS environment
> While there are several round about ways to find this stuff, they are all
I guess I was coming from my perspective in a large shop and projecting
that onto FEDEX as another large shop... We would never entertain a
"one-off" automation request for a single job unless it was a critical path job
that had enterprise-wide significance. We would have thousands of these.
Having averaged over a million scheduled batch jobs per month for the last
10 years, this would be an unmanageable stream of requests.
All batch customers have access to the Job Scheduler, Restart Manager and
Sysout Management products and are provided with training on the online
query tools and provided JCL examples for batch utilities. Without a self
help approach, we would be inundated with requests. This mandated several
features in the products selected to insure it was possible to get the self
help. Things like user customization (notifications, email alerts, pager
alerts, etc) had to be easy for a customer to accomplish. Online history and
query tools were also a high priority in product selection.
Most customers that need extra/enhanced application specific runtime
information will tack extra steps on the end of their jobs to post details to a
database, send an SMTP email or log to a history file or something. Many
jobs will write all reports to DASD and have post scraper steps to generate
the required results. However, the desired approach is to modify the
original program to implement the new function. Since project schedules and
delivery dates are driven by others, this can mean interim solutions.
So, trying to stay off the soap-box and provide some value I provides my
SDSF/REXX suggestion...
Rob
In a message dated 7/30/2010 4:36:11 A.M. US Mountain Standard Time,
David, you should definitely contact the Systemware Technical support
folks, and tell them what you want, and ask them for the best
solution. I've had the opportunity to do just that with them in the
past, and they are fairly good to work with. We utilize the Xptr (now
CS/z side of their software, so I am not as familiar with the JHS
offering. I do know, they have multiple ways of setting up 'report
distribution'/bundling in it, and would not be surprised to see it in
the JHS offering. If it is in there, they also have email drivers,
where you may be able to set up index programs to look at the job as
it is being captured into JHS and cause automatic emails to come out,
and possibly to write to MVS dsns at the same time (if you want to).
We do that with the CS Z offering, with the information that is
collected into their JHSLOG for the started task.
Regards,
Bob
/* REXX */
CALL RUNMON GACHKACB
SAY 'NTV309I MYRC='MYRC
EXIT
RUNMON:
ARG TMPMON
INTERPRET 'MYRC='TMPMON||'(VTHOM)'
RETURN MYRC
This is going to be a dynamic routine that calls a monitor. In this
case I simply hardcoded GACHKACB. In the real world the routine will
lookup the routine name and pass it to the code so I have to be able
to interpret TMPMON somehow at runtime. Does anyone have any
thoughts? Thanks for your ideas. I do have the CALL VALUE in my
solution package, but I do not see how this will get me closer to a
solution in this case.
Thanks,
Thom Stone
Deere & Company
Capacity Planning and Performance
NetView Automation Team
StoneT...@JohnDeere.com
ston...@mchsi.com
ts2...@gmail.com
"Run Smart... Run Fast... Run Lean with our Great Machines"
/* REXX */
CALL RUNMON GACHKACB
SAY 'NTV309I MYRC='MYRC
EXIT
RUNMON:
ARG TMPMON
INTERPRET 'MYRC='TMPMON||'(VTHOM)'
RETURN MYRC
This is going to be a dynamic routine that calls a monitor. In this case I simply hardcoded GACHKACB. In the real world the routine will lookup the routine name and pass it to the code so I have to be able to interpret TMPMON somehow at runtime. Does anyone have any thoughts? Thanks for your ideas. I do have the CALL VALUE 'GA.JOBNAME.'PTR, MBRNAME in my solution package, but I do not see how this will get me closer to a solution in this case.
Thanks,
Thom Stone
Deere & Company
Capacity Planning and Performance
NetView Automation Team
StoneT...@JohnDeere.com
"Run Smart... Run Fast... Run Lean with our Great Machines"
----------------------------------------------------------------------
/* REXX */
CALL RUNMON GACHKACB
SAY 'NTV309I MYRC='MYRC
EXIT
RUNMON:
ARG TMPMON
INTERPRET 'MYRC='TMPMON||'(VTHOM)'
RETURN MYRC
This is going to be a dynamic routine that calls a monitor. In this
case I simply hardcoded GACHKACB. In the real world the routine will
lookup the routine name and pass it to the code so I have to be able
to interpret TMPMON somehow at runtime. Does anyone have any
thoughts? Thanks for your ideas. I do have the CALL VALUE in my
Tony
/* REXX */
CALL RUNMON GACHKACB
SAY 'NTV309I MYRC='MYR
EXIT
RUNMON:
ARG TMPMON
MYRC=TMPMON||'(VTHOM)'
RETURN MYRC
Not quite:
NTV309I MYRC=GACHKACB(VTHOM)
but I'll try and massage it a bit more.
This works if you are returning Return Codes:
/* REXX */
CALL RUNMON GACHKACB
SAY 'NTV309I MYRC='MYRC
EXIT
RUNMON:
TRACE O
ARG TMPMON
TMPVAR=TMPMON 'VTHOM'
TMPVAR
MYRC=RC
RETURN MYRC
I'll have to keep thinking about this for values.
> -----Original Message-----
> From: TSO REXX Discussion List [mailto:TSO-...@VM.MARIST.EDU] On Behalf Of Thom Stone
> Sent: Thursday, September 09, 2010 1:32 PM
> To: TSO-...@VM.MARIST.EDU
> Subject: Help with INTERPRET
>
> Hello,
> I have the following short sample of code that I want to use in a larger project, but I'd prefer not to use interpret if possible.
>
> /* REXX */
> CALL RUNMON GACHKACB
> SAY 'NTV309I MYRC='MYRC
> EXIT
>
>
> RUNMON:
> ARG TMPMON
> INTERPRET 'MYRC='TMPMON||'(VTHOM)'
> RETURN MYRC
-- gil
(Note that here you're using the variable MYRC that was set in the
RUNMON routine, and ignoring the result that it returned. The value it
returns is put in the variable RESULT.)
> RUNMON:
> ARG TMPMON
> INTERPRET 'MYRC='TMPMON||'(VTHOM)'
> RETURN MYRC
Does the monitor exec return anything other than a number, and does it
care how it was called? If not, how about just issuing it as a command?
RunMon:
Arg tmpMon
tmpMon vthom
Return rc
If you do need to handle non-numeric results, or if the exec is
sensitive to whether it's called as a command or a function, you're
stuck with either INTERPRET or a hardcoded list of monitor names:
RunMon:
Arg tmpMon
Select
When tmpMon = 'GACHKACB' then myrc = 'GACHKACB'(vthom)
When tmpMon = 'BLAHBLAH' then myrc = 'BLAHBLAH'(vthom)
...
End
Return myrc
If they were internal routines, you could use SIGNAL VALUE to pass
control to them:
RunMon:
Arg tmpMon
Signal Value tmpMon
GACHKACB:
...
Return ...
BLAHBLAH:
...
Return ...
But function and subroutine calls just don't have any comparable way to
specify the name of the routine as an expression.
¬R
Classic REXX doesn't have a CALL [variable] construct. Not sure about added-value versions out there.
Tony
-----Original Message-----
From: Paul Gilmartin
Sent: Thursday, September 09, 2010 4:40 PM
To: TSO-...@VM.MARIST.EDU
Subject: Re: Help with INTERPRET
No, because it does not call the function whose name is stored in TMPMON.
On 09/09/10 12:11, Vitonis, Tony wrote:
> Does the code below do what you're expecting?
>
> Tony
>
> /* REXX */
>
> CALL RUNMON GACHKACB
> SAY 'NTV309I MYRC='MYRC
> EXIT
>
> RUNMON:
> ARG TMPMON
> MYRC=TMPMON||'(VTHOM)'
> RETURN MYRC
-----Original Message-----
From: TSO REXX Discussion List [mailto:TSO-...@VM.MARIST.EDU] On Behalf Of
Glenn Knickerbocker
Sent: Thursday, September 09, 2010 4:21 PM
To: TSO-...@VM.MARIST.EDU
GACHKACB:
...
Return ...
BLAHBLAH:
...
Return ...
¬R
Thanks for the thoughts. I am not certain the monitors will always return a
number. It would be nice, but one never knows. At the moment I am sticking
with one of the versions on INTERPRET unless I figure out another way to do
this. Sorry about the mutiple posts. Had some issues posting from work and
finding them in google groups. But I learned, I hope.
ITschak
> ŹR
> On 09/09/2010 01:32 PM, Thom Stone wrote:
>> /* REXX */
>> CALL RUNMON GACHKACB
>> SAY 'NTV309I MYRC='MYRC
>> EXIT
>
> (Note that here you're using the variable MYRC that was set in the
> RUNMON routine, and ignoring the result that it returned. The value it
> returns is put in the variable RESULT.)
>
>> RUNMON:
>> ARG TMPMON
>> INTERPRET 'MYRC='TMPMON||'(VTHOM)'
>> RETURN MYRC
>
> Does the monitor exec return anything other than a number, and does it
> care how it was called? If not, how about just issuing it as a command?
>
> RunMon:
> Arg tmpMon
> tmpMon vthom
> Return rc
>
Despite the concern over INTERPRET (well founded unless the
programmer has complete control of its argument), issuing as
a command a string over which the programmer has no better
control is similarly risky.
> If you do need to handle non-numeric results, or if the exec is
> sensitive to whether it's called as a command or a function, you're
> stuck with either INTERPRET or a hardcoded list of monitor names:
>
> RunMon:
> Arg tmpMon
> Select
> When tmpMon = 'GACHKACB' then myrc = 'GACHKACB'(vthom)
> When tmpMon = 'BLAHBLAH' then myrc = 'BLAHBLAH'(vthom)
> ...
otherwise report error.
> End
> Return myrc
>
> If they were internal routines, you could use SIGNAL VALUE to pass
> control to them:
>
> RunMon:
> Arg tmpMon
> Signal Value tmpMon
>
Danger Will Robinson! This allows a maliciously crafted argument
to pass control to an arbitrary label within the EXEC.
-- gil
I just love references to 1960's campy shows... "Oh the pain, the pain...."
Stan Weyman
Senior Software Engineer
stan....@emc.com
EMC² (508)249-3966
where information lives
It is wise to keep in mind that neither
success nor failure is ever final...
-----Original Message-----
From: TSO REXX Discussion List [mailto:TSO-...@vm.marist.edu] On Behalf Of Paul Gilmartin
Sent: Friday, September 10, 2010 10:26 AM
To: TSO-...@vm.marist.edu
Subject: Re: [TSO-REXX] Help with INTERPRET
return value(tmpmon'(VTHOM)')
Still don't know whether VALUE is willing to call whatever routine whose
name was passed to tmpmon, though.
---
Bob Bridges, rhb...@attglobal.net, cell 336 382-7313
work bob.b...@libertymutual.com, 317 581-6487
/* Everyone is someone's wierdo. -Scott Adams, creator of "Dilbert" */
-----Original Message-----
From: Itschak Mugzach
Sent: Friday, September 10, 2010 01:56
Did you try myrc=tmpmon||'('Value(VTHOM)')' ?
-----Original Message-----
From: Thom Stone
Sent: Thursday, September 9, 2010 13:32
I have the following short sample of code that I want to use in a
larger project, but I'd prefer not to use interpret if possible.
/* REXX */
CALL RUNMON GACHKACB
SAY 'NTV309I MYRC='MYRC
EXIT
RUNMON:
ARG TMPMON
INTERPRET 'MYRC='TMPMON||'(VTHOM)'
RETURN MYRC
This is going to be a dynamic routine that calls a monitor. In this case I
simply hardcoded GACHKACB. In the real world the routine will lookup the
routine name and pass it to the code so I have to be able to interpret
TMPMON somehow at runtime. Does anyone have any thoughts? Thanks for your
ideas. I do have the CALL VALUE 'GA.JOBNAME.'PTR, MBRNAME in my solution
package, but I do not see how this will get me closer to a solution in this
case.
----------------------------------------------------------------------
> I don't think that's the way to do it, Itzchak; I'm looking for
>
> return value(tmpmon'(VTHOM)')
>
> Still don't know whether VALUE is willing to call whatever routine whose
> name was passed to tmpmon, though.
>
No. The argument to VALUE must be a legal (possibly compound)
variable name; the parentheses violate that. But it's pointless.
Giving the caller the ability to cause your code to call an
arbitrary function introduces the same risks as INTERPRET.
You're just trying to introduce INTERPRET under another name.
-- gil
> Date: Mon, 13 Sep 2010 08:36:27 -0600
> From: PaulGB...@AIM.COM
> Subject: Re: [TSO-REXX] Help with INTERPRET
> To: TSO-...@VM.MARIST.EDU
>
> On Sep 13, 2010, at 04:57, Bob Bridges wrote:
>
> > I don't think that's the way to do it, Itzchak; I'm looking for
> >
> > return value(tmpmon'(VTHOM)')
> >
> > Still don't know whether VALUE is willing to call whatever routine whose
> > name was passed to tmpmon, though.
> >
> No. The argument to VALUE must be a legal (possibly compound)
> variable name; the parentheses violate that. But it's pointless.
> Giving the caller the ability to cause your code to call an
> arbitrary function introduces the same risks as INTERPRET.
> You're just trying to introduce INTERPRET under another name.
>
> -- gil
INTERPRET in this instance would be safe so long as you filter the variable "tmpmon" for valid values first. Perhaps using something like
if wordpos(tmpmon,list_of_valid_dsns) > 0 then
interpret "return" tmpmon"('VTHOM')"
else
do
say 'Invalid value for tmpmon'
return /* Invalid value for tmpmon */
end
Mark Wheeler
UnitedHealth Group
The original post:
<quote>
Hello,
I have the following short sample of code that I want to use in a larger project, but I'd prefer not to use interpret if possible.
/* REXX */
CALL RUNMON GACHKACB
SAY 'NTV309I MYRC='MYRC
EXIT
RUNMON:
ARG TMPMON
INTERPRET 'MYRC='TMPMON||'(VTHOM)'
RETURN MYRC
This is going to be a dynamic routine that calls a monitor. In this case I simply hardcoded GACHKACB. In the real world the routine will lookup the routine name and pass it to the code so I have to be able to interpret TMPMON somehow at runtime. Does anyone have any thoughts? Thanks for your ideas. I do have the CALL VALUE in my solution package, but I do not see how this will get me closer to a solution in this case.
Thanks,
Thom Stone
<\quote>
Notice Thom indicated that the routine (I am assuming by "routine" he means the REXX he is developing) will look up the routine to call. If that is the case, AND the user does not have the ability to change that control table, then INTERPRET would be fine to use with little to no exposure. At least that's how I interpret what Thom wants.
Chuck
Charles Hardee
CA technologies
Sr Sustaining Engineer
Tel: +1-952-838-1039
Charles...@ca.com
Not necessarily a variable name, but a symbol.
VALUE('123abc') will always return '123ABC'. (*)
>> Giving the caller the ability to cause your code to call an
>> arbitrary function introduces the same risks as INTERPRET.
> INTERPRET in this instance would be safe so long as you filter the
> variable "tmpmon" for valid values first.
But that seems to be exactly what Thom is trying to avoid. I'm guessing
he wants the user to be able to add new monitor execs without having to
update his main exec to recognize them.
If the user specifies just the monitor name and Thom's exec fills in the
argument, then the way to validate the name before doing the INTERPRET
would just be to check that it's a valid symbol:
If Symbol(tmpmon) = 'BAD' then
/* the value of TMPMON is not a symbol,
so we can't use it as a function name */
ŹR
but forgot to fill in the footnote:
(*) except in implementations where this is broken! I tried it out
just to double-check, and didn't happen to be logged onto VM or
TSO, so I used ooRexx (v3.2.0)--and came out with some nonsense
starting with a dot instead!
-----Original Message-----
From: TSO REXX Discussion List [mailto:TSO-...@VM.MARIST.EDU] On Behalf Of
Glenn Knickerbocker
Sent: Monday, September 13, 2010 11:50 AM
To: TSO-...@VM.MARIST.EDU
Subject: Re: [TSO-REXX] Help with INTERPRET
ŹR
To Itsak reply, I tried it and it did not execute the routine, it seemed to
only evaluate it.
To Glenn, yes, I want this to be dynamic, and I then I guess I have some
give and take with someone playing games as I indicate below.
Actually the monitors will be specified in a configuration file and read
into global variables because my environment is NetView. Then when an
automation routine decides to run a monitor it will read the global
variables for a specific task and run the named monitor. Granted if one is
wise enough he could outfox the automation and update the global variables
or figure out how to run a monitor with a fudged monitor/task name or maybe
even update the configuration file in the first place, but perhaps a company
shouldn't hire those types. :-) But I guess even management can make a
mistake. Thank the powers that be for RACF or whatever security product we
use. I've heard some say security by obscurity. Looking at it now I think
I probably do not need to return rtnval, but I think I'll leave well enough
alone until I can do more testing at work.
Anyway this is what I decided to do:
do ptr=1 to thismon.0
call runmon thismon.ptr
/* do what you will with rtnval */
thisvar='GA.'thisitem'.MON.'ptr'.STAT'
call saveglbl thisvar rtnval
end
RETURN
/*------------------------------------------------------------------*/
RUNMON:
trace o
arg tmpmon
parse var tmpmon mon parms
interpret 'rtnval='mon'('parms')'
return rtnval
/*------------------------------------------------------------------*/
SAVEGLBL: Procedure Expose STGSEP DELIM
ARG VARNAME VALUE
'PIPE (STAGESEP 'STGSEP') LIT 'DELIM''VALUE''DELIM ,
STGSEP' VAR (COMMON) 'VARNAME
RETURN
/*------------------------------------------------------------------*/
<panel name=ispfpnl1>
blah blah
</panel>
I simply stripped off the ><'s and interpreted the "name=ispfpnl1". Also my Rexx runs in a user's TSO address space so it doesn't do anything that a user cannot do directly.
Having said that, can someone give a real world example of how INTERPRET can be misused? I hear a lot about why not to use it, but I cannot think of any example.
Best regards,
Lindy
What I did many years ago was to add a step to every job that ALWAYS
ran (check cond codes for how to do that). The step wrote the sysout
file I wanted (SYSMSGS I think it was) to a daily pds usung the
jobname as member name - the pds being created by the first job to
complete that day.
I already had a normative pds with members for all the jobs that
should run - running a simple compare job produced a daily list of the
status - jobs run, result jobs NOT run.
Pretty simple and robust and cheap!
I may have some code still if you need help
Adrian
Mickey
--------------------------------------------------
From: "Lindy Mayfield" <lindy.m...@SSF.SAS.COM>
Sent: Tuesday, September 14, 2010 2:42 AM
To: <TSO-...@VM.MARIST.EDU>
Subject: Re: [TSO-REXX] Help with INTERPRET
> I have found that INTERPRET is a very useful statement. One example I
/* Rexx */
'EXECIO 1 DISKR SYSUT1 (STEM X.'
INTERPRET X.1
Would you run this EXEC on your user ID letting me supply the
content of SYSUT1?
-- gil
Once many years ago I created some utility that had a PARM file something like this:
DNSNAME=MY.DNSNAME
FLAG1=Y
FLAG2=N
TRACE=N
and so on.
It was very simple to first set defaults and then INTERPRET each statement.
How would you do this without INTERPRET?
/Lindy
-----Original Message-----
From: TSO REXX Discussion List [mailto:TSO-...@VM.MARIST.EDU] On Behalf Of Paul Gilmartin
Sent: Tuesday, September 14, 2010 2:02 PM
To: TSO-...@VM.MARIST.EDU
Subject: Re: [TSO-REXX] Help with INTERPRET
On Tue, Sep 14, 2010 at 2:25 PM, Lindy Mayfield
<lindy.m...@ssf.sas.com>wrote:
--
best regards,
matan cohen
MF System Administrator.
ERORMESSAGE1="TÄMÄ ON VIRHE"
/* This is the translated error message text for xyz */
ERRORMESSAGE1="Miksi teit näin"
I think I understand my problem with Gil's example. If you purposely give my Rexx exec something that will cause damage or whatnot in my TSO session, you'll most likely get fired. There are a number of ways to do such things other than hacking a Rexx exec.
I see a lot of sites that have . in the PATH. That happens to be on my mind because I saw this at this customer site where I am now.
In all cases I have seen this technique the parameter file is protected
since it's importance to the application requires consistency before we even
talk about maliciousness...
I agree with the other posters. While I try to use CALL VALUE when
possible, sometimes INTERPRET is the answer. I also find that CALL VALUE is less
known to the casual REXX users (that may have to support my code at some
point) and requires more documentation than INTERPRET...
I also think the FUD surrounding INTERPRET has been overblown. Since BOTH
INTERPRET and CALL VALUE create difficult to read code both require lots
of documentation. The only warning should be to test thoroughly with
INTERPRET and insure user input can not interject an unexpected command.
My two cents.
Rob
In a message dated 9/14/2010 4:04:54 A.M. US Mountain Standard Time,
Lindy,
Here's a little exec that can cause a problem:
/* rexx */
clrscrn
say "Enter calculation request ..."
parse pull variable
interpret variable
/* ----------------------------------- */
When you run this, if the user is malicious, they could enter
a TSO command; for example:
Enter calculation request ...
del bunk.dirlist
IDC0550I ENTRY (A) SCOMSTO.BUNK.DIRLIST DELETED
***
--
Kind regards,
-Steve Comstock
The Trainer's Friend, Inc.
303-393-8716
http://www.trainersfriend.com
* To get a good Return on your Investment, first make an investment!
+ Training your people is an excellent investment
CALL VALUE has its own hazards, allowing the supplier of the
parameter to modify arbitrary variables in the EXEC. Rather
than:
parse pull Name Content
call value Name, Content
I prefer to use a compound variable:
parse pull Name Content
Parms.Name = Content
quarantining the values modified to the Parms stem. Provided
the programmer understands compound variables. I've had
programmers insist that compound tails _must_ be numeric, and
that the array size _must_ be kept in the 0th element.
-----Original Message-----
From: TSO REXX Discussion List [mailto:TSO-...@VM.MARIST.EDU] On Behalf Of Steve Comstock
Sent: Tuesday, September 14, 2010 6:38 PM
To: TSO-...@VM.MARIST.EDU
Subject: Re: [TSO-REXX] Help with INTERPRET
The problem isn't limitted to sending imbedded commands into REXX "interpret". Any environment that can be tricked into running a command could be exploited. Take CMS/TSO Pipelines, for example:
/* BLORT EXEC */
arg filename
'PIPE <' filename '| ....' /* Looks innocent enough */
Now issue "blort some_file | hole | append (nefarious_command)" and stand back.
Clearly in this case, some checking should occur to make sure "filename" doesn't include any "pipe" (|) characters, especially if the exec will ever be invoked by a privileged userid.
Well, of course nothing.
A lot depends on context and whatever safeguards you
have in place. Suppose someone copies your dialog and
runs it somewhere else.
But, as Paul says, it's the user's gun and the user's
foot. I was just pointing out INTERPRET can be used to
enter unexpected commands unless you parse what the
user enters before you issue the INTERPRET.
I agree.
A few years ago, I worked in a shop that did not have SAS.
I needed to merge the DFHSTAT output from 5 AORs, and the fastest, best method, was a table update/merge.
I found that INTERPRET sped up programming and testing.
The same code was used over and over again.
I am loathe to duplicate code paths, because of the onus on the programmer to remember to fix/change all occurances.
In SAS, you do it with MACROs (their term).
In REXX, the closest equivalence is INTERPRET.
At first, I believed the FUD.
But, with time as a factor, I decided that the most important issue was to get the job done in time.
I don't find many uses for it, but it's now a screwdriver in my toolbox.
-
I'm a SuperHero with neither powers, nor motivation!
Kimota!
That has to be a home-grown command.
>say "Enter calculation request ..."
>parse pull variable
>interpret variable
Change that to
interpret SAY variable
The use of INTERPRET, like any 'dangerous' practice, is subject to discipline.
Just because I can do it, doesn't mean I shall do it.
Especially, if I like my job.
INTERPRET doesn't kill systems!
People kill systems.
That is a convention for things like EXECIO, but it is not a general requirement.
I do use the convention a lot; I do a lot of I/O in my EXECs, though.
That's the thing we keep forgetting (well, at least I do): If I write a
REXX with an INTERPRET command and the user executes it and inserts
something malicious, the REXX is running under his own ID and thus he can do
only what he can already do. The REXX doesn't give him any additional
authority, nor mask the source of the problem if he deletes a file or
something.
---
Bob Bridges, rhb...@attglobal.net, cell 336 382-7313
work bob.b...@libertymutual.com, 317 581-6487
/* Everyone is someone's wierdo. -Scott Adams, creator of "Dilbert" */
-----Original Message-----
From: Mark Wheeler
Sent: Tuesday, September 14, 2010 12:27
The REXX exec could be a CGI script taking input from a web page. You
probably don't want your web server running ad hoc commands.
-----Original Message-----
From: Lindy Mayfield
Sent: Tuesday, September 14, 2010 11:56
What's the difference if I enter a command to the rexx or enter it
explicitly?
-----Original Message-----
From: Steve Comstock
Sent: Tuesday, September 14, 2010 6:38 PM
Lindy, Here's a little exec that can cause a problem:
/* rexx */
clrscrn
say "Enter calculation request ..."
parse pull variable
interpret variable
/* ----------------------------------- */
When you run this, if the user is malicious, they could enter a TSO command;
for example:
Enter calculation request ...
del bunk.dirlist
IDC0550I ENTRY (A) SCOMSTO.BUNK.DIRLIST DELETED
***
----------------------------------------------------------------------
> The web page would not accept ad-hoc commands when I run the REXX unless my
> ID has the authority to get the web page to take ad-hoc commands. I'm still
But that's just what CGI does. The author should know better
than to perform unfiltered INTERPRET. Better still to parse
the command string and perform operations without INTERPRET.
> with Lindy; so far, there's no harm that can be done that the user couldn't
> do without the INTERPRET command.
>
> That's the thing we keep forgetting (well, at least I do): If I write a
> REXX with an INTERPRET command and the user executes it and inserts
> something malicious, the REXX is running under his own ID and thus he can do
> only what he can already do. The REXX doesn't give him any additional
> authority, nor mask the source of the problem if he deletes a file or
> something.
>
Transparency. It's hard to tell reading an INTERPRET what it
might do. That's masking.
> -----Original Message-----
> From: Mark Wheeler
> Sent: Tuesday, September 14, 2010 12:27
>
> The REXX exec could be a CGI script taking input from a web page. You
> probably don't want your web server running ad hoc commands.
-- gil
- folks HAVE implemented INTERPRET statements that can be easily abused
- there are *usually* ways to avoid INTERPRET (VALUE being the most common replacement)
- programmers like to be clever, so in the early days of Rexx, it became something of a sport to find ways around using INTERPRET
Any such discussion always makes me think of http://xkcd.com/327/ -- if you don't know XKCD you should.
...phsiii
We've been told by IBM that "There is a possibility that you could write to a
CSV file and then load it into the database."
Anybody doing something similar to this via REXX? Any other options available
to us? Alternative DB2 load utility?
- Wally Vogtmann
----------------------------Disclaimer----------------------------
This email may contain privileged and/or confidential information that
is intended solely for the use of the addressee. If you are not the
intended recipient, you are strictly prohibited from disclosing, copying,
distributing or using any of the information contained in the transmission.
If you received this communication in error, please contact the sender
(“Company”) immediately and destroy the material in its entirety,
including all electronic and hard copies.
This communication may contain nonpublic personal information about
consumers which is subject to restrictions under the Gramm-Leach-Bliley
Act and the Sarbanes-Oxley Act. You may not directly or indirectly reuse
or disclose such nonpublic personal information for any purpose other than
to provide the services for which you are receiving the information.
There are risks associated with the use of electronic transmission. The
sender of this information does not control the method of transmittal or
any service providers and the sender assumes no duty, liability, or
obligation for the security, receipt, or any third party interception of
this transmission.
The Company reserves the right to amend statements made herein in the event
of a mistake. Unless expressly stated herein to the contrary, only agreements
in writing signed by an authorized officer of the Company may be enforced
against it.
Mickey
--------------------------------------------------
From: "Phil Smith III" <li...@AKPHS.COM>
Sent: Wednesday, September 15, 2010 10:32 AM
To: <TSO-...@VM.MARIST.EDU>
Subject: Re: [TSO-REXX] Help with INTERPRET
> INTERPRET has its place. And of course it can be abused. There are several
Mickey
--------------------------------------------------
From: "Vogtmann, Wallace B" <wvog...@TCFBANK.COM>
Sent: Wednesday, September 15, 2010 10:51 AM
To: <TSO-...@VM.MARIST.EDU>
Subject: [TSO-REXX] CICS IA and DB2 LOAD Utility
----------------------------------------------------------------------
INTERPRET SORTSTEM("Stem")
It's easy to understand, and it hides the implementation details.
Tony
-----Original Message-----
From: TSO REXX Discussion List [mailto:TSO-...@VM.MARIST.EDU] On Behalf
Of Phil Smith III
Sent: Wednesday, September 15, 2010 10:33 AM
To: TSO-...@VM.MARIST.EDU
FSVO "easy to understand". I assume that SORTSTEM returns a set of "Stem.1 = value;" pairs?
It sure does hide the implementation details!
When I say "easy to understand", I mean that once you know the
constraints above, it takes roughly zero mental cycles to see what the
INTERPRET statement does. =)
-----Original Message-----
From: TSO REXX Discussion List [mailto:TSO-...@VM.MARIST.EDU] On Behalf
Of Phil Smith III
Sent: Thursday, September 16, 2010 12:29 AM
To: TSO-...@VM.MARIST.EDU
Subject: Re: Help with INTERPRET
"Vitonis, Tony" wrote:
>I use INTERPRET to call an external routine that'll sort a stem for me:
> INTERPRET SORTSTEM("Stem")
>It's easy to understand, and it hides the implementation details.
FSVO "easy to understand". I assume that SORTSTEM returns a set of
"Stem.1 = value;" pairs?
It sure does hide the implementation details!
----------------------------------------------------------------------
Rob
In a message dated 9/16/2010 8:42:43 A.M. US Mountain Standard Time,
-----Original Message-----
From: TSO REXX Discussion List [mailto:TSO-...@VM.MARIST.EDU] On Behalf
Of Robert Zenuk
Sent: Thursday, September 16, 2010 12:35 PM
To: TSO-...@VM.MARIST.EDU
Subject: Re: Help with INTERPRET
I think that wins the obfuscation award... ;-)
I also adopted his philosophy. I also have several "sample" execs to test
or prove something clever works, but anything I turn over for production
usage and/or share as a production ready piece of code avoids "clever"
techniques. To be honest, sometimes (admittedly rarely) using clever code is
unavoidable. In these cases, I heavily document what is going on every place
I use them (if not in a subroutine or function - then they are documented
only once in there).
My two cents...
Rob
In a message dated 9/16/2010 10:27:00 A.M. US Mountain Standard Time,
I think of SORTSTEM as corresponding to a public method of a published
class. If the stem were an object in typical OOP code, you might instead
see my_stem.sort(). Not at all clever or hard to maintain.
Kent Fiala
How about:
if X==Y then
X_MATCHES_Y = 'TRUE'
else
X_MATCHES_Y = 'FALSE'
...
if X_MATCHES_Y=='TRUE' then do
something
end; else do
something_else
end
versus:
X_MATCHES_Y = ( X==Y )
...
if X_MATCHES_Y then do
something
end; else do
something_else
end
I will unhesitatingly employ the second construct. I rather
expect some reaction on this list that only the first is
acceptable. BASICthink. In (original, at least) BASIC,
relational expressions were allowed only in IF statements,
and only relational expressions had boolean values.
-- gil
-----Original Message-----
From: TSO REXX Discussion List [mailto:TSO-...@VM.MARIST.EDU] On Behalf Of Vitonis, Tony
Sent: Thursday, September 16, 2010 9:24 PM
To: TSO-...@VM.MARIST.EDU
Subject: Re: [TSO-REXX] Help with INTERPRET
Understood and agreed about clever code. I suppose we'll just differ on whether this particular bit of code is "clever". The invoked routine is a straightforward implementation of the shell sort, and the invoking code is in my opinion very easy to read and understand.
----------------------------------------------------------------------
--------------------------------------------------
From: "Lindy Mayfield" <lindy.m...@SSF.SAS.COM>
Sent: Friday, September 17, 2010 2:46 AM
Exactly. I'm sure everyone who's been in the business for
a year or more has had the experience of re-visiting code
they wrote earlier in their career only to find an
embarrasing string of almost incomprensible statements.
Code with the future maintainer in mind - it might be you!
>
> -----Original Message-----
> From: TSO REXX Discussion List [mailto:TSO-...@VM.MARIST.EDU] On Behalf Of Vitonis, Tony
> Sent: Thursday, September 16, 2010 9:24 PM
> To: TSO-...@VM.MARIST.EDU
> Subject: Re: [TSO-REXX] Help with INTERPRET
>
> Understood and agreed about clever code. I suppose we'll just differ on whether this particular bit of code is "clever". The invoked routine is a straightforward implementation of the shell sort, and the invoking code is in my opinion very easy to read and understand.
--
Kind regards,
-Steve Comstock
The Trainer's Friend, Inc.
303-393-8716
http://www.trainersfriend.com
* To get a good Return on your Investment, first make an investment!
+ Training your people is an excellent investment
----------------------------------------------------------------------
Tony
I agree with the subsequent emails: If I can come back six months later and
understand my code in five minutes one way and half an hour another, then
the five-minute technique usually wins. That's why I use the parens, same
as you did, in the statement
fX_matches_Y=(x=y)
The parens are unnecessary, but they make the statement easier to understand
for someone who never tried that sort of thing before.
One of my favorite techniques in REXX seems unaccountably to be almost
unknown, yet it's both clever AND simple:
idexists.=0
'EXECIO * DISKR DDIP (FINIS'
do queued()
parse pull 1 uid +8 143 can +3
if can<>'YES' then idexists.uid=1; end
The details vary, but in this case I've taken a few lines to create a quick
true-or-false table of non-canceled UIDs that my program can later consult
to know whether the user ID it's currently looking at is in that file:
if idexists.uid then iterate
I know a few of us here do that sort of thing, but I don't understand why
everyone doesn't. It isn't "clever" in the sense we've been discussing up
'til now, ie difficult to understand.
---
Bob Bridges, rhb...@attglobal.net, cell 336 382-7313
work bob.b...@libertymutual.com, 317 581-6487
/* In science one tries to tell people, in such a way as to be understood by
everyone, something that no one ever knew before....in poetry, it's the
exact opposite. -Paul Dirac */
How about:
versus:
--- On 09/16/10 11:49, Robert Zenuk wrote:
> One of my mentors used to differentiate "clever code" from "good
> supportable code". He wrote tons of clever code for himself and we would
> debate the level of cleverness. However, anything that someone else would
> ever need to support, he would restrict himself to writing only good
> supportable code. The main difference being the readability and ease of
> understanding factors for someone new... He found he spent less time on
> maintenance using that approach... He also said that since he did not
> memorize every line of code he ever wrote, it saved him time when he had
> to go back and decipher his own cleverness...
----------------------------------------------------------------------
Let me spell this out, just in case it isn't already clear: Suppose I write
a REXX like this:
/* This REXX example is ridiculous. */
say 'What evil, malicious act would you like to perpetrate',
'upon this LPAR?'
pull evil_malicious_TSO_command
interpret evil_malicious_TSO_command
Along comes some evil, malicious user who runs EVILMAL and types in a DELETE
command, say, "DEL 'SYS1.BRODCAST'", which EVILMAL tries to execute.
Now, there are two possibilities. If the user has the authority to delete
SYS1.BRODCAST, then the command succeeds. But the program didn't give him
the ability to issue the command DEL 'SYS1.BRODCAST'; he could have done
that any time he wanted. Or if (more likely) the user does NOT have the
authority to delete 'SYS1.BRODCAST', then the INTERPRET command will fail;
the user hasn't the authority.
Why will it fail? Because no matter who wrote the REXX, at run-time the
REXX has the authority not of the author but of the user. It is the USER
who is running the program and attempting to delete the file, not the
author. The INTERPRET statement I included in the program when I wrote it
doesn't grant the user any authority he didn't already have.
Now, there may be other objections to INTERPRET. But I don't see how this
can be one of them.
---
Bob Bridges, rhb...@attglobal.net, cell 336 382-7313
work bob.b...@libertymutual.com, 317 581-6487
/* Everyone is someone's wierdo. -Scott Adams, creator of "Dilbert" */
-----Original Message-----
From: Paul Gilmartin
Sent: Tuesday, September 14, 2010 23:10
But that's just what CGI does. The author should know better than to
perform unfiltered INTERPRET. Better still to parse the command string and
perform operations without INTERPRET.
--- On Sep 14, 2010, at 18:39, Bob Bridges wrote:
> The web page would not accept ad-hoc commands when I run the REXX unless
> my ID has the authority to get the web page to take ad-hoc commands.
> -----Original Message-----
> From: Mark Wheeler
> Sent: Tuesday, September 14, 2010 12:27
>
> The REXX exec could be a CGI script taking input from a web page. You
> probably don't want your web server running ad hoc commands.
----------------------------------------------------------------------
The old OS/VS COBOL (COBOL 68) used to create a severe performance problem
and other nasty stuff in CICS if STRING and UNSTRING were used. So the
history is that some shops just banned the use of CICS prohibited COBOL
verbs... That restriction was removed in VS/COBOL II (over 20 years ago), but
many folks did not get the message...
The example being used in your email and Gil's email is an excellent use of
REXX. I use the non-numeric stem "flags" approach all the time for very
similar purposes. One of the examples that comes to mind is one of several
EXEC's I wrote for parsing the CICS CSD where I use MANY non-numeric stems
to keep track of which resources I have to worry about in which groups,
list or regions while doing my processing (not to mention numerous numeric
stems and counts as well). In fact in some cases I have 5 level stems to
keep track of CICS resources by resource TYPE within GROUP within LIST within
CICS GRPLIST within CICS region... In my mind this is a core feature of
REXX.
My original "clever" response was to the use of INTERPRET with a function
name. The reason ended up coming out, but my concern was the STEMSORT
token itself was a resolvable variable... I ALWAYS use SIGNAL NOVALUE in
anything other than demonstration code. Therefore, I was assuming (I know...
big problem in this case) that STEMSORT (since it wasn't quoted) was also
being substituted and if not a valid variable would have raised a NOVALUE
condition. My coding style is not to let REXX default an undefined variable to
the variable name. If everyone is writing small EXEC's with minimal code,
I can see people depending on this feature... I am guilty of assumptions
about an out of context code snippet and I withdraw my "obfuscation"
comment and "clever code" story.
Rob
In a message dated 9/18/2010 9:23:42 A.M. US Mountain Standard Time,
rhb...@ATTGLOBAL.NET writes:
fX_matches_Y=(x=y)
if idexists.uid then iterate
---
Bob Bridges, rhb...@attglobal.net, cell 336 382-7313
work bob.b...@libertymutual.com, 317 581-6487
/* In science one tries to tell people, in such a way as to be understood
by
everyone, something that no one ever knew before....in poetry, it's the
exact opposite. -Paul Dirac */
-----Original Message-----
From: Paul Gilmartin
How about:
versus:
----------------------------------------------------------------------
Mickey
--------------------------------------------------
From: "Steve Comstock" <st...@TRAINERSFRIEND.COM>
Sent: Friday, September 17, 2010 8:33 AM
The easiest blunder for the web page author to commit is to
validate the input thoroughly with a Javascript on the browser
side and assume that therefore only query strings consisting of
valid input will be passed to the CGI script. In fact, the
browser user, malicious, mischievous, or merely curious may
enter an entire URL _including_the_QUERY_STRING_ and submit it
to the browser, entirely invalidated.
Long ago my employer had a time accounting system which required
each employee to enter his weekly time by project in an extremely
cumbersome form interface, entering a code in each of 8 hour
fields for each of 5 days. No entries were preset by a profile
or skeleton. That user interface then validatedthe input and
formatted an email which was sent to the payroll system which
received it automatically and processed it.
Finding the process tedious, I intercepted one of the emails and
converted it to a script with instream data after I had modified
the few hourly entries which differed from the previous week.
I then typed "GO" and my script formatted and sent the email.
I was cautious; my entries were valid; the scheme worked well
for me. I boasted of it to a colleague, and even shared my
script with him. He adopted it, but made a typo. The payroll
system crashed. When he didn't receive a timely acknowledgment
that his time sheet had been accepted, he sent it again. The
payroll system crashed again ...
> Let me spell this out, just in case it isn't already clear: Suppose I write
> a REXX like this:
>
> /* This REXX example is ridiculous. */
> say 'What evil, malicious act would you like to perpetrate',
> 'upon this LPAR?'
> pull evil_malicious_TSO_command
> interpret evil_malicious_TSO_command
>
> Along comes some evil, malicious user who runs EVILMAL and types in a DELETE
> command, say, "DEL 'SYS1.BRODCAST'", which EVILMAL tries to execute.
>
What evidently isn't already clear to you is that the CGI script is running
on the server with the privileges of the HTTP daemon; evil malicious user
who has no authority to delete anything on the server is entering his command
remotely on a web browser.
Perhaps your mental block is in the presumption that no website author would
ever be so careless as to INTERPRET a QUERY string submitted by a browser
user without validating it completely.
Alas, similar things have happened. See my payroll example above.
-- gil
parse value S with head ',' +0 delim +1 tail
if delim==',' then
It's clever and NOT simple; it's easy for me simply because I use
it so frequently.
-- gil
This is one of my favorites. If I didn't know what it already does I would be digging into the documentation for quite a while.
/* Rexx */
Numeric Digits 10
Depth = 0
ASCB = Get_Stor('224'x)
ASCBRCTP = Get_Stor(ASCB,'7C'x)
Call Process_TCB ASCBRCTP
Return
Process_TCB: Procedure Expose Depth
Say Copies(".",Depth) C2X(Arg(1))
Daughter = Get_Stor(Arg(1),'88'x)
If C2D(Daughter) <> 0 Then Do
Depth = Depth + 1
Call Process_TCB Daughter
Depth = Depth - 1
End
Sister = Get_Stor(Arg(1),'80'x)
If C2D(Sister) <> 0 Then call Process_TCB Sister
Return
Get_Stor: Procedure
Parse Arg Area,Offset,Leng
If Arg(2,'O') Then Offset=0
If Arg(3,'O') Then Leng=4
If DataType(Area) = 'CHAR' Then Do
Area = C2D(Area)
End
If DataType(Offset) = 'CHAR' Then Do
Offset = C2D(Offset)
End
Return Storage((D2X(Area+Offset)),Leng)
-----Original Message-----
From: TSO REXX Discussion List [mailto:TSO-...@VM.MARIST.EDU] On Behalf Of Mickey
Sent: Sunday, September 19, 2010 6:55 AM
To: TSO-...@VM.MARIST.EDU
Subject: Re: [TSO-REXX] Help with INTERPRET
I keep my code VERY simple, with one exception. If I am writing code which for example, walks around the task control blocks, which I know will never change, and I want to prevent from dingbat from screwing around with it in the future, then I will make certain to do my best to write some truly impenetrable code :)
Mickey
----------------------------------------------------------------------
Mickey
--------------------------------------------------
From: "Vitonis, Tony" <Tony.V...@CA.COM>
Sent: Friday, September 17, 2010 4:59 PM
--------------------------------------------------
From: "Lindy Mayfield" <lindy.m...@SSF.SAS.COM>
Sent: Sunday, September 19, 2010 9:21 AM
To: <TSO-...@VM.MARIST.EDU>
Subject: Re: [TSO-REXX] Help with INTERPRET
> Most code that accesses control blocks is pretty much obfuscated as it is
> without any extra help.
>
> This is one of my favorites. If I didn't know what it already does I
> would be digging into the documentation for quite a while.
>
> /* Rexx */
> Numeric Digits 10
> Depth = 0
> ASCB = Get_Stor('224'x)
> ASCBRCTP = Get_Stor(ASCB,'7C'x)
> Call Process_TCB ASCBRCTP
> Return
>
> Process_TCB: Procedure Expose Depth
> Say Copies(".",Depth) C2X(Arg(1))
> Daughter = Get_Stor(Arg(1),'88'x)
> If C2D(Daughter) <> 0 Then Do
> Depth = Depth + 1
> Call Process_TCB Daughter
> Depth = Depth - 1
> End
> Sister = Get_Stor(Arg(1),'80'x)
> If C2D(Sister) <> 0 Then call Process_TCB Sister
> Return
>
----------------------------------------------------------------------
Ah, that would do it, yes. I was thinking in terms of REXX/TSO, running on
MVS, where no such thing could happen. In my defense, this is the TSO-REXX
forum, after all. About web design I know almost nothing.
I said it "couldn't happen" in MVS, but let's see: If I were to set up such
a REXX to run in production under the authority of some production ID or
even a started task ... Well, in that case it likely wouldn't be accepting
on-line use input, but it certainly could be pulling prepared user input
from a file somewhere. In that case if I set up an INTERPRET, yeah, the
same thing could happen.
Seems to me, then, that the rule of thumb is Never allow user input to an
INTEPRET statement in ~production~ REXX, where "production" applies to your
CGI thingy as well as to anything I write in MVS. Yeah, I get it (finally.
Khar fahm shodam?); thanks for keeping at it with me.
---
Bob Bridges, rhb...@attglobal.net, cell 336 382-7313
work bob.b...@libertymutual.com, 317 581-6487
/* Ignorance is the mother of adventure. -Hagar the Horrible */
-----Original Message-----
From: Paul Gilmartin
Sent: Sunday, September 19, 2010 01:43
----------------------------------------------------------------------
When I worked at the State of Connecticut people like that were moved to a corner and put in charge of "special projects".
-----Original Message-----
From: TSO REXX Discussion List [mailto:TSO-...@VM.MARIST.EDU] On Behalf Of Don Leahy
Sent: Monday, September 20, 2010 12:52 AM
To: TSO-...@VM.MARIST.EDU
Subject: Re: [TSO-REXX] Help with INTERPRET
I once worked with a programmer who liked to 'uglify' his Rexx code by running a macro that stripped out all comments and indentation. He would publish the ugly version in a public library and keep the real version in a safe place.
----------------------------------------------------------------------
I started carving out my subroutines about 10 years ago and designed my
entry/exit code to make building new stuff easier as well as create a
consistent set of development/debugging features in all my code. I can easily
activate some of my debugging features when needed or leave them dormant.
Over the years I have refined many of my subroutines when one gets used a lot
and a module trace proves it is a performance hog. Then I focus on it and
streamline it. When it is finally performing well, I can refresh all the
EXEC's using it so everyone gets the benefits. Sometimes refinement means
adding more flexibility or splitting a routine into 2 or more flavors for
specialized purposes. Since I diligently try to avoid duplicating code, many
of my subroutines require/exploit other existing subroutines.
I have subroutines for several things; TSO commands, ISPF services, Edit
Macro services, CICS support, CPSM, DB2 support, FTP, HTML, MIM/GRS, INFOMAN
(we don't use it anymore), SMTP, MIME, SDSF, TCP/IP commands, Sockets,
Sorting, DSNREXX/SQL, Sysview, List Management, USS, Text/String/Number/Date
Formatting, Report formatting, Screen Management, Dataset Management, DASD
Management, Resource Allocation, Logging, Security, Control Block Chasing,
Stem management, SMF, etc.
I really came to like the concept of "wrappering" all calls to a specific
environment. This allows for standardized error logic that grows and you
maintain in only one place.. For example, every time I execute a TSO
command I call my TSOTRAP routine.
call tsotrap "ALLOC F(XXXX) DA(....."
It executes the command and captures all the output in a common stem name.
I can use the stem data if I need it. It will print the command and the
output if an unexpected return code is received along with an environmental
error report. If the EXEC is running in batch, the error report is
printed in SYSTSPRT. If the EXEC is running under ISPF, it puts the output in
the ISPF LOG. If I provide an optional numeric parameter as the first parm
as the expected non-zero return code, it can handle errors internally and
not produce the error report..
call tsotrap 12 "DELETE" dsn
or
if tsotrap(12 "DELETE" dsn) = 12 then....
My ISPWRAP is very similar for ISPF services. I don't create a wrapper
for every unique command, but I do have a wrapper for all ISPF commands that
provides similar features as above. The additional benefit of ISPWRAP is
that it returns any ZERRLM that may exist. If there was no expected return
code provided the program dies with the ISPF return code and displays the
failed command, the return code and the ZERRLM as a batch message in SYSTSPRT
or as a long message on the screen.
call ispwrap "LMINIT..."
call ispwrap 4 "TBCREATE..."
if ispwrap(8 "TBSKIP" table) = 8 then...
My XXXTRAP routines are for commands that execute and return data as well
as a return code. My XXXWRAP routines are for commands that only return a
return code and do not return data.
Since my subroutine entry code puts the subroutine name, the parms, the
start time and the line number on the stack and the exit code removes it, my
error report will show a "parentage report" or calling tree of where we came
from if there was an unexpected exit.
Some of my 'abend' logic uses interpret in a signal trap to re-execute the
failing portion of code with a trace active so I can see what happened and
how the variables resovled. This technique using interpret is not 100%
accurate, but it helps in over 90% of the cases.
Since I tend to keep a model member around with a common "starter set" of
my subroutines, my average production style EXEC starts with a minimum of
1000 lines. When I'm done, I simply remove the stuff in the starter set I
didn't use. However, there is a chunk of refreshable "framework" code that
is in every single EXEC. I have found I can churn out decent quality code
fairly quickly using this approach and when errors do occur, I have left
myself enough diagnostic information to usually figure out the problem without
having to recreate it.
So, yes, lots of small chunks of code (bricks), but I build a lot of houses
using several of those bricks each time I write a new EXEC.
Rob
In a message dated 9/19/2010 10:11:22 A.M. US Mountain Standard Time,
mic...@COMCAST.NET writes:
Well, I also find that if I build code in tight little routines that have
but one function, I can often build a new program just by chopping out 6
routines from 6 existing ones, and writing a little code around them. My
method is to build bricks. Once I have bricks, building houses is easy.
Mickey
--------------------------------------------------
From: "Vitonis, Tony" <Tony.V...@CA.COM>
Sent: Friday, September 17, 2010 4:59 PM
To: <TSO-...@VM.MARIST.EDU>
Subject: Re: [TSO-REXX] Help with INTERPRET
> I couldn't agree with you more. I didn't want to write the sort routine
> more than once, and I wanted the calling code to be small and
> self-documenting - so I didn't have to think about it later.
>
> Tony
>
> -----Original Message-----
> From: TSO REXX Discussion List [mailto:TSO-...@VM.MARIST.EDU] On Behalf
> Of Mickey
> Sent: Friday, September 17, 2010 8:28 AM
> To: TSO-...@VM.MARIST.EDU
> Subject: Re: [TSO-REXX] Help with INTERPRET
>
> I'm with you. I keep it very simple. I rarely even write a procedure
> that
> won't fit on one screen.
>
> --------------------------------------------------
> From: "Lindy Mayfield" <lindy.m...@SSF.SAS.COM>
> Sent: Friday, September 17, 2010 2:46 AM
> To: <TSO-...@VM.MARIST.EDU>
> Subject: Re: [TSO-REXX] Help with INTERPRET
>
>> I don't write code that I cannot easily figure out months or years
> later.
>> That's why I stay away from writing clever (if clever == difficult to
>> understand) code. Each to their own I guess.
>>
>> -----Original Message-----
>> From: TSO REXX Discussion List [mailto:TSO-...@VM.MARIST.EDU] On
> Behalf
>> Of Vitonis, Tony
>> Sent: Thursday, September 16, 2010 9:24 PM
>> To: TSO-...@VM.MARIST.EDU
>> Subject: Re: [TSO-REXX] Help with INTERPRET
>>
>> Understood and agreed about clever code. I suppose we'll just differ
> on
>> whether this particular bit of code is "clever". The invoked routine
> is a
>> straightforward implementation of the shell sort, and the invoking
> code is
>> in my opinion very easy to read and understand.
>
Tony
-----Original Message-----
From: Mickey
Sent: Sunday, September 19, 2010 1:11 PM
To: TSO-...@VM.MARIST.EDU
Subject: Re: [TSO-REXX] Help with INTERPRET
Well, I also find that if I build code in tight little routines that
have but one function, I can often build a new program just by chopping
out 6 routines from 6 existing ones, and writing a little code around
them. My method is to build bricks. Once I have bricks, building houses
is easy.
----------------------------------------------------------------------
Mickey
--------------------------------------------------
From: "Robert Zenuk" <Robz...@AOL.COM>
Sent: Monday, September 20, 2010 1:41 AM
Mickey
--------------------------------------------------
From: "Vitonis, Tony" <Tony.V...@CA.COM>
Sent: Monday, September 20, 2010 12:14 PM
---
Bob Bridges, rhb...@attglobal.net, cell 336 382-7313
work bob.b...@libertymutual.com, 317 581-6487
/* Ignorance is the mother of adventure. -Hagar the Horrible */
-----Original Message-----
From: Mickey
Sent: Monday, September 20, 2010 12:59
These come in particularly useful in edit macros. I have the need to run
through a lot of COBOL, and I have these little bricks to do things like
find the next "good" line (not commented), find the next verb, find the data
definition for a variable, etc. I also have them for common services, like
ALLOCATE, FREE, LISTCAT (in many flavors), LISTDSI, SYSDSN, and a host of
others. Inventing the wheel was fun..... ONCE :)
--------------------------------------------------
From: "Robert Zenuk" <Robz...@AOL.COM>
Sent: Monday, September 20, 2010 1:41 AM
> Agreed. I have about 200 of those little "bricks". They are wrappered
> with special entry and exit logic (about 2 lines up front and in the back)
> and special comments (above and beyond normal doc type comments). This
> is so I can use an Edit Macro (called @REFRESH) to call in the needed
> routines and/or refresh them with the most current versions (I prefer to
> use internal subroutines/functions and have a single module to
> distribute). The entry and exit logic provides some extra built in
> debugging features (indented module trace with parms-line numbers-
> start/stop timestamps, command timings, performance data, subroutine level
> tracing, standardized diagnostic output, standardized "abend" logic,
> standardized logging, version control, standard batch report headers,
> etc)....
> ... something to trap
> LISTALC so I can check to see whether certain DD names are already
> allocated; ...
>
For some purposes, it's simpler to use BPXWDYN( '... rtddn(VAR) ...' )
and let DYNALLOC pick one for me so I needn't probe for a free one.
(BPXWDYN: it's not just for Unix any more!)
Like many coders, I have an elaborate wrapper for "address SYSCALL"
to analyze errors.
In some cases, I copy a member to a temporary DSN SYSEXEC from
SYSIN with my cliche functions concatenated.
-- gil
Mickey
--------------------------------------------------
From: "Paul Gilmartin" <PaulGB...@AIM.COM>
Sent: Monday, September 20, 2010 9:44 PM
To: <TSO-...@VM.MARIST.EDU>
Subject: Re: [TSO-REXX] Help with INTERPRET
> On 09/20/10 18:01, Bob Bridges wrote:
READY
free dd(foo junk)
READY
allocate dd(junk) path('/etc/rc')
READY
rexx trace R; call LISTDSI 'junk file'; say sysreason
1 *-* call LISTDSI 'junk file'
>>> "junk file"
>>> "16"
*-* say sysreason
>>> "0002"
0002
READY
rexx trace R; call LISTDSI 'foo file'; say sysreason
1 *-* call LISTDSI 'foo file'
>>> "foo file"
>>> "16"
*-* say sysreason
>>> "0002"
0002
READY
allocate dd(junk) dummy
IKJ56246I FILE JUNK NOT ALLOCATED, FILE IN USE
IKJ56112A ENTER 'FREE' OR 'END'+-
end
READY
allocate dd(foo) dummy
READY
I hate LISTDSI!
I've never understood trying to use an API for an unintended and
undocumented purpose and getting frustrated and/or complaining when it doesn't
work... I see it as a bonus when experimentation uncovers an unintended use and
it unexpectedly works.
I have found LISTALC STATUS to be the most reliable source of allocation
information when verifying non traditional allocations (uncataloged things).
Inserting code to walk the TIOT and JFCB is just too cryptic...
I have a DDLIST function that culls the DD's from LISTALC. My DDCHECK
routine first attempts a LISTDSI. If that fails it calls DDLIST and does a
wordpos against the returned DDLIST to determine if an allocation exists. If
more information is needed (like if the allocation is a PDS or VSAM or), I
use the LISTDSI information already available from DDCHECK. If it is a
USS file and I need to know if it is a directory or a file or pipe or
symlink, I call my USSEXIST routine that accepts the PATH does a stat call and
returns the stat.ST_TYPE value. The path is available in the LISTALC STATUS.
My companion DDDSNS routine builds a DSN list for every DD in a unique
stem dd.ddname (non numeric stem).
Rob
In a message dated 9/20/2010 8:30:18 P.M. US Mountain Standard Time,
-----Original Message-----
From: Bob Bridges
Sent: Monday, September 20, 2010 8:01 PM
To: TSO-...@VM.MARIST.EDU
Subject: Re: Help with INTERPRET
... As you say, it's fun discovering how to do something, but there's no
real charm in doing it again later.
----------------------------------------------------------------------
> LISTDSI does stand for LIST DataSet Information... Not USS file
> information, SYSOUT information or DUMMY information... When used for the intended
There is a passage in "Using Data Sets" which appears to
define a Data Set as anything that can be allocated to
a DDNAME: DASD, tape, card readers, punches, printers,
terminals, etc. I assume that extends to USS files allocated
to DDNAMEs.
And I did supply the FILE option. In TSO jargon FILE
generally refers to the allocation not to the underlying
backing storage.
> purpose it does work fine. The return code and sysreason let you know you
> have either used it for something it doesn't support or you have an
> environmental issue that is keeping it from returning your data...
>
But Mickey said that he uses LISTDSI to determine whether a
a DDNAME was allocated. I supplied a case in which RC and
SYSREASON are identical for an unallocated DDNAME and an
allocated DDNAME. I wonder how Mickey makes the determination.
As a minimum, LISTDSI ... FILE should return a unique
SYSREASON for "file unallocated."
> I've never understood trying to use an API for an unintended and
> undocumented purpose and getting frustrated and/or complaining when it doesn't
> work... I see it as a bonus when experimentation uncovers an unintended use and
> it unexpectedly works.
>
Times change. A driver of a modern automoble rightfully
complains when a highway engineered a century ago has curves
that can not be driven at greater than 15 MPH, regardless
that he's using the highway for " an unintended and
undocumented purpose. LISTDSI is stuck in the mid-20th
century. It needs to get better. Programmers shouldn't
be required to use a different interface for each device
type.
YES! I agree. IBM has had more than enough time to modernize LISTDSI (and
many other interfaces as well) into a more effective interface.
Don Williams
DBWi...@unch.unc.edu
(919) 966-3968
UNC Hospitals
Information Services Division, 2nd Floor
321 Meadowmont Village Circle, Chapel Hill, NC 27517
"The time is always right to do what is right" -- Martin Luther King, Jr.
When I want a free DDN for output, I have a subroutine that accepts a
prefix, say "TEST", and generates a few random numbers to see whether
LISTDSI thinks TEST0369 is free, then TEST1039, TEST9973 and so on. If it
hits 10 in a row already allocated, something's wrong and it fails. It's
kludgy, I guess, but I've been using it happily for a decade or so now. And
it's not the sort of thing that I'd ever need to use in a loop, so it
doesn't matter much if it could be faster. It just saves me having to make
up a name that might already be used by some other program that's also
running at the same time.
I've heard you guy's talking about this BPX...thingy; I never supposed it
was available outside OMVS so I never looked seriously at it. Should I?
---
Bob Bridges, rhb...@attglobal.net, cell 336 382-7313
work bob.b...@libertymutual.com, 317 581-6487
/* Ignorance is the mother of adventure. -Hagar the Horrible */
-----Original Message-----
From: Mickey
Sent: Monday, September 20, 2010 22:27
I also use BPX. If all I want to know is IF a DD is allocated, I will
usually use LISTDSI with the FILE option.
-----Original Message-----
From: Paul Gilmartin
Sent: Monday, September 20, 2010 21:44
For some purposes, it's simpler to use BPXWDYN( '... rtddn(VAR) ...' )
and let DYNALLOC pick one for me so I needn't probe for a free one.
(BPXWDYN: it's not just for Unix any more!)
--- On 09/20/10 18:01, Bob Bridges wrote:
> ... something to trap LISTALC so I can check to see whether certain DD
> names are already allocated...
-- gil
BPXWDYN
_http://publibz.boulder.ibm.com/cgi-bin/bookmgr_OS390/BOOKS/BPXZB690/6.0?SHE
LF=BPXZSHA1&DT=20090603025450_
(http://publibz.boulder.ibm.com/cgi-bin/bookmgr_OS390/BOOKS/BPXZB690/6.0?SHELF=BPXZSHA1&DT=20090603025450)
Another cool tool is BPXWUNIX
_http://publibz.boulder.ibm.com/cgi-bin/bookmgr_OS390/BOOKS/BPXZB690/5.2?SHE
LF=BPXZSHA1&DT=20090603025450_
(http://publibz.boulder.ibm.com/cgi-bin/bookmgr_OS390/BOOKS/BPXZB690/5.2?SHELF=BPXZSHA1&DT=20090603025450)
Rob
In a message dated 9/21/2010 9:25:07 P.M. US Mountain Standard Time,