home *** CD-ROM | disk | FTP | other *** search
/ The Best of Windows 95.com 1996 September / WIN95_09961.iso / mailsrv / LSV95.ZIP / win95.z / listlpun.memo < prev    next >
Text File  |  1995-05-24  |  36KB  |  1,032 lines

  1.              LISTSERV historical documentation, release 1.5m
  2.              -----------------------------------------------
  3.                      Copyright Eric Thomas 1986,1987
  4.  
  5.  
  6.  
  7.       +-----------------------------------------------------------+
  8.       |   Revised LISTSERV: LISTSERV-Punch Implementation Guide   |
  9.       +-----------------------------------------------------------+
  10.       |                                                           |
  11.       |       Document number: R01-007-0 (October 4th, 1987)      |
  12.       |                                                           |
  13.       |   Document fileid: "LISTLPUN MEMO"  (from "Info LPunch")  |
  14.       +-----------------------------------------------------------+
  15.  
  16.  
  17.  
  18.   Preface
  19.  
  20.  
  21.  
  22.   This  manual is a Reference Guide for application programmers who have
  23.   to implement the LISTSERV-Punch file transfer format  on  their  oper-
  24.   ating  system.    It  provides a complete technical description of the
  25.   LISTSERV-Punch format, along with a brief  summary  of  some  relevant
  26.   information about the CMS file system.  In addition, sample conversion
  27.   programs  in  PASCAL  and  C  are  provided  to assist the application
  28.   programmer in implementing a  satisfactory  LISTSERV-Punch  conversion
  29.   program on his system.
  30.  
  31.   NOTE: The  LISTSERV-Punch  file  transfer  format  was introduced with
  32.   release 1.4 of Revised LISTSERV.  Although the  LISTSERV-Punch  format
  33.   might  be expanded in the future to provide additional functions, full
  34.   upwards compatibility is warrantied  provided  that  the  user-written
  35.   conversion  program  strictly conforms to the standard defined in this
  36.   document.  Deviations from the norm (e.g. not ignoring  the  remainder
  37.   of the ID control card) might lead to problems with future releases of
  38.   LISTSERV.
  39.  
  40.  
  41.  
  42.   Conventions
  43.   -----------
  44.  
  45.   The  following  typographical conventions have been made in this docu-
  46.   ment to improve its readability:
  47.  
  48. | o   Recent changes in the publication are indicated by a vertical  bar
  49. |     in the left margin.
  50.  
  51. ! o   Intermediate  changes  between two releases of the document ("Pre-
  52. !     releases") are flagged with  an  exclamation  point  in  the  left
  53. !     margin.    Features described in this fashion should be considered
  54. !     as not documented and not officially supported until the  exclama-
  55. !     tion point is removed.
  56.  
  57. > o   Temporary   restrictions  or  circumventions  are  marked  with  a
  58. >     "greater than" sign in the left margin. This sign may also be used
  59. >     to signal obsolete features for which support will be  dropped  in
  60. >     the next release.
  61.  
  62.  
  63.  
  64.  
  65.  
  66.  
  67.  
  68.  
  69.   LISTSERV-PUNCH FORMAT DESCRIPTION
  70.   _________________________________
  71.  
  72.  
  73.  
  74.  
  75.  
  76.  
  77.   ****************
  78.   * Introduction *
  79.   ****************
  80.  
  81.  
  82.   The term "LISTSERV-Punch" refers to a "file transmission format" which
  83.   is  used  by LISTSERV when sending files larger than 80 characters per
  84.   record to computing systems which do not have the ability  to  process
  85.   Netdata, CARD DUMP or DISK DUMP format.  It was designed to accomodate
  86.   file  transmission  through mail-only gateways.   Its primary features
  87.   are:
  88.  
  89.   o   Ability to transfer files of any record length up to 65535 charac-
  90.       ters per record.  This limit is arbitrary and corresponds  to  the
  91.       longest string a high-level language compiler can usually handle.
  92.  
  93.   o   Ability  to transfer files without automatically padding or strip-
  94.       ping records of trailing blanks.   That is,  leading  or  trailing
  95.       blanks are not removed by the file transfer process itself.
  96.  
  97.   o   Simplicity of the decoding program.  Sample conversion programs in
  98.       PASCAL and C are provided at the end of this document.  The PASCAL
  99.       program was written and tested in about 45 minutes, and any PASCAL
  100.       programmer  should be able to adapt it very quickly to work on his
  101.       own system.
  102.       The C program should  work  unmodified  under  any  standard  UNIX
  103.       system,  but  might need to be improved to allow the specification
  104.       of input and output parameters  and/or  system-dependent  switches
  105.       for the various filing system calls.
  106.  
  107.   o   Acceptable  network efficiency: very little extra lines are gener-
  108.       ated, and trailing blanks are stripped before transmission.
  109.  
  110.   o   Possibility for a human reader  to  get  a  general  idea  of  the
  111.       contents  of  the  file  without  having to resort to a conversion
  112.       program.
  113.  
  114.  
  115.  
  116.  
  117.   ****************************
  118.   * Format of the INPUT file *
  119.   ****************************
  120.  
  121.  
  122.   A LISTSERV-Punch formatted file (also called  "card  deck",  with  the
  123.   term  "card"  being  used to refer to a 80-characters file record) has
  124.   the following outer aspect:
  125.  
  126.   +--------------------------------------------------------------------+
  127.   |    junk line                                                       |
  128.   |        .                                                           |
  129.   |        .                                                           |
  130.   |    junk line                                                       |
  131.   |                                                                    |
  132.   |   ID/ control card                                                 |
  133.   |                                                                    |
  134.   |    data line #1                                                    |
  135.   |        .                                                           |
  136.   |        .                                                           |
  137.   |    data line #n                                                    |
  138.   |                                                                    |
  139.   |   END/ control card                                                |
  140.   |                                                                    |
  141.   |    junk line                                                       |
  142.   |        .                                                           |
  143.   |        .                                                           |
  144.   |    junk line                                                       |
  145.   |                                                                    |
  146.   | Figure 1.  Input card deck format                                  |
  147.   +--------------------------------------------------------------------+
  148.  
  149.  
  150.  
  151.   Junk lines
  152.   ----------
  153.  
  154.  
  155.   Anything before  the  "ID/"  card  (e.g.  mail  header,  comments)  is
  156.   ignored.    Similarly,  anything  after  the  "END/" card (e.g. mailer
  157.   keywords, "Acknowledge-To:" field) is discarded.  Encountering the end
  158.   of the file without any ID or END card is an error.  However, encount-
  159.   ering an END card before any ID card is not an  error  since  anything
  160.   before the first ID card must be ignored without even being parsed.
  161.  
  162.  
  163.  
  164.   Control lines
  165.   -------------
  166.  
  167.  
  168.   The  ID card contains information about the file being sent, while the
  169.   END card is merely an end-of-stream indicator.   The format  of  these
  170.   two cards is:
  171.  
  172.   +--------------------------------------------------------------------+
  173.   |                 ID/filename filetype recfm lrecl reserved          |
  174.   |                 |  |        |        |     |    |                  |
  175.   |                 V  V        V        V     V    V                  |
  176.   | Column numbers: 1  4        13       22    24   29                 |
  177.   |                                                                    |
  178.   |                 END/reserved                                       |
  179.   |                 |   |                                              |
  180.   |                 V   V                                              |
  181.   | Column numbers: 1   5                                              |
  182.   |                                                                    |
  183.   | Blanks  shown  between  keywords are real.   See later on for more |
  184.   | information on the meaning of "filename", "recfm", etc.            |
  185.   |                                                                    |
  186.   | Figure 2.  Control cards format                                    |
  187.   +--------------------------------------------------------------------+
  188.  
  189.   NOTE: The end of the ID card (from column 30 onwards,  inclusive)  and
  190.   the  end  of  the  END  card  (from  column  5 onwards, inclusive) are
  191.   reserved fields which should be ignored  by  the  conversion  program.
  192.   Failure  to  observe  this  rule  might result in severe compatibility
  193.   problems with future releases of LISTSERV.
  194.  
  195.  
  196.  
  197.   Data lines
  198.   ----------
  199.  
  200.  
  201.  
  202.  
  203.   Folding algorithm
  204.  
  205.  
  206.   Each record of the source file is broken into  one  or  more  physical
  207.   "cards"  before  being transmitted.  The first card of each such group
  208.   will indicate the number of cards in the group, counting itself as one
  209.   card (i.e. this is not the number of continuation cards but the  total
  210.   number  of  cards),  and possibly the length of the source record line
  211.   (only if "recfm" is 'V' - see below).   The  remainder  of  the  first
  212.   card, as well as the second and following cards in the group, are pure
  213.   data  bytes.  The resulting concatenated record will have to be padded
  214.   with blanks as determined by the record length indication, if needed.
  215.  
  216.  
  217.  
  218.   Description of the format of a data line
  219.  
  220.  
  221.  
  222.   Fixed-length records
  223.  
  224.  
  225.  
  226.   +--------------------------------------------------------------------+
  227.   | recfm = F                                                          |
  228.   |                 ncards/data                                        |
  229.   |                 |      |                                           |
  230.   |                 V      V                                           |
  231.   | Column numbers: 1      2+Length(ncards)                            |
  232.   |                                                                    |
  233.   | Figure 3.  Data line format, fixed-length records                  |
  234.   +--------------------------------------------------------------------+
  235.  
  236.  
  237.  
  238.   Variable-length records
  239.  
  240.  
  241.  
  242.   +--------------------------------------------------------------------+
  243.   | recfm = V                                                          |
  244.   |                 lrecl/ncards/data                                  |
  245.   |                 |     |      |                                     |
  246.   |                 V     |      V                                     |
  247.   | Column numbers: 1     |      3+Length(lrecl)+Length(ncards)        |
  248.   |                       V                                            |
  249.   |                       2+Length(lrecl)                              |
  250.   |                                                                    |
  251.   | Figure 4.  Data line format, variable-length records               |
  252.   +--------------------------------------------------------------------+
  253.  
  254.   NCARDS    is the total number of cards in the group (ncards >= 1).
  255.  
  256.   LRECL     is the logical record length of the source file record asso-
  257.             ciated with the group; it does not appear in recfm  F  files
  258.             for which the record length is defined in the ID card.
  259.  
  260.  
  261.  
  262.  
  263.   ***************************************
  264.   * Summary of CMS file characteristics *
  265.   ***************************************
  266.  
  267.  
  268.   Since  LISTSERV  operates in an IBM VM/SP CMS environment and the file
  269.   will have to be received on a different operating system, a very short
  270.   description of the CMS file system has been included here.
  271.  
  272.  
  273.  
  274.   CMS file names
  275.   --------------
  276.  
  277.  
  278.   Under CMS, each file is identified by a "filename" and  a  "filetype",
  279.   both  of  them  being  strings  of  1 to 8 characters taken out of the
  280.   following set:
  281.  
  282.        A-Z   a-z   0-9   #$@-+:_
  283.  
  284.  
  285.   However, LISTSERV will never send a file containing a lowercase  char-
  286.   acter  in  its  filename or filetype, because a lot of systems have to
  287.   convert them to uppercase or will convert network interactive messages
  288.   to uppercase, thus making it impossible for users to enter mixed  case
  289.   file names in the commands they send to LISTSERV.
  290.  
  291.  
  292.  
  293.   CMS file structure
  294.   ------------------
  295.  
  296.  
  297.   CMS  files  consist  in  a  series of "records", as opposed to UNIX or
  298.   MS-DOS files which consist in a series of bytes.    When  calling  the
  299.   filing  system  to  perform a write operation, you must provide a full
  300.   record.  It is not possible to write "byte by byte" since this has  no
  301.   meaning  (you  could  of course write a series of one-byte records but
  302.   this would not create the file you  expected).    Each  CMS  file  has
  303.   therefore, among other attributes:
  304.  
  305.   o   A "number of records" field.
  306.  
  307.   o   A  "logical  record  length" (which is called lrecl).  This is the
  308.       size of the longest record  in  the  file,  and  consequently  the
  309.       minimum  size  of  the  storage  buffer  required to read the file
  310.       record by record.
  311.  
  312.   o   A "record format" (which is called recfm).   This "record  format"
  313.       is  a single character, F for FIXED or V for VARIABLE.  A recfm of
  314.       "F" indicates that all the records in the file  have  exactly  the
  315.       same  lrecl,  while "V" indicates the opposite.  The filing system
  316.       uses more efficient algorithms when handling recfm  F  files,  but
  317.       they require more disk space of course.
  318.  
  319.  
  320.  
  321.   Implementation considerations
  322.   -----------------------------
  323.  
  324.  
  325.   Before  you  start writing the conversion program, you must answer the
  326.   following set of questions:
  327.  
  328.   1.  Which name will I use on my system for the newly converted file?
  329.  
  330.       The sample C program reads from  standard  input  and  writes  the
  331.       converted  file  to  standard output, leaving the user responsible
  332.       for providing adequate redirection on the command line.
  333.       The sample PASCAL program, which is written for MS-DOS,  uses  the
  334.       filename  field as file name and the three first characters of the
  335.       filetype as file extension, i.e. filename+'.'+Left(filetype,3).
  336.       You may use a similar algorithm or select a constant  output  file
  337.       name such as "LISTSERV.PUN".
  338.  
  339.   2.  How should recfm F files be written on my system?
  340.  
  341.       The  sample  program treats a recfm F file as a recfm V file which
  342.       just happens to  have  records  of  identical  length.    A  CR+LF
  343.       sequence  is therefore output at the end of each record, regarless
  344.       of the recfm.  Alternatively, the program could have been designed
  345.       to write recfm F files "as is", i.e. without any CR+LF sequence at
  346.       the end of the record.  It all depends on the capabilities of your
  347.       system and (above all) of your system's editor.
  348.  
  349.  
  350.  
  351.  
  352.   SAMPLE PASCAL PROGRAM
  353.   _____________________
  354.  
  355.  
  356.  
  357.  
  358.  
  359.  
  360.   *********************
  361.   * Preliminary notes *
  362.   *********************
  363.  
  364.  
  365.   This sample PASCAL program was written for Turbo-PASCAL  (a  trademark
  366.   of  Borland  International).    It is provided only as an example - no
  367.   warranty of any kind is made that the program will  function  properly
  368.   on  your  operating system.   Detailed comments have been provided for
  369.   all the "system dependent" procedures.  The program was  designed  for
  370.   transportability,  not  efficiency  -  there are a lot of places where
  371.   some optimization would greatly improve execution speed, but that  was
  372.   not  the  objective  of the program.  All the functions and procedures
  373.   which are not part of the  standard  library  have  been  Capitalized,
  374.   while standard functions have been entered in lower case.  These func-
  375.   tions might exist on some of the compilers, possibly under a different
  376.   name.  The compiler is assumed to be able to handle the "string" type;
  377.   if  it  doesn't,  you will have to write a few "string-handling" func-
  378.   tions which emulate strings from an array of char.
  379.  
  380.   Finally, since not all terminals accept the special characters used by
  381.   PASCAL, the following conversion has been made:
  382.  
  383.     opening bracket     --> (.
  384.     closing bracket     --> .)
  385.     opening curly brace --> (*
  386.     closing curly brace --> *)
  387.  
  388.  
  389.  
  390.   NOTE: in Turbo-PASCAL, string concatenation  is  done  using  the  "+"
  391.   sign.
  392.  
  393.  
  394.  
  395.  
  396.  
  397.   *----------------------------- Cut here --------------------------------*
  398.  
  399.      (*
  400.      * LISTSERV-Punch PASCAL conversion program, version number 03
  401.      *
  402.      *    Written by Eric Thomas <ERIC@FRECP11.BITNET>
  403.      *
  404.      *
  405.      * This public domain program has  been tested on an IBM PC-compatible
  406.      * system on several  small files that had to be  keyed-in manually on
  407.      * the PC since no PC-to-mainframe connection was available.
  408.      *
  409.      * The working version  of the program had to be  printed and re-keyed
  410.      * in manually into the document  you are reading. There can therefore
  411.      * be several  keying errors --  proofreading programs is  very tiring
  412.      * and consequently very difficult.
  413.      *
  414.      *
  415.      * Synopsis:
  416.      *
  417.      *   The input file from LISTSERV is assumed to be CARDS.DAT
  418.      *
  419.      *   Output is  directed to  file "filename.filetype", with filetype
  420.      *   being truncated to 3 characters of course.
  421.      *
  422.      *
  423.      * Problems:
  424.      *
  425.      *   Send   problem   or   bug   reports   to   <ERIC@FRECP11.BITNET>.
  426.      *   Metaphysical complaints about the Rules of Structured Programming
  427.      *   and their relationship to  this blasphemous program should better
  428.      *   stay in their author's own warm, safe and cosy mailbox.
  429.      *
  430.      *)
  431.     program LPUNCH(input,cardfile,output,outfile);
  432.  
  433.     (* Note: Turbo-PASCAL requires square brackets for the "string" type,
  434.              while other compilers require parenthesis. Since some terminals
  435.              cannot display square brackets, parenthesis will be used. *)
  436.  
  437.     type cards=string(80);
  438.          string5=string(5); (* This is because Turbo is not a very power-  *)
  439.          string8=string(8); (* ful compiler                                *)
  440.          anystring=string(255); (* Substitute the maximum length of a
  441.                                    "string" var on your compiler *)
  442.  
  443.     var cardfile:text; (* Input file -- compiler dependent declaration *)
  444.         outfile:file of char;        (* compiler dependent declaration *)
  445.         card:cards;
  446.         filename,filetype:string8;
  447.         recfm:char;
  448.         i,ncards,lrecl,xlrecl:integer;
  449.  
  450.     function Substr(s:anystring;start,size:integer):anystring;
  451.     (* This function must return the substring of "s" starting at character
  452.        number "start" and of length "size". The resulting string must NOT be
  453.        padded with blanks if start+size-1 > length of the string. *)
  454.  
  455.       begin
  456.         Substr:=Copy(s,start,size)  (* Turbo has it under another name *)
  457.       end;
  458.  
  459.     function Length(s:anystring):integer;
  460.     (* This return the length of the string, with 0 for a null string *)
  461.  
  462.       begin
  463.         Length:=ord(s(.0.)) (* Same as the built-in Turbo function *)
  464.       end;
  465.  
  466.     procedure Opencards;
  467.     (* This procedure must open the input file, wherever it may be or your
  468.        system, and display an error message and exit it there is an error *)
  469.  
  470.       begin
  471.         assign(cardfile,'CARDS.DAT');
  472.         (*$i-*)
  473.         reset(cardfile);
  474.         (*$i+*)
  475.         if ioresult <> 0 then
  476.          begin
  477.            writeln('Error opening input file');
  478.            halt (* HALT is a GOTO just before the END. statement *)
  479.          end
  480.       end;
  481.  
  482.     procedure Closecards;
  483.     (* This procedure must close the input file. You may wish to have it
  484.        delete the input file too *)
  485.  
  486.       begin
  487.         (*$i-*)
  488.         close(cardfile);
  489.         if ioresult = 0 then; (* just reset turbo's hang... *)
  490.         (*$i+*)
  491.       end;
  492.  
  493.     function Getcard:cards;
  494.      var result:cards;
  495.     (* This function must read one 80-chars line (one "card") from input
  496.        and return it as result. A premature EOF is an error and must cause
  497.        termination of the program. The result must be EXACTLY 80 characters
  498.        in length *)
  499.  
  500.       begin
  501.         (*$i-*)
  502.         readln(cardfile,result);
  503.         (*$i+*)
  504.         if ioresult <> 0 then
  505.          begin
  506.            writeln('Premature EOF on input');
  507.            halt
  508.          end;
  509.         while Length(result) <> 80 do result:=result+' ';
  510.         Getcard:=result
  511.       end;
  512.  
  513.     function Dec2bin(s:string5):integer;
  514.      var n,error:integer;
  515.     (* This function converts a string of numeric characters into its
  516.        binary representation ("integer"). An error should cause termination*)
  517.  
  518.       begin
  519.         val(s,n,error);
  520.         if error = 0 then Dec2bin:=n
  521.                      else begin
  522.                             writeln('Invalid decimal argument');
  523.                             halt
  524.                           end
  525.       end;
  526.  
  527.     procedure Openout(fn,ft:string8);
  528.     (* This procedure must open the output file under whatever file-id you
  529.        may choose *)
  530.  
  531.       begin
  532.         assign(outfile,fn+'.'+Substr(ft,1,3));
  533.         (*$i-*)
  534.         rewrite(outfile);
  535.         (*$i+*)
  536.         if ioresult <> 0 then
  537.          begin
  538.            writeln('Error opening output file');
  539.            halt
  540.          end
  541.       end;
  542.  
  543.     procedure Closeout;
  544.     (* This procedure must close the output file. Errors should be detected
  545.        since they can mean a disk-full condition while writing the last
  546.        buffer, or suchlike *)
  547.  
  548.       begin
  549.         (*$i-*)
  550.         close(outfile);
  551.         if ioresult <> 0 then
  552.          begin
  553.            writeln('Error occured while closing output file');
  554.            halt
  555.          end
  556.         (*$i+*)
  557.       end;
  558.  
  559.     function Gobbleword(var card:cards):string5;
  560.      var s:string5;
  561.     (* This function should be left "as is" *)
  562.  
  563.       begin
  564.         s:='';
  565.         repeat
  566.           s:=s+card(.1.);
  567.           card:=Substr(card,2,80)
  568.         until card(.1.) = '/';
  569.         card:=Substr(card,2,80); (* Delete the "/" sign too *)
  570.         Gobbleword:=s
  571.       end;
  572.  
  573.     procedure Outchar(c:char);
  574.     (* This outputs a character to "outfile". On byte-based file systems such
  575.        as UNIX or MS-DOS, the character is just sent to standard output. On
  576.        record-based systems it must be appended to a buffer (string(65535) or
  577.        array of char) before the actual write is performed (see below) *)
  578.  
  579.       begin
  580.         (*$i-*)
  581.         write(outfile,c);
  582.         (*$i+*)
  583.         if ioresult <> 0 then
  584.          begin
  585.            writeln('Error writing to output file');
  586.            halt
  587.          end
  588.       end;
  589.  
  590.     procedure Endofrecord;
  591.     (* This procedure is called when the end of a record is reached. On
  592.        record-based file systems, the buffer must be written; on byte-based
  593.        systems a CR+LF (or similar) must be output for recfm V files, and
  594.        possibly for recfm F files (your option) *)
  595.  
  596.       begin
  597.         Outchar(chr(13));  (* CR *)
  598.         Outchar(chr(10))   (* LF *)
  599.       end;
  600.  
  601.     procedure Writeout(s:cards;var l:integer);
  602.      var i:integer;
  603.     (* This one must be left "as is" *)
  604.  
  605.       begin
  606.         if Length(s) > l then s:=Substr(s,1,l);
  607.         for i:=1 to Length(s) do Outchar(Substr(s,i,1));
  608.         l:=l-Length(s)
  609.       end;
  610.  
  611.     (* Main program -- nothing needs to be changed *)
  612.  
  613.     begin
  614.       Opencards;
  615.       repeat
  616.         card:=Getcard
  617.       until Substr(card,1,3) = 'ID/';
  618.  
  619.       filename:=Substr(card,4,8);
  620.       filetype:=Substr(card,13,8);
  621.       recfm:=Substr(card,22,1);
  622.       lrecl:=Dec2bin(Substr(card,24,5));
  623.  
  624.       Openout(filename,filetype);
  625.  
  626.       repeat
  627.         card:=Getcard;
  628.         if Substr(card,1,4) <> 'END/' then
  629.          begin
  630.            if recfm = 'V' then xlrecl:=Dec2bin(Gobbleword(card))
  631.                           else xlrecl:=lrecl;
  632.            ncards:=Dec2bin(Gobbleword(card));
  633.  
  634.            repeat
  635.              Writeout(card,xlrecl);
  636.              ncards:=ncards-1;
  637.              if ncards <> 0 then card:=Getcard
  638.            until ncards = 0;
  639.            for i:=1 to xlrecl do Outchar(' ');
  640.            Endofrecord
  641.          end
  642.       until Substr(card,1,4) = 'END/';
  643.  
  644.       Closecards;
  645.       Closeout;
  646.       writeln('File "',filename,' ',filetype,
  647.                    '" has been successfully converted.')
  648.     end.
  649.  
  650.     *----------------------------- Cut here --------------------------------*
  651.  
  652.  
  653.  
  654.  
  655.   SAMPLE C PROGRAM
  656.   ________________
  657.  
  658.  
  659.  
  660.  
  661.  
  662.  
  663.   *********************
  664.   * Preliminary notes *
  665.   *********************
  666.  
  667.  
  668.   This  sample C program is provided only as an example - no warranty of
  669.   any kind is made that the program will function properly on your oper-
  670.   ating system.   Detailed comments  have  been  provided  for  all  the
  671.   "system dependent" procedures.  All the functions and procedures which
  672.   are  not  part  of  the  standard library have been Capitalized, while
  673.   standard functions have been entered in lower case.
  674.  
  675.   The program should operate properly as is on any standard UNIX system,
  676.   although some system-dependent additions might be  necessary  in  some
  677.   cases (e.g. special options on the output file fopen call, or addition
  678.   of command-line switches).
  679.  
  680.   Finally, since not all terminals accept the special characters used by
  681.   C, the following conversion has been made:
  682.  
  683.     opening bracket     --> (:
  684.     closing bracket     --> :)
  685.     opening curly brace --> (*
  686.     closing curly brace --> *)
  687.     backslash           --> <bs>
  688.  
  689.   You  should  be  able  to  reverse  this  conversion  easily with your
  690.   favourite text editor before compiling the program.
  691.  
  692.  
  693.  
  694.   *----------------------------- Cut here --------------------------------*
  695.  
  696.     /*
  697.      * LISTSERV-Punch C conversion program, version number 02
  698.      *
  699.      *    Written by Eric Thomas <ERIC@FRECP11.BITNET>
  700.      *
  701.      *
  702.      * This public domain program has been  tested on a VM system with the
  703.      * huge BITEARN NODES file as input (over 23,000 LISTSERV-Punch format
  704.      * records), as  well as several  other smaller files. No  problem has
  705.      * been encountered in the testing phase.
  706.      *
  707.      * The working version  of the program has  been electronically copied
  708.      * into the document  you are reading, untouched.  There can therefore
  709.      * be no keying error, or then it  was in the original program too and
  710.      * was not detected during the testing period.
  711.      *
  712.      *
  713.      * Synopsis:
  714.      *
  715.      *   The input file from LISTSERV is assumed to be the standard input.
  716.      *
  717.      *   Output is  directed to  the standard output,  but the  program is
  718.      *   structured in such a way that this can be easily changed.
  719.      *
  720.      *
  721.      * Problems:
  722.      *
  723.      *   Send   problem   or   bug   reports   to   <ERIC@FRECP11.BITNET>.
  724.      *   Philosophical lectures about the  grandiose organization of C and
  725.      *   how  it has  been violated  in  this program  should be  directly
  726.      *   forwarded to /dev/null for a prompt answer.
  727.      *
  728.      */
  729.     #include <stdio.h>
  730.  
  731.     char card(:81:),     /* Input record image */
  732.          filename(:9:),
  733.          filetype(:9:),
  734.          number(:6:),    /* Scratch string to hold a number */
  735.          recfm;
  736.  
  737.     int  i,ncards,lrecl,xlrecl;
  738.  
  739.     FILE *outfile;
  740.  
  741.  
  742.     /* This function does not have to be tailored */
  743.     Substr(outstring,instring,start,length)
  744.      char *outstring,*instring;
  745.      int  start,length;
  746.     (*
  747.       register int rd=0,wr=0;
  748.       register char c;
  749.  
  750.      --start;
  751.      while(rd < start) (*
  752.        if (instring(:rd++:)=='<bs>0') (*
  753.          outstring="";
  754.          return;
  755.        *)
  756.      *)
  757.  
  758.      while(length-- > 0) (*
  759.        if ((c=instring(:rd++:)) != '<bs>0')
  760.         outstring(:wr++:)=c;
  761.        else break;
  762.      *)
  763.      outstring(:wr:)='<bs>0';
  764.      return;
  765.     *)
  766.  
  767.  
  768.     /* This function  must read one  80-chars line (one "card")  from input
  769.        and return it as result. A premature  EOF is an error and must cause
  770.        termination of the program. The result must be EXACTLY 80 characters
  771.        in length */
  772.     Getcard(string)
  773.     char *string;
  774.     (*
  775.       register int i=0,c;
  776.  
  777.       while(i < 80) (*
  778.         if (((c=getchar()) != EOF) && (c != '<bs>n'))
  779.           string(:i++:)=c;
  780.         else
  781.           break;
  782.       *)
  783.       if (c == EOF) (*
  784.         fprintf(stderr,"Premature EOF on input.<bs>n");
  785.         exit(100); *)
  786.  
  787.       if (i==80) (*
  788.         if (getchar() != '<bs>n') (*
  789.           fprintf(stderr,"Input file contains records larger than 80.<bs>n");
  790.           exit(100);
  791.         *)
  792.       *)
  793.       while (i < 80) (*
  794.         string(:i++:)=' ';
  795.       *)
  796.       string(:i:)='<bs>0';
  797.       return;
  798.     *)
  799.  
  800.  
  801.     /* This function does not have to be tailored */
  802.     Dec2bin(result,string)
  803.     char *string;
  804.     int  *result;
  805.     (*
  806.       if (sscanf(string,"%d",result) != 0) return;
  807.       fprintf(stderr,"Invalid decimal argument -- '%s'.<bs>n",string);
  808.       exit(100);
  809.     *)
  810.  
  811.  
  812.     /* This procedure must open the output file under whatever file-id you
  813.        may choose */
  814.     Openout(fn,ft)
  815.     char *fn,*ft;
  816.     (*
  817.       /* Our implementation uses standard output as file pointer */
  818.       outfile=stdout;
  819.  
  820.       /* The following instruction must be uncommented for use under
  821.          most VM C's if the output file is to have a lrecl > 80 */
  822.       /* outfile=fopen("LPUNCH OUTPUT A (recfm v lrecl 65535","w"); */
  823.       return;
  824.     *)
  825.  
  826.  
  827.     /* This procedure must close the output file. Errors should be detected
  828.        since they  can mean  a disk-full condition  while writing  the last
  829.        buffer, or suchlike */
  830.     Closeout()
  831.     (* /* The chosen implementation does nothing and relies on the operating
  832.          system  to  close the  standard  output  file.  This is  not  good
  833.          programming practice but at least it's transportable. */
  834.       return;
  835.     *)
  836.  
  837.  
  838.     /* This function should be left "as is" */
  839.     Gobbleword(inpstring,outstring)
  840.     char *inpstring,*outstring;
  841.     (*
  842.       register int rd=0,wr=0;
  843.  
  844.       while (inpstring(:rd:) != '/') (*
  845.         outstring(:wr++:)=inpstring(:rd++:);
  846.       *)
  847.       outstring(:wr:)='<bs>0';
  848.  
  849.       for(wr=0;inpstring(:++rd:) != '<bs>0';) (*
  850.         inpstring(:wr++:)=inpstring(:rd:);
  851.       *)
  852.       inpstring(:wr:)='<bs>0';
  853.       return;
  854.     *)
  855.  
  856.  
  857.     /* This function does not have to be tailored */
  858.     Writeout(string,lenptr)
  859.     char *string;
  860.     int  *lenptr;
  861.     (*
  862.       int i=0;
  863.       while((string(:i:) != '<bs>0') && ( *lenptr > 0)) (*
  864.         putc(string(:i++:),outfile);
  865.         --( *lenptr);
  866.       *)
  867.     *)
  868.  
  869.  
  870.     /* Main program -- nothing needs to be changed */
  871.     main() (*
  872.  
  873.       do (* /* Read up to and including 'ID/' card */
  874.         Getcard(card);
  875.     *) while ((card(:0:)!='I') || (card(:1:)!='D') || (card(:2:)!='/'));
  876.  
  877.       Substr(filename,card,4,8);
  878.       Substr(filetype,card,13,8);
  879.       recfm=card(:21:);
  880.       Substr(number,card,24,5);
  881.       Dec2bin(&lrecl,number);
  882.  
  883.       Openout(filename,filetype);
  884.  
  885.       for (;;) (*
  886.         Getcard(card);
  887.         if ((card(:0:)=='E') && (card(:1:)=='N') &&
  888.             (card(:2:)=='D') && (card(:3:)=='/'))
  889.           break;
  890.  
  891.         if (recfm=='V') (*
  892.           Gobbleword(card,number);
  893.           Dec2bin(&xlrecl,number); *)
  894.         else
  895.           xlrecl=lrecl;
  896.  
  897.         Gobbleword(card,number);
  898.         Dec2bin(&ncards,number);
  899.  
  900.         do (*
  901.           Writeout(card,&xlrecl);
  902.           if (--ncards != 0)
  903.             Getcard(card);
  904.       *) while(ncards!=0);
  905.  
  906.         for(i=1;i <= xlrecl;i++) (*
  907.           putc(' ',outfile);
  908.         *)
  909.         putc('<bs>n',outfile);
  910.       *)
  911.       Closeout();
  912.     *)
  913.  
  914.     *----------------------------- Cut here --------------------------------*
  915.  
  916.  
  917.  
  918.  
  919.  
  920.   *************************************
  921.   * Appendix A.  The LISTSERV Library *
  922.   *************************************
  923.  
  924.       o User's guide  . . . . . . . . . . . . . . . . . . . .  (U01-001)
  925.  
  926.       o List Manager's guide  . . . . . . . . . . . . . . . .  (M01-002)
  927.  
  928.       o Installation guide  . . . . . . . . . . . . . . . . .  (S01-003)
  929.  
  930.       o Application Programmer's guide  . . . . . . . . . . .  (A01-004)
  931.  
  932.       o Maintenance guide . . . . . . . . . . . . . . . . . .  (S01-005)
  933.  
  934.       o File Server Functions . . . . . . . . . . . . . . . .  (U01-006)
  935.  
  936.   --> o Listserv-Punch Implementation . . . . . . . . . . . .  (R01-007)
  937.  
  938.       o File Maintainer's guide . . . . . . . . . . . . . . .  (M01-008)
  939.  
  940.       o BITNET-Oriented Presentation  . . . . . . . . . . . .  (P01-009)
  941.  
  942.       o Public Utilities Reference  . . . . . . . . . . . . .  (A01-010)
  943.  
  944.       o Licensed Utilities Reference  . . . . . . . . . . . .  (S01-011)
  945.  
  946.       o Database Functions  . . . . . . . . . . . . . . . . .  (U01-012)
  947.  
  948.  
  949.  
  950.  
  951.  
  952.  
  953.  
  954.  
  955.  
  956.   LISTSERV Document Numbers
  957.   -------------------------
  958.  
  959.                                 U 01 - 006 - 0
  960.                                 _ __   ___   _
  961.                                 |  |    |    |
  962.   Document Class     -----------+  |    |    |
  963.                                    |    |    |
  964.                                    |    |    |
  965.                                    |    |    |
  966.   Product Number     --------------+    |    |
  967.                                         |    |
  968.                                         |    |
  969.                                         |    |
  970.   Publication Number -------------------+    |
  971.                                              |
  972.                                              |
  973.                                              |
  974.   Revision Number    ------------------------+
  975.  
  976.  
  977.  
  978.   Document Class
  979.  
  980.  
  981.   The Document Class indicates for which category of persons the  publi-
  982.   cation was written.  The current classes are:
  983.  
  984.   A    Documents  intended  for Application Programmers.  These publica-
  985.        tions are usually very technical.
  986.  
  987.   M    Documents intended for Software Managers, i.e.  operators,  "list
  988.        owners", "file maintainers", et al.
  989.  
  990.   P    General  Presentation  documents  intended for persons who do not
  991.        have any particular knowledge in the product.   These are  gener-
  992.        ally non-technical documents.
  993.  
  994.   R    Reference  documents  defining  protocols  used  by  the product.
  995.        These documents are very technical and are  intended  for  people
  996.        who  have  to write interfaces for the product or attempt to port
  997.        it to an operating system or environment for  which  it  was  not
  998.        originally written.
  999.  
  1000.   S    Documents  intended  for  Systems Programmers, i.e.   the persons
  1001.        responsible for the installation and operation of the product.
  1002.  
  1003.   U    Documents intended for General Users.
  1004.  
  1005.  
  1006.  
  1007.  
  1008.   Product Number
  1009.  
  1010.  
  1011.   The Product Number is a unique number associated with the  product  to
  1012.   which  the  publication relates.  Number 01 refers to LISTSERV, number
  1013.   02 corresponds to the NETINFO sub-product, etc.
  1014.  
  1015.  
  1016.  
  1017.   Publication Number
  1018.  
  1019.  
  1020.   This is a unique number associated with the publication.   Publication
  1021.   Numbers  are  assigned  sequentially, disregarding the Document Class.
  1022.   There is a different set of Publication Numbers for each product.
  1023.  
  1024.  
  1025.  
  1026.   Revision Number
  1027.  
  1028.  
  1029.   This number is incremented at every release change in the publication.
  1030.   Fractional numbers indicate intermediate changes between two releases.
  1031.  
  1032.