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
 |