Inside COBOL #40
by
Shawn Gordon
President
The Kompany

I was recently lurking in the HPSYS forum on CompuServe and picked up a thread on having your programs talk to FTP. Craig Engel responded with a little program he had written to do just such a thing, and received a bunch of requests for

it, including one from me. Craig’s program was specifically desinged for an application he was working on, so I ripped it apart and made a generic utility out of it. Turned out this was a timely bit of technology for a project I was

working on.

What’s the point of all this you may ask. First a little background for those of you who don’t know what I’m talking about. FTP stands for File Transfer Protocol, and is one of the older protocols on the Intnet for transferring files.

HP started bundeling FTP on the HP a while back, it’s kind of nice because you can use it as both a client and server FTP process, not to mention it is blazingly fast on your local network, I can transfer 10 Meg of data in about 20

seconds.

Since FTP is a standard protocol, that means you can have an FTP server running on your Netware server, NT server, Unix server, whatever, and be able to easily transfer files from your HP to any of these other environments. The only real

drawback is that you have to sit and run the FTP client and pass all the information. The idea to this utility is that it will read a file that contains a file name that you want to transfer, read the destination information out of a

config file, and then send it off to the program featured here, which will then feed it to FTP. These means you can automatically, and programmatically ship stuff around your network very easily.

Let’s talk about the config file that FTPSCHED will use, figure 1 has an example. I am only going to care about the first line, so the rest is documentation. My notes in the file should explain everything that is required from the

config file.

This program has everything in it. We are using macros, we are getting JCW’s, we are using intrinsics to do timed reads on message files. We are use the HPCICOMMAND intrinsic to run another program as a child process while passing

parameters to it’s STDIN via I/O redirection. This program is filled with lots of little tricks that can be used in other programs. One of the things I do here that I started some years ago, is use a JCW in conjunction with a macro to

get run time statistics. The advantage to this method is that it can be applied to sub-programs, and programs that are ‘created’ from other programs where you can’t set a run PARM to use standard debugging techniques. It can be placed
anywhere in the program, and set up to display anything.

One of the things I stripped out of this example, was that we wanted to purge the file on the host after the FTP ran, so there was a series of code to save the access date on each file, and compare to the current, once it was exceeded,

and we passed a P flag in the message file, I would purge the file on the host. I had to strip the code due to size constraints.

The only real change I would make to this program is to allow you to send an overriding destination node inside FTPIN with the file name, but this is more applicable in a multi node environment.

I hope you enjoyed our little foray into the Internet. I’m not really sure what I am going to do next month, but it might have something to do with carriage control.

Figure 1

print ftpcon.data.smga
PRODUCTION          FTPSCHED,MANAGER.SYS ,TRASH
*Only the first line of this file will be read, the first 20
*bytes should contain the IP address, or node name as defined
*in HOSTS.NET.SYS to connect too.  From byte 21 to 70 it should
*contain the complete logon name and password for that node.
*This will be read by FTPSCHED.PROG.SMGA everytime it goes
*to launch a new instance of FTP.  This allows you to change
*the destination without bringing down the server.
*To shut down the server explicitly just put the string SHUTDOWN
*in FTPPIPE.DATA.  this file MUST be 72 bytes wide.


Figure 2

$CONTROL BOUNDS,POST85,USLINIT
 IDENTIFICATION DIVISION.
 PROGRAM-ID.     FTPSCHED.
 AUTHOR.         Shawn M. Gordon.
 DATE-WRITTEN.   THU, FEB 27, 1997.
 DATE-COMPILED.
******************************************************************
*                          Program Description                   *
*----------------------------------------------------------------*
*  Program reads message file, picks up additional data from     *
*  config file.  It will pause for 5 minutes so as to group as   *
*  many transactions into a single create as possible.  We then  *
*  FTP the files to the IP address found in the config file.     *
******************************************************************
*                           Compilation Data                     *
*----------------------------------------------------------------*
*   CAP=PH                                                       *
******************************************************************
*                           Record of Changes                    *
*----------------------------------------------------------------*
*                                                                *
*  mm/dd/yy  xxx  Initial Installation.                          *
******************************************************************

 ENVIRONMENT DIVISION.
 CONFIGURATION SECTION.
 SOURCE-COMPUTER. HP3000 WITH DEBUGGING MODE.
 OBJECT-COMPUTER. HP3000.

 SPECIAL-NAMES.
    CONDITION-CODE IS CC.

 INPUT-OUTPUT SECTION.

 FILE-CONTROL.

    SELECT FTPCON ASSIGN TO "FTPCON.DATA.SMGA".
    SELECT FTPIN  ASSIGN TO "FTPIN.DATA.SMGA".

 DATA DIVISION.
