Updated September 2017
xcall MIAMEX, MX_FILEHOOK, opcode, status, file {,fid, handler, events, flags, enabled}
The file hook mechanism allows you to establish file "hooks" on specific files and file events. The "hook" is a means by which you can insert a call to a "handler" (sometimes referred to as a "plug-in") into the midst of what would otherwise be an entirely internal operation, allowing you to monitor, filter, or otherwise customize the operation. Typical uses for file hooks are:
• audit trails
• event logs
• exporting changes
• enforcing access security rules
opcode (Num) [in]
may be one of the following (defined in ashinc:hook.def):
Symbol |
Value |
Meaning |
HOOKOP_DISABLE |
0 |
disable one (or all) hooks |
HOOKOP_ENABLE |
1 |
re-enable one (or all) hooks |
HOOKOP_ADD |
2 |
add a new hook |
HOOKOP_DEL |
3 |
delete a hook |
HOOKOP_APPEVENT |
6 |
call the hook to process an app-defined event |
HOOKOP_QRY |
7 |
query a file hook by its fileid or filespec. If found, the status will be >= 0 and all of the remaining fields will be returned. See the sample/utility program QRYHOOKS in EXLIB:[908,50] for examples of querying the file hook table. |
Definition File: ashinc:hook.def |
status (Signed Num) [out]
returns status code:
Value |
Meaning |
>=0 |
success |
-1 |
unable to allocate memory for hook table |
-2 |
illegal fspec (must be AMOS-style) |
-3 |
invalid handler syntax |
-4 |
fspec not found (opcode 0,1,2,6) |
-5 |
fid not found (opcode 0,1,2,6) |
-6 |
opcode not yet implemented |
-7 |
illegal opcode |
file (String) [in]
is the specification of the file whose operations are to be hooked. Only AMOS-compatible filespecs are supported. Note that with opcode 0, 1 and 3, file may be "*" to perform the operation on all the hooks in the hook table. Note that in the case of ISAM and ISAM-A files, you must specify the extension, typically IDA or DAT.
fid (Num) [in]
a unique integer identifier for the file, which will be used in any output files to reference the file (more compact than outputting the file spec each time.)
handler (String) [in]
depends on opcode. For opcode 2 (HOOKOP_ADD), it must specify the handler for the hook, using one of the following syntax variations:
SBX:sbxnam
LOGFIL:fspec
In the case of the SBX:sbxnam handler, A-Shell will XCALL the specified SBX subroutine (sbxnam) to process the hook, allowing you to add custom logic into the file operation in real time. Note that sbxnam is limited to a maximum of six characters, e.g. SBX:AROPEN. In the case of the LOGFIL:fspec handler, A-Shell uses its own built-in logic to output information about the event to the specified file, allowing you to process the log file later. Each type of hook is described in greater detail in the sections that follow.
For opcode 6 (HOOKOP_APPEVENT), the handler parameter may be used to pass an arbitrary string to the handler previously set up by opcode 2. Typically this may be used to send a contextual message to the handler, such as "starting check run" or "posting run complete".
events (B,4) [in]
a bit-field of events to hook, from the following (defined in ashinc:hook.def):
Symbol |
Value |
Meaning |
HFE_PRE_OPEN |
&h00000001 |
prior to open |
HFE_POST_OPEN |
&h00000002 |
after open |
HFE_PRE_CLOSE |
&h00000004 |
prior to close |
HFE_POST_CLOSE |
&h00000008 |
after close |
HFE_PRE_READ |
&h00000010 |
prior to read or get (any) |
HFE_POST_READ |
&h00000020 |
after read or get (any) |
HFE_PRE_READL |
&h00000040 |
prior to readl or getl |
HFE_POST_READL |
&h00000080 |
after readl or getl |
HFE_PRE_WRITE |
&h00000100 |
prior to write (or update'record) |
HFE_POST_WRITE |
&h00000200 |
after write (or update'record) |
HFE_PRE_WRITEL |
&h00000400 |
prior to writel (or create'record) |
HFE_POST_WRITEL |
&h00000800 |
after writel (or create'record) |
HFE_PRE_ALLOC |
&h00002000 |
prior to allocate |
HFE_POST_ALLOC |
&h00004000 |
after allocate |
HFE_PRE_KILL |
&h00008000 |
prior to kill |
HFE_POST_KILL |
&h00010000 |
after kill |
HFE_PRE_SORT |
&h00020000 |
prior to sort |
HFE_POST_SORT |
&h00040000 |
after sort |
HFE_ISAM_ADD |
&h00080000 |
after ISAM 5 (add); see History |
HFE_ISAM_DEL |
&h00100000 |
after ISAM 6 (delete); see History |
HFE_PRE_ISAMA_DEL |
&h00200000 |
ISAM-A pre delete'record |
HFE_POST_ISAMA_DEL |
&h00400000 |
ISAM-A post delete'record |
HFE_APP_EVENT1 |
&h10000000 |
custom application event |
Definition File: ashinc:hook.def |
flags (B,4) [in]
a bit-field of flags which are passed to the hook routine (as a clue to how the hook should operate), and/or which are used by A-Shell to modify the operation of the hook (from ashinc:hook.def):
Symbol |
Value |
Meaning |
HFF_PROG |
&h00000001 |
include program name |
HFF_SBX |
&h00000002 |
include sbx name |
HFF_DATA |
&h00000004 |
include copy of data just written (POST_WRITE only) |
HFF_DATA_WAS |
&h00000008 |
include copy of data as previously read or written, for comparison with data now being written (POST_WRITE only) |
HFF_RECNO |
&h00000010 |
include recno |
HFF_TIME |
&h00000020 |
include time |
HFF_DATE |
&h00000040 |
include date |
HFF_TIMESTAMP |
&h00000060 |
Include timestamp in log for each event |
HFF_USER |
&h00000080 |
include user name |
HFF_PID |
&h00000100 |
include process id |
HFF_AUTO_DEL |
&h00001000 |
auto delete hook on prog exit |
HFF_SQZ_ENV |
&h00080000 |
'squeeze' env rec (LOGFIL: hooklogs) |
HFF_DATA_WAS_NA |
&h00010000 |
there is no "was" data available to pass to the hook routine in response to the HFF_DATA_WAS flag |
HFF_DATA_CHG_ONLY |
&h00020000 |
may be used in conjunction with HFE_POST_WRITE to suppress calling the hook function after the write if the record data hasn't changed. |
HFF_SQZ_DATA |
&h00100000 |
'squeeze' data recs (LOGFIL: hooklogs) |
Definition File: ashinc:hook.def |
Note that for the SBX handlers, most of the flags affecting the data that is included in the information passed to handler are ignored. The packet is a fixed size and there is nothing to be gained by blanking out certain fields. The flags which do matter are: HFF_DATA and HFF_DATA_WAS, HFF_DATA_CHG_ONLY, and HFF_AUTO_DEL.
enabled (Num) [out]
returns zero or one to indicate if the hook is disabled or enabled.
Comments
Hook definitions are not directly affected by file open and close operations. Nor are they affected by termination of the program unless the HFF_AUTO_DEL flag is specified when the hook is established. They are automatically removed by termination of the A-Shell session. So you can add/delete all your file hooks in a common application startup/shutdown program, without making any modifications to the individual programs which operate on the files.
MX_FILEHOOK works with random, ISAM, and ISAM-A files. In the case of ISAM and ISAM-A files, only the data file is hooked.
Use the following pattern to establish a file hook...
++include'once ashinc:ashell.def
++include'once ashinc:hook.def
define FID_CUST = 1001 ! file ID for customer file
map1 hook'vars
map2 hook'status,f
map2 hook'file$,s,40
map2 hook'fid,b,4
map2 hook'handler$,s,16
map2 hook'events,b,4
map2 hook'flags,b,4
hook'file$ = "DSK2:CUST.DAT[100,50]"
hook'fid = FID_CUST
hook'handler$ = "SBX:MYHOOK"
hook'events = HFE_POST_OPEN or HFE_POST_WRITE or HFE_POST_WRITEL or HFE_POST_CLOSE or HFE_PRE_ALLOC
hook'flags = HFF_PROG or HFF_SBX or HFF_RECNO or HFF_TIME or HFF_DATE &
or HFF_USER or HFF_DATA or HFF_DATA_WAS
xcall MIAMEX, MX_FILEHOOK, HOOKOP_ADD, hook'status, hook'file$, hook'fid, hook'handler$, hook'events, hook'flags
if hook'status < 0 then ? "Error setting hook: ";hook'status
After the above code is executed the hook handler (MYHOOK.SBX) will be called after every open, write, writel and close operation on the file DSK2:CUST.DAT[100,50], and also every allocate operation on the file. See the following topic Hook SBX Specification.
The above example could be changed to use the LOGFIL: handler instead, by changing the hook'handler$ assignment to something like:
hook'handler$ = "LOGFIL:APPLOG:FILEIO.LOG
or
hook'handler$ = "LOGFIL:dsk0:audit.log[1,2]
See the following topic, File-Based File Hook Handler, for more details.
2018 July, A-Shell 6.5.1642: Added handler LOGFIL: and File-Based File Hook Handler to A-Shell
2015 February, A-Shell 5.1.1402: Added events HFE_ISAM_ADD and HFE_ISAM_DEL. Note that unlike most of the other file hooks, these don't come in PRE- and POST-flavors. For the ADD hook, the record data supplied to the hook routine (rec parameter) will contain the key rather than the record data. Since ISAM adds are followed by a WRITE statement, you can hook that to get the contents of the record itself. For the DEL hook, the record data of the record being deleted is supplied to the hook routine in the pre'rec parameter. The rec parameter should be ignored. The sample hook program FHOOKTST3.BP and hook subroutine FHOOK1.SBX in EXLIB:[908,50] have been updated to illustrate both hooks.
2011 June, A-Shell 5.1.1221: Added flag HFF_DATA_CHG_ONLY to suppress calling the hook function after the write if the record data hasn't changed.
2010 December, A-Shell 5.1.1197: File hook refinement: When there is no "was" data available to pass to the hook routine (in response to the HFF_DATA_WAS flag), A-Shell now sets a new flag, HFF_DATA_WAS_NA in the flags field in the hook environment structure passed to the hook routine. This allows the hook routine to distinguish between an empty prior record and unknown prior record contents. The prior contents of the record can only be supplied to the hook routine if the last record # read is the same record # being written. ashinc:hook.def has been updated with the new flag, and the sample hook routine FHOOK1.BP in EXLIB[908,50] (SBX) has been updated to show testing the flag.
2010 January, A-Shell 5.1.1174: Routine added to A-Shell