Thanks for all the replies.
My worry about IBM not allowing me to call QLICRDUP directly seems to be
confirmed.
I was hoping to take the incoming parameters and pass them directly to
QLICRDUP, then follow up with my own programming.
Using QIBM_QCA_CHG_COMMAND won't work for me because I don't want to
change the existing CRTDUPOBJ command at all.
My course of action now will be to parse all of the incoming parameters
and put them into a QCMDEXC call to execute CRTDUPOBJ.
Thanks,
Karl Abbott 
-----Original Message-----
From: MIDRANGE-L [mailto:midrange-l-bounces@xxxxxxxxxxxx] On Behalf Of
rob@xxxxxxxxx
Sent: Monday, March 30, 2015 4:16 AM
To: Midrange Systems Technical Discussion
Subject: Re: pre process command
I suggest you read Chuck's post thoroughly, lengthy though it is.  For
many people it's hard for them to digest anything longer than a tweet
but there are some real gems in there.  Like, but not limited to,
- IBM could add a parameter to the program called by CRTDUPOBJ at any
simple PTF since that program is not a published API and your program
could be screwed.
And that's just one of many gems.
Rob Berendt
--
IBM Certified System Administrator - IBM i 6.1 Group Dekko Dept 1600
Mail to:  2505 Dekko Drive
          Garrett, IN 46738
Ship to:  Dock 108
          6928N 400E
          Kendallville, IN 46755
http://www.dekko.com
From:   CRPence <CRPbottle@xxxxxxxxx>
To:     midrange-l@xxxxxxxxxxxx
Date:   03/28/2015 05:35 PM
Subject:        Re: pre process command
Sent by:        "MIDRANGE-L" <midrange-l-bounces@xxxxxxxxxxxx>
On 27-Mar-2015 17:37 -0500, Karl Abbott wrote:
I want to create a duplicate of the CRTDUPOBJ command, which will
process the CRTDUPOBJ command and then follow up duplicating logical
files, if necessary.
   Hmm. Seems very likely then, that a post-processor for the command 
would be required, not a pre-processor.?  Anyhow, some thoughts 
[composed in-line to the quoted text]:
   FWiW: The Create Duplicate Object (CRTDUPOBJ) already has the 
built-in capability to duplicate the physicals and then the dependent 
logical files.  That capability however depends on there being a shared 
naming prefix for both the Physical File(s) and the dependent Logical 
File(s); the Object (OBJ) specification merely need specify the Generic*
name [or special-value *ALL], and as with the other benefits for the DBF
network contained within the same library, all of the dependents with 
that naming would be in and thus duplicated from the one From Library 
(FROMLIB) named on the CRTDUPOBJ invocation.  The feature ensures the 
/duplicated/ files are created in the proper order, first the physical 
files then the logical files ordered both after any based-on PF and 
after any based-on LF [i.e. for any VIEW over VIEW].
   Unfortunately the database-file dependency ordering feature [used in 
the save, restore, and duplicate paths] is not exposed as an API.  So 
outside of a common naming prefix, the ordering must be done by other 
means; e.g. for a simplest scenario of a PF with only LFs over that one 
based-on PF, by using the order of the entries in the directory for the 
file, as presented by the Display Database Relations (DSPDBR) for the PF
[or the equivalent API invocation].
I created a duplicate of the CRTDUPOBJ command, named it CRTDUP,
changed the CPP to my program "CRTDUP" in my lib.
   That method limits the customization, most notably for an inability 
to add extra parameters, and requires that the same [re]customization 
takes place again after every time the system-supplied command changes 
[which is possible albeit unlikely, to be via a PTF, rather than just to
be via only either a TR or a release-upgrade].
   So if the unchanged command is satisfactory, then a better option 
might be to intercept the command with Change Command Exit Program 
feature (QIBM_QCA_CHG_COMMAND) to effect an alternate outcome for the 
existing command invocation; of course probably instead limited as 
implemented against a Proxy Command, and probably best named other than 
CRTDUP which is consistent with system-command naming mnemonics, so 
perhaps something like DUPPFEXT (DUPlicate PF EXTended)].
   But because the implied as-desired effect is additional work that 
