*DECK FCSFFTS 
USETEXT TEXTFCS;
      FUNC FCSFFTS (FTPCMD1, FTPPAR1, FTPCMD2, FTPPAR2) B;
*CALL COPYRITE
# TITLE FCSFFTS - PROCESS FTP FILE TRANSFER SEQUENCE.                  #
  
      BEGIN                            # FCSFFTS                       #
  
# 
**    FCSFFTS - PROCESS FTP FILE TRANSFER SEQUENCE. 
* 
*     C. J. RAMSAY                     87/11/03 
* 
*     THIS PROCEDURE PROCESSES AN FTP FILE TRANSFER SEQUENCE. 
* 
*     FUNC FCSFFTS (FTPCMD1, FTPPAR1, FTPCMD2, FTPPAR2) 
* 
*     ENTRY   FTPCMD1    = FTP COMMAND TO SEND TO LOCAL HOST. 
*             FTPPAR1    = PARAMETER BLOCK ASSOCIATED WITH FTPCMD1. 
*             FTPCMD2    = FTP COMMAND TO SEND TO REMOTE HOST.
*             FTPPAR2    = PARAMETER BLOCK ASSOCIATED WITH FTPCMD2. 
*             MBXX       = FILE TRANSFER MBT ENTRY INDEX. 
* 
*     EXIT    FCSFFTS    = TRUE IF COMMAND SEQUENCE COMPLETED OK. 
*             FCSFFTS    = FALSE IF COMMAND SEQUENCE NOT COMPLETED OK.
*             FTPUSERE   = TRUE IF USER ERROR DETECTED. 
*             FTPERROR   = TRUE IF PROTOCOL ERROR DETECTED. 
*             FTPFAIL    = TRUE IF COMMAND FAILURE DETECTED.
* 
*     METHOD  REWIND THE LOCAL FILE.
*             CHECK LOCAL FILE DEVICE TYPE. 
*             SET UP DATA CONNECTION. 
*             LOAN LOCAL FILE FNT ENTRY TO *FTPI*.
*             WAIT FOR FNT LOAN TO *FTPI* TO COMPLETE.
*             SEND FTP COMMAND WITH PARAMETERS TO LOCAL HOST. 
*             WAIT FOR INTERMEDIATE REPLY FROM LOCAL HOST.
*             SEND FTP COMMAND WITH PARAMETERS TO REMOTE HOST.
*             SET UP APPLICATION ABORT CONDITIONS.
*             WAIT FOR FINAL REPLIES FROM BOTH HOSTS. 
*             RETURN LOCAL FILE FNT ENTRY FROM *FTPI*.
*             SET UP APPLICATION ABORT CONDITIONS.
*             WAIT FOR FNT LOAN TO *FTPI* TO COMPLETE.
*             REWIND THE LOCAL FILE.
*             UPDATE FTP STATE IF CLOSED DURING FILE TRANSFER.
* 
# 
  
# 
****  FUNC FCSFFTS - XREF LIST
# 
      XREF
        BEGIN 
        PROC ABORT;                    # ABORT JOB                     #
        PROC FCSNODB;                  # OUTPUT DATA BLOCK             #
        PROC FCSNOSM;                  # OUTPUT SUPERVISORY MESSAGE    #
        PROC FCSNWFR;                  # WAIT FOR FTP REPLY            #
        PROC FCSNWFS;                  # WAIT FOR FTP STATE            #
        PROC FCSOWOF;                  # WRITE TO OUTPUT FILE          #
        PROC FCSUCRE;                  # COPY FTP REPLY TO ERROR BUFFER#
        PROC FSTATUS;                  # CHECK IF LOCAL FILE EXISTS    #
        PROC MESSAGE;                  # DISPLAY / DAYFILE A MESSAGE   #
        PROC NETUCAC;                  # COPY AN ASCII CHARACTER       #
        PROC NETUCAS;                  # COPY AN ASCII STRING          #
        PROC RECALL;                   # WAIT TILL OPERATION COMPLETES #
        PROC REWIND;                   # REWIND A FILE                 #
        END 