***************************************************************
 FILE SECTION.
***************************************************************

 FD FTPCON
    RECORD CONTAINS 72 CHARACTERS.
 01 FTPCON-RECORD.
    03 FR-NODE                PIC X(20).
    03 FR-LOGON               PIC X(50).
    03                        PIC X(02).

 FD FTPIN
    RECORD CONTAINS 132 CHARACTERS.
 01 FTPIN-RECORD              PIC X(132).
*
 WORKING-STORAGE SECTION.

 01 FNUM                 PIC S9(4)  COMP VALUE 0.
 01 ERR                  PIC S9(4)  COMP VALUE 0.
 01 ERR-LEN              PIC S9(4)  COMP VALUE 80.
 01 ERR-PARM             PIC S9(4)  COMP VALUE 0.
 01 MSG-LEVEL            PIC S9(4)  COMP VALUE 0.
 01 P                    PIC S9(4)  COMP VALUE 0.
 01 S1                   PIC S9(4)  COMP VALUE 0.

 01 PIPE-FILE            PIC X(26)  VALUE "FTPPIPE.DATA.SMGA".
 01 ERR-MSG              PIC X(76)  VALUE SPACES.
 01 OUT-BUFF             PIC X(80)  VALUE SPACES.

 01 MSG-BUFF.
    03 MB-PURGE          PIC X      VALUE SPACES.
    03 MB-FROM-FILE      PIC X(26)  VALUE SPACES.
    03 MB-TO-FILE        PIC X(101) VALUE SPACES.
*
 01 COM-IMAGE.
    03 COMMAND-IMAGE     PIC X(79)  VALUE SPACES.
    03                   PIC X      VALUE %15.

 01 TRACE-JCW.
    03 TJ-NAME           PIC X(14)    VALUE "FTPSCHEDTRACE".
    03 TJ-VALUE          PIC S9(4)    COMP VALUE 0.
       88 STATS-ON                         VALUE 1.

 01 TIMER-JCW.
    03 TW-NAME           PIC X(15)  VALUE "FTPSCHEDTIMER".
    03 TW-TIMER          PIC S9(4)  COMP VALUE 0.

 01 JCW-STATUS           PIC S9(4)  COMP VALUE 0.
*
 PROCEDURE DIVISION.
$INCLUDE DEBUG.I
 FTPSCHED-SECT01                 SECTION 1.
 A0000-MACROS.
$DEFINE %COMIMAGE=
        MOVE
          !1
          TO COMMAND-IMAGE
        CALL INTRINSIC 'HPCICOMMAND' USING COM-IMAGE,
                                       ERR,
                                       ERR-PARM,
                                       MSG-LEVEL#
