× The internal search function is temporarily non-functional. The current search engine is no longer viable and we are researching alternatives.
As a stop gap measure, we are using Google's custom search engine service.
If you know of an easy to use, open source, search engine ... please contact support@midrange.com.



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-retrieve-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-commands-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.

This thread ...

Follow-Ups:

Follow On AppleNews
Return to Archive home page | Return to MIDRANGE.COM home page

This mailing list archive is Copyright 1997-2024 by midrange.com and David Gibbs as a compilation work. Use of the archive is restricted to research of a business or technical nature. Any other uses are prohibited. Full details are available on our policy page. If you have questions about this, please contact [javascript protected email address].

Operating expenses for this site are earned using the Amazon Associate program and Google Adsense.