# 
****
# 
      ARRAY FTPCMD1 [00:00] S(1); 
        BEGIN                          # FTP COMMAND TO LOCAL HOST     #
        ITEM CMDC1       U(00,00,60);  # FIRST WORD REFERENCE          #
        ITEM CMDL1       U(00,52,08);  # COMMAND LENGTH IN OCTETS      #
        END 
      ARRAY FTPPAR1 [00:00] S(PARSIZ$); 
        BEGIN                          # PARAMETERS WITH LOCAL COMMAND #
        ITEM PARP1       U(00,00,60);  # FIRST WORD REFERENCE          #
        ITEM PARS1       U(S$,00,60);  # PARAMETER LENGTH IN OCTETS    #
        END 
      ARRAY FTPCMD2 [00:00] S(1); 
        BEGIN                          # FTP COMMAND TO REMOTE HOST    #
        ITEM CMDC2       U(00,00,60);  # FIRST WORD REFERENCE          #
        ITEM CMDL2       U(00,52,08);  # COMMAND LENGTH IN OCTETS      #
        END 
      ARRAY FTPPAR2 [00:00] S(PARSIZ$); 
        BEGIN                          # PARAMETERS WITH REMOTE COMMAND#
        ITEM PARP2       U(00,00,60);  # FIRST WORD REFERENCE          #
        ITEM PARS2       U(S$,00,60);  # PARAMETER LENGTH IN OCTETS    #
        END 
  
      ITEM I             I;            # LOOP INDUCTION VARIABLE       #
      ITEM L             I;            # CHARACTER INDEX               #
      ITEM LOCDONE       B;            # LOCAL COMPLETION FLAG         #
      ITEM REMDONE       B;            # REMOTE COMPLETION FLAG        #
      ITEM SIND          I;            # SOURCE INDEX                  #
      ITEM SPACE         U = X"200000000000000";
  
      ARRAY THISCHAR [00:00] S(1);     # CURRENT CHARACTER             #
        BEGIN 
        ITEM THISCHR     U(00,00,08); 
        END 
  
      ARRAY ETTMSG [00:00] S(7);
        BEGIN 
        ITEM  ETT$TEXT   C(00,00,60) =
       ["--ERROR--  LOCAL FILE SPECIFIED IS ASSIGNED TO THE TERMINAL."];
        ITEM  ETT$ZBYTE  U(06,00,60) = [0]; 
        END 
  
      ARRAY BEGFTS [00:00] S(4);
        BEGIN 
        ITEM  BFT$TEXT   C(00,00,34) =
       [" FTP BEGIN FILE TRANSFER SEQUENCE."];
        ITEM  BFT$ZBYTE  U(03,24,36) = [0]; 
        END 
  
      ARRAY ENDFTS [00:00] S(4);
        BEGIN 
        ITEM  EFT$TEXT   C(00,00,37) =
       [" FTP FILE TRANSFER SEQUENCE COMPLETE."]; 
        ITEM  EFT$ZBYTE  U(03,42,18) = [0]; 
        END 
      CONTROL EJECT;
      PROC FCS2IFL; 
      BEGIN                            # FCS2IFL                       #
# 
**    THIS EMBEDDED PROCEDURE INITIATES THE LOANING OF THE LOCAL
*     FILE FNT ENTRY TO *FTPI*. 
# 
      FTPSTATE   = FTPUFILE;           # STATE NOW TRANSFER IN PROGRESS#
      P<APSM>    = LOC(OUTBUF);        # BASE SUPERVISORY MESSAGE PTR  #
      SPMSG0[0]  = 0;                  # CLEAR FIRST WORD              #
      SPMSG1[0]  = 0;                  # CLEAR SECOND WORD             #
      FNTFILE[0] = MBT$LFN[MBXX];      # STORE LOCAL FILE NAME         #
      FNTFNTO[0] = MBT$FNTO[MBXX];     # STORE FNT ORDINAL             #
      FCSNOSM (FNTIFL, LFNTS);         # SEND FNT/IFL/R SM             #
      MBT$STAT[MBXX] = 1;              # CLEAR STATUS + SET COMPLETION #
      MBT$FNTO[MBXX] = 0;              # CLEAR FNT ORDINAL IN FET      #
  
      RETURN;                          # RETURN TO CALLER              #
  
      END                              # FCS2IFL                       #
      CONTROL EJECT;
      PROC FCS2IFR; 
      BEGIN                            # FCS2IFR                       #
