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