The NetRexx Tutorial
- Interface with the system
NetRexx Tutorial - Interface with the system


Interface with the system

Introduction.

One of the most important points for coding effective NetRexx programs, is the ability to dialogue with the operating system. Thus we want to be capable of executing OS commands, getting the output in a variable or in a array, starting other processes, and so on.

Calling System Commands.

Sooner or later you will find yourself in the need to call a System Command from your NetRexx code, and have the output (if any) stored somewhere.

You should also note that you have ALWAYS an output from a System Command or Program. This is the Return Code rc from the Command itself.

Pictorially:

 
  +---------+           +--------------------+
  | O.S.    |<----------| NetRexx            |
  | (OS/2   |           | Program            |
  |  UNIX   |---------->|....................|---------> display
  |  W95    |  result   | .                  |           immediately
  |  WNT)   |           | ....> save in a    |
  |         |           | .     VARIABLE     |
  |         |           | ....> save in an   |
  |         |           |       ARRAY        |
  +---------+           +--------------------+
 

As we have just stated, we will distinguish three cases:

We want also to make some decisions depending on the result of the command we just executed. If the command fails, i.e. exits with a $RETURN, not zero we want to be able to choose to continue, inform the user, or abort.

Related JAVA classes

 
 java.lang.Process
 java.lang.Runtime
 

Calling a command immediately

This is probably the easiest instance: you want to execute an OS command (or a program). This means you will write:

 
(...)
cmd = 'zip files.zip file1 file2'
r  = Runtime.GetRuntime()
p  = r.exec(cmd)
(...)
 

It is ALWAYS a good practice to check the return code rc: a command or a program can fail for many reasons, and your program must be prepared for such eventualities. Note that if you do not check the rc, the program will happily continue with the following instructions. So we modify the above code as:

 
(...)
cmd = 'zip files.zip file1 file2'
r  = Runtime.GetRuntime()
p  = r.exec(cmd)
rc = p.exitValue()
if rc <> 0 then
  do
    say 'Command "'cmd'" failed with rc:' rc'.'
    exit rc
  end
(...)
 

This will allow us to check if the zip command in the above example didn't crash for a disk full problem, or for a missing input file.

Note that in the 2 above examples the output of the command is NOT displayed

A final WARNING

WARNING: I feel necessary to warn you about a potential problems if you abuse of calls to System Commands.