# 
**    THIS EMBEDDED PROCEDURE INITIATES THE RETURNING OF THE LOCAL
*     FILE FNT ENTRY FROM *FTPI*. 
# 
      FCSNWFS (FTPULENT);              # ENSURE *FTPI* HAS FNT ENTRY   #
      P<APSM>    = LOC(OUTBUF);        # BASE SUPERVISORY MESSAGE PTR  #
      SPMSG0[0]  = 0;                  # CLEAR FIRST WORD              #
      SPMSG1[0]  = 0;                  # CLEAR SECOND WORD             #
      FCSNOSM (FNTIFR, LFNTS);         # SEND FNT/IFR/R SM             #
  
      RETURN;                          # RETURN TO CALLER              #
  
      END                              # FCS2IFR                       #
      CONTROL EJECT;
# 
*     START MAIN PROCEDURE
# 
      REWIND (MBT[MBXX]);              # REWIND THE FILE               #
      RECALL (MBT[MBXX]);              # WAIT TILL OPERATION COMPLETES #
      IF MBT$DT[MBXX] EQ "TT" 
      THEN
        BEGIN                          # FILE ASSIGNED TO TERMINAL     #
        FCSOWOF (ETTMSG[0], INTERNAL$);# WRITE MESSAGE TO OUTPUT FILE  #
        FTPUSERE = TRUE;               # SET USER ERROR FLAG           #
        FCSFFTS  = FALSE;              # RETURN FALSE TO CALLER        #
        RETURN;                        # GET OUT OF HERE QUICKLY       #
        END 
  
      MESSAGE (BEGFTS[0], 1);          # DISPLAY START MESSAGE         #
# 
*     INITIATE LOAN OF LOCAL FILE FNT ENTRY TO *FTPI*.
*     IF PORT COMMANDS ARE TO BE USED THEN THE LOANING OF THE FNT 
*     ENTRY IS OVERLAPPED WITH SETTING UP THE DATA CONNECTION.
*     SEND A *PASV* COMMAND TO THE LOCAL HOST, AND PROCESS ITS REPLY. 
# 
      FTPCLOSED = FALSE;               # RESET CLOSED DURING TRANSFER  #
  
      IF FTPPORTM EQ OPTOFF$
      THEN
        BEGIN                          # USAGE OF PORT COMMANDS OFF    #
        FCS2IFL;                       # INITIATE LOAN OF FNT ENTRY    #
        END 
      ELSE
        BEGIN                          # USAGE OF PORT COMMANDS ON     #
        OUTLEN = AIPIHDR$;             # INITIALIZE OUTPUT LENGTH      #
        NETUCAS (FTPCPASV, 0, 4,
                 OUTBUF, OUTLEN);      # COPY *PASV* FTP COMMAND       #
        FCSNODB (AIPISC, LOCALID);     # SEND TO LOCAL HOST            #
        FCSNWFR (LOCALID);             # WAIT FOR RESPONSE             #
        IF FTPREPLY NQ 227
        THEN
          BEGIN                        # NOT ENTERING PASSIVE MODE     #
          FCSUCRE;                     # COPY FTP REPLY TO ERROR BUFFER#
          FTPERROR = TRUE;             # SET FTP ERROR FLAG            #
          FCSFFTS  = FALSE;            # RETURN FALSE TO CALLER        #
          RETURN;                      # GET OUT OF HERE QUICKLY       #
          END 
