Executing operating system commands on a Caché server

  • Tutorial
Based on an article in Developer Connection, he wrote his own implementation of a class for invoking commands from the server operating system where Caché or Ensemble is installed.
A class can come in handy when you need to do something on the host OS from Caché: manage backup files, configure work with the version control system and other useful actions.
The class allows you to execute a command on any host OS and get a response to a global or local variable.

Class code with comments
Class Server.Manage Extends% RegisteredObject

Parameter cmdlist = "dir, type, ver";

/// method removes command sequences from the command line
/// leaves only allowed commands
ClassMethod safeCmd (cmd) As% String
  set cmd = $ piece (cmd, "&&") // leave one command
  set cmd = $ piece (cmd , "|")
  for i = 1: 1: $ length (.. # cmdlist, ",") set safe ($ p (.. # cmdlist, ",", i)) = "" // list of allowed commands
  if '$ data (safe ($ piece (cmd, ""))) set cmd = ""   
  quit cmd

/// the method executes the cmd command on the server and adds the result to the global ad so that:

ClassMethod runCmd (cmd, ad As% String) As% Status
  set sc = $$$ OK
  do $ SYSTEM.Process.SetZEOF (1) // turn off the error generation mode on EOF
  // make the command line safe
  set cmd (1) = .. safeCmd (cmd) 
  quit: cmd (1) = "" $$$ ERROR ($$$ GeneralError, "Invalid command" _cmd)
  set cmd = cmd (1)
  // clear the sent global
  kill @ad
  set count = 0

  try {
  // open the device by running the command line and reading the answer
  open cmd: "QR: K \ CP866 \" if '$ test $$$ ThrowStatus ($$$ ERROR ($$$ GeneralError, "Failed to execute the command" _cmd))
  the Set the IO = $ // remember the IO current device
  // read the result of the command line by line until the end of the file     arrives and add it to the global
  for { 
    use cmd 
read str quit: $ zeof = -1
    set @ad @ ($ Increment (count)) = str
  set @ ad = count
  // close the device 
  #dim e as% Exception.AbstractException
  } Catch e {
      set sc = e.AsStatus ()
      // do e.Log () // 
  // close the device 
  close cmd

  // return the current device
  If $ data (IO) Use IO
 quit sc


The cmdlist parameter contains a list of allowed commands, separated by commas.
The safeCmd () method combs the command line.
The runCmd () method actually executes the cmd command and puts the result in the indirect address ad.

The above code works on all operating systems supported by Caché, executes commands, receives the result and processes errors. Unlike the implementation described in the article , the work is organized through the CommandPipe device - the “QR” mode for the open command. Read more in the documentation .


An example of the use can be observed here - a small project built on CSP + Twitter Bootstrap.
The server was not sent for slaughter - allowed commands: type, ver, format c, dir.
The class and web project code is posted on the github .

Also popular now: