Remote command execution from VOS

Blue Bar separator

Ever want to execute a sequence of commands on a remote system from a VOS command macro? Ever want to execute the same sequence of commands on multiple systems from a VOS system? Ever want to change your password on all the systems that you log into at the same time? Well, now you can.

The send_cmds PM will connect to a remote system (VOS, Linux, other, it doesn't matter) and execute a simple script, basically a sequence of "send a string", "wait for a string". It does not have any loops or conditional execution (version 2 maybe) but it can be run from a command macro - something that you cannot do with the telnet client. Passwords can be supplied via command line arguments, so it is not necessary to embed passwords into the scripts.

All receive characters, after a string is sent and before the wait string is received, are displayed in the terminal window (or written to a file if output is redirected). The maximum number of characters that can be received before the matching wait for string is found is 32767. If that number of characters are received without matching the wait for string, an error will be returned and the script will stop.

Display Form

---------------------------------- send_cmds ---------------------------------  
 -IPAddress:    
 -PortNumber:    23                                                
 -InputFilePath:        
 -TimeOut:       15                          
 -EchoSend:      no
 -Debug:         no
 -Verbose:       yes
 -arg0:                                        
 -arg1:         
 -arg2:         
 -arg3:         
 -arg4:                                                                        
 -arg5:         
 -arg6:                        
 -arg7:         
 -arg8:         
 -arg9:         

Arguments

IPAddress string
This is the IP address of the server. Note that names will not work, it must be an IP address.

PortNumber number
This is the port number to connect to. The default is 23 (telnet).

InputFilePath string
This is the path of the script file. An absolute or relative path can be used.

TimeOut number
The number of seconds to wait for the expected response.

EchoSend yes/no cycle option
If set to yes, the "send strings" are echoed to the output stream (see this example). If set to no, (the default) the send strings are not echoed - BUT it is possible (likely) that the remote host will echo them.

Debug yes/no cycle option
All characters with an ASCII value less than 32 or greater than 127 are by default displayed as [%x] with the following exceptions:
   0x0d 0x00   displayed as \n
   0x0d 0x0a   displayed as \n
   0x0a 0x0d   displayed as \n
   0x08   displayed as \b
   0x09   displayed as \t
If you want to actually see these characters displayed in the [%x] format set the -Debug argument to yes (see this example). The default is no.

Note that setting Debug to yes also forces Verbose to yes. You cannot set "-Debug -no_Verbose" (see the example).

Verbose yes/no cycle option
If set to yes, (the default) all characters with an ASCII value less than 32 or greater than 127, with the exceptions stated above, are displayed as [%x]. In addition, at the start of execution lines identifying the version of the send_cmds command and displaying all the arguments are displayed. If set to no, characters with an ASCII value less than 32 or greater than 127 are NOT displayed and the lines identifying the version and arguments are not displayed (see this example).

argN string
Arguments arg0 thru arg9 are used to set the SEND_STRING and WAIT_FOR_STRING strings. Any SEND_STRING or WAIT_FOR_STRING string that is argN, where N is between 0 and 9 is replaced with the corresponding argument string. This was primarily designed for password replacement so that passwords do not have to part of the script. It can also be used when the WaitForString begins or terminates in a space or other white space character that will be stripped by the read routine (see this example).

InputFilePath file format

The input file is made up of a series of lines in the form of
      <delimiter>SEND_STRING<delimiter>WAIT_FOR_STRING

Note that there is no delimiter after the WAIT_FOR_STRING. The WAIT_FOR_STRING is terminated by the end of the line. The delimiter can be any character that does not occur in the SEND_STRING, and it can change from one line to the next.

The SEND_STRING can be null in which case the format would be
      <delimiter><delimiter>WAIT_FOR_STRING
This is useful as the first line in a script when the program does not need to send anything but needs to wait for a login prompt. I have also used it when the WAIT_FOR_STRING is not unique but occurs within the text generated by the SEND_STRING (see this example).

If the SEND_STRING or WAIT_FOR_STRING is argN, where N is 0 thru 9 then the string that was supplied as the argN argument is substituted for argN. This lets you include passwords and/or user names without putting them in the input file. It also lets you add white space that is normally stripped by the input routine to the end or beginning of the WAIT_FOR_STRING (see this example). If you really want to send or wait for the string argN set that as the argument. Note when using argument substitution the ONLY thing that can be in the send string is argN. If you want to do something like:
      /arg0 XYZZY/ready
change it to:
      /arg0/ready
and in the command line type "-arg0 'arg0-value XYZZY'".

A line with the SEND_STRING and the WAIT_FOR_STRING both equal to QUIT indicates that the program should exit.

The maximum length of the SEND_STRING + WAIT_FOR_STRING + delimiters is 256 characters.

NOTES:
case is important in the WAIT_FOR_STRING

Most servers, after the connection is made, will send telnet options strings. Some servers wait for a response. The NIO will wait for several seconds. HP UX 11x systems seem to wait forever. For these systems, you may want/need to send a response (see this example). Look up RFC 1060 "telnet options" for an explanation of all the options. So far, I have gotten away with responding to a DO request (0xff 0xfd) with a WONT(as in won't) response (0xff 0xfc). Look at the example for details.

Examples

The usage message
If you execute send_cmds with no arguments you get a usage message. You will also get it if you do not include the -IPAddress or -InputFilePath arguments. All other arguments are optional.
send_cmds                                                        
Usage:
     send_cmd -IPAddress <server IP address> [-PortNumber <server port number>]
+-InputFilePath <path to script file> [-TimeOut <max wait time in seconds>] [-Ec
+hoSend] [-Debug] [-no_Verbose]

The next few examples all use the following script.

//login                                                                         
/login nd /Password?
/arg0/ready
/set_terminal_parameters -terminal_type ascii/ready
/logout/ogout
/quit/quit

Here is a breakdown of each line:

//login send nothing, wait for the string "login"
/login nd /Password? send "login nd", wait for "Password?"
/arg0/ready replace the string arg0 with the value of arg0 argument, send it and wait for "ready"
/set_terminal_parameters -terminal_type ascii/readysend the set_terminal_parameters command and wait for ready
/logout/ogout send logout wait for "ogout"
/quit/quit special combination of strings to indicate that send_cmds should quit

Login into a module and execute a command
This output shows the basic features of send_cmds.

The first line is the command typed into the local system.

The next three lines are the send_cmds program identifying itself and repeating the input arguments. NOTE that arg0 is my password and for these examples my password is really XXXXXXXX. If you are going to send this output to someone or include it in a document you probably want to use the no_Verbose argument. Your password will still be on the command line but send_cmds will not echo the arguments (see the next example).

The next line with characters corresponds to the telnet options sent by the server. Typically, you can just ignore these characters, but see example .

We now come to the login banner. The first script line is now triggered since it was waiting for "login". It sends the command "login nd" and waits for the "Password?" prompt. When it gets the prompt, it sends the password which it obtained from arg0. Note that the server echoes the "login nd" command but not the password. Once logged in, the initial string from the default TTP is sent. This string contains a lot of terminal control sequences which typically begin with the ESC character (0x1B). When the script sees the "ready" it sends the command, which in this case changes the TTP to ascii. For some reason the system echoes it twice. This will eliminate all the terminal control sequences from the rest of the output and I recommend that you always do this. The script then logs out and finally exits.

send_cmds -IPAddress 127.0.0.1 -InputFilePath test -arg0 XXXXXXXX         
send_cmds version 1.1 08-04-27 Noah.Davids@stratus.com
send_cmds -IPAddress 127.0.0.1 -PortNumber 23 -InputFilePath test -TimeOut 15 -n
+o_EchoSend -no_Debug -Verbose  -arg0 XXXXXXXX

[0xff][0xfb][0x 1][0xff][0xfb][0x 3][0xff][0xfd][0x 3]
        P H O E N I X   C A C   V O S   T E S T   S Y S T E M
VOS Release 15.3.0av, Module %phx_vos#m15
Please login  16:10:18
login nd
Password?
Noah_Davids.CAC logged in on %phx_vos#m15 at 08-04-24 16:10:18 mst.
[0x1b][f[0x1b][J[0x1b][?7l[0x1b][20l[0x1b]=[0x1b][1m[0x1b][1;24r[0x1b][f[0x1b][J
+[0x1b][J[0x1b][24;80f[0x1b][77D[0x1b][0;1m[0x f]Noah_Davids.CAC (#m15)
* Noah_Davids.CAC (#m15)
[0x1b][2CNoah_Davids.SysAdmin (#m14/stcp_telnet_msd)
ready  16:10:18
[0x1b][0mset_terminal_parameters -terminal_type ascii
[0x1b][1mset_terminal_parameters -terminal_type ascii

ready  16:10:18
logoutready  16:10:18

Login into a module and execute a command with -no_Verbose
This is running the same script, but this time, the command_line includes the no_Verbose argument. Note that the ID and argument lines are missing. Also missing are all the [0xXX] characters. You are left with the printable character part of the terminal control sequences, but at least they take up less space.

send_cmds -IPAddress 127.0.0.1 -InputFilePath test -arg0 XXXXXXXX -no_Verbose   

        P H O E N I X   C A C   V O S   T E S T   S Y S T E M
VOS Release 15.3.0av, Module %phx_vos#m15
Please login  16:13:27
login nd
Password?
Noah_Davids.CAC logged in on %phx_vos#m15 at 08-04-24 16:13:27 mst.
[f[J[?7l[20l=[1m[1;24r[f[J[J[24;80f[77D[0;1mNoah_Davids.CAC (#m15)
* Noah_Davids.CAC (#m15)
[2CNoah_Davids.SysAdmin (#m14/stcp_telnet_msd)
ready  16:13:27
[0mset_terminal_parameters -terminal_type ascii
[1mset_terminal_parameters -terminal_type ascii

ready  16:13:27
logoutready  16:13:27

Login into a module and execute a command with -EchoSend
Notice the "---> " lines. These indicate what send_cmds is actually sending to the remote host. Note that the password is echoed.

send_cmds -IPAddress 127.0.0.1 -InputFilePath test -arg0 XXXXXXXX -EchoSend
send_cmds version 1.1 08-04-27 Noah.Davids@stratus.com
send_cmds -IPAddress 127.0.0.1 -PortNumber 23 -InputFilePath test -TimeOut 15 -E
+choSend -no_Debug -Verbose  -arg0 XXXXXXXX

[0xff][0xfb][0x 1][0xff][0xfb][0x 3][0xff][0xfd][0x 3]
        P H O E N I X   C A C   V O S   T E S T   S Y S T E M
VOS Release 15.3.0av, Module %phx_vos#m15
Please login  16:23:02
---> login nd
login nd
Password?---> XXXXXXXX

Noah_Davids.CAC logged in on %phx_vos#m15 at 08-04-24 16:23:02 mst.
[0x1b][f[0x1b][J[0x1b][?7l[0x1b][20l[0x1b]=[0x1b][1m[0x1b][1;24r[0x1b][f[0x1b][J
+[0x1b][J[0x1b][24;80f[0x1b][77D[0x1b][0;1m[0x f]Noah_Davids.CAC (#m15)
* Noah_Davids.CAC (#m15)
[0x1b][2CNoah_Davids.SysAdmin (#m14/stcp_telnet_msd)
ready  16:23:03
---> set_terminal_parameters -terminal_type ascii
[0x1b][0mset_terminal_parameters -terminal_type ascii
[0x1b][1mset_terminal_parameters -terminal_type ascii

ready  16:23:03
---> logout
logoutready  16:23:03

Login into a module and execute a command with -Debug -no_Verbose
Debug shows the control characters that are normally translated into printing format control characters, i.e. new lines, back spaces and tabs.

Note that even though -no_Verbose is set in the command, it is echoed as Verbose. Remember that Debug=yes forces Verbose to yes.

send_cmds -IPAddress 127.0.0.1 -InputFilePath test -arg0 XXXXXXXX -Debug -no_Ver
+bose
send_cmds version 1.1 08-04-27 Noah.Davids@stratus.com
send_cmds -IPAddress 127.0.0.1 -PortNumber 23 -InputFilePath test -TimeOut 15 -n
+o_EchoSend -Debug -Verbose  -arg0 XXXXXXXX

[0xff][0xfb][0x 1][0xff][0xfb][0x 3][0xff][0xfd][0x 3][0x d][0x a]
        P H O E N I X   C A C   V O S   T E S T   S Y S T E M[0x d][0x a]
VOS Release 15.3.0av, Module %phx_vos#m15[0x d][0x a]
Please login  16:26:08[0x d][0x a]
login nd[0x d][0x a]
Password?[0x d][0x a]
Noah_Davids.CAC logged in on %phx_vos#m15 at 08-04-24 16:26:08 mst.[0x d][0x a]
[0x1b][f[0x1b][J[0x1b][?7l[0x1b][20l[0x1b]=[0x1b][1m[0x1b][1;24r[0x1b][f[0x1b][J
+[0x1b][J[0x1b][24;80f[0x1b][77D[0x1b][0;1m[0x f]Noah_Davids.CAC (#m15)[0x d][0x
+ a]
* Noah_Davids.CAC (#m15)[0x d][0x a]
[0x1b][2CNoah_Davids.SysAdmin (#m14/stcp_telnet_msd)[0x d][0x a]
ready  16:26:08[0x d][0x a]
[0x1b][0mset_terminal_parameters -terminal_type ascii[0x d][0x 0]
[0x1b][1mset_terminal_parameters -terminal_type ascii[0x d][0x a]
[0x d][0x 0]
ready  16:26:08[0x d][0x a]
logoutready  16:26:08

Login into a module and execute a command with -EchoSend and -Debug
This will give you the most visibility to what is being sent and received.

send_cmds -IPAddress 127.0.0.1 -InputFilePath test -arg0 XXXXXXXX -EchoSend -Deb
+ug
send_cmds version 1.1 08-04-27 Noah.Davids@stratus.com
send_cmds -IPAddress 127.0.0.1 -PortNumber 23 -InputFilePath test -TimeOut 15 -E
+choSend -Debug -Verbose  -arg0 XXXXXXXX

[0xff][0xfb][0x 1][0xff][0xfb][0x 3][0xff][0xfd][0x 3][0x d][0x a]
        P H O E N I X   C A C   V O S   T E S T   S Y S T E M[0x d][0x a]
VOS Release 15.3.0av, Module %phx_vos#m15[0x d][0x a]
Please login  16:29:29[0x d][0x a]
---> login nd
login nd[0x d][0x a]
Password?---> XXXXXXXX
[0x d][0x a]
Noah_Davids.CAC logged in on %phx_vos#m15 at 08-04-24 16:29:29 mst.[0x d][0x a]
[0x1b][f[0x1b][J[0x1b][?7l[0x1b][20l[0x1b]=[0x1b][1m[0x1b][1;24r[0x1b][f[0x1b][J
+[0x1b][J[0x1b][24;80f[0x1b][77D[0x1b][0;1m[0x f]Noah_Davids.CAC (#m15)[0x d][0x
+ a]
x Noah_Davids.CAC (#m15)[0x d][0x a]
x Noah_Davids.CAC (#m15)[0x d][0x a]
* Noah_Davids.CAC (#m15)[0x d][0x a]
[0x1b][2CNoah_Davids.SysAdmin (#m14/stcp_telnet_msd)[0x d][0x a]
ready  16:29:29[0x d][0x a]
---> set_terminal_parameters -terminal_type ascii
[0x1b][0mset_terminal_parameters -terminal_type ascii[0x d][0x 0]
[0x1b][1mset_terminal_parameters -terminal_type ascii[0x d][0x a]
[0x d][0x 0]
ready  16:29:29[0x d][0x a]
---> logout
logoutready  16:29:29

Now that I have shown examples of the effects of all the arguments let's look at some scripts that actually do something.

Logging onto an HP-UX system
This initial script does not include any telnet options. HP-UX waits forever (or at least more than 15 seconds) and the send_cmds command eventually times out.

//login                                                                         
/root /Password?
/arg0/#
/netstat -ni/#
/exit/exit
/quit/quit




send_cmds -IPAddress 10.10.1.101 -InputFilePath test1
send_cmds version 1.1 08-04-27 Noah.Davids@stratus.com
send_cmds -IPAddress 164.152.76.101 -PortNumber 23 -InputFilePath test1 -TimeOut
+ 15 -no_EchoSend -no_Debug -Verbose

[0xff][0xfd]$

Timeout waiting for [login] after sending []
ready  11:33:12

By adding into the script an initial line that sends control characters, which basically says we will not do the requested options, we can proceed to the login and the rest of the script. It required several iterations to get past the point where HP-UX was expecting a response. It would send an option and wait, send the next option and wait. Note the third option string ends in a space.

//`FF`FD$
/`FF`FC$/`FF`FD`18
/`FF`FC`18/`FF`FD 
/`FF`FC /login
/root /Password:
/arg0/#
/netstat -ni/#
/exit/exit
/quit/quit



send_cmds -IPAddress 10.10.1.101 -InputFilePath test1 -arg0 tw33k
send_cmds version 1.1 08-04-27 Noah.Davids@stratus.com
send_cmds -IPAddress 164.152.76.101 -PortNumber 23 -InputFilePath test1 -TimeOut
+ 15 -no_EchoSend -no_Debug -Verbose  -arg0 tw33k

[0xff][0xfd]$[0xff][0xfd][0x18][0xff][0xfe][0x18][0xff][0xfd] [0xff][0xfe] [0xff
+][0xfb][0x 1][0xff][0xfb][0x 3][0xff][0xfd][0x1f][0xff][0xfd]![0xff][0xfd][0x 1
+][HP Release B.11.00] [Stratus Release 11.00.03]
Patch Level: Complete CD 60

Patch SPCO_0121 has been installed and is running.
  (This patch tests the SCSI bus for errors)
  (See 'man scsiBusMonitor' for more info)

System: tweek


login: login: login: root
Password:
Please wait...checking for disk quotas
[0xff][0xfa]![0x 0][0xff][0xf0].[0x1b] i
     [0x d].[0x1b][ci
     [0x d].[0x1b]*s1^[0x11]i
     [0x d][0xff][0xfa]![0x 1][0xff][0xf0][0x 0](c)Copyright 1983-1997 Hewlett-P
+ackard Co.,  All Rights Reserved.
(c)Copyright 1979, 1980, 1983, 1985-1993 The Regents of the Univ. of California
(c)Copyright 1980, 1984, 1986 Novell, Inc.
(c)Copyright 1986-1992 Sun Microsystems, Inc.
(c)Copyright 1985, 1986, 1988 Massachusetts Institute of Technology
(c)Copyright 1989-1993  The Open Software Foundation, Inc.
(c)Copyright 1986 Digital Equipment Corp.
(c)Copyright 1990 Motorola, Inc.
(c)Copyright 1990, 1991, 1992 Cornell University
(c)Copyright 1989-1991 The University of Maryland
(c)Copyright 1988 Carnegie Mellon University
(c)Copyright 1991-1997 Mentat, Inc.
(c)Copyright 1996 Morning Star Technologies, Inc.
(c)Copyright 1996 Progressive Systems, Inc.
(c)Copyright 1997 Isogon Corporation


                           RESTRICTED RIGHTS LEGEND
Use, duplication, or disclosure by the U.S. Government is subject to
restrictions as set forth in sub-paragraph (c)(1)(ii) of the Rights in
Technical Data and Computer Software clause in DFARS 252.227-7013.


                           Hewlett-Packard Company
                           3000 Hanover Street
                           Palo Alto, CA 94304 U.S.A.

Rights for non-DOD U.S. Government Departments and Agencies are as set
forth in FAR 52.227-19(c)(1,2).
You have mail.


        [0x1b]2       [0x1b]2       [0x1b]2       [0x1b]2       [0x1b]2       [0
+x1b]2       [0x1b]2       [0x1b]2       [0x1b]2       [0x1b]2       [0x1b]2
+   [0x1b]2       [0x1b]2       [0x1b]2       [0x1b]2       [0x1b]2       [0x1b]
+2       [0x1b]2       [0x1b]2       [0x1b]2


Value of TERM has been set to "unknown".
WARNING:  YOU ARE SUPERUSER !!

# netstat -ni
Name           Mtu Network            Address                 Ipkts      Opkts
lan0          1500 164.152.76.0       164.152.76.101       52850722   77856514
lo0           4136 127.0.0.0          127.0.0.1                  13         13
# ready  15:32:58

Logging onto an ftLinux system
By default ftLinux does not start a telnet server, it starts an SSH server. The send_cmds command cannot be used to talk directly with an SSH server. However, you can still use send_cmds to send commands to an ftLinux system, all you need to do is run send_cmds on a VOS system that has openssl installed or send the commands to a system with both telnet and SSH running.

In the following example openssl is running on the VOS system, so I can send_cmds to the system using the loopback address 127.0.0.1 and then execute the ssh command to login to the ftLinux system and run commands. Note that the script uses arg0 for the VOS password and arg1 for the ftLinux password. If I had set up public key authentication between the VOS and ftLinux systems I would not need the second password (example).

I also use no_Verbose so that the passwords are not echoed in the output and to cut down on the control character output.

//login
/login nd/Password?
/arg0/ready
/set_terminal_parameters -terminal_type ascii/ready
/>system>openssl>bin>ssh ndav@164.152.77.155/password:
/arg1/$
/netstat -ni/$
/quit/quit/


send_cmds -IPAddress 127.0.0.1 -InputFilePath ftlinux -arg0 XXXXXXXX -arg1 ABCDE
+FGH -no_Verbose

        P H O E N I X   C A C   V O S   T E S T   S Y S T E M
VOS Release 15.3.0av, Module %phx_vos#m15
Please login  09:47:18
login nd
Password?
Noah_Davids.CAC logged in on %phx_vos#m15 at 08-04-27 09:47:18 mst.
[f[J[?7l[20l=[1m[1;24r[f[J[J[24;80f[77D[0;1mNoah_Davids.CAC (#m15)
* Noah_Davids.CAC (#m15)
[2CNoah_Davids.SysAdmin (#m14/stcp_telnet_msd)
ready  09:47:18
[0mset_terminal_parameters -terminal_type ascii
[1mset_terminal_parameters -terminal_type ascii

ready  09:47:18
>system>openssl>bin>ssh ndav@164.152.77.155
ndav@164.152.77.155's password:
Last login: Sat Apr 26 19:42:12 2008 from phxtest-m15.az.stratus.com

[ndav@164dhcp-1728-37 ~]$ netstat -ni
Kernel Interface table
Iface       MTU Met    RX-OK RX-ERR RX-DRP RX-OVR    TX-OK TX-ERR TX-DRP TX-OVR
+Flg
bond0      1500   0  2306004      0      0      0    46875      0      0      0
+BMmRU
eth000010  1500   0  1174934      0      0      0    46870      0      0      0
+BMsRU
eth080010  1500   0  1131070      0      0      0        5      0      0      0
+BMsRU
lo        16436   0   670867      0      0      0   670867      0      0      0
+LRU
[ndav@164dhcp-1728-37 ~]$ ready  09:47:21

Getting the status of an ftStorage array
This example shows two things.

First, notice that the command sets arg0 to (byte 33)manage. The default password for an ftStorage array is !manage BUT the VOS command processor has other uses for the ! character. To get around this I use the byte command function to place a ! character into the command line bypassing VOS's use of it. Notice that the echoed command line does indicate that arg0 is !manage.

Second, the ftstorage array's prompt character is a # character and this is the wait-for-string used in the script. BUT the output from the "show enclosure-status" command includes a # character in the second header line. The script therefore needs to include a "//#" after the "show enclosure-status" command to wait for the actual end of the output and the actual command prompt.

//Login:                                                                        
/manage/Password:
/arg0/#
/set output-format pager disable/#
/show enclosure-status/#
//#
/quit/quit/



send_cmds -IPAddress 10.10.1.40 -InputFilePath ftstorage -arg0 (byte 33)manage  
send_cmds version 1.1 08-04-27 Noah.Davids@stratus.com
send_cmds -IPAddress 10.10.1.40 -PortNumber 23 -InputFilePath ftstorage -TimeOut
+ 15 -no_EchoSend -no_Debug -Verbose  -arg0 !manage

[0xff][0xfc][0x 1][0xff][0xfb][0x 1][0xff][0xfb][0x 3][0xff][0xfd][0x18][0xff][0
+xfb][0x18][0xff][0xfd][0x1f][0xff][0xfb][0x1f][0xff][0xfb]"[0xff][0xfb][0x 5]Lo
+gin: manage
Password: *******

Stratus AA-D91600
System Name: phx_vos (m16)
System Location: Phoenix, Arizona
Version: W411R06

# set output-format pager disable
Success: CLI parameter changed successfully
# show enclosure-status
Chassis                          Vendor   Product ID       Rev  CPLD
  WWPN             Status
---------------------------------------------------------------------
DHSIMIL-06510A5E9B               Stratus  AA-D91600        2032 25
  500C0FF00A5E9B3C OK
---------------------------------------------------------------------

Type     #  Status   FRU P/N      FRU S/N              Add'l Data
------------------------------------------------------------------------------
FAN      00 OK       AA-P72500    DHSITOR-0651MG1729   --
FAN      01 OK       AA-P72500    DHSITOR-0651MG1701   --
PSU      00 OK       AA-P72500    DHSITOR-0651MG1729   --
PSU      01 OK       AA-P72500    DHSITOR-0651MG1701   --
Temp     00 OK       AA-D91810    DHSIMIL-06500A6044   temp=25
Temp     01 OK       AA-D91810    DHSIMIL-06500A6036   temp=23
Temp     02 OK       AA-P72500    DHSITOR-0651MG1729   temp=19
Temp     03 OK       AA-P72500    DHSITOR-0651MG1701   temp=23
Voltage  00 OK       AA-P72500    DHSITOR-0651MG1729   voltage=12.420V
Voltage  01 OK       AA-P72500    DHSITOR-0651MG1729   voltage=5.520V
Voltage  02 OK       AA-P72500    DHSITOR-0651MG1729   voltage=3.440V
Voltage  03 OK       AA-P72500    DHSITOR-0651MG1701   voltage=12.450V
Voltage  04 OK       AA-P72500    DHSITOR-0651MG1701   voltage=5.520V
Voltage  05 OK       AA-P72500    DHSITOR-0651MG1701   voltage=3.350V
DiskSlot 00 OK       AA-D91600    DHSIMIL-06510A5E9B   addr=0
DiskSlot 01 OK       AA-D91600    DHSIMIL-06510A5E9B   addr=1
DiskSlot 02 OK       AA-D91600    DHSIMIL-06510A5E9B   addr=2
DiskSlot 03 OK       AA-D91600    DHSIMIL-06510A5E9B   addr=3
DiskSlot 04 OK       AA-D91600    DHSIMIL-06510A5E9B   addr=4
DiskSlot 05 OK       AA-D91600    DHSIMIL-06510A5E9B   addr=5
DiskSlot 06 Absent   AA-D91600    DHSIMIL-06510A5E9B   addr=6
DiskSlot 07 Absent   AA-D91600    DHSIMIL-06510A5E9B   addr=7
DiskSlot 08 Absent   AA-D91600    DHSIMIL-06510A5E9B   addr=8
DiskSlot 09 Absent   AA-D91600    DHSIMIL-06510A5E9B   addr=9
DiskSlot 10 Absent   AA-D91600    DHSIMIL-06510A5E9B   addr=10
DiskSlot 11 Absent   AA-D91600    DHSIMIL-06510A5E9B   addr=11
------------------------------------------------------------------------------
# ready  10:50:29

Logging onto Cisco switch
This example is getting the status of the ports in a Cisco switch. IOS has its own paging mechanism when it thinks it is at the bottom of a terminal screen. The prompt is --More-- and the response to get another page is a space. When writing the script you have to know how many "--More--" prompts you will get to include the correct number of spaces. Notice that in the actual output you do not see the"--More--" prompt, IOS clears the line after the space is received. You can use the -Debug argument to see how it does this.

//Password:
/arg0/>
/sh int status/--More--
/ />
/quit/quit

ready  11:40:26
send_cmds -IPAddress 172.16.1.222 -InputFilePath cisco -arg0 secret
send_cmds version 1.1 08-04-27 Noah.Davids@stratus.com
send_cmds -IPAddress 172.16.1.222 -PortNumber 23 -InputFilePath cisco -TimeOut 1
+5 -no_EchoSend -no_Debug -Verbose  -arg0 secret

[0xff][0xfb][0x 1][0xff][0xfb][0x 3][0xff][0xfd][0x18][0xff][0xfd][0x1f]

User Access Verification

Password:
CiscoSW>sh int status
Port      Name               Status       Vlan       Duplex  Speed Type
Fa0/1                        connected    1          a-half   a-10 10/100BaseTX
Fa0/2                        notconnect   1            auto   auto 10/100BaseTX
Fa0/3                        notconnect   1            auto   auto 10/100BaseTX
Fa0/4                        connected    1          a-full  a-100 10/100BaseTX
Fa0/5                        notconnect   1            auto   auto 10/100BaseTX
Fa0/6                        connected    1          a-full  a-100 10/100BaseTX
Fa0/7                        notconnect   1            auto   auto 10/100BaseTX
Fa0/8                        notconnect   1            auto   auto 10/100BaseTX
Fa0/9                        connected    1          a-full  a-100 10/100BaseTX
Fa0/10                       connected    1          a-half   a-10 10/100BaseTX
Fa0/11                       connected    1          a-full  a-100 10/100BaseTX
Fa0/12                       notconnect   1            auto   auto 10/100BaseTX
Fa0/13                       notconnect   1            auto   auto 10/100BaseTX
Fa0/14                       notconnect   1            half     10 10/100BaseTX
Fa0/15                       monitoring   1          a-half  a-100 10/100BaseTX
Fa0/16                       connected    1            full    100 10/100BaseTX
Fa0/17                       notconnect   1            auto   auto 10/100BaseTX
Fa0/18                       notconnect   1            auto   auto 10/100BaseTX
Fa0/19                       connected    trunk      a-full  a-100 10/100BaseTX
Fa0/20                       notconnect   1            auto   auto 10/100BaseTX
Fa0/21                       notconnect   1            auto   auto 10/100BaseTX

Port      Name               Status       Vlan       Duplex  Speed Type
Fa0/22                       connected    1          a-half   a-10 10/100BaseTX
Fa0/23                       notconnect   1            auto   auto 10/100BaseTX
Fa0/24                       notconnect   1            auto   auto 10/100BaseTX
Po1                          notconnect   0            auto   auto
Po6                          notconnect   0            auto   auto
Po5                          notconnect   0            auto   auto
CiscoSW>ready  11:40:37

Changing passwords
The following scripts can be used to change a VOS password and an ftLinux password. There is also an example command macro that shows calling both scripts. This gives you an idea how to change all your passwords at the same time.

d change_vos_password

%phx_vos#m15_mas>SysAdmin>Noah_Davids>send_cmds>change_vos_password  08-04-27 17

//login
/login nd -change_password/Password?
/arg0/?
/arg1/?
/arg1/ready
/logout/ogout
/quit/quit

ready  17:37:54



d change_ftlinux_password

%phx_vos#m15_mas>SysAdmin>Noah_Davids>send_cmds>change_ftlinux_password  08-04-2

//login
/login nd/Password?
/arg0/ready
/set_terminal_parameters -terminal_type ascii/ready
/>system>openssl>bin>ssh ndav@164.152.77.155/password:
/arg1/$
/passwd/password:
/arg1/password:
/arg2/password:
/arg2/$
/quit/quit/

ready  17:38:04


d change_my_passwords.cm

%phx_vos#m15_mas>SysAdmin>Noah_Davids>send_cmds>change_my_passwords.cm  08-04-27

send_cmds -IPAddress 127.0.0.1 -PortNumber 23 -InputFilePath change_vos_password
+ -arg0 ABCDEFGH1 -arg1 XXXXXXXX -no_Verbose
send_cmds -IPAddress 164.152.77.6 -PortNumber 23 -InputFilePath change_vos_passw
+ord -arg0 ABCDEFGH -arg1 XXXXXXXX -no_Verbose
send_cmds -IPAddress 127.0.0.1 -InputFilePath change_ftlinux_password -arg0 XXXX
+XXXX -arg1 ABCDEFGH -arg2 XXXXXXXX -no_Verbose

ready  17:38:47

Using argument substitution in the WAIT_FOR_STRING
In this example, I set the WAIT_FOR_STRING to line feed followed by the # character. I cannot do this in the script so I set the WAIT_FOR_STRING to arg1 and set arg1 in the command line to the string (byte 10)#.

Notice that when the command line is echoed arg1 is followed by the new line and the # character.


d ftstorage2                                                                    

%phx_vos#m15_mas>SysAdmin>Noah_Davids>send_cmds>ftstorage2  08-05-08 16:00:55 ms

//Login:
/manage/Password:
/arg0/arg1
/set output-format pager disable/arg1
/show enclosure-status/arg1
/quit/quit/

send_cmds -IPAddress 10.10.1.40 -InputFilePath ftstorage2 -arg0 (byte 33)manage
+-arg1 (byte 10)#                                                              
send_cmds version 1.2 08-05-08 Noah.Davids@stratus.com
send_cmds -IPAddress 10.10.1.40 -PortNumber 23 -InputFilePath ftstorage2 -TimeOu
+t 15 -no_EchoSend -no_Debug -Verbose  -arg0 !manage -arg1
#

[0xff][0xfc][0x 1][0xff][0xfb][0x 1][0xff][0xfb][0x 3][0xff][0xfd][0x18][0xff][0
+xfb][0x18][0xff][0xfd][0x1f][0xff][0xfb][0x1f][0xff][0xfb]"[0xff][0xfb][0x 5]Lo
+gin: manage
Password: *******

Stratus AA-D91600
System Name: phx_vos (m16)
System Location: Phoenix, Arizona
Version: W411R06

# set output-format pager disable
Success: CLI parameter changed successfully
# show enclosure-status
Chassis                          Vendor   Product ID       Rev  CPLD
  WWPN             Status
---------------------------------------------------------------------
DHSIMIL-06510A5E9B               Stratus  AA-D91600        2032 25
  500C0FF00A5E9B3C OK
---------------------------------------------------------------------

Type     #  Status   FRU P/N      FRU S/N              Add'l Data
------------------------------------------------------------------------------
FAN      00 OK       AA-P72500    DHSITOR-0651MG1729   --
FAN      01 OK       AA-P72500    DHSITOR-0651MG1701   --
PSU      00 OK       AA-P72500    DHSITOR-0651MG1729   --
PSU      01 OK       AA-P72500    DHSITOR-0651MG1701   --
Temp     00 OK       AA-D91810    DHSIMIL-06500A6044   temp=25
Temp     01 OK       AA-D91810    DHSIMIL-06500A6036   temp=24
Temp     02 OK       AA-P72500    DHSITOR-0651MG1729   temp=20
Temp     03 OK       AA-P72500    DHSITOR-0651MG1701   temp=23
Voltage  00 OK       AA-P72500    DHSITOR-0651MG1729   voltage=12.430V
Voltage  01 OK       AA-P72500    DHSITOR-0651MG1729   voltage=5.510V
Voltage  02 OK       AA-P72500    DHSITOR-0651MG1729   voltage=3.440V
Voltage  03 OK       AA-P72500    DHSITOR-0651MG1701   voltage=12.420V
Voltage  04 OK       AA-P72500    DHSITOR-0651MG1701   voltage=5.520V
Voltage  05 OK       AA-P72500    DHSITOR-0651MG1701   voltage=3.350V
DiskSlot 00 OK       AA-D91600    DHSIMIL-06510A5E9B   addr=0
DiskSlot 01 OK       AA-D91600    DHSIMIL-06510A5E9B   addr=1
DiskSlot 02 OK       AA-D91600    DHSIMIL-06510A5E9B   addr=2
DiskSlot 03 OK       AA-D91600    DHSIMIL-06510A5E9B   addr=3
DiskSlot 04 OK       AA-D91600    DHSIMIL-06510A5E9B   addr=4
DiskSlot 05 OK       AA-D91600    DHSIMIL-06510A5E9B   addr=5
DiskSlot 06 Absent   AA-D91600    DHSIMIL-06510A5E9B   addr=6
DiskSlot 07 Absent   AA-D91600    DHSIMIL-06510A5E9B   addr=7
DiskSlot 08 Absent   AA-D91600    DHSIMIL-06510A5E9B   addr=8
DiskSlot 09 Absent   AA-D91600    DHSIMIL-06510A5E9B   addr=9
DiskSlot 10 Absent   AA-D91600    DHSIMIL-06510A5E9B   addr=10
DiskSlot 11 Absent   AA-D91600    DHSIMIL-06510A5E9B   addr=11
------------------------------------------------------------------------------
# ready  16:07:44

Secure execution environment for operations staff
By putting the command line in a command macro that only has execute access, making the script file read only, putting passwords in arguments on the command line in the macro and not in the script file, and using the no_Verbose option on the command line you can give people the ability to login and execute commands using user IDs and passwords that they would not normally be able to use. Breaking out of the macro automatically closes the connection so they cannot use the connection for other commands.

If the connection is to another host, it is still possible for someone to connect a protocol analyzer to the network (or use packet_monitor if they are privileged on the local system) and display the password. However, if you telnet to localhost and use SSH to make the connection, a protocol analyzer will not display the password. Since packet_monitor can not trace connections to localhost (stcp-145) the passwords are secure.

In the following example the person executing the script is given the ability to login to a remote system using a privileged user ID and stop a process. The process name is supplied as a argument to the macro.

I first display the macro so you can see how it is constructed, just 1 line executing the send_cmds commands. Note that I use the string command function to construct the stop_process command along with the process_name from the macro's argument. I then remove all access and set execute access for *.*, display_access confirms that the only access to the macro is execute for *.*. Attempting to display it now fails.

Executing the macro prompts for a process name because I did not supply it. It then runs the script and stops the process.

Notice in the script that I do not provide a password for the remote system. This is because the user ID used to log into the local system has set up public key authentication between the local and remote systems so no password is requested.

d secure.cm

%phx_vos#m15_mas>SysAdmin>Noah_Davids>send_cmds>secure.cm  08-04-27 15:11:31 mst

&begin_parameters
PROCESS_NAME process_name:string,req
&end_parameters
&
send_cmds -IPAddress 127.0.0.1 -InputFilePath secure -arg0 XXXXXXXX -arg1 (strin
+g stop_process &PROCESS_NAME& -no_ask) -no_Verbose

ready  15:11:31



remove_access secure.cm -all
ready  15:11:47
give_access execute secure.cm -user *.*
ready  15:12:00
display_access secure.cm -all

%phx_vos#m15_mas>SysAdmin>Noah_Davids>send_cmds>secure.cm

 e  *.*
ready  15:12:15
d secure.cm
display: Read permission to file is required.
     %phx_vos#m15_mas>SysAdmin>Noah_Davids>send_cmds>secure.cm
ready  15:12:19



secure
process_name: foo

        P H O E N I X   C A C   V O S   T E S T   S Y S T E M
VOS Release 15.3.0av, Module %phx_vos#m15
Please login  15:12:34
login nd
Password?
Noah_Davids.CAC logged in on %phx_vos#m15 at 08-04-27 15:12:35 mst.
[f[J[?7l[20l=[1m[1;24r[f[J[J[24;80f[77D[0;1mNoah_Davids.CAC (#m15)
* Noah_Davids.CAC (#m15)
[2CNoah_Davids.CAC (#m16)
[2CNoah_Davids.CAC (#m16/foo)
[2CNoah_Davids.SysAdmin (#m14/stcp_telnet_msd)
ready  15:12:35
[0mset_terminal_parameters -terminal_type ascii
[1mset_terminal_parameters -terminal_type ascii

ready  15:12:35
>system>openssl>bin>ssh nd@172.16.1.116

Noah_Davids.CAC logged in on %phx_vos#m16 at 08-04-27 15:12:36 mst.
[f[J[?7l[20l=[1m[1;24r[f[J[J[24;80f[77D[0;1mNoah_Davids.CAC (#m15)
[2CNoah_Davids.CAC (#m15)
[2CNoah_Davids.CAC (#m16)
* Noah_Davids.CAC (#m16)
[2CNoah_Davids.CAC (#m16/foo)
[2CNoah_Davids.SysAdmin (#m14/stcp_telnet_msd)
ready  15:12:36
[0mstop_process foo -no_ask
[1mstop_process foo -no_ask
[CStopping Noah_Davids.CAC (foo).
ready  15:12:36
ready  15:12:36



d secure

%phx_vos#m15_mas>SysAdmin>Noah_Davids>send_cmds>secure  08-04-27 15:12:49 mst

//login
/login nd/Password?
/arg0/ready
/set_terminal_parameters -terminal_type ascii/ready
/>system>openssl>bin>ssh nd@172.16.1.116/ready
/arg1/ready
/quit/quit

ready  15:12:49

send_cmds.c

I wrote this on a VOS 15.3 system and tested it on that system and a VOS 16.2 system. I see no reason why it would not work on any VOS system. The include files assume that it will be compiled and run under the STCP environment. However, with suitable changes it could work in a TCP_OS environment.

Except for the use of s$parse_command to process the arguments the code is generic C and TCP/IP, I expect that with minimal effort it could be made to run under other operating systems.

/* *****************************************************************

   send_cmds written by NSDavids Stratus CAC
   08-04-27 version 1.1 initial release
   08-05-08 version 1.2 Added argument substitution for the
                        WaitForString (suggested and coded by
                        Paul Farley)
   10-11-26 version 1.3 added disclaimer
   See http://noahdavids.org/self_published/send_cmds.html
   for lastest version and documentation

This software is provided on an "AS IS" basis, WITHOUT ANY WARRANTY OR ANY
SUPPORT OF ANY KIND. The AUTHOR SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES
OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE.  This disclaimer
applies, despite any verbal representations of any kind provided by the
author or anyone else.

***************************************************************** */

#define _POSIX_SOURCE

#include <sys/select.h>
#include <prototypes/inet_proto.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <c_utilities.h>

#define bzero(s, len)             memset((char *)(s), 0, len)

int errno;
void s$parse_command ();

main ()
{

int                 error_code;
char_varying (16)   vIPAddress;
char                IPAddress [16];
unsigned int        PortNumber;
char_varying (256)  vInputFilePath;
char                InputFilePath [256];
char_varying (80)   varg0;
char_varying (80)   varg1;
char_varying (80)   varg2;
char_varying (80)   varg3;
char_varying (80)   varg4;
char_varying (80)   varg5;
char_varying (80)   varg6;
char_varying (80)   varg7;
char_varying (80)   varg8;
char_varying (80)   varg9;
short int           EchoSend;
short int           Debug;
short int           Verbose;
unsigned int        TimeOut;
char                arguments [10][80];
FILE *              InputFileFD;
int                 sd;
struct sockaddr     bind_saddr;
struct sockaddr_in *sin;
#define MAXSCRIPTLINE 256
char                InputLine [MAXSCRIPTLINE];
char                delimChar;
char               *delim2Ptr;
char                SendString [MAXSCRIPTLINE];
char                WaitForString [MAXSCRIPTLINE];
unsigned int        argIndex;
unsigned int        i, j, do_nothing;
unsigned int        SentChars;
unsigned int        RecvChars;
#define MAXRECVSTRING 32767
char                RecvString [MAXRECVSTRING];
fd_set              fdsetR;
struct timeval      timeout;
int                 nfds;
int                 sdSelected;

/* set arguments for parse_command */
vIPAddress = "";
PortNumber = 23;
vInputFilePath = "";
EchoSend = 0;
Debug = 0;
Verbose = 1;
TimeOut = 15;
s$parse_command(&(char_varying(32))"send_cmds", &error_code,
        &(char_varying)"option(-IPAddress), string, value", &vIPAddress,
        &(char_varying)"option(-PortNumber), number,longword, value",
            &PortNumber,
        &(char_varying)"option(-InputFilePath), string, value",
            &vInputFilePath,
        &(char_varying)"option(-TimeOut), number,longword, value", &TimeOut,
        &(char_varying)"switch(-EchoSend),=0", &EchoSend,
        &(char_varying)"switch(-Debug),=0", &Debug,
        &(char_varying)"switch(-Verbose),=1", &Verbose,
        &(char_varying)"option(-arg0), string, value", &varg0,
        &(char_varying)"option(-arg1), string, value", &varg1,
        &(char_varying)"option(-arg2), string, value", &varg2,
        &(char_varying)"option(-arg3), string, value", &varg3,
        &(char_varying)"option(-arg4), string, value", &varg4,
        &(char_varying)"option(-arg5), string, value", &varg5,
        &(char_varying)"option(-arg6), string, value", &varg6,
        &(char_varying)"option(-arg7), string, value", &varg7,
        &(char_varying)"option(-arg8), string, value", &varg8,
        &(char_varying)"option(-arg9), string, value", &varg9,
        &(char_varying(32))"end");

    if (error_code != 0)
        exit(error_code);

/* convert varying length strings to standard C strings */

    strcpy_nstr_vstr(IPAddress, &vIPAddress);
    strcpy_nstr_vstr(InputFilePath, &vInputFilePath);
    strcpy_nstr_vstr(arguments[0], &varg0);
    strcpy_nstr_vstr(arguments[1], &varg1);
    strcpy_nstr_vstr(arguments[2], &varg2);
    strcpy_nstr_vstr(arguments[3], &varg3);
    strcpy_nstr_vstr(arguments[4], &varg4);
    strcpy_nstr_vstr(arguments[5], &varg5);
    strcpy_nstr_vstr(arguments[6], &varg6);
    strcpy_nstr_vstr(arguments[7], &varg7);
    strcpy_nstr_vstr(arguments[8], &varg8);
    strcpy_nstr_vstr(arguments[9], &varg9);

/* if the server IP address of input script file are missing print a
   usage message and exit */
if ((strlen (IPAddress) == 0) || (strlen (InputFilePath) == 0))
   {
   printf ("Usage:\n\tsend_cmd -IPAddress <server IP address> ");
   printf ("[-PortNumber <server port number>] -InputFilePath <path to ");
   printf ("script file> [-TimeOut <max wait time in seconds>]");
   printf (" [-EchoSend] [-Debug] [-no_Verbose]\n\n");
   exit (0);
   }

/* If Debug is set also set Verbose */
if (Debug)
   Verbose = 1;

/* if Verbose is set print the ID and argument lines */
if (Verbose)
   {
/* print some identification stuff */
   printf ("send_cmds version 1.2 08-05-08 Noah.Davids@stratus.com\n");

/* Otherwise print out the arguments */
   printf ("send_cmds -IPAddress %s -PortNumber %d -InputFilePath %s",
        IPAddress, PortNumber, InputFilePath);
   printf (" -TimeOut %d ", TimeOut);
   if (EchoSend == 0)
      printf ("-no_EchoSend ");
   else
      printf ("-EchoSend ");
   if (Debug == 0)
      printf ("-no_Debug ");
   else
      printf ("-Debug ");
   if (Verbose)
      printf ("-Verbose ");
   else
      printf ("-no_Verbose ");
   for (i = 0; i <10; i++)
      if (strlen (arguments [i]) > 0)
         printf (" -arg%1d %s", i, arguments[i]);
   printf ("\n\n");
   } /* if (Verbose) */

/* open the input file */
InputFileFD = fopen (InputFilePath, "r");
if (InputFileFD == NULL)
   {
   printf ("Could not open InputFile %s, errno = %d\n", InputFilePath, errno);
   exit (errno);
   }

/* create the socket and connect to the server */
sd = socket(AF_INET, SOCK_STREAM, 0);
if (sd <0)
   {
   printf ("Could not create socket, errno = %d\n", errno);
   exit (errno);
   }
sin = (struct sockaddr_in *)&bind_saddr;
sin->sin_family = AF_INET;
sin->sin_port = htons (PortNumber);
sin->sin_addr.s_addr = inet_addr(IPAddress);
if (sin->sin_addr.s_addr == -1)
   {
   printf ("Could not convert %s to IP address, errno = %d\n",
           IPAddress, errno);
   exit (errno);
   }
if (connect (sd, &bind_saddr, sizeof(struct sockaddr)) <0)
   {
   printf ("Error connecting to %s, errno = %d\n", IPAddress, errno);
   exit (errno);
   }

/* loop through all of the lines in the input file */
while (!feof(InputFileFD))
   {
   if (fgets (InputLine, MAXSCRIPTLINE, InputFileFD) == NULL)
      {
      printf ("Error reading input file\n");
      break;
      }

/* delimiter is always the first character, find it and its match */
   delimChar = InputLine [0];
   delim2Ptr = strchr (&InputLine [1], delimChar);
   if (delim2Ptr == NULL)
      {
      printf ("Formating error in input file %s - no second delimiter\n",
              InputLine);
      exit(1057);
      }

/* replace second delimiter with null - this terminates the SendString */
   *delim2Ptr = 0x0;
   strcpy (SendString, &InputLine [1]);

/* skip second delimited (now NULL) and copy the rest of the input line */
   strcpy (WaitForString, delim2Ptr + 1);

/* InputLine included the terminating new line character which we don't want */
   WaitForString [strlen (WaitForString) - 1] = 0;

/* is this a place holder for one of the command arguments */
   if (strncmp (WaitForString, "arg", 3) == 0)
      {
      argIndex = atoi (&WaitForString [3]);
      if (argIndex <0 | argIndex > 9)
         {
         printf ("\n\nError in keyword %s, N must be between 0 and 9\n",
                  WaitForString);
         exit (1);
         }
      if (strlen (arguments [argIndex]) == 0)
         {
         printf ("\n\nScript is calling for arg%d, ", argIndex);
         printf ("but arg%d was not set\n", argIndex);
         exit (1);
         }
      if (strlen (WaitForString) > 4)
         {
         printf ("\n\nScript is using argument substitution within a ");
         printf ("bigger string\n\t'%s'.\n", WaitForString);
         printf ("Argument substituion must be used alone.\n");
         exit (1);
         }
      strcpy (WaitForString, arguments [argIndex]);
      } /* if (strncmp (WaitForString, "arg", 3) == 0) */

/* If both SendString and WaitForString are "quit" - quit */
   if ((strlen (SendString) > 3) && (strlen (WaitForString) > 3))
      if ((strncmp (SendString, "quit", 4) == 0) &&
                          (strncmp (WaitForString, "quit", 4) == 0))
         break;

/* if the SendString is not NULL do something with it */
   if (strlen (SendString) > 0)
      {

/* is this a place holder for one of the command arguments */
      if (strncmp (SendString, "arg", 3) == 0)
         {
         argIndex = atoi (&SendString [3]);
         if (argIndex <0 | argIndex > 9)
            {
            printf ("\n\nError in keyword %s, N must be between 0 and 9\n",
                     SendString);
            exit (1);
            }
         if (strlen (arguments [argIndex]) == 0)
            {
            printf ("\n\nScript is calling for arg%d, ", argIndex);
            printf ("but arg%d was not set\n", argIndex);
            exit (1);
            }
         if (strlen (SendString) > 4)
            {
            printf ("\n\nScript is using argument substitution within a ");
            printf ("bigger string\n\t'%s'.\n", SendString);
            printf ("Argument substituion must be used alone.\n");
            exit (1);
            }
         strcpy (SendString, arguments [argIndex]);
         } /* if (strncmp (SendString, "arg", 3) == 0) */

/* need to terminate the SendString with a new line sequence */
      i = strlen (SendString);
      SendString [i] = 0x0d;
      SendString [i + 1] = 0x0;

/* now send the SendString, continue trying until its all sent */
      i = 0;
      while (i <strlen (SendString))
         {
         SentChars = send (sd, &SendString [i], strlen (&SendString [i]), 0);
         i = i + SentChars;
         }

/* Echo the SendString if requested to do so */
      if (EchoSend)
         {
         printf ("---> %s\n", SendString);
         fflush (stdout);
         }
      } /* if (strlen (SendString) > 0 */

/* now deal with the received characters */

/* Make sure that we do not overrun the buffer */
   i = 0;
   while (i <MAXRECVSTRING)
      {

/* Set up to wait for something. Wait only so long before giving up */
      FD_SET (sd, &fdsetR);
      nfds = sd + 1;
      timeout.tv_sec = TimeOut;
      timeout.tv_usec = 0;
      sdSelected = select (nfds, &fdsetR, (fd_set *) 0, (fd_set *) 0,
                           &timeout);
      if (sdSelected <0)
         {
         printf ("Error from select, errno = %d\n", errno);
         exit (errno);
         }
      if (sdSelected == 0)
         {                   /* get rid of terminating 0x0d */
         SendString [strlen (SendString) - 1] = 0x00;
         printf ("\n\nTimeout waiting for [%s] after sending [%s]\n",
               WaitForString, SendString);
         exit (1081);
         }

/* select indicated that a socket is ready, since there is only 1 socket
   no need to test */
/* all characters received after a string is sent go into the same buffer
   this makes testing for the WaitForString easy but not very efficient
   you want to do better go for it */
      RecvChars = recv (sd, &RecvString [i], MAXRECVSTRING - i, 0);
      if (RecvChars <0)
         {
         printf ("Error after sending %s and waiting for %s, errno = %d\n",
             SendString, WaitForString, errno);
         exit (errno);
         }

/* Loop though the just received characters for processing. Certain sequences
   are replaced with other sequences. If you want to see the raw characters
   as well use the Debug argument.
          0x0d 0x00      \n
          0x0d 0x0a      \n
          0x0a 0x0d      \n
          0x09           \t
          0x08           \b
   all other non-printing characters are displayed as [0xXX] */

      for (j = i; j <i + RecvChars; j++)
          {
          if ((RecvString [j] == 0x0d) && (RecvString [j+1] == 0x00))
             {
             if (Debug && Verbose)
                {
                printf ("[0x%2x]", RecvString [j]);
                printf ("[0x%2x]", RecvString [j+1]);
                }
             printf ("\n");
             }
          else
          if ((RecvString [j-1] == 0x0d) && (RecvString [j] == 0x00))
             do_nothing++;
          else
          if ((RecvString [j] == 0x0a) && (RecvString [j+1] == 0x0d))
             {
             if (Debug && Verbose)
                {
                printf ("[0x%2x]", RecvString [j]);
                printf ("[0x%2x]", RecvString [j+1]);
                }
             printf ("\n");
             }
          else
          if ((RecvString [j-1] == 0x0a) && (RecvString [j] == 0x0d))
             do_nothing++;
          else
          if ((RecvString [j] == 0x0d) && (RecvString [j+1] == 0x0a))
             {
             if (Debug && Verbose)
                {
                printf ("[0x%2x]", RecvString [j]);
                printf ("[0x%2x]", RecvString [j+1]);
                }
             printf ("\n");
             }
          else
          if ((RecvString [j-1] == 0x0d) && (RecvString [j] == 0x0a))
             do_nothing++;
          else
          if (RecvString [j] == 0x08)
             {
             if (Debug && Verbose)
                printf ("[0x%2x]", RecvString [j]);
             printf ("\b");
             }
          else
          if (RecvString [j] == 0x09)
             {
             if (Debug && Verbose)
                printf ("[0x%2x]", RecvString [j]);
             printf ("\t");
             }
          else
          if ((RecvString [j] <32) || (RecvString [j] > 126))
             {
             if (Verbose)
                printf ("[0x%2x]", RecvString [j]);
             }
          else
             printf ("%c", RecvString [j]);

/* Any null characters are replaced at this point so that the string search
   function doesn't terminate too soon */
          if (RecvString [j] == 0x00)
              RecvString [j] = 0xFF; /* so string compares aren't stopped */
          } /* for (j = i; j <i + RecvChars; j++) */

/* sometimes the output needs a little help */
      fflush (stdout);

/* make sure that the RecvString is terminated at the end of the currently
   received set of characters and look for the WaitForString */
      RecvString [i + RecvChars] = 0;
      i = i + RecvChars;
      if (strstr (RecvString, WaitForString) != NULL)
         break;
      } /* while (i <MAXRECVSTRING) */

/* If we are out of the receive loop and the number of received characters is
   our maximum print out an error and exit. We could probably purge the last
   30,000 and continue but it is more likely something is wrong and the
   script is out of sequence with the commands so just quit */
   if (i >= MAXRECVSTRING)
      {                 /* get rid of terminating 0x0d */
      SendString [strlen (SendString) - 1] = 0x00;
      printf ("More then %d characters have been received after\n",
              MAXRECVSTRING);
      printf ("sending [%s] and waiting for [%s]\n",
              SendString, WaitForString);
      printf ("Break the thing up using null send strings\n");
      exit (1114);
      }
   } /* while (!feof(InputFileFD)) */
}



Blue Bar separator
This page was last modified on 10-11-26
mailbox Send comments and suggestions
to ndav1@cox.net