# 
*     SEND PORT NUMBER RETURNED TO THE REMOTE HOST VIA AN FTP *PORT*
*     COMMAND.
# 
        OUTLEN = AIPIHDR$;             # INITIALIZE OUTPUT LENGTH      #
        NETUCAS (FTPCPORT, 0, 4,
                 OUTBUF, OUTLEN);      # COPY *PORT* FTP COMMAND       #
        NETUCAC (SPACE, 0,
                 OUTBUF, OUTLEN);      # COPY ASCII SPACE              #
        THISCHR = ASCISPACE;           # CURRENT CHARACTER A SPACE     #
        FOR SIND = 4 STEP 1 
          WHILE THISCHR NQ ASCILPAREN DO
          BEGIN                        # LOOP TILL LEFT PARENTHESIS    #
          L = 0;
          NETUCAC (LRB[0], SIND,
                   THISCHAR, L);       # GET NEXT CHARACTER            #
          END 
        FOR SIND = SIND STEP 1
          WHILE THISCHR NQ ASCIRPAREN DO
          BEGIN                        # COPY ALL CHARS OF PORT ADDRESS#
          L = 0;
          NETUCAC (LRB[0], SIND,
                   THISCHAR, L);       # GET NEXT CHARACTER            #
          IF THISCHR NQ ASCIRPAREN
          THEN
            BEGIN 
            NETUCAC (THISCHAR, 0, 
                     OUTBUF, OUTLEN);  # COPY CHARACTER OF PORT ADDRESS#
            END 
          END 
        FCSNODB (AIPISC, REMOTEID);    # SEND TO REMOTE HOST           #
        FCS2IFL;                       # INITIATE LOAN OF FNT ENTRY    #
        FCSNWFR (REMOTEID);            # WAIT FOR RESPONSE             #
# 
*     PROCESS REPLY TO FTP *PORT* COMAND. 
# 
        IF (FTPRPYC1 EQ 1) OR 
           (FTPRPYC1 EQ 3)
        THEN
          BEGIN                        # PROTOCOL ERROR DETECTED       #
          FTPERROR = TRUE;             # SET FTP ERROR FLAG            #
          FCSUCRE;                     # COPY FTP REPLY TO ERROR BUFFER#
          FCS2IFR;                     # INITIATE FNT RETURN           #
          GOTO ENDFFTS;                # GET OUT OF HERE QUICKLY       #
          END 
        IF (FTPRPYC1 EQ 4) OR 
           (FTPRPYC1 EQ 5)
        THEN
          BEGIN                        # COMMAND FAILURE DETECTED      #
          FTPFAIL = TRUE;              # SET FTP FAILURE FLAG          #
          FCSUCRE;                     # COPY FTP REPLY TO ERROR BUFFER#
          FCS2IFR;                     # INITIATE FNT RETURN           #
          GOTO ENDFFTS;                # GET OUT OF HERE QUICKLY       #
          END 
        END 
# 
*     WAIT FOR FNT LOAN TO *FTPI* TO COMPLETE.
# 
      FCSNWFS (FTPULENT);              # WAIT TILL FILE IS LOANED      #
      FSTATUS (MBT[MBXX]);             # CHECK IF FILE EXISTS          #
      IF MBT$FSTAT[MBXX] NQ 0 
      THEN
        BEGIN                          # LOCAL FILE DOES EXIST         #
        FTPSTATE = FTPUOPEN;           # DONT RETRIEVE IN REPRIEVE     #
        FTPABORT = EUNLEND;            # SET UP ABORT CODE             #
        ABORT;                         # ABORT JOB                     #
        END 
