PARM localfiles=? remotesystem=? remoteuser=* remotedir=* encrypt=true & remoteSysT="MPE/IX" remSysHasCrypt=true entry=main # # This script transfers, via FTP/iX, "localfiles" from the host MPE system to # the "remotesystem". Depending on the "encrypt" parameter and the type of # file (needs to be ASCII) the file(s) may be encrypted, via the POSIX crypt # utility, before being transferred. If the remote system is an MPE system a # job will be streamed, via the 'site stream' FTP command, which automatically # decrypts the file. If the remote system is not an MPE system then the file # needs to be decrypted manually: $crypt key finalFilename # The key is FTP'd in its own file named "FileName.key". # # To force this script to evaluate the remote system type enter "*" as the # value of the 'remoteSysT' parm. An extra FTP run is necessary in this case. # # FTP PASSIVE mode is used to increase the chances of being able to connect # through client firewalls. # # This script is sensitive to the existence of the NETRC file, which provides # automatic logins to remote systems. If NETRC exists, FTP logs-in using the # first entry matching the 'remotesystem' name. Thus, the 'remoteuser' parm is # typically ignored. More on NETRC can be found in the notes section. # # A user-settable variable, _SFTP_DEBUG, can be set to true to cause this # script to display diagnostic messages to $STDLIST. If this variable is set # to false or missing, the script displays fewer messages (but still some). # # Parameters are defined in the HELP section near the end of this script. # # There are important notes on NETRC, crypt, and IO redirection at the end of # this file. # if '!entry' = 'main' then # main entry point: validate parms, prompt for remote user password if, # needed, etc. echo setvar _ftp_me basename(hpfile) echo --- !_ftp_me --- version A.06 echo # Help/usage needed? if pos('?','!localfiles!remotesystem') > 0 then xeq !hpfile !localfiles, !remotesystem ;entry=help escape endif # *** Begin customize with CI variables *** # ** _SFTP_DEBUG setvar _ftp_dbg '#' if bound(_SFTP_DEBUG) then if typeof(_sftp_debug) <> 3 then echo _SFTP_DEBUG CI variable must be boolean TRUE or FALSE. echo FALSE is assumed. echo elseif _sftp_debug then setvar _ftp_dbg 'echo' echo ++ Note: _SFTP_DEBUG=TRUE so all temporary files and variables echo used by the script are preserved, and more verbose messages echo are displayed. To see the script variables enter :showvar echo _ftp_@. To see the temp files enter :listfile ./@;temp echo To disable this feature :deletevar _sftp_debug, or set this echo variable to FALSE. echo endif endif # *** End customize with CI variables *** # validate "encrypt" parm if typeof(!encrypt) <> 3 then echo *** Error: expected a TRUE or FALSE for the "encrypt" parm. This echo parameter controls whether or not to encrypt the file prior to echo FTP'ing it to the remote system. Note: only plain text files are echo encrypted. escape endif # some MPE machines don't have the crypt utility installed. if !encrypt and not finfo('crypt.hpbin.sys','exists') then echo *** Error: encryption file: CRYPT.HPBIN.SYS missing. echo Please download this file from http://jazz.external.hp.com/src escape endif # validate "remoteSysT" parm setvar _ftp_remSysT ups("!remoteSysT") if lft(_ftp_remSysT,3) = "MPE" then # any variation of MPE is acceptable setvar _ftp_remSysT "MPE/IX" elseif not(_ftp_remSysT="*" or _ftp_remSysT="UNIX" or & _ftp_remSysT="WINDOWS") then echo *** Error: expected values for "remoteSysT" (remote system type) & parm are: echo "MPE/iX" or "Unix" or "Windows" or "*" (meaning unknown). & Specifying echo this parameter as non-* improves performance since the system & type echo for the remote system does not need to be determined. escape endif # validate "remSysHasCrypt" parm if typeof(!remSysHasCrypt) <> 3 then echo *** Error: expected a TRUE or FALSE for the "RemSysHasCrypt" parm. & This echo parameter indicates if the remote MPE system has the crypt & utility. echo If it does, crypt will not be FTP'd to the remote machine. escape endif # deal with 'remoteuser' parm, passwords and netrc implications setvar _ftp_user "!remoteuser" setvar _ftp_pass "*" # check if netrc file will be used by FTP -- see notes at end of script. # If so, any supplied user name/pass is overridden by the values in netrc. if setvar(_ftp_useNetrc,(finfo('*netrc.!hphgroup','exists') or & finfo('netrc.!hphgroup','exists'))) then !_ftp_dbg ++ Note: NETRC file in effect if _ftp_user = '*' then # using netrc and no 'remoteuser' parm supplied. Set remote user to # 'user.acct' and hope for the best. setvar _ftp_user "!hpuser.!hpaccount" setvar _ftp_pass "" endif elseif _ftp_user = '*' then # not using netrc and no remote user supplied echo *** Error: 'RemoteUser' parameter is required as there is no NETRC echo file to automate the FTP login. Either supply a remote user name echo (3rd parm) or make use of [*]NETRC.!hphgroup. escape else !_ftp_dbg ++ Note: no NETRC file in effect endif # At this point we have a user name. Parse the user parm even if netrc # will be used. This way we can capture a username used to logon to # the remote MPE system for the decrypt job. Syntaxes supported are: # username[:[pass]] or, for non-MPE users, username[/[pass]]. MPE username # is "user.acct". MPE embedded passwords can be specified as: # "user/upass.acct/apass" or "user.acct:upass,apass", but NOT # "user.acct/upass,apass". # Note: all embedded passwords are ignored if netrc is used. if pos(".",_ftp_user) > 0 then # we better have an MPE user.acct # capture and remove embedded passwords, if any setvar _ftp_u_pwd "" setvar _ftp_a_pwd "" setvar _ftp_u word(_ftp_user,".") setvar _ftp_a word(_ftp_user,".",-1) if pos("/",_ftp_u) > 0 or pos("/",_ftp_a) > 0 then # format is: user[/upass].acct[/apass] if pos("/",_ftp_u) > 0 then setvar _ftp_u_pwd word(_ftp_u,"/",-1) setvar _ftp_u word(_ftp_u,"/") endif if pos("/",_ftp_a) > 0 then setvar _ftp_a_pwd word(_ftp_a,"/",-1) setvar _ftp_a word(_ftp_a,"/") endif setvar _ftp_user _ftp_u+"."+_ftp_a setvar _ftp_pass _ftp_u_pwd+","+_ftp_a_pwd elseif pos(":",_ftp_user) > 0 then # format is: user.acct[:[[upass][,apass]]] # note: _ftp_a (acct name) already contains ':[password(s)]' setvar _ftp_a word(_ftp_a,":") setvar _ftp_pass word(_ftp_user,":",-1) setvar _ftp_user word(_ftp_user,":") # break apart MPE passwords for possible stream job if pos(",",_ftp_pass) > 0 then setvar _ftp_u_pwd word(_ftp_pass,",") setvar _ftp_a_pwd word(_ftp_pass,",",-1) else setvar _ftp_u_pwd _ftp_pass endif endif #else, no embedded MPE password(s) # since the user format is MPE the remote system type should also be # mpe, which is the default. Check for this case. if not (_ftp_remSysT = "MPE/IX" or _ftp_remSysT = "*") then echo *** Error: "!_ftp_u.!_ftp_a" is an MPE format for a user name, & but the echo remote system type was passed as "!_ftp_remSysT". & Re-enter the correct echo remote system type (parm 6) or use a properly formatted & user name. escape endif else # non-MPE user name. Format is: user[:pass] or user[/pass] # since the user format is non-MPE the remote system type should not be # mpe either, but this is the default. Check for this case. if delimpos(_ftp_user,":/") > 0 then setvar _ftp_pass word(_ftp_user,":/",-1) setvar _ftp_user word(_ftp_user,":/") endif if _ftp_remSysT = "MPE/IX" then echo *** Error: "!_ftp_user" is a non-MPE format for a user name, & but the echo remote system type was passed (or defaulted) as "MPE/iX". & Re-enter echo the correct remote system type (parm 6) or use a properly & formatted echo MPE user name ("user.account"). escape endif endif # embedded password(s) provided in remoteUser? If not, prompt. Note: a # null password is allowed in the remoteuser parm and will not trigger a # prompt. Null passwords are specified as: "username:" or "username/". if _ftp_pass = "*" and hpinteractive then set echo=off if pos(".",_ftp_user) > 0 then # assume MPE user.acct echo Password for !_ftp_user on !remotesystem? setvar _ftp_pass & repl(input(" (MPE password syntax is 'user[,acct]') ")," ","") # remove quotemarks in case user enters literally "upass,apass" setvar _ftp_pass repl(repl(_ftp_pass,'"',''),"'","") if setvar(_ftp_u_pwd,word(_ftp_pass,",")) <> _ftp_pass then # extract acct password setvar _ftp_a_pwd word(_ftp_pass,",",-1) endif else setvar _ftp_pass repl(& input("Password for !_ftp_user on !remotesystem ")," ","") endif set echo=on echo endif # convert "remotedir" to POSIX syntax, if needed setvar _ftp_logonGrp "" if setvar(_ftp_remDir,ltrim(rtrim("!remotedir"))) <> "*" and & alpha(lft(_ftp_remDir,1)) then # convert assumed MPE group[.acct] name to POSIX syntax if pos(".",setvar(_ftp_remDir,ups(_ftp_remDir))) = 0 then # qualify MPE group name setvar _ftp_remDir _ftp_remDir+"."+hpaccount endif setvar _ftp_remDir "/"+word(_ftp_remDir,".",-1)+"/"+word(_ftp_remDir,".") setvar _ftp_logonGrp "," + word(_ftp_remDir,"/",-1) endif # finally, deal with the fileset (localfiles) parm # if the 1st char is '^' then parm 1 is the name of a file which contains # a list of file(s), one file per record, and wildcards are not supported. # Otherwise, 'localfiles' is the name of a single file with may include # wildcard characters. if pos('^',"!localfiles") = 1 then setvar _ftp_listF rht("!localfiles",-2) setvar _ftp_purge "#" else # use listfile to expand wildcarding and qualify filenames. # the name of the temp file for listfile's $stdlist is "flist" setvar _ftp_listF "FLIST" setvar _ftp_purge "purge" errclear continue listfile !localfiles,6;seleq=[object=file] >!_ftp_listF if hpcierr <> 0 then echo *** Error: LISTFILE !localfiles print !_ftp_listF escape endif endif # **** FTP the file(s) **** # **** **** continue xeq !hpfile !localfiles, !remotesystem, "!remoteuser", !remotedir, !encrypt & !remoteSysT, !remSysHasCrypt, entry=put 0 are encrypted. # setvar _ftp_total setvar(_ftp_cnt,finfo(hpstdin,'eof')) setvar _ftp_xfer setvar(_ftp_cryptCnt,0) # see if we need to determine the remote system type. if _ftp_remSysT = "*" then # get remote sys type via FTP's syst command echo > ftpin EXITONERROR echo >>ftpin OPEN !remotesystem if not _ftp_useNetrc then echo >>ftpin USER !_ftp_user !_ftp_pass endif echo >>ftpin PASSIVE echo >>ftpin SYST echo >>ftpin :setvar _ftp_remSysT FTPLASTREPLY echo >>ftpin BYE continue xeq ftp.arpa.sys ftplist if FTPLASTERR >= 0 then setvar _ftp_remSysT ups(word(_ftp_remSysT,,2)) !_ftp_dbg ++ Note: Remote system type is: !_ftp_remSysT echo elseif FTPLASTERR = -8 or FTPLASTERR = -9 or FTPLASTERR = -66 then echo *** FTP error ![-ftplasterr]: cannot connect to "!remotesystem". escape elseif FTPLASTERR = -65 then echo *** FTP error 65: invalid user ID or password. escape else echo Warn: cannot determine remote system type. Default is "unkn". setvar _ftp_remSysT "*" if not (_ftp_dbg = '#') then echo *** FTP $stdlist follows: echo pause 2 print ftplist endif endif endif # If the remote system is MPE/iX and the encrypt parm is true then we'll # likely need to decrypt the file on the remote MPE machine. if _ftp_remSysT = "MPE/IX" and !encrypt then if not !remSysHasCrypt then # remote system doesn't have crypt (we're told), so make copy w/o PH setvar _ftp_cryptF 'crypt.hpbin.sys' setvar hpcierr 0 continue copy crypt.hpbin.sys,crypt01;yes if hpcierr = 0 then setvar _ftp_cryptF 'crypt01' setvar hpcierr 0 setjcw CJCW 0 continue xeq linkedit.pub.sys "altprog crypt01;cap=ia,ba" >$null if hpcierr <> 0 or CJCW <> 0 then !_ftp_dbg ++ Note: unable to remove PH cap from crypt. & Decryption on remote !_ftp_dbg system may fail if remote group lacks PH. else !_ftp_dbg ++ Note: made local copy of CRYPT which will be & transferred to remote system. endif endif endif # if the remoteuser parm was not supplied and netrc is used all could # be fine, as long as the login user in netrc matches the user's # user.acct. If they don't match then we'll later try to logon to the # remote MPE system with a user different from the user used to FTP the # file(s). This still may be ok if the netrc login user homes to the same # group as this script's user. The bottom line is we don't want the job # to logon on to a group different from where the files were transferred. # Issue a note/warn here to let the user know of the potential risk. if _ftp_useNetrc and '!remoteuser' = '*' and not (_ftp_dbg = '#') then echo ++ Note: No 'remoteuser' parm supplied so "!_ftp_user" is assumed echo to be the remote MPE logon user.acct. If this is not the same echo login user id found in the NETRC file, then the MPE job to echo decrypt the file(s) will logon as a different user (or the echo logon could fail), and could logon to a different group, and echo thus may not find the encrypted file(s). When using NETRC it's echo better to supply the NETRC machine user as the 'remoteuser' echo parm (parm 3) here. echo endif endif # *** main loop *** # *** *** # read filenames from $stdin input file, encrypt if necessary, and transfer # file to remote system. while setvar(_ftp_cnt,_ftp_cnt-1) >= 0 and & setvar(_ftp_file,ltrim(rtrim(input()))) <> "" do # convert MPE filenames to POSIX if lft(_ftp_file,1) <> "/" then setvar _ftp_file "/" + word(_ftp_file,".",-1) + "/" + & word(_ftp_file,".",2) + "/" + word(_ftp_file,".") endif setvar _ftp_baseN basename(_ftp_file) setvar _ftp_putAs "" if _ftp_remDir <> '*' then setvar _ftp_putAs _ftp_remDir+"/" endif # create FTP's $stdin temp file for this file transfer echo >ftpin OPEN !remotesystem if not _ftp_useNetrc then echo >>ftpin USER !_ftp_user !_ftp_pass endif echo >>ftpin :setvar _ftp_loginErr FTPLASTERR echo >>ftpin PASSIVE if _ftp_remSysT <> "MPE/IX" then echo >>ftpin BYTESTREAM endif # encrypt file? setvar _ftp_did_crypt false if !encrypt and & pos("ASCII",setvar(_ftp_fopts,finfo(_ftp_file,'fmtfopt'))) > 0 and & finfo(_ftp_file,'eof') > 0 then # add the suffix ".enc" and encrypt the file in the CWD. However, # since some of the file xfers will be from/to MPE groups, limit the # encrypted file's name the key file's name to 16 characters. setvar _ftp_encF "./"+lft(_ftp_baseN,16-4)+".enc" setvar _ftp_keyF "./"+lft(_ftp_baseN,16-4)+".key" # create key based on MPE file properties setvar _ftp_key & decimal(finfo(_ftp_file,'eof'))+ & decimal(setvar(_ftp_rsize,finfo(_ftp_file,'recsize')))+ & decimal(finfo(_ftp_file,'bytefilesize')) echo ** encrypting file : !_ftp_file # set up the file equations necessary to get crypt to work correctly - # see IO redirection note near the end of this script. file cryptin=!_ftp_file,old file cryptout=!_ftp_encF;rec=-1,,b,ascii;disc=2147483647 setvar hpcierr 0 setjcw CJCW 0 continue xeq crypt.hpbin.sys "!_ftp_key" <*cryptin >*cryptout if not (setvar(_ftp_did_crypt,& (CJCW=0 and HPCIERR=0 and finfo(_ftp_encF,'exists')))) then echo *** Error: encryption of !_ftp_file failed... escape endif setvar _ftp_cryptCnt _ftp_cryptCnt+1 # write the key to the temp key file echo !_ftp_key >!_ftp_keyF !_ftp_dbg ++ Note: key=!_ftp_key, written to file !_ftp_keyF # append the the FTP stdin file to 'put' the files echo >>ftpin PUT !_ftp_keyF !_ftp_putAs!_ftp_keyF echo >>ftpin PUT !_ftp_encF !_ftp_putAs!_ftp_encF echo >>ftpin :setvar _ftp_xferErrMsg FTPLASTREPLY if _ftp_remSysT = "MPE/IX" then # special case where source and target systems are MPE. # The goal is to be able to automatically decrypt, on the remote # system, the file just FTP'd over. To do this we do the following: # 1) xfer the crypt pgm in case not present on remote system (note # if the remote sys has crypt this step is skipped), # 2) create a jobstream (JCL) file which decrypts the file, # 3) xfer this jobstream file, # 4) execute this jobstream via FTP's 'site stream' command. if not !remSysHasCrypt then echo >>ftpin PUT !_ftp_cryptF !"_ftp_putAs"CRYPT01 endif echo >>ftpin PUT jdecrypt !"_ftp_putAs"JDECRYPT echo >>ftpin SITE STREAM !"_ftp_putAs"JDECRYPT echo >>ftpin :setvar _ftp_streamMsg FTPLASTREPLY # create stream job to be sent to the remote system and # executed there via SITE STREAM. xeq !hpfile !localfiles, !remotesystem ;entry=job >jdecrypt endif else # no encryption done !_ftp_dbg ++ Note: !_ftp_file not encrypted echo >>ftpin PUT !_ftp_file !_ftp_putAs!_ftp_baseN echo >>ftpin :setvar _ftp_xferErrMsg FTPLASTREPLY endif # **** do the actual ftp file transfer **** # **** **** echo >>ftpin QUIT echo ** transferring file: !_ftp_file continue xeq ftp.arpa.sys ftplist if (FTPXFERFILES > 0) and (FTPREQFILES = FTPXFERFILES) then # requested number of files were transferred. However, for MPE remote # system's SITE STREAM could have failed, eg. netrc logon worked but, # by omitting the 'remoteuser' parm, the default SFTPPUT logon was # wrong. If _sftp_debug=true a note to this effect has been displayed. !_ftp_dbg ++ Note: transfer of !_ftp_file successful setvar _ftp_xfer _ftp_xfer+1 if FTPLASTERR = -76 then # Assume remote system is MPE since "stream" is the only 'site' # command used. FTP returns error -76 for site stream errors and # warnings. We will ignore warnings, as should FTP/iX. An error vs. # warn is determined by examining FTPLASTREPLY looking for "CIERR". if pos("(CIERR ",_ftp_streamMsg) > 0 then echo echo *** SITE STREAM failed on remote system, therefore file echo "!_ftp_encF" remains encrypted on "!remotesystem". if _ftp_useNetrc then echo FTP logon is via NETRC. echo Decrypting job logon is "!_ftp_user". See below: else # don't know how this code is reached: the files were all # xfer'd meaning FTP logged on, meaning the 'remoteuser' parm # is good enough for FTP but not good enough for MPE stream?? echo NETRC not used. echo FTP and decrypting job logon is "!_ftp_user. See & below: endif echo print jdecrypt;end=3 echo . . . echo The local FTPLIST temp file contains more information. echo # Try to purge the remote copy of jdecrypt, if it contains # passwords, but note that jdecrypt could be deleted by itself, # or by another instance of this script. if not (_ftp_u_pwd = "" and _ftp_a_pwd = "") then # FTP login back to the remote system to delete jdecrypt. # Use new temp files for ftp in/out to preserve the original # ftpin and ftplist since the user may want to debug the # problem. echo > ftpin1 EXITONERROR echo >>ftpin1 OPEN !remotesystem if not _ftp_useNetrc then echo >>ftpin1 USER !_ftp_user !_ftp_pass endif echo >>ftpin1 PASSIVE echo >>ftpin1 DELETE !"_ftp_putAs"JDECRYPT echo >>ftpin1 BYE continue xeq ftp.arpa.sys ftplist1 ## and it worked or it didn't -- that's it. purge ftpin1;temp purge ftplist1;temp #else, no password in jdecrypt, but still a fatal stream error endif escape #else, 'site stream' CIWARN only, ignore endif endif if FTPLASTERR <> 0 and not (_ftp_dbg = '#') then # some non-fatal situation... echo ++ Note: successful transfer, however FTPLASTERR=!ftplasterr & and the echo following FTP messages were received: echo XFER: !_ftp_xferErrMsg echo STREAM: !_ftp_streamMsg echo Print the local FTPLIST file for more info. endif else # FTP connection or transferm error... echo echo *** Error transferring file: !_ftp_file if _ftp_did_crypt then echo (actual file for FTP 'put' is: !_ftp_encF) endif if FTPLASTERR = -8 or FTPLASTERR = -9 or FTPLASTERR = -66 then echo *** FTP error ![-ftplasterr]: cannot connect to & "!remotesystem" . escape elseif FTPLASTERR = -65 or _ftp_loginErr = -65 then echo *** FTP error 65: invalid user ID or password. escape elseif pos('pathname specified does not exist.',_ftp_xferErrMsg) > 0 & then # remote dir/group name is not valid, so all xfers will fail... echo *** Remote directory !_ftp_PutAs is invalid. escape # ok to continue with the script even with this xfer error elseif not (_ftp_dbg = '#') then echo FTP $stdlist follows: pause 2 echo ... print ftplist;start=-10 echo if _ftp_cnt > 0 then echo continuing... echo endif endif endif if _ftp_dbg = '#' then # clean up temp files if _ftp_did_crypt then # delete the local encrypted and key files purge !_ftp_encF;temp purge !_ftp_keyF;temp if _ftp_remSysT = "MPE/IX" then # delete the stream job JCL file purge jdecrypt;temp endif endif # delete the local ftp stdin/list files purge ftpin;temp purge ftplist;temp endif endwhile # report some stats echo echo ===================================================== if _ftp_xfer = 1 then echo 1 file transferred successfully. else echo !_ftp_xfer files transferred successfully. endif if _ftp_xfer <> _ftp_total then echo *** Error: ![_ftp_total-_ftp_xfer] out of !_ftp_total files not & transferred. endif if _ftp_cryptCnt = 1 then echo 1 file was encrypted. else echo !_ftp_cryptCnt files were encrypted. endif echo # delete crypt01 file, if created. purge crypt01 >$null return elseif '!entry' = 'job' then # The 'job' entry point creates a job stream to be executed on the remote # MPE system. This job's main purpose is to automatically decrypt the # encrypted file just FTP'd across. STDLIST has been redirected to the # name of the job stream(JCL) file. # echo !!job JDECRYPT,!_ftp_u/!_ftp_u_pwd.!_ftp_a/!_ftp_a_pwd!_ftp_logonGrp;& outclass=,2 echo !# This job was created by !hpfile to decrypt file echo !# !_ftp_file sent from !hpsysname at IP: !hplocipaddr. echo !# Job create time: !hpdatef !hptimef echo !# Job created by user: !hpuser.!hpaccount echo !# echo !# always purge this job since it may contain passwords. echo !!purge jdecrypt !>$null echo !# echo !!if not finfo("!_ftp_encF","exists") then echo ! continue echo ! tell !_ftp_user; Encrypted file !_ftp_encF missing. Job stopped. echo ! escape 1 echo !!endif echo !!setvar _decryptf "./"+basename("!_ftp_encF",".enc")+".dec" echo !!echo Decrypting !_ftp_encF as !!_decryptf echo !!setvar _rootfile "./!_ftp_baseN" echo !# remember FTP overwrites the target file, if it exists echo !!purge !!_rootfile !>$null echo !# decrypt the file based on the same key in the key file echo !!input _key !*jcryout echo !!if not (CJCW=0 and HPCIERR=0 and & finfo(_decryptf,'exists')) then echo ! tell !_ftp_user; Decryption failed on !_ftp_encF. Job stopped. echo ! escape 3 echo !!endif echo !# save decrypted file for either FCOPY or the rename below echo !!purge !!_decryptf !>$null echo !!save !!_decryptf echo !# don't fcopy the file if it was a bytestream file to begin with. if pos('BYTESTREAM',_ftp_fopts) = 0 then # original file was not a bytestream file so ok to convert back to it's # original file properties. echo !# convert decrypted file from bytestream to fixed/variable file # fcopy FROM=file eq echo !!file fcin=!!_decryptf,old # fcopy TO=file eq, need to create rec= & disc= side of file eq echo !!file fcout=!!_rootfile,new & ;rec=!_ftp_rsize,,![lft(word(_ftp_fopts,,2),1)],ascii & ;disc=![finfo(_ftp_file,'limit')] & ;code=![finfo(_ftp_file,'fcode')] # note: don't need fcopy input "yes" file when run in batch for truncation # prompt. echo !!setvar HPCIERR 0 echo !!continue echo !!fcopy from=*fcin;to=*fcout !>$null echo !!if not (HPCIERR=0 and finfo(_rootfile,'exists')) then echo ! tell !_ftp_user; FCOPY failed on !!_decryptf. HPCIERR=!!hpcierr. & Job stopped. echo ! escape 4 echo !!endif echo !!purge !!_decryptf else # original file was BS, no fcopy but need the right final name. echo !!rename !!_decryptf, !!_rootfile echo !!echo rename !!_decryptf, !!_rootfile endif if _ftp_dbg = '#' then echo !# clean up echo !!purge !_ftp_encF echo !!purge !_ftp_keyF echo !!purge crypt01 !>$null else echo !# JDECRYPT cleanup skipped due to _SFTP_DEBUG=TRUE, therefore TEMP echo !# files have not been deleted. endif echo !!eoj return elseif '!entry' = 'help' then # The 'help' entry point displays help/usage text. # echo !_ftp_me transfers one or more files, via FTP/iX, to the specified remote echo system. Most commonly the file(s) will be encrypted prior to being echo transferred using the POSIX 'crypt' utility. echo echo Usage: echo !_ftp_me fileset, remoteSystem, remoteUser, remoteDir, echo encrypt, remoteSysType, remSysHasCrypt echo where: echo 'fileset' (required) a single file, a wildcarded fileset, or an indirect echo file (^filename) which can be supplied in MPE or POSIX syntax. echo The format for indirect files is one fully qualified file name per echo record with MPE or POSIX style names supported. Eg. F@, ./f#, echo /ACCT/dir/f2, ^ftplist, ^/ftp/ftplist. echo echo 'remotesystem' (required) the name or IP address of the system where the echo file is being transferred. The remote system can be all flavors of echo Unix, Windows or MPE, as long as the remote system can decrypt echo encrypted files via the POSIX crypt utility. The decryption is done echo automatically for MPE systems; whereas, non-MPE systems will need echo to run the crypt utility using the key which is transferred in its echo own file, "FileName.key". For a NETRC file to be used by FTP the echo machine name must match the 'remotesystem' parm name. echo echo 'remoteuser" - (sometimes optional) the user name which FTP will use to echo connect to the remote system. The syntax is: "username[:password]" or echo "username[/password]". To suppress password prompting the username echo should terminate with a ":" or "/", meaning a null password, eg. echo 'foo:'. For MPE remote systems the username field consists of echo "user.account". If passwords are embedded in MPE user names the echo format is: "user/upass.acct/apass" or "user.acct:upass,apass". If all echo passwords are omitted the user may be prompted for the passwords. echo The expected user response for MPE passwords is: "userpass,acctpass". echo echo NOTE: if a comma is used then the entire name needs to be quoted so echo that it is treated as a single token. echo echo NOTE: this parameter is optional if a NETRC file is present since echo NETRC provides automatic FTP logins without the need to specify user echo names and passwords. However, if the remote system is MPE and the echo file is encrypted, a job will be streamed, named JDECRYPT, to auto- echo matically decrypt the FTP'd file. This job needs to be able to logon echo to the remote MPE system and thus may need user and/or account pass- echo words. This SFTPPUT script has no access to passwords contained in a echo NETRC file. Therefore, in order for the JDECRYPT job to logon, either echo :JOBSECURITY must be set to allow the desired users to logon without echo passwords, or the passwords must be provided to this script. echo echo 'remotedir' - (optional) the name of the directory (or group.account) on echo the remote system where the file will be sent. Syntax: "/dir", echo "./dir" "../dir", "~user", "group.acct", or "group". If omitted the echo remote user's home directory is assumed. If can be useful to specify echo 'remotedir' even when the logon is done via NETRC. This allows the echo files to be transferred to a location other than the remote user's echo home directory/group. echo echo 'encrypt' - (optional) TRUE (default) means to encrypt text files. FALSE echo means no encryption. However, even if 'encrypt' is TRUE, only non- echo empty ASCII files will be encrypted. echo echo 'remoteSysT' - (optional) "MPE/iX", default, means the remote system is echo known to be an MPE system. "Unix" means the remote system is known to echo be a Unix system. '*' means the remote system type will be determined echo by this script, which is extra overhead. If the file is encrypted and echo the remote system is an MPE system then a job will be streamed on the echo remote system to decrypt the file and do some minor cleanup. echo echo 'remSysHasCrypt' - (optional) only applies when the remote system is MPE. echo TRUE (default) indicates that the remote system already has the crypt echo utility, and thus it does not need to be FTP'd across the wire. FALSE echo means the remote MPE system may not have Crypt, in which case, a echo non-PH version is FTP'd to the remote system, executed, and then echo removed. If the remote system is not MPE this parameter is ignored. echo echo If a CI variable named _SFTP_DEBUG is set to TRUE prior to executing echo this script, diagnostic information will be displayed to $STDLIST and echo the temp files and variables used by the script are kept. Otherwise, the echo script still displays errors and some useful information, and deletes all echo TEMP files and variables. echo return else # Invalid entry point echo *** Error: invalid entry '!entry'. echo Enter !_ftp_me with no parameters for help text. echo return endif ################ Version History and Notes #################### Notes on NETRC: the netrc file has the following format: machine "name" login "userName" password "userPass" If NETRC exists in the user's homegroup or if there's a file equation with "netrc.!hphgroup" on the left-hand side then FTP will read this file looking for the first entry which matches the 'remoteSystem' parm. The match must be exact. For instance if NETRC contains: machine "JOY.CUP.HP.COM" ... and the user enters ':FTP JOY', NETRC will be skipped because the machine names do not match. For matches, FTP will then login to the remote system using the username and password from the file. Even if a user name is provided directly to FTP (eg. via a redirected $stdin file) FTP quietly overrides this user name with the name and password in NETRC. It also appears that a password is required in the NETRC entry, otherwise the file is completely skipped. It is common for the NETRC file to deny all access except for eXecute in order to protect the clear text passwords. There is a case where if the remote system is MPE and the file is encrypted, a job will be streamed on the remote machine to automatically decrypt the file. This job needs to logon correctly to the remote 3000, which is easy if the 'remoteuser' parm is supplied. But, if NETRC is available then it dictates the remote user name, and the 'remoteuser' parm becomes optional and defaults to the user's user.acct. If the login name in NETRC differs from the user.acct of the person running this script then the 'remoteuser' parm must be specified and should match the login name in NETRC. Failure to do this could result in the remote MPE job logging on incorrectly. Eg. the current user does not have the same logon on the remote box, or the current user has a remote logon but their home group is different from where the file was transferred. To be safe, whenever NETRC is used, supply the 'remoteuser' parm and specify the same user name as found in the matching NETRC entry. It is recommended, when NETRC is used, to specify the remote user name without any embedded passwords. However, the JDECRYPT job needs to logon to the remote MPE box. If the specified 'remoteuser' user name requires a password, the JDECRYPT job can't logon unless SFTPPUT gets the required password. In this situation, either set :JOBSECURITY ;passexempt=max on the remote system, or interactively enter the passwords when prompted by the script. Notes on crypt: crypt requires PH capability to load, thus the group and account containing crypt must have PH -- it doesn't seem to matter if the user has PH or not. However, crypt does not NEED PH in order to run properly, it was just linked with PH to make life interesting... Thus, if crypt is copied locally, PH is removed, and this copy is sent to the remote system. Note on IO redirection: Crypt also has some strangeness around IO redirection. It appears that a redirected filename cannot contain a leading "./" or "/" when running crypt directly from the CI via an info= string. This may be an artifact of the C library as other programs in hpbin.sys have similar behavior. One solution is to run the shell with an input file which contains the crypt command. In this case the filename can be absolute pathnames. Another idea is to run the shell from the CI with a "-c crypt name2" but if "name1" or "name2" are absolute pathnames we get the same IO redirection mentioned in the 1st sentence above. The solution chosen saves a process create (the shell) and uses the CI's IO redirection via file equations which create bytestream files and allow absolute pathnames. Be CAREFUL if you change this part of the script! X.00 - Initial version based on scripts written by Murali. (JV) X.01 - uncommented the !EOJ line in the job and some minor cleanup. (JV) X.02 - some minor bug fixes based on testing in a "clean" group, improved summary reporting, strip quotes from prompted passwords, detect FTP error -66 indicating can't connect remote system. (JV) X.03 - fix test for crypt failing in temp job stream. Place ".enc" suffix file in /tmp/_PIN-filename.enc to avoid problems with longer filenames under an MPE group. (JV) X.04 - using PASSIVE ftp now to increase chances of transfer working across client firewalls, display script version ID, some ftp connection error fixes, changed previous versions to "X" since script is not ready for customers yet, redirect ftp stdlist to a TEMP file for better error messaging, which means no longer using /tmp/_PIN..., detect ftp xfer errors by comparing ftpxferfiles with ftpreqfiles variables due to ftp bug where >16 char filenames appear to be xfer'd to an MPE group (can't due to fname length) but they aren't -- no ftp error reported in vars or $stdlist. (JV) Note: this is not an ftp bug. It turns out that, even if you ftp CD to a different location, when you PUT an absolute pathname with no second name on the PUT line, FTP places the file in the location defined by the full pathname-- ignoring the CD. This is how ftp works on HP-UX too. X.05 - allow any string beginning with "mpe" to indicate the remote sys is MPE, replace frombyte with FCOPY to preserve source file attributes, created a 'job' entry to improve readability and increase performance. (JV) X.06 - don't call finfo to get 'recsize' twice, display encryption key for non- MPE remote systems, redirect fcopy output to $null to make spoolfiles less cluttered, detect bad remote dir and stop transfers, detects site stream error, no longer use EXITONERR (in order for these errors to be detectable), don't truncate ".enc" name for non-MPE remote systems. (JV) X.07 - minor spelling and help text fixes. (JV) X.08 - remotesysT now defaults to "mpe/ix", added new parm to indicate that crypt already remote system, per BT queen djg. (JV) X.09 - sftpput is now sensitive to the existence of the NETRC file which allows FTP to connect to the remote system without the user specifying a user name, and more importantly a password. Read the NETRC notes above. X.09 also fixes a bug where text/ASCII files were transferred to non-MPE systems via ASCII mode rather than bytestream mode, when the file has been encrypted. (JV) X.10 - fixed MPE job logon bug using netrc and no remoteuser parm. (JV) X.11 - no longer display the key to stdlist for non-MPE remote systems. Instead the key is transferred in its own file (non-encrypted). For remote MPE systems the key is read from the key file and used to automatically decrypt 'localfiles'. Also added the first external variable, _SFTP_DEBUG, which if present and set to TRUE, causes some diagnostic messages (including the key) to be written to $stdlist, and temp files and the _ftp_@ variables to be kept. (JV) A.00 - first non-beta version. Extra effort to make sure the jdecrypt job, which could contain passwords, is always deleted from the remote MPE system. Added more comments related to netrc and jdecrypt logons. (JV) A.01 - fixed bug where bad ftp connection was not detected adequately. (JV) A.02 - fixed bug where sftpput to non-MPE system, but remSysType was defaulted to "MPE/iX", the site stream command fails since the remote system is not MPE. Fix is to improve user name syntax and remSysT error handling. (JV) A.03 - fixed bug where HFS names under an MPE group between 13-16 bytes in length caused an illegal name to be formed, e.g.: "./f2345678901234.enc". This breaks CRYPT which uses the long name as an output file. (JV) A.04 - fixed problem where FTP allows a user to specify a password (to connect) when none is required, but FTP returns an error when SITE STREAM returns a CI warning indicating that the same password was ignored. Use FTPLASTREPLY in this case. (JV) A.05 - moved code to deal with FTP error -76 (site command error) to where we detect ftpreqfiles=ftpxferfiles (all files xfer'd). Fixes a problem where the FTP connects fine to the remote system (via netrc), but the 'remoteuser' parm is omitted and the default doesn't work, so site stream correctly fails but sftpput reports all ok. (JV) A.06 - support of an indirect file (^filename) for parm 1. (JV)