*
$DEFINE %STATS=
        IF STATS-ON
           DISPLAY !1
                   !2
        END-IF#

 A1000-MAIN.
     DISPLAY 'FTPSCHED Version 10.70227 '
             '(S.M.Gordon & Associates (C) 1997)'.
     CALL INTRINSIC "FINDJCW" USING TW-NAME, TW-TIMER, JCW-STATUS.
     IF JCW-STATUS = 3
        MOVE 600                  TO TW-TIMER
        DISPLAY 'JCW FTPSCHEDTIMER not found - defaulting to '
                '10 minute time out'
     ELSE
        DISPLAY 'FTPSCHEDTIME is set to ' TW-TIMER ' seconds'.

     CALL INTRINSIC 'FINDJCW' USING TJ-NAME, TJ-VALUE, JCW-STATUS.
     %STATS("Tracing is enabled"#).

     CALL INTRINSIC 'FOPEN' USING PIPE-FILE, %32105, %2340
                           GIVING FNUM.
     IF CC < 0
        DISPLAY 'Failed to open ' PIPE-FILE
        CALL INTRINSIC 'FCHECK' USING FNUM, ERR
        CALL INTRINSIC 'FERRMSG' USING ERR, OUT-BUFF, ERR-LEN
        DISPLAY OUT-BUFF
        DISPLAY 'FTPSCHED - ' OUT-BUFF UPON CONSOLE
        STOP RUN.
     %STATS("Successfully opened "#, PIPE-FILE#).

     CALL INTRINSIC "FCONTROL" USING FNUM, 4, TW-TIMER.
     IF CC <> 0
        DISPLAY 'Failed on FCONTROL 4'
        CALL INTRINSIC 'FCHECK' USING FNUM, ERR
        CALL INTRINSIC 'FERRMSG' USING ERR, OUT-BUFF, ERR-LEN
        DISPLAY OUT-BUFF
        STOP RUN.

     MOVE 1                     TO S1.
     CALL INTRINSIC "FCONTROL" USING FNUM, 45, S1.
     IF CC < 0
        DISPLAY 'Failed on FCONTROL 45'
        CALL INTRINSIC 'FCHECK' USING FNUM, ERR
        CALL INTRINSIC 'FERRMSG' USING ERR, OUT-BUFF, ERR-LEN
        DISPLAY OUT-BUFF
        DISPLAY 'FTPSCHED - ' OUT-BUFF UPON CONSOLE
        STOP RUN.
     %STATS("Extended waits have been enabled on "#, PIPE-FILE#).

     OPEN OUTPUT FTPIN.

 A2000-READ.
     %STATS("A2000-READ"#).
     MOVE SPACES               TO MSG-BUFF.
     CALL INTRINSIC 'FREAD' USING FNUM, MSG-BUFF, -128.
     IF CC < 0
        CALL INTRINSIC 'FCHECK' USING FNUM, ERR
* Our timed read timed out so do time out processing
        IF ERR = 22
           IF MSG-BUFF = SPACES
              GO TO A2000-READ
           END-IF
           PERFORM B1000-PROCESS  THRU B1000-EXIT
        ELSE
           CALL INTRINSIC 'FERRMSG' USING ERR, OUT-BUFF, ERR-LEN
           DISPLAY OUT-BUFF
           DISPLAY 'FTPSCHED - ' OUT-BUFF UPON CONSOLE
           STOP RUN.

 A2000-TAG.
     IF MSG-BUFF = SPACES
        GO TO A2000-READ.

     %STATS("OPEN INPUT FTPCON"#).
     OPEN INPUT FTPCON.

     READ FTPCON AT END DISPLAY "BAD END OF FILE ON FTPCON".

     %STATS(FTPCON-RECORD#).
     CLOSE FTPCON.

     MOVE SPACES               TO FTPIN-RECORD.
     STRING "OPEN " DELIMITED BY SIZE
            FTPCON-RECORD(1:20) DELIMITED BY SPACES
            INTO FTPIN-RECORD.
     WRITE FTPIN-RECORD.
     %STATS("WRITE"#).
     %STATS(FTPIN-RECORD#).

     MOVE SPACES               TO FTPIN-RECORD.
     STRING "USER " DELIMITED BY SIZE
            FTPCON-RECORD(21:50) DELIMITED BY SIZE
            INTO FTPIN-RECORD.
     WRITE FTPIN-RECORD.
     %STATS("WRITE"#).
     %STATS(FTPIN-RECORD#).

 A2000-LOOP.
     %STATS("A2000-LOOP"#).
     MOVE SPACES               TO FTPIN-RECORD.
     STRING "PUT " DELIMITED BY SIZE
            MB-FROM-FILE DELIMITED BY SPACES
            " " DELIMITED BY SIZE
            MB-TO-FILE DELIMITED BY SPACES
       INTO FTPIN-RECORD.
     WRITE FTPIN-RECORD.
     %STATS("WRITE"#).
     %STATS(FTPIN-RECORD#).

     MOVE SPACES               TO MSG-BUFF.
     CALL INTRINSIC 'FREAD' USING FNUM, MSG-BUFF, -128.
     IF CC < 0
        CALL INTRINSIC 'FCHECK' USING FNUM, ERR
* Our timed read timed out so do time out processing
        IF ERR = 22
           PERFORM B1000-PROCESS  THRU B1000-EXIT
           GO TO A2000-READ
        ELSE
           CALL INTRINSIC 'FERRMSG' USING ERR, OUT-BUFF, ERR-LEN
           DISPLAY OUT-BUFF
           DISPLAY 'FTPSCHED - ' OUT-BUFF UPON CONSOLE
           STOP RUN.

     IF MSG-BUFF = "SHUTDOWN"
        GO TO C9000-EOJ.

     GO TO A2000-LOOP.
 A2000-EXIT.
*
 B1000-PROCESS.
     %STATS("B1000-PROCESS"#).
     MOVE "CLOSE"              TO FTPIN-RECORD.
     WRITE FTPIN-RECORD.
     CLOSE  FTPIN.
     %COMIMAGE("RUN FTP.ARPA.SYS