# 
*     SEND FTP COMMAND WITH PARAMETERS TO LOCAL HOST AND WAIT FOR 
*     INTERMEDIATE REPLY FROM LOCAL HOST. 
# 
      OUTLEN = AIPIHDR$;               # INITIALIZE OUTPUT LENGTH      #
      NETUCAS (FTPCMD1[0], 0, CMDL1[0], 
               OUTBUF, OUTLEN);        # COPY FTP COMMAND              #
      NETUCAC (SPACE, 0,
               OUTBUF, OUTLEN);        # COPY ASCII SPACE              #
      NETUCAS (FTPPAR1[0], 0, PARS1[0], 
               OUTBUF, OUTLEN);        # COPY PARAMETERS               #
      FCSNODB (AIPISC, LOCALID);       # SEND TO LOCAL HOST            #
      FCSNWFR (LOCALID);               # WAIT FOR FTP REPLY            #
      IF (FTPRPYC1 EQ 2) OR 
         (FTPRPYC1 EQ 3)
      THEN
        BEGIN                          # PROTOCOL ERROR DETECTED       #
        FTPERROR = TRUE;               # SET FTP ERROR FLAG            #
        FCSUCRE;                       # COPY FTP REPLY TO ERROR BUFFER#
        FCS2IFR;                       # INITIATE FNT RETURN           #
        GOTO ENDFFTS;                  # GET OUT OF HERE QUICKLY       #
        END 
      IF (FTPRPYC1 EQ 4) OR 
         (FTPRPYC1 EQ 5)
      THEN
        BEGIN                          # COMMAND FAILURE DETECTED      #
        FTPFAIL = TRUE;                # SET FTP FAILURE FLAG          #
        FCSUCRE;                       # COPY FTP REPLY TO ERROR BUFFER#
        FCS2IFR;                       # INITIATE FNT RETURN           #
        GOTO ENDFFTS;                  # GET OUT OF HERE QUICKLY       #
        END 
# 
*     SEND FTP COMMAND WITH PARAMETERS TO REMOTE HOST.
# 
      OUTLEN = AIPIHDR$;               # INITIALIZE OUTPUT LENGTH      #
      NETUCAS (FTPCMD2[0], 0, CMDL2[0], 
               OUTBUF, OUTLEN);        # COPY FTP COMMAND              #
      IF PARS2[0] NQ 0
      THEN
        BEGIN                          # PARAMETERS WITH FTP COMMAND   #
        NETUCAC (SPACE, 0,
                 OUTBUF, OUTLEN);      # COPY ASCII SPACE              #
        NETUCAS (FTPPAR2[0], 0, PARS2[0], 
                 OUTBUF, OUTLEN);      # COPY THE PARAMETERS           #
        END 
      FCSNODB (AIPISC, REMOTEID);      # SEND TO REMOTE HOST           #
# 
*     SET UP APPLICATION ABORT CONDITIONS.
# 
      P<APSM>    = LOC(OUTBUF);        # BASE SUPERVISORY MESSAGE PTR  #
      SPMSG0[0]  = 0;                  # CLEAR FIRST WORD              #
      SACSHCD[0] = TRUE;               # ABORT ON SHUT/INSD            #
      SACINCD[0] = FALSE;              # DO NOT ABORT ON FC/INAC       #
      SACCBCD[0] = TRUE;               # ABORT ON CON/CB               #
      FCSNOSM (SACNCL, LSAC);          # SEND SAC/NCL SM               #
# 
*     WAIT FOR FINAL REPLIES FROM BOTH HOSTS. 
# 
      LOCDONE = FALSE;                 # WAIT FOR LOCAL COMPLETION     #
      REMDONE = FALSE;                 # WAIT FOR REMOTE COMPLETION    #
      FOR I = 0 
        WHILE (NOT LOCDONE) OR
              (NOT REMDONE) DO
        BEGIN                          # LOOP FOR LOCAL AND REMOTE     #
        FCSNWFR (EITHERID);            # WAIT FOR FTP REPLY            #
        IF (FTPRPYC1 EQ 3)
        THEN
          BEGIN                        # FTP ERROR DETECTED            #
          FTPERROR = TRUE;             # UPDATE ERROR FLAG             #
          FCSUCRE;                     # COPY FTP REPLY TO ERROR BUFFER#
          END 
        IF (FTPRPYC1 EQ 4) OR 
           (FTPRPYC1 EQ 5)
        THEN
          BEGIN                        # FTP FAILURE DETECTED          #
          FTPFAIL = TRUE;              # UPDATE FAILURE FLAG           #
          FCSUCRE;                     # COPY FTP REPLY TO ERROR BUFFER#
          END 