depends upon the completion of the invoked command, merely changing the 
command [string] before the CPP is invoked would not be helpful [except 
to invoke a different command].  In that case, an additional Retrieve 
Command Exit Program (QIBM_QCA_RTV_COMMAND) apparently may be required.
   Some resources in that regard:
<
http://iprodeveloper.com/rpg-programming/apis-example-change-and-retriev
e-command-exit-points-and-command-exit-cl-commands
APIs by Example:
Change and Retrieve Command Exit Points - and Command Exit CL Commands
Mar 25, 2010 Carsten Flensburg
System iNetwork Programming Tips Newsletter
"...
Today's APIs by Example focuses on two distinct exit points: Change 
Command and Retrieve Command Exit Points. The former enables you to 
register a single exit program for almost any CL command on your system.
The latter provides for up to 10 exit programs being registered for each
CL command. ...
  ..."
<
http://www.mcpressonline.com/cl/the-cl-corner-new-support-for-cl-command
s-lets-you-know-when-a-command-ends.html
The CL Corner:
New Support for CL Commands Lets You Know When a Command Ends 
Programming - CL
Written by Bruce Vining
Friday, 24 February 2012 00:00
"Need to know when "something" has finished? The Command Analyzer 
Retrieve exit point capability tells you what you need to know.
  ...
This new support allows you to designate a program that is to be called 
when the command processing program (CPP) of a CL command completes. ...
As some background, starting with V4R5, IBM has supported exit point 
capabilities allowing you to have exit programs called before the system
transfers control to the CPP of a given command. Using the Retrieve exit
point, documented here 
<
http://publib.boulder.ibm.com/infocenter/iseries/v5r4/topic/apis/xcartv.
htm
, 
your exit program could access the command string originally submitted 
to the command analyzer. Using the Change exit point, documented here 
<
http://publib.boulder.ibm.com/infocenter/iseries/v5r4/topic/apis/xcachg.
htm
and utilized in the 2009 CL Corner article 
<
http://www.mcpressonline.com/tips-techniques/cl/the-cl-corner-overriding
-commands-and-their-parameter-values.html
"Overriding Commands and Their Parameter Values," your exit program 
could not only access the original command string, but also change the 
command prior to the CPP running. With the PTFs mentioned previously, 
you now also have the ability for the Retrieve exit point to call an 
exit program after the CPP of a given command has returned control to 
the IBM i.
  ..."
Since I'm using a duplicate of the CRTDUPOBJ command, I was thinking
I could just take the parameters coming in to my CPP and pass them
with a call to the program QLICRDUP, so that the normal CRTDUPOBJ
would process.
   Note: Be aware that the prompted order of parameters does not 
necessarily match the order of parameters defined to the Command 
Processing Program (CPP).  There may also be arguments that are passed 
to the CPP that are not visible as parameters on the prompted Command 
because they are defined as constants.  Thus each command for which such
an attempt is made, first should be disassembled; there is a published 
command [system-like named IIRC] called Retrieve Command Source 
(RTVCMDSRC) that does just that.  Doing that makes both creating the 
custom command and knowing the nearly exact interface requirements, very
simple\straightforward.
   Consider: If creating a custom Command Processing Program (CPP) is 
required whether /borrowing/ the system command via a duplicate or 
whether creating a custom command object, then a conspicuous 
consideration might be to create also, a custom Command (*CMD) object. 
Having defined both a CPP and a CMD in conjunction, any changes to 
either the system-supplied command or the system-supplied CPP should 
have no future impacts, except what might be documented in a future Memo
To Users (MTU) for a release [due to differences with the documented 
command interface].  Given the system-program QLICRDUP is an 
undocumented interface, any changes to that OS program effectively 
always will remain undisclosed to customers [except what might be 
inferred from the operation of the CPP or changes made to any commands 
naming QLICRDUP as the CPP].
But when I call QLICRDUP I get an error "Object domain or storage
protection error for offset  in object QLICRDUP."
   The OS ensures a level of protection for the call interfaces to most 
