Using the Callout Gateway
Running Programs or System Commands with $ZF(-100)
provides functionality similar to that of a command line interface, allowing you to invoke an executable program or a command of the host operating system. The syntax of this function is:
The first argument must be a literal -100
. The other three arguments specify the following information:
a string containing keywords that specify various options. For example, the string "/ASYNC/LOGCMD"
specifies that the program should run asynchronously and write the command line to a log file.
a string specifying the program or system command to invoke. If the full path to an executable is not specified, the operating system will apply standard search path rules.
command arguments are specified as a series of comma-delimited expressions (as demonstrated in the example below).
function returns an exit status code determined by the operating system and the program that was invoked.
The following example passes three strings to the echo
command and then displays the status code. This example does not use any keywords, so the keywords
argument is an empty string. The final command argument specifies a quoted string (following standard ObjectScript string rules):
USER>set status = $ZF(-100,"","echo","hello","world","""goodbye now""")
hello world "goodbye now"
allows you to run a program or command either synchronously or asynchronously, with or without invoking the operating system shell. The default is to execute synchronously without invoking a shell. Default execution can be overridden by specifying optional keywords in the function call.
The following keywords can be used to control program execution:
Indicates that the program should run asynchronously, allowing the $ZF(-100)
call to return without waiting for the program to complete.
Indicates that the program should run in an operating system shell.
As mentioned in the last section, you can specify an empty string for the keyword
parameter if you don’t want to use either of these options. This example deliberately tries to list nonexistent files so that an error code 1
will be generated:
USER>set status = $ZF(-100,"", "ls","*.scala")
ls: cannot access *.scala: No such file or directory
If we run the same command asynchronously, the output is not displayed and st
is undefined because no error code has been returned:
USER>set status = $ZF(-100,"/ASYNC", "ls","*.scala")
Logging Commands and Redirecting Output
The following keywords control logging and I/O redirection:
Logging Command Arguments
keyword causes command arguments and the exit status code to be logged in the console log (<install-dir>\mgr\messages.log
). This is intended primarily as a debugging tool that allows you to see how expressions passed to $ZF(-100)
were actually evaluated.
03/28/18-11:49:51:898 (26171) 0 $ZF(-100) cmd=echo "hello" "world"
03/28/18-11:49:51:905 (26171) 0 $ZF(-100) ret=0
However, on UNIX® when /SHELL
is not specified, values are logged one per line:
03/28/18-12:09:22:243 (26171) 0 $ZF(-100) argv=echo
03/28/18-12:09:22:500 (26171) 0 $ZF(-100) argv=hello
03/28/18-12:09:22:559 (26171) 0 $ZF(-100) argv=world
03/28/18-12:09:22:963 (26171) 0 $ZF(-100) ret=0
In either case, arguments are logged exactly as they are received by the program.
The following keywords and file specifiers control I/O redirection:
I/O redirection keywords are followed by an operator ( =
) and a filename or file path. Spaces are permitted around the operators. Standard input should point to an existing file. The standard output and standard error files are created if they don't exist and are truncated if they already exist. Use the =
operator to create or truncate a file, or the +=
operator to append to an existing file. To make standard error and standard output to go to the same file, specify the same file for both keywords.
In the following example, the first line redirects the standard output from the echo
command to file temp.txt
., and the second line displays the resulting file contents:
USER>set st = $ZF(-100,"/STDOUT=""temp.txt""","echo","-e","three\ntwo\none\nblastoff")
USER>set st = $ZF(-100,"","cat","temp.txt")
In this next example, we display two lines of temp.txt
in a different way, by redirecting the file to standard input. The tail
command accepts the input and displays the last two lines:
This final example redirects standard error to temp.txt
, and attempts to display a nonexistent file. It also uses the /ASYNC
keyword to run the command asynchronously, causing the $ZF(-100)
call to return before the error message can be displayed. The second line (identical to the previous example) again displays the last two lines of the file, which now contain the redirected error message:
USER>set st = $ZF(-100,"/ASYNC /STDERR+=""temp.txt""","cat","nosuch.file")
cat: nosuch.file: No such file or directory
Adding the %System_Callout:USE Privilege
If your InterSystems security setting is higher than minimal, 0 $ZF(-100)
requires the %System_Callout:USE
resource is already assigned to the %Developer
Role, which you will have if you selected the Developer setup during installation. The following procedures describe how to assign this resource if you do not already have it:
Assigning a Role to a User
Use the following procedure to assign the %Developer
role to a User:
Open the Management Portal, go to [System Administration] > [Security Management] > [Users]
and click Edit
on the user description you want to use, then select the [Roles]
Move the %Developer
role from the Available
column to the Selected
column and click Assign
. The role will appear in the list of roles assigned to this user. (If the %Developer
role does not appear in the Available
column, check the list of roles to see if you already have this role).
Click the Profile
button. The %Developer
role should be listed on the Roles:
In some cases, it may be desirable to have a role that allows use of $ZF(-100)
but does not grant any other privileges. Use the following procedure to create a new role that grants only the %System_CallOut:USE
Open the Management Portal and go to [System Administration] > [Security Management] > [Roles]
Fill in the name and description:
When you click Save
, an Add
button appears on the form.
Click the Add
button to pop up a scrolling list of resources, select %System_CallOut
from the list, and click Save
. Click Close
on the Edit Role
On the Roles
page, the new UseCallout
role is now in the list of role definitions.