# 
*     WHEN THE LOCAL HOST IS FINISHED INITIATE THE RETURN OF LOCAL FILE 
*     FNT ENTRY AND SET UP APPLICATION ABORT CONDITIONS.
# 
        IF (FTPID EQ LOCALID) AND 
           (FTPRPYC1 NQ 1)
        THEN
          BEGIN                        # LOCAL HOST FINISHED           #
          LOCDONE = TRUE;              # SET LOCAL COMPLETION FLAG     #
          FCS2IFR;                     # INITIATE FNT RETURN           #
          P<APSM>    = LOC(OUTBUF);    # BASE SUPERVISORY MESSAGE PTR  #
          SPMSG0[0]  = 0;              # CLEAR FIRST WORD              #
          SACSHCD[0] = TRUE;           # ABORT ON SHUT/INSD            #
          SACINCD[0] = TRUE;           # ABORT ON FC/INAC              #
          SACCBCD[0] = TRUE;           # ABORT ON CON/CB               #
          FCSNOSM (SACNCL, LSAC);      # SEND SAC/NCL SM               #
          END 
# 
*     IF THE REMOTE HOST REPORTS AN ERROR AND WE HAVE NOT RECEIVED THE
*     FINAL REPLY FROM THE LOCAL HOST, THEN ABORT THE FILE TRANSFER 
*     SEQUENCE BY SENDING AN ABORT TRANSFER BLOCK TO THE LOCAL HOST.
# 
        IF (FTPID EQ REMOTEID) AND
           (FTPRPYC1 NQ 1)
        THEN
          BEGIN                        # REMOTE HOST FINISHED          #
          REMDONE = TRUE;              # SET REMOTE COMPLETION FLAG    #
          IF (NOT LOCDONE) AND
             (FTPRPYC1 NQ 2)
          THEN
            BEGIN                      # UNSUCCESSFUL COMPLETION       #
            OUTLEN = AIPIHDR$;         # INITIALIZE OUTPUT LENGTH      #
            FCSNODB (AIPIAT, LOCALID); # SEND ABORT TRANSFER TO LOCAL  #
            END 
          END 
        END 
# 
*     WAIT FOR FNT ENTRY TO BE RETURNED.
# 
  
ENDFFTS:  
  
      FCSNWFS (FTPUIDLE + FTPUOPEN);   # WAIT TILL FILE IS RETURNED    #
      FSTATUS (MBT[MBXX]);             # CHECK IF FILE EXISTS          #
      IF MBT$FSTAT[MBXX] EQ 0 
      THEN
        BEGIN                          # LOCAL FILE DOES NOT EXIST     #
        FTPABORT = EUNRETR;            # SET UP ABORT CODE             #
        ABORT;                         # ABORT JOB                     #
        END 
# 
*     REWIND THE LOCAL FILE.
# 
      REWIND (MBT[MBXX]);              # REWIND THE FILE               #
      RECALL (MBT[MBXX]);              # WAIT TILL OPERATION COMPLETES #
# 
*     UPDATE FTP STATE IF DISCONNECTED DURING FILE TRANSFER.
# 
      IF FTPCLOSED
      THEN
        BEGIN                          # REMOTE CONNECTION CLOSED      #
        FTPSTATE = FTPUIDLE;           # UPDATE FTP STATE              #
        END 
  
      MESSAGE (ENDFTS[0], 1);          # DISPLAY COMPLETE MESSAGE      #
  
      FCSFFTS = NOT (FTPERROR OR FTPFAIL);
  
      RETURN;                          # RETURN TO CALLER              #
  
      END                              # FCSFFTS                       #
  
      TERM
