﻿# MX\_FILEHOOK

_Updated September 2017_

**xcall MIAMEX, MX\_FILEHOOK, opcode, status, file \{,fid, handler, events, flags, enabled\}**

MX\_FILEHOOK (MIAMEX 178) 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

**Parameters**

_opcode_  ([Num](num.md))  \[in\]

may be one of the following (defined in [ashinc:hook.def](https://bitbucket.org/microsabio/soslib/src/master/907016/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\]](https://bitbucket.org/microsabio/exlib/src/master/908050/qryhooks.bp) for examples of querying the file hook table. |
| **Definition File: **[ashinc:hook.def](https://bitbucket.org/microsabio/soslib/src/master/907016/hook.def) | | 



_status_  (Signed [Num](num.md))  \[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](string.md))  \[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](num.md))  \[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](string.md))  \[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_  (B4)  \[in\]

a bit-field of events to hook, from the following (defined in [ashinc:hook.def](https://bitbucket.org/microsabio/soslib/src/master/907016/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](https://bitbucket.org/microsabio/soslib/src/master/907016/hook.def) | | 



_flags  _(B4)  \[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](https://bitbucket.org/microsabio/soslib/src/master/907016/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](https://bitbucket.org/microsabio/soslib/src/master/907016/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](num.md))  \[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.

**Example**

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](hooksbxspecification.md). 

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 topics, [File-Based File Hook Handler](file-basedfilehookhandler.md) and [MX\_FILEHOOK Support for ISAM-A](mx_filehookforisam-a.md), for more details.



**History**

2018 July, A-Shell 6.5.1642:  Added _handler_ LOGFIL: and [File-Based File Hook Handler](file-basedfilehookhandler.md) 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\]](https://bitbucket.org/microsabio/exlib/src/master/908050/) have been updated to illustrate both hooks.