You should NEVER use a call to System Commands if your call can be implemented in Java itself. So you should not (if you're a UNIX user) do:

 
--
-- NEVER DO THIS !!!
--
ls = xexec('ls -l toto','VAR','ABORT')
parse ls.out . . . . size .

 

This code is, infact, no portable (DOS and Windows) do not know about "ls".

NOTE: if you want to implement "ls" you do something like:

 
+----------------------------------------------------------------------+
| l = String[]                                                         |01
| f = File(".")                                                        |02
| l = f.list()                                                         |03
| loop i = 0 to l.length-1                                             |04
|   say l[i]                                                           |05
| end                                                                  |06
+----------------------------------------------------------------------+
                                                                 lls.nrx
Download the source for the lls.nrx example

Simple examples

Execute a System command

 
+----------------------------------------------------------------------+
| -- syex1.nrx                                                         |01
| -- SYstem EXec                                                       |02
| --                                                                   |03
| class syex1 public                                                   |04
|                                                                      |05
|   method main(args=String[]) public static                           |06
|                                                                      |07
|     arg = Rexx(args)                                                 |08
|     parse arg cmd                                                    |09
|                                                                      |10
|     -- do the REAL job                                               |11
|     --                                                               |12
|     do                                                               |13
|       rtim = Runtime.GetRuntime()                                    |14
|       proc = rtim.exec(cmd)                                          |15
|       dis  = DataInputStream(proc.getInputStream())                  |16
|                                                                      |17
|       loop forever                                                   |18
|         line = dis.readline()                                        |19
|         if line = NULL then leave                                    |20
|         say line                                                     |21
|       end                                                            |22
|       rc   = proc.waitFor()                                          |23
|       say 'Return code:' rc'.'                                       |24
|     catch err = IOEXception                                          |25
|       say 'ERROR:' err                                               |26
|     end                                                              |27
|     exit 0                                                           |28
+----------------------------------------------------------------------+
                                                               syex1.nrx
Download the source for the syex1.nrx example

Execute an "interactive" System command

Some programs, like the following one, might require some "interactive" input.

 
+----------------------------------------------------------------------+
| n = 0                                                                |01
| loop forever                                                         |02
|   n = n+1                                                            |03
|   say 'Please enter something (quit to QUIT)'                        |04
|   parse ask line                                                     |05
|   if line = 'quit' then leave                                        |06
|   say n '>>>' line                                                   |07
| end                                                                  |08
+----------------------------------------------------------------------+
                                                            interact.nrx
Download the source for the interact.nrx example

It would be nice if it was possible to make (when needed) the input "automatic". This small example shows how.

 
+----------------------------------------------------------------------+
| -- syex2.nrx                                                         |01
| -- SYstem EXec                                                       |02
| --                                                                   |03
| class syex2 public                                                   |04
|                                                                      |05
|   method main(args=String[]) public static                           |06
|                                                                      |07
|     -- this is the interactive command                               |08
|     cmd = 'java interact'                                            |09
|                                                                      |10
|     -- do the REAL job                                               |11
|     --                                                               |12
|     do                                                               |13
|       rtim = Runtime.GetRuntime()                                    |14
|       proc = rtim.exec(cmd)                                          |15
|       dos  = PrintStream(proc.getOutputStream())                     |16
|       dis  = DataInputStream(proc.getInputStream())                  |17
|       dos.println('help')                                            |18
|       dos.println('quit')                                            |19
|       dos.close()                                                    |20
|                                                                      |21
|       loop forever                                                   |22
|         line = dis.readline()                                        |23
|         if line = NULL then leave                                    |24
|         say line                                                     |25
|       end                                                            |26
|       rc   = proc.waitFor()                                          |27
|       say 'Return code:' rc'.'                                       |28
|     catch err = IOEXception                                          |29
|       say 'ERROR:' err                                               |30
|     end                                                              |31
|     exit 0                                                           |32
+----------------------------------------------------------------------+
                                                               syex2.nrx
Download the source for the syex2.nrx example

The "key" instruction is:

 
dos  = PrintStream(proc.getOutputStream())
 

where we get an OUTPUT stream to the process proc. We now can simulate the keyboard input, which we do via:

 
dos.println('help')
dos.println('quit')
 

so all is like if you were typing help and quit from your keyboard.

The xexec method

 
+----------------------------------------------------------------------+
| -- method......: xexec
                                              |33
| -- purpose.....: constructor
                                        |34
| --
                                                                  |35
|   method xexec(cmd=String,dest=Rexx,oner=Rexx) public
               |36
|     dest = dest.upper()                  -- uppercase params
        |37
|     oner = oner.upper()
                                             |38
|     valid_dest = 'ARRAY SCREEN VAR NULL'
                            |39
|     valid_oner = 'WARNING ABORT IGNORE'
                             |40
| 
                                                                    |41
|     -- setting the defaults
                                         |42
|     --
                                                              |43
|     if dest = '' then dest = default_dest
                           |44
|     if oner = '' then oner = default_oner
                           |45
| 
                                                                    |46
|     -- check if the parms are OK
                                    |47
|     --
                                                              |48
|     if valid_dest.wordpos(dest) = 0 then
                            |49
|       do
                                                            |50
|         say 'Error: "'dest'" is not a valid destination.'
           |51
|         exit 1
                                                      |52
|       end
                                                           |53
|     if valid_oner.wordpos(oner) = 0 then
                            |54
|       do
                                                            |55
|         say 'Error: "'oner'" is not a valid ONERROR action.'
        |56
|         exit 1
                                                      |57
|       end
                                                           |58
| 
                                                                    |59
|     -- do the real job
                                              |60
|     --
                                                              |61
|     do
                                                              |62
|       r  = Runtime.GetRuntime()
                                     |63
|       p  = r.exec(cmd)
                                              |64
|       cr = DataInputStream(BufferedInputStream(p.getInputStream()))
 |65
| 
                                                                    |66
|       -- Output handling
                                            |67
|       --
                                                            |68
|       lines   = 0
                                                   |69
|       out = ''
                                                      |70
|       j = 0
                                                         |71
|       loop forever
                                                  |72
|         s = cr.Readline()
                                           |73
|         if s = NULL then leave
                                      |74
|         if dest.wordpos('SCREEN')
                                   |75
|           then say s
                                                |76
|         if dest.wordpos('VAR')
                                      |77
|           then out = out s
                                          |78
|         if dest.wordpos('ARRAY')
                                    |79
|           then
                                                      |80
|             do
                                                      |81
|               j = j+1
                                               |82
|               line[j] = s
                                           |83
|             end
                                                     |84
|       end
                                                           |85
|       lines = j
                                                     |86
|       line[0] = lines
                                               |87
|   
                                                                  |88
|       -- Return code handling
                                       |89
|       --
                                                            |90
|       rc = p.exitValue()
                                            |91
|       if rc <> 0 then
                                               |92
|         do
                                                          |93
|           select
                                                    |94
|             when oner = 'WARNING' then
                              |95
|               do
                                                    |96
|                 say 'WARNING: rc=' rc 'from "'cmd'".'
               |97
|               end
                                                   |98
|             when oner = 'ABORT' then
                                |99
|               do
                                                    |00
|                 say 'WARNING: rc=' rc 'from "'cmd'".'
               |01
|                 say 'ABORTING.'
                                     |02
|                 exit 5
                                              |03
|               end
                                                   |04
|              otherwise NOP
                                          |05
|           end
                                                       |06
|         end
                                                         |07
|     catch error = IOException
                                       |08
|       say error
                                                     |09
|   end
                                                               |10
| 
                                                                    |11
|   method xexec(cmd=Rexx,dest=Rexx) public
                           |12
|     this(cmd,dest,default_oner)
                                     |13
| 
                                                                    |14
|   method xexec(cmd=Rexx) public
                                     |15
|     this(cmd,default_dest,default_oner)
                             |16
| 
                                                                    |17
+----------------------------------------------------------------------+
                                                  xsys.nrx(Method:xexec)
Download the complete source for the xsys.nrx library

Some application: a simple "shell"

With the knowledge we developped in this chapter, we can now imagine to write a simple shell

 
+----------------------------------------------------------------------+
| --       package:  xshell                                            |01
| --       version:  1.000 beta                                        |02
| --          date:  23 FEB 1997                                       |03
| --        author:  P.A.Marchesini                                    |04
| --     copyright:  (c) P.A.MArchesini, 1997                          |05
| --  latest vers.:  http://wwwcn.cern.ch/news/netrexx                |06
| --                                                                   |07
| --  This program is free software; you can redistribute it and/or mod|08
| --  it under the terms of the GNU General Public License as published|09
| --  the Free  Software  Foundation;  either version 2 of the License,|10
| --  (at your option) any later version.                              |11
| --                                                                   |12
| --  This program is distributed in the hope that it will be useful,  |13
| --  but WITHOUT ANY WARRANTY; without even the  implied warranty of  |14
| --  MERCHANTABILITY or FITNESS FOR A  PARTICULAR  PURPOSE.  See the  |15
| --  GNU General Public License for more details.                     |16
| --                                                                   |17
| --  You should have received a copy of the GNU General Public License|18
| --  along with  this  program;  if not,  write  to  the Free Software|19
| --  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.        |20
| --                                                                   |21
|                                                                      |22
| -- class xshell                                                      |23
| --   This class implements a "shell" environment, something like     |24
| --   'zsh' or 'bash' (with very less functions!)                     |25
| --                                                                   |26
| class xshell                                                         |27
|                                                                      |28
|   properties public static                                           |29
|   properties private static                                          |30
|     version   = 'v0r000 beta'                                        |31
|     copyright = '(c) 1997 Pierantonio Marchesini, ETH Zurich'        |32
|     contact   = 'Pierantonio.Marchesini@cern.ch'                    |33
|                                                                      |34
| -- method......: shell                                               |35
| -- purpose.....: constructor                                         |36
| --                                                                   |37
|   method xshell() public                                             |38
|     version = version        -- make NetRexx happy                   |39
|     copyright = copyright    -- ditto                                |40
|     contact = contact        -- ditto                                |41
|                                                                      |42
| -- method......: main                                                |43
| -- purpose.....: just run typing "java shell"                        |44
| --                                                                   |45
|   method main(args=String[]) public static                           |46
|     args = args                                                      |47
|                                                                      |48
|     -- Initialization                                                |49
|     --                                                               |50
|     cmdno = 1                                                        |51
|     rc = 0                                                           |52
|     validlcmds = 'history'                                           |53
|     validecmds = 'ls pwd java' -                                     |54
|                  'ftp cp help dir'                                   |55
|     host = xsock.hostname()    -- get my host,pls                    |56
|     extracmd = ''                                                    |57
|     his = history(100)                                               |58
|                                                                      |59
|     loop forever                                                     |60
|       say host '['his.counter()':'rc'] 'extracmd'\-'                 |61
|       todo = ask                                                     |62
|       if extracmd <> ''                                              |63
|         then todo = extracmd||todo                                   |64
|                                                                      |65
|       --  check special cases                                        |66
|       --                                                             |67
|       if todo = '' then iterate                                      |68
|       if todo = 'exit' | todo = 'quit' then leave                    |69
|       if todo.left(1) = '!' then                                     |70
|         do                                                           |71
|           parse todo '!'rest                                         |72
|           select                                                     |73
|             when rest = '!' then ptr=cmdno-1                         |74
|             otherwise ptr = rest                                     |75
|           end                                                        |76
|           if ptr < 1 then ptr = 1                                    |77
|           extracmd = his.retrieve(ptr)                               |78
|           iterate                                                    |79
|         end                                                          |80
|                                                                      |81
|       extracmd = ''                                                  |82
|       cmdno = cmdno+1                                                |83
|       his.save(todo)                                                 |84
|       parse todo cmd arg                                             |85
|       arg = arg                                                      |86
|                                                                      |87
|       -- process local commands                                      |88
|       --                                                             |89
|       if validlcmds.wordpos(cmd) <> 0 then                           |90
|         do                                                           |91
|           select                                                     |92
|             when cmd = 'history' then his.dump(10)                   |93
|             otherwise say 'Sorry. "'cmd'" is not yet implemented.'   |94
|           end                                                        |95
|           iterate                                                    |96
|         end                                                          |97
|                                                                      |98
|       -- check for .class                                            |99
|       --                                                             |00
|       if xfile.fexist(cmd'.class') then                              |01
|         do                                                           |02
|           todo = 'java' todo                                         |03
|           cmd = 'java'                                               |04
|         end                                                          |05
|                                                                      |06
|       -- process external commands                                   |07
|       --                                                             |08
|       if validecmds.wordpos(cmd) = 0 then                            |09
|         do                                                           |10
|           say 'Invalid command "'cmd'".'                             |11
|           iterate                                                    |12
|         end                                                          |13
|       c = xexec(todo,'SCREEN','IGNORE')                              |14
|       rc = c.rc                                                      |15
|     end                                                              |16
|     exit 0                                                           |17
+----------------------------------------------------------------------+
                                                              xshell.nrx
Download the source for the xshell.nrx example
 
 *** This section is: 
  
 *** and will be available in next releases


File: nr_16.html.

The contents of this WEB page are Copyright © 1997 by Pierantonio Marchesini / ETH Zurich.

Last update was done on 18 May 1998 21:47:53(GMT +2).