Visual FoxPro
Visual FoxPro
SSH to a Cisco Switch - Processing "More" Responses
See more SSH Examples
Demonstrates connecting to a Cisco switch, entering privileged mode with the ena command, and running a command whose response is paged. Each page ends with --More-- and requires a SPACE character to request the next page.
Note: QuickShell allocates a PTY, which is what a network device console expects. The device presents an interactive prompt, and each command's output is read up to the next prompt.
Background: Paged output is the console equivalent of a pager like
more, and a client must reproduce the keypress a human would make. Matching a set of patterns is what makes this tractable: each read ends either at the device prompt (output complete) or at --More-- (another page waiting), and the code branches accordingly. Note the prompt pattern includes the device name rather than a bare #, because that character also appears inside configuration text and would otherwise match far too early.Chilkat Visual FoxPro Downloads
LOCAL lnSuccess
LOCAL loSsh
LOCAL lnPort
LOCAL lcPassword
LOCAL lnChannelNum
LOCAL lnCaseSensitive
LOCAL lcReceived
LOCAL lcEnablePassword
LOCAL loSaMatch
LOCAL loSbReceived
LOCAL lnMoreComing
LOCAL lcPageText
lnSuccess = 0
* This example requires the Chilkat API to have been previously unlocked.
* See Global Unlock Sample for sample code.
* Demonstrates connecting to a Cisco switch, entering privileged mode, and running a command
* whose response is paged -- each page ends with "--More--" and requires a SPACE character to
* request the next page.
loSsh = CreateObject('Chilkat.Ssh')
lnPort = 22
lnSuccess = loSsh.Connect("172.16.16.100",lnPort)
IF (lnSuccess = 0) THEN
? loSsh.LastErrorText
RELEASE loSsh
CANCEL
ENDIF
* Normally you would not hard-code the password in source. You should instead obtain it
* from an interactive prompt, environment variable, or a secrets vault.
lcPassword = "mySshPassword"
lnSuccess = loSsh.AuthenticatePw("mySshLogin",lcPassword)
IF (lnSuccess = 0) THEN
? loSsh.LastErrorText
RELEASE loSsh
CANCEL
ENDIF
lnChannelNum = loSsh.QuickShell()
IF (lnChannelNum < 0) THEN
? loSsh.LastErrorText
RELEASE loSsh
CANCEL
ENDIF
* IMPORTANT: Set a read timeout before receiving until a match. ReadTimeoutMs defaults to 0,
* which means no limit -- without it, this call waits forever if the received data never
* contains a match.
loSsh.ReadTimeoutMs = 15000
lnCaseSensitive = 1
* In unprivileged mode the switch prompt ends with ">".
lnSuccess = loSsh.ChannelReceiveUntilMatch(lnChannelNum,">","utf-8",lnCaseSensitive)
IF (lnSuccess = 0) THEN
? loSsh.LastErrorText
RELEASE loSsh
CANCEL
ENDIF
lcReceived = loSsh.GetReceivedText(lnChannelNum,"utf-8")
IF (loSsh.LastMethodSuccess = 0) THEN
? loSsh.LastErrorText
RELEASE loSsh
CANCEL
ENDIF
? lcReceived
* Send "ena" to enter privileged mode. Cisco devices expect a bare CR to terminate a command.
lnSuccess = loSsh.ChannelSendString(lnChannelNum,"ena" + CHR(13),"utf-8")
IF (lnSuccess = 0) THEN
? loSsh.LastErrorText
RELEASE loSsh
CANCEL
ENDIF
lnSuccess = loSsh.ChannelReceiveUntilMatch(lnChannelNum,"Password:","utf-8",lnCaseSensitive)
IF (lnSuccess = 0) THEN
? loSsh.LastErrorText
RELEASE loSsh
CANCEL
ENDIF
lcReceived = loSsh.GetReceivedText(lnChannelNum,"utf-8")
IF (loSsh.LastMethodSuccess = 0) THEN
? loSsh.LastErrorText
RELEASE loSsh
CANCEL
ENDIF
? lcReceived
* The enable password is separate from the login password, and likewise should come from a
* secure source rather than being hard-coded.
lcEnablePassword = "myEnablePassword"
lnSuccess = loSsh.ChannelSendString(lnChannelNum,lcEnablePassword,"utf-8")
IF (lnSuccess = 0) THEN
? loSsh.LastErrorText
RELEASE loSsh
CANCEL
ENDIF
lnSuccess = loSsh.ChannelSendString(lnChannelNum,CHR(13),"utf-8")
IF (lnSuccess = 0) THEN
? loSsh.LastErrorText
RELEASE loSsh
CANCEL
ENDIF
* In privileged mode the prompt ends with "#" instead of ">".
lnSuccess = loSsh.ChannelReceiveUntilMatch(lnChannelNum,"#","utf-8",lnCaseSensitive)
IF (lnSuccess = 0) THEN
? loSsh.LastErrorText
RELEASE loSsh
CANCEL
ENDIF
lcReceived = loSsh.GetReceivedText(lnChannelNum,"utf-8")
IF (loSsh.LastMethodSuccess = 0) THEN
? loSsh.LastErrorText
RELEASE loSsh
CANCEL
ENDIF
? lcReceived
* Run a command whose output is delivered a page at a time.
lnSuccess = loSsh.ChannelSendString(lnChannelNum,"show running-config" + CHR(13),"utf-8")
IF (lnSuccess = 0) THEN
? loSsh.LastErrorText
RELEASE loSsh
CANCEL
ENDIF
* Each read ends either at the device prompt (output complete) or at "--More--" (another page
* is waiting). Match the full prompt rather than a bare "#", because "#" also appears inside
* configuration text and would match too early.
loSaMatch = CreateObject('Chilkat.StringArray')
loSaMatch.Append("MySwitchName#")
loSaMatch.Append("--More--")
loSbReceived = CreateObject('Chilkat.StringBuilder')
lnMoreComing = 1
DO WHILE lnMoreComing
lnSuccess = loSsh.ChannelReceiveUntilMatchN(lnChannelNum,loSaMatch,"utf-8",lnCaseSensitive)
IF (lnSuccess = 0) THEN
? loSsh.LastErrorText
RELEASE loSsh
RELEASE loSaMatch
RELEASE loSbReceived
CANCEL
ENDIF
loSbReceived.Clear()
lcPageText = loSsh.GetReceivedText(lnChannelNum,"utf-8")
IF (loSsh.LastMethodSuccess = 0) THEN
? loSsh.LastErrorText
RELEASE loSsh
RELEASE loSaMatch
RELEASE loSbReceived
CANCEL
ENDIF
loSbReceived.Append(lcPageText)
? lcPageText
* If this page ended with "--More--", send a SPACE to request the next page.
lnMoreComing = loSbReceived.Contains("--More--",lnCaseSensitive)
IF (lnMoreComing) THEN
lnSuccess = loSsh.ChannelSendString(lnChannelNum," ","utf-8")
IF (lnSuccess = 0) THEN
? loSsh.LastErrorText
RELEASE loSsh
RELEASE loSaMatch
RELEASE loSbReceived
CANCEL
ENDIF
ENDIF
ENDDO
loSsh.Disconnect()
RELEASE loSsh
RELEASE loSaMatch
RELEASE loSbReceived