home *** CD-ROM | disk | FTP | other *** search
/ Fresh Fish 1 / FFMCD01.bin / bbs / libdisks / d700t799 / disk774.lha / ExtraCmds / src / Split.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-12-05  |  9.1 KB  |  307 lines

  1. /*
  2.  * Split - Split a file into pieces
  3.  *
  4.  * Version 1 =TP= ??-???-89  (Write some comments  ;-(  )
  5.  *      Unix look-alike command
  6.  * Version 37.2 =TP= 21-Jan-92 26-Jan-92
  7.  * Compile with SAS/C 5.10 and link without startup code:
  8.  *      lc -cqfist -v -b0 -rr -O -ms Split
  9.  *      blink Time.o to Split sd sc
  10.  *      protect Split +p
  11.  *
  12.  * Copyright (c) 1989, 1992 Torsten Poulin
  13.  *
  14.  * Note: The program do not check for errors while writing
  15.  *       because the include files for SAS/C declared
  16.  *       FPutC() to be VOID instead of LONG!!!!  ;-(
  17.  *
  18.  * Torsten Poulin
  19.  * Banebrinken 99, 2, lejlighed 77
  20.  * DK 2400  København NV
  21.  * DENMARK
  22.  */
  23.  
  24. /****** English:SPLIT ******************************************************
  25. *
  26. *   FORMAT
  27. *       SPLIT [[FROM] <file>] [TO <name>] [NUMBER <n> [PARTS]]
  28. *             [BYTES] [PROMPT]
  29. *
  30. *   TEMPLATE
  31. *       FROM,TO/K,NUM=NUMBER/K/N,PARTS/S,BYTES/S,PROMPT/S
  32. *
  33. *   PURPOSE
  34. *       To split a file into pieces.
  35. *
  36. *   SPECIFICATION
  37. *       Split reads <file> and writes it in <n>-line pieces (default
  38. *       1000 lines) onto a set of output files.  The name of the
  39. *       first output file is <name> with aa appended, and so on
  40. *       lexicographically, up to zz (a maximum of 676 files). <name>
  41. *       is truncated to 28 characters if it is longer.  If no output
  42. *       name is given, x is default.
  43. *
  44. *       If the BYTES switch is used, the input file will be split in
  45. *       <n>-character pieces instead.  This is especially useful
  46. *       if the input is a binary file.
  47. *
  48. *       The PARTS switch, which can only be used in conjunction with
  49. *       the NUMBER option, splits the input file in the specified
  50. *       number of parts.
  51. *
  52. *       The PARTS switch implies the BYTES switch.
  53. *
  54. *       If the PROMPT switch is specified, the user will be prompted
  55. *       before each output file is written, to make it possible to
  56. *       change disks.
  57. *
  58. *       If no input file is given then the default input is used
  59. *       making it possible to use Split as the end of a pipe-line.
  60. *       
  61. *   EXAMPLE
  62. *       If the file `myfile' is split up with a command like this:
  63. *           1> SPLIT myfile TO splitfile.
  64. *       it can be assembled again with the following command:
  65. *           1> CONCAT splitfile.?? TO newfile SORT
  66. *
  67. *   WARNING
  68. *       Do not use the PARTS switch if reading from a pipe as
  69. *       it causes Split to attempt to determine the size of it's
  70. *       input using the dos.library function Seek().  If you do
  71. *       it chances are that you end up with lots of small files
  72. *       typically containing one byte each.
  73. *
  74. *   SEE ALSO
  75. *       CONCAT, JOIN, TYPE
  76. *
  77. ***************************************************************************
  78. *
  79. */
  80. /****** dansk:SPLIT *******************************************************
  81. *
  82. *   FORMAT
  83. *       SPLIT [[FROM] <fil>] [TO <navn>] [NUMBER <n> [PARTS]]
  84. *             [BYTES] [PROMPT]
  85. *
  86. *   SKABELON
  87. *       FROM,TO/K,NUM=NUMBER/K/N,PARTS/S,BYTES/S,PROMPT/S
  88. *
  89. *   FORMÅL
  90. *       At splitte en fil i mindre stykker.
  91. *
  92. *   SPECIFIKATION
  93. *       Split læser <fil> og udskriver den i <n>-linje stykker
  94. *       (standard er 1000 linjer) som en gruppe filer.  Navnet
  95. *       på den første uddatafil er <navn> efterfulgt af aa og
  96. *       så fremdeles, leksikografisk, indtil zz (højst 676 filer).
  97. *       <navn> forkortes til 28 tegn hvis det er længere.  Hvis
  98. *       der ikke er angivet noget uddatanavn, bruges x.
  99. *
  100. *       Hvis kontakten BYTES bruges vil inddatafilen blive delt
  101. *       i stykker på <n> tegn i stedet.  Dette er særlig nyttigt
  102. *       hvis inddata er en binær fil.
  103. *
  104. *       Kontakten PARTS, der kun kan bruges sammen med argumentet
  105. *       NUMBER, deler inddatafilen i det angivne antal dele.
  106. *
  107. *       Kontakten PARTS indebærer automatisk kontakten BYTES.
  108. *
  109. *       Hvis kontakten PROMPT angives vil brugeren blive spurgt
  110. *       før hver uddatafil skrives for at muliggøre disketteskift.
  111. *
  112. *       Hvis ingen inddatafil er angivet læses fra standardinputtet,
  113. *       hvilket gør det muligt at bruge Split som afslutningen på
  114. *       en pipe.
  115. *
  116. *   EKSEMPEL
  117. *       Hvis filen `minfil' splittes op med en kommando som
  118. *           1> SPLIT minfil TO splitfil.
  119. *       kan den samles igen med følgende kommando:
  120. *           1> CONCAT splitfil.?? TO nyfil SORT
  121. *
  122. *   ADVARSEL
  123. *       Brug ikke kontakten PARTS hvis der læses fra en pipe, da
  124. *       den får Split til at forsøge at bestemme størrelsen af
  125. *       sit input med funktionen Seek() fra dos.library.  Hvis
  126. *       man gør det vil man sandsynligvis ende med en mængde
  127. *       små filer med typisk én oktet i hver.
  128. *
  129. *   SE OGSÅ
  130. *       CONCAT, JOIN, TYPE
  131. *
  132. ***************************************************************************
  133. *
  134. */
  135.  
  136.  
  137. #include <exec/types.h>
  138. #include <dos/dos.h>
  139. #include <dos/dostags.h>
  140. #include <proto/exec.h>
  141. #include <proto/dos.h>
  142. #include <proto/utility.h>
  143. #include <string.h>
  144.  
  145. #define EOF (-1)
  146.  
  147. #define OPT_FROM   0
  148. #define OPT_TO     1
  149. #define OPT_NUM    2
  150. #define OPT_PARTS  3
  151. #define OPT_BYTES  4
  152. #define OPT_PROMPT 5
  153.  
  154.  
  155. char const *version = "\0$VER: Split 37.2 (26.1.92)\
  156.  ©1989,92 Torsten Poulin";
  157.  
  158. LONG error(struct DosLibrary *, LONG);
  159.  
  160. LONG entrypoint(void)
  161. {
  162.     struct RDArgs     *args;
  163.     struct Library    *UtilityBase;
  164.     struct DosLibrary *DOSBase;
  165.     struct Library    *SysBase;
  166.  
  167.     LONG     arg[6];
  168.     LONG     rc = RETURN_OK;
  169.     BPTR     in, out = NULL;
  170.     LONG     c, cnt, totalfiles = 0;
  171.     LONG     len = 1;
  172.     UBYTE    name[31] = "x";
  173.     ULONG    number = 1000L;
  174.     register UBYTE breakcheck = 0;
  175.     
  176.     SysBase = *(struct Library **) 4L;
  177.     if(!(DOSBase = (struct DosLibrary *) OpenLibrary("dos.library", 37L)))
  178.     {
  179.         rc = RETURN_FAIL;
  180.         goto exit1;
  181.     }
  182.     if(!(UtilityBase = OpenLibrary("utility.library", 37L)))
  183.     {
  184.         rc = RETURN_FAIL;
  185.         goto exit2;
  186.     }
  187.  
  188.     arg[OPT_FROM]  = arg[OPT_TO]    = arg[OPT_NUM] =
  189.     arg[OPT_PARTS] = arg[OPT_BYTES] = arg[OPT_PROMPT] = 0L;
  190.     
  191.     if(args = ReadArgs("FROM,TO/K,NUM=NUMBER/K/N,PARTS/S,BYTES/S,PROMPT/S",
  192.                        arg, NULL))
  193.     {
  194.         if(arg[OPT_NUM])
  195.         {
  196.             number = *(ULONG *) arg[OPT_NUM];
  197.             if(number < 1L)
  198.                 number = 1L;
  199.         }
  200.  
  201.         if(arg[OPT_TO])
  202.         {
  203.             UBYTE *a = (UBYTE *) arg[OPT_TO];
  204.  
  205.             for(len = 0; len < 28 && a[len]; len++)
  206.                 name[len] = a[len];
  207.             name[len] = '\0';
  208.         }
  209.  
  210.         if(in = arg[OPT_FROM] ? Open((UBYTE *) arg[OPT_FROM], MODE_OLDFILE)
  211.                               : Input())
  212.         {
  213.             name[len] = 'a';
  214.             name[len + 1] = 'a' - 1;
  215.             name[len + 2] = '\0';
  216.  
  217.             if((BOOL) arg[OPT_PARTS] && arg[OPT_NUM])
  218.             {
  219.                 ULONG n = (ULONG) number;
  220.                 
  221.                 if(n > 676L)
  222.                     n = 676L;
  223.                 Seek(in, 0L, OFFSET_END);
  224.                 number = Seek(in, 0L, OFFSET_BEGINNING);
  225.                 number = UDivMod32((ULONG) number, n) + 1L;
  226.                 arg[OPT_BYTES] = TRUE;
  227.             }
  228.             cnt = number;
  229.  
  230.             while((c = FGetC(in)) != EOF)
  231.             {
  232.                 if(cnt == number && 676L > totalfiles++)
  233.                 {
  234.                     cnt = 0;
  235.                     if(name[len + 1] < 'z')
  236.                         name[len + 1]++;
  237.                     else
  238.                     {
  239.                         name[len + 1] = 'a';
  240.                         name[len]++;
  241.                     }
  242.                     name[len + 2] = '\0';
  243.                     if(out)
  244.                         Close(out);
  245.                     if((BOOL) arg[OPT_PROMPT])
  246.                     {
  247.                         BPTR console;
  248.                         
  249.                         Write(Output(), "Press RETURN to write ", 22L);
  250.                         Write(Output(), name, strlen(name));
  251.                         if(console = Open("CONSOLE:", MODE_OLDFILE))
  252.                         {
  253.                             FGetC(console);
  254.                             Close(console);
  255.                         }
  256.                     }
  257.                     if(!(out = Open(name, MODE_NEWFILE)))
  258.                     {
  259.                         rc = error(DOSBase, RETURN_ERROR);
  260.                         goto openErr;
  261.                     }
  262.                 }
  263.                 /* if( */   FPutC(out, c)  /* == EOF)
  264.                 {
  265.                     rc = error(DOSBase, RETURN_FAIL);
  266.                     goto writeErr;
  267.                 } 
  268.                 */;
  269.                 if((BOOL) arg[OPT_BYTES] || c == '\n')
  270.                     cnt++;
  271.                 if(!(breakcheck -= 8) && SetSignal(0L,0L) & SIGBREAKF_CTRL_C)
  272.                 {
  273.                     PrintFault(ERROR_BREAK, NULL);
  274.                     rc = RETURN_WARN;
  275.                     break;
  276.                 }
  277.         }
  278.  writeErr:
  279.             Close(out);
  280.  openErr:
  281.             if(arg[OPT_FROM])
  282.                 Close(in);
  283.         }
  284.         else
  285.             rc = error(DOSBase, RETURN_ERROR);
  286.  
  287.         FreeArgs(args);
  288.     }
  289.     else
  290.         rc = error(DOSBase, RETURN_ERROR);
  291.  
  292.     CloseLibrary(UtilityBase);
  293.  exit2:
  294.     CloseLibrary((struct Library *) DOSBase);
  295.  exit1:
  296.     return rc;
  297. }
  298.  
  299.  
  300. LONG error(struct DosLibrary *DOSBase, LONG code)
  301. {
  302.     LONG err = IoErr();
  303.  
  304.     PrintFault(err, "Split");
  305.     return code;
  306. }
  307.