mirror of
https://github.com/libssh2/libssh2.git
synced 2025-07-04 09:22:28 +03:00
- Handle MD5 conditionals in os400qc3. - Check for errors in os400qc3 pbkdf1. - Implement an optional build options override file. - Sync ILE/RPG copy files with current C header files. - Allow a null session within a string conversion cache. - Add an ILE/RPG example. - Adjust outdated copyrights in changed files.
327 lines
12 KiB
Plaintext
327 lines
12 KiB
Plaintext
* Example: print a remote ascii file using sftp
|
|
*
|
|
h DFTACTGRP(*NO) ACTGRP(*NEW)
|
|
h OPTION(*NOSHOWCPY)
|
|
h BNDDIR('LIBSSH2')
|
|
h BNDDIR('QC2LE')
|
|
*
|
|
* Copyright (C) The libssh2 project and its contributors.
|
|
*
|
|
* Usage:
|
|
*
|
|
* CALL SFTPXMPLE ('<host>' '<port>' '<user>' '<password>' '<filepath>')
|
|
*
|
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
*
|
|
fQPRINT o f 120 printer
|
|
*
|
|
/include LIBSSH2RPG,SSH2_SFTP
|
|
/include LIBSSH2RPG,SSH2_CCSID
|
|
*
|
|
d pi
|
|
d host 120
|
|
d port 5
|
|
d user 20
|
|
d password 120
|
|
d filepath 120
|
|
*
|
|
**************************************************************************
|
|
* External definitions
|
|
**************************************************************************
|
|
*
|
|
d atoi pr 10i 0 extproc('atoi')
|
|
d numstr * value options(*string)
|
|
*
|
|
d inet_addr pr 10u 0 extproc('inet_addr')
|
|
d char_addr * value options(*string)
|
|
*
|
|
d socket pr 10i 0 extproc('socket')
|
|
d domain 10i 0 value
|
|
d type 10i 0 value
|
|
d protocol 10i 0 value
|
|
*
|
|
d AF_INET c 2
|
|
d SOCK_STREAM c 1
|
|
d IPPROTO_IP c 0
|
|
*
|
|
d connect pr 10i 0 extproc('connect')
|
|
d sockfd 10i 0 value
|
|
d addr * value
|
|
d addrlen 10u 0 value
|
|
*
|
|
d sockaddr_in ds based(######typedef######)
|
|
d align qualified
|
|
d sin_family 5i 0
|
|
d sin_port 5i 0
|
|
d sin_addr 10u 0
|
|
d sin_zero 8
|
|
*
|
|
d shutdown pr 10i 0 extproc('shutdown')
|
|
d socket 10i 0 value
|
|
d how 10i 0 value
|
|
*
|
|
d SHUT_RDWR c 2
|
|
*
|
|
d qmhsndpm pr extpgm('QMHSNDPM')
|
|
d msgid 7 const
|
|
d qmsgfn 20 const
|
|
d data 999999 const options(*varsize)
|
|
d datalength 10u 0 const
|
|
d msgtype 10 const
|
|
d csentry 999999 const options(*varsize)
|
|
d cscounter 10u 0 const
|
|
d msgkey 4
|
|
d errcode 999999 options(*varsize)
|
|
d csentrylen 10u 0 const options(*nopass)
|
|
d csqual 20 const options(*nopass)
|
|
d waittime 10u 0 const options(*nopass)
|
|
d csentrytype 10 const options(*nopass)
|
|
d ccsid 10u 0 const options(*nopass)
|
|
*
|
|
**************************************************************************
|
|
* Constants
|
|
**************************************************************************
|
|
*
|
|
d EBCDIC_CR c X'0D'
|
|
d EBCDIC_LF c X'25'
|
|
*
|
|
**************************************************************************
|
|
* Global storage
|
|
**************************************************************************
|
|
*
|
|
d sc s * inz(*NULL) String cache
|
|
d session s * inz(*NULL) Session
|
|
d sftp_session s * inz(*NULL) LIBSSH2_SFTP *
|
|
d sftp_handle s * inz(*NULL) LIBSSH2_SFTP_HANDLE*
|
|
d sin ds likeds(sockaddr_in) Remote IP address
|
|
d sock s 10i 0 inz(LIBSSH2_INVALID_SOCKET) Socket descriptor
|
|
d rc s 10i 0 Result code
|
|
d hostlen s 10u 0 Host name length
|
|
*
|
|
**************************************************************************
|
|
* Main program
|
|
**************************************************************************
|
|
|
|
// Initialize ssh lbrary
|
|
rc = libssh2_init(0);
|
|
if rc <> 0;
|
|
error('libssh2 initialization failed (' + %trim(%char(rc)) + ')');
|
|
else;
|
|
// Build remote address
|
|
sin.sin_family = AF_INET;
|
|
hostlen = trimmed_length(host: %len(host): %addr(port));
|
|
if hostlen <> 0;
|
|
sin.sin_addr = inet_addr(%subst(host: 1: hostlen));
|
|
else;
|
|
sin.sin_addr = inet_addr('127.0.0.1');
|
|
endif;
|
|
sin.sin_port = atoi(port);
|
|
if sin.sin_port <= 0;
|
|
sin.sin_port = 22;
|
|
endif;
|
|
sin.sin_zero = *ALLX'00';
|
|
|
|
main();
|
|
cleanout();
|
|
endif;
|
|
|
|
*inlr = *on;
|
|
/space 3
|
|
begsr *pssr;
|
|
cleanout();
|
|
endsr;
|
|
/eject
|
|
**************************************************************************
|
|
* Main procedure
|
|
**************************************************************************
|
|
*
|
|
p main b
|
|
*
|
|
d buf s 1024 Data buffer
|
|
d nread s 10i 0 Read bytes count
|
|
|
|
// Connect to remote server
|
|
sock = socket(AF_INET: SOCK_STREAM: IPPROTO_IP);
|
|
if sock = LIBSSH2_INVALID_SOCKET;
|
|
error('failed to create socket');
|
|
return;
|
|
endif;
|
|
if connect(sock: %addr(sin): %size(sin)) <> 0;
|
|
error('failed to connect');
|
|
return;
|
|
endif;
|
|
|
|
// Create a session instance
|
|
session = libssh2_session_init();
|
|
if session = *NULL;
|
|
error('Could not initialize SSH session');
|
|
return;
|
|
endif;
|
|
|
|
// Since we have set non-blocking, tell libssh2 we are blocking
|
|
libssh2_session_set_blocking(session: 1);
|
|
|
|
// ... start it up. This will trade welcome banners, exchange keys,
|
|
// and setup crypto, compression, and MAC layers
|
|
rc = libssh2_session_handshake(session: sock);
|
|
if rc <> 0;
|
|
error('Failure establishing SSH session: ' + %trim(%char(rc)));
|
|
return;
|
|
endif;
|
|
|
|
// Authenticate
|
|
if libssh2_userauth_password(session:
|
|
libssh2_from_ccsid(session: sc: 0: user:
|
|
trimmed_length(user: %size(user):
|
|
%addr(password)): *omit):
|
|
libssh2_from_ccsid(session: sc: 0: password:
|
|
trimmed_length(password: %size(password):
|
|
%addr(filepath)): *omit)) <> 0;
|
|
error('Authentication by password failed');
|
|
return;
|
|
endif;
|
|
|
|
// Request a file via SFTP
|
|
sftp_session = libssh2_sftp_init(session);
|
|
|
|
if sftp_session = *NULL;
|
|
error('Unable to init SFTP session');
|
|
return;
|
|
endif;
|
|
|
|
sftp_handle = libssh2_sftp_open(sftp_session:
|
|
libssh2_from_ccsid(session: sc: 0: filepath:
|
|
trimmed_length(filepath: %size(filepath): *null):
|
|
*omit): LIBSSH2_FXF_READ: 0);
|
|
if sftp_handle = *NULL;
|
|
error('Unable to open file with SFTP: ' +
|
|
%trim(%char(libssh2_sftp_last_error(sftp_session))));
|
|
return;
|
|
endif;
|
|
|
|
// Download and display the remote file
|
|
nread = libssh2_sftp_read(sftp_handle: %addr(buf): %size(buf));
|
|
dow nread > 0; // loop until we fail
|
|
print(libssh2_to_ccsid(session: sc: 0: %addr(buf): nread: *omit):
|
|
-1);
|
|
libssh2_release_string_cache(session: sc);
|
|
nread = libssh2_sftp_read(sftp_handle: %addr(buf): %size(buf));
|
|
enddo;
|
|
p main e
|
|
/eject
|
|
**************************************************************************
|
|
* Release all allocated resources
|
|
**************************************************************************
|
|
*
|
|
p cleanout b
|
|
*
|
|
|
|
if sftp_handle <> *NULL;
|
|
libssh2_sftp_close(sftp_handle);
|
|
endif;
|
|
|
|
if sftp_session <> *NULL;
|
|
libssh2_sftp_shutdown(sftp_session);
|
|
endif;
|
|
|
|
if session <> *NULL;
|
|
libssh2_session_disconnect(session: libssh2_from_ccsid(session: sc:
|
|
0: 'Normal shutdown': -1: *omit));
|
|
libssh2_release_string_cache(session: sc);
|
|
libssh2_session_free(session);
|
|
endif;
|
|
|
|
if sock <> LIBSSH2_INVALID_SOCKET;
|
|
shutdown(sock: SHUT_RDWR);
|
|
LIBSSH2_SOCKET_CLOSE(sock);
|
|
endif;
|
|
|
|
libssh2_exit();
|
|
p cleanout e
|
|
/eject
|
|
**************************************************************************
|
|
* Print data line by line
|
|
**************************************************************************
|
|
*
|
|
p print b
|
|
d pi
|
|
d string * value options(*string)
|
|
d len 10i 0 value
|
|
*
|
|
d recout ds Output line buffer
|
|
d lineout 120 inz(*blanks)
|
|
*
|
|
d i s 10u 0
|
|
d j s 10u 0 inz(0)
|
|
|
|
if len < 0;
|
|
len = %len(%str(string));
|
|
endif;
|
|
|
|
for i = 0 to len - 1;
|
|
if %str(string + i: 1) <> EBCDIC_CR;
|
|
if %str(string + i: 1) = EBCDIC_LF;
|
|
write QPRINT recout;
|
|
lineout = *blanks;
|
|
j = 0;
|
|
else;
|
|
if j >= %size(lineout);
|
|
write QPRINT recout;
|
|
lineout = *blanks;
|
|
j = 0;
|
|
endif;
|
|
j = j + 1;
|
|
%subst(lineout: j: 1) = %str(string + i: 1);
|
|
endif;
|
|
endif;
|
|
endfor;
|
|
if j > 0;
|
|
write QPRINT recout;
|
|
endif;
|
|
p print e
|
|
/eject
|
|
**************************************************************************
|
|
* Error procedure
|
|
**************************************************************************
|
|
*
|
|
p error b
|
|
d pi
|
|
d message * value options(*string)
|
|
*
|
|
d errcode ds qualified
|
|
d provided 10u 0 inz(0)
|
|
d available 10u 0
|
|
*
|
|
d msgkey s 4
|
|
|
|
// Send error as an exception to the calling level.
|
|
qmhsndpm('CPF9898': 'QCPFMSG QSYS':
|
|
%str(message): %len(%str(message)): '*ESCAPE':
|
|
'* ': 1: msgkey: errcode);
|
|
p error e
|
|
/eject
|
|
**************************************************************************
|
|
* Get the length of right-trimmed string
|
|
**************************************************************************
|
|
*
|
|
p trimmed_length b
|
|
d pi 10u 0
|
|
d string 999999 options(*varsize)
|
|
d length 10u 0 value
|
|
d nextarg * value
|
|
*
|
|
d len s 10u 0
|
|
|
|
if nextarg <> *null;
|
|
len = nextarg - %addr(string);
|
|
if length > len;
|
|
length = len;
|
|
endif;
|
|
endif;
|
|
len = %scan(X'00': string: 1: length); // Maybe zero-terminated
|
|
if len = 0;
|
|
len = length + 1;
|
|
endif;
|
|
return %checkr(' ': string: len - 1); // Trim right
|
|
p trimmed_length e
|