system-programs, especially for which the inputs and outputs are not 
published; i.e. generally, for those that are not an API.  The programs 
are protected from non-standard invocations, allowing only those 
invocations that are expected would occur only via the published Command
(*CMD) invocation method.
   Such non-API programs are generally prevented from being invoked by 
either commands or programs that were not created by\for the IBM i OS or
LPPs, mostly because those non-API interfaces [e.g. as a CPP for the 
commands], are subject to change without notification [to customers]. 
IBM can ensure the matching changes are made both to the dependent OS or
LPP Command objects [and to any OS\LPP features that might invoke them 
directly, thus bypassing the CMD objects] if\when the CPP changes, 
because those commands and programs are under a change control system 
that includes notifying those affected.  But any changes to those 
unpublished interfaces [e.g. to a CPP of a system-supplied command] 
would remain unknown to the users, and as unpublished, would remain so. 
  Because user-coded invocations would not necessarily be [able to be] 
appropriately updated to match the changed OS program, those invocations
could lead to unpredictable difficulties.  Thus the user program is 
properly being prevented from potentially debasing the integrity of the 
system, as notified via the exception x4401 domain violation [msg 
MCH6801 "Object domain or storage protection error for offset &5 in 
object &1."]; the design intends the program should not be invoked, to 
prevent potential side effects from unpredictable behavior, due to a 
user-coded invocation of an undocumented and possibly changing interface
being essentially a GIGO scenario.
At this point all I am trying to do is pass the parameters through
my program and have the CRTDUPOBJ run.
Here is my program.
The contents of field LENOBJTYPES is variable, based on the object
types you select. I've tried adjusting it from 310 to 410, but always
get the same error.
   Just to reiterate, the error is due to the user-domain program [i.e. 
the user-created program] being prevented from invoking the 
system-domain program [i.e. the OS program], as a consequence of the OS 
enforcing domain /integrity/ checking.  No matter how accurately the 
arguments are declared and ordered [prototyped] to match the parameters 
of the invoked program, the invocation still will fail.  Only by 
changing the user-program into a system-domain program [or in old 
releases, possibly not with newer release, by reducing the Security 
Level (QSECURITY) system value for the system], can the CALL be effected
without that MCH6801 error.
<<SNIP RPG src with D-Specs, PLIST, and CALL QLICRDUP>>
   I would suggest creating a custom command; whether the CPP is REXX or
a PGM() is of no consequence, although the REXX interface provides the 
original command string more directly, and sometimes is convenient.  The
since-snipped source could be the CPP, but rather than issuing a CALL to
the system-program QLICRDUP, the CPP should construct\retrieve the CL 
command-string for what would be the original CRTDUPOBJ request and then
construct each additional CRTDUPOBJ request [or whatever other actions 
are required], and then perform the ordered requests successively to 
achieve the as-desired reformulated effects for the request to 
/Duplicate/ object(s).
   A custom command could remove parameters [e.g. such as Object Type 
(OBJTYPE) if the intent is that the custom command would support only 
<database> *FILE objects], or add parameters [e.g. a specification of 
how to deal with a JLF or other multiple-file LF over a PF or a VIEW 
over a LF that was either unspecified on the request or was otherwise 
omitted per OBJ() specification], or to provide alternate capabilities 
perhaps with additional special-values for existing parameters [e.g. the
 From Object (OBJ) parameter might be expanded to support multiple 
names, could be restricted to an explicit rather than any generic name 
specifications, or the Trigger (TRG) parameter might add a *ONLYPF so as
to suggest only triggers on PF are copied whereas INSTEAD OF triggers on
VIEWs would not be copied].
   A custom command also resolves the issue of a /pre-process/ operation
being inherently unable to effect what was described-as the extra work 
[to duplicate the dependent Logical Files of a PF being duplicated with 
the CRTDUP as a command defined as effective duplicate of CRTDUPOBJ] 
because that work actually must be performed as a /post-process/; i.e. 
must be performed after the end-effect from the originally requested 
CRTDUPOBJ, such that a simple changed-command-string as the effect for 
the intercepted CRTDUP command string is insufficient.
As an Amazon Associate we earn from qualifying purchases.