⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 csplit.c

📁 FIDO网超大文件传输的C语言源程序,仅仅只是为了学习和交流
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
 * CSplit.C
 * This program is used to process source files for the purpose
 * of transmission through a FidoNet (tm) echo in such a manner
 * as to circumvent over-size message problems.
 *
 * This process is specified as follows:
 *
 * 1) a. Combine multiple source files
 *    b. Split into 50-60 line sections
 *    c. Add header and trailer markers
 *       delimiting each section and file
 * 2) a. Delete trailing whitespace
 *    b. Replace tabs with spaces
 *    c. Default to 4 spaces per tab
 *    d. Allow user to specify alternate
 *       number of spaces per tab
 * 3) a. Wrap lines longer than 75 characters
 *       long using the C "\ at the end of a
 *       line" notation (using space break).
 *    b. Wrapped lines will be followed by a
 *       line with a single "\" character then
 *       followed by the remainder of the line.
 * 4) a. Calculate a CRC for each section and
 *       include in the section trailer line
 * 5) a. Provide a help display for program usage when
 *       the program is executed without parameters
 *
 * Syntax:
 *
 * Extract:   CSPLIT  /x  infile
 *
 * Split:     CSPLIT  [/tn]  outfile  src.ext  [ ... ]
 *
 * Where:         n - For TAB expansion, the number of spaces to
 *                    replace each TAB character (the default is 4)
 *           infile - Name of file that contains the parts properly
 *                    placed in consecutive order for extraction
 *          outfile - Name of the output file(s).  The extension will
 *                    be ignored if specified and each output file will
 *                    be named such that the section number will be the
 *                    extension (e.g., outfile.001, outfile.002, etc..)
 *          src.ext - The first source file..etc  Wildcard filespecs are
 *                    supported under non-ANSI compiling conditions.
 *                    Filenames are limited to "8.3" string lengths to
 *                    avoid separator line length problems.
 *
 * 08/31/93  Fred Cole  Original draft
 * 09/05/93  FC         Added CRC calculation, fixed line wrap problem,
 *                      added extraction ability, fixed a couple of bugs
 * 09/14/93  FC         Added conditional compilation directives to
 *                      allow non-ANSI, multi-compiler, filespec support
 *                      Squashed extract() bug
 * 11/21/93  Thad Smith Test for incomplete input file on extraction.
 *                      Remove spaces added in message transmission.
 *                      Default to 90 lines /section.
 *                      Fix tab expansion.
 * 12/03/93  FC         Fix file cleanup() bug.
 * 12/09/93  Keith Campbell / TS
 *                      Fix bug with options preceded by '-', fix
 *                      tempfile opening bug, eliminate unused variables.
 *                      Make sepcrc same type as crc.
 * 01/02/94  david nugent / FC
 *                      Additions for findfirst/findnext support for
 *                      MSC6 (& 7) for OS/2 in initlist() routine
 * 01/02/94  Auke Reitsma / FC
 *                      Increased number of characters read in to prevent
 *                      line numbers from becoming out-of-sync with input
 * 01/12/94  Chad Wagner / FC
 *                      Correction to initlist() function to eliminate
 *                      the redundant line increment
 *
 * Donated to public domain
 */

#include "csplit.h"

FILE *Fin  = NULL,  /* necessary evils - global variables */
     *Fout = NULL,
     *Ftmp = NULL;
char tempfile[FNAME+1];
SLST *head = NULL,
     *cur  = NULL;

int main(int argc, char **argv)
{
  char *ext, line[81], outfile[FNAME+1], *s;
  int  argndx = 1,
       tab2spac = TABDEF,
       lines_per_sect = LINES,
       j, key, lines, curpart, maxpart, rc;
  unsigned short crc;

  printf("\nCSplit - (pd) 1993 Revision %s by Fred Cole\n", VERSION);
  puts("This executable program is in public domain.\n");

  if (('/' == argv[1][0]) || ('-' == argv[1][0]))
  {
    if ('x' == tolower(argv[1][1]))    /* if extract option */
    {
      if (argc < 3)
      {
        disp_help();
        return(HELP);
      }

      rc = extract(argv[2]);
      cleanup();
      return(rc);
    }
    else if ('t' == tolower(argv[1][1]))   /* if tab option */
    {
      tab2spac = atoi(&argv[1][2]);
      if ((tab2spac < TABMIN) || (tab2spac > TABMAX))
        tab2spac = TABDEF;
      argndx++;
    }
  }

  if ((argc - argndx) < 2)
  {
    disp_help();
    return(HELP);
  }

  if (strlen(argv[argndx]) > FNAME)
  {
    printf("Output filename too long:  %s\n", argv[argndx]);
    cleanup();
    return(OUTFILE);
  }

  strcpy(outfile, argv[argndx]);
  if (NULL == (ext = strstr(outfile, ".")))  /* ignore any ext */
    ext = &outfile[strlen(outfile)];

  *ext = 0;                         /* make temp file name */
  strcpy(tempfile, outfile);
  strcat(tempfile, ".$$$");

  if (NULL == (Ftmp = fopen(tempfile, "w+t")))
  {
    printf("Error creating temp file:  %s\n", tempfile);
    cleanup();
    return(PROCESS);
  }

  if (NOERR != initlist(argc, argv, argndx+1))
  {
    cleanup();
    return(MEMORY);
  }

  for (cur = head, lines = 0; NULL != cur; cur = cur->next)
  {
    if (NULL == Fin)
    {
      if (NULL == (Fin = fopen(cur->srcfile, "rt")))
      {
        printf("Error opening source file:  %s\n", cur->srcfile);
        cleanup();
        return(INFILE);
      }

      rc = fprintf(Ftmp, "%s%s%s%s\n",
                   SEP_ID, SEP_BF, cur->srcfile, SEP_AR);

      if (0 == rc)
      {
        puts("Error writing output\n");
        cleanup();
        return(WRITE);
      }
      lines++;
    }

    while (NULL != Fin)
    {
      /*
       * The function my_fgets() is equivalent to fgets() in that it
       * too reads n-1 characters or up to a newline character.  This
       * function additionally expands TAB characters, deletes trailing
       * whitespace and will wrap lines exceeding the specified length.
       */
      s = my_fgets(line, LENGTH, Fin, tab2spac);
      if (NULL == s)
      {
        if (feof(Fin))
        {
          fclose(Fin);
          Fin = NULL;
          rc = fprintf(Ftmp, "%s%s%s%s\n",
                       SEP_ID, SEP_EF, cur->srcfile, SEP_AR);
          if (0 == rc)
          {
            puts("Error writing output\n");
            cleanup();
            return(WRITE);
          }
          lines++;   /* adjust line count */
        }
        else
        {
          puts("Error reading input\n");
          cleanup();
          return(READ);
        }
      } /* endif NULL string */
      else
      {
        if (EOF == fputs(line, Ftmp))
        {
          puts("Error writing output\n");
          cleanup();
          return(WRITE);
        }

        lines++; /* increment line count */
      } /* endif non-NULL string */
    } /*endwhile*/
  } /*endfor*/

  if (lines < lines_per_sect)     /* if only one section */
    maxpart = 1;
  else
  {
    maxpart = lines / lines_per_sect;

    if (lines % lines_per_sect < 5)/* if < 5 lines in last section */
    {
      lines_per_sect--;           /* decrement lines per section */
      maxpart = lines / lines_per_sect;
    }

    if ((maxpart > 0) &&          /* why can't those go on one line? */
        (lines % lines_per_sect > 0))
      maxpart++;                  /* perform ceil function */
  }

  curpart = 1;

  /* warn user if 1st output filename already in use */
  sprintf(ext, ".%03.3d", curpart); /* make 1st output file name */
  if (NULL != (Fout = fopen(outfile, "rt")))
  {
    key = 0;
    printf("Output file already exists:  %s\n", outfile);
    do
    {
      printf("Overwrite? (y/n) ");
      key = getchar();
      puts("");
      j = key;
      while (j != '\n')
        j = getchar();  /* eat all extra keystrokes */
      if (('n' == key) || ('N' == key))
      {
        cleanup();
        return(OUTFILE);
      }
    } while (('y' != key) && ('Y' != key));
    fclose(Fout);
    Fout = NULL;
  }

  if (NULL == freopen(tempfile, "rt", Ftmp))
  {
    printf("Error reopening temp file:  %s\n", tempfile);
    cleanup();
    return(PROCESS);
  }

  initcrctab();

  while (NULL != Ftmp)
  {
    if (NULL == Fout)
    {
      sprintf(ext, ".%03.3d", curpart); /* make output file name */
      if (NULL == (Fout = fopen(outfile, "w+t")))
      {
        printf("Error opening output file:  %s\n", outfile);
        cleanup();
        return(OUTFILE);
      }
      rc = fprintf(Fout, "%s%s%d/%d%s\n",
                   SEP_ID, SEP_BP, curpart, maxpart, SEP_AR);
      if (0 == rc)
      {
        puts("Error writing output\n");
        cleanup();
        return(WRITE);
      }
    }

    crc = 0;
    lines = 0;

    while ((lines < lines_per_sect) && (NULL != Ftmp))
    {
      s = fgets(line, 80, Ftmp);
      if (NULL == s)
      {
        if (feof(Ftmp))
        {
          fclose(Ftmp);
          Ftmp = NULL;
        }
        else
        {
          puts("Error reading input\n");
          cleanup();
          return(READ);
        }
      } /*endif NULL string*/
      else
      {
        crc = updcrc(crc, (unsigned char *)line, strlen(line));
        if (EOF == fputs(line, Fout))
        {
          puts("Error writing output\n");
          cleanup();
          return(WRITE);
        }

        lines++; /* increment line count */

      } /*endif non-NULL string*/
    } /*endwhile*/


    if (0 == fprintf(Fout, "%s%s%d/%d  crc: %04x %s\n",
                     SEP_ID, SEP_EP, curpart, maxpart, crc, SEP_AR))
    {
      puts("Error writing output\n");
      cleanup();
      return(WRITE);
    }

    fclose(Fout);
    Fout = NULL;
    curpart++;

  } /*endwhile*/

  cleanup();
  return(NOERR);
}

/*
 * cleanup() - Just a convenient way to provide housekeeping
 *             for all the places the code returns from main.
 */
void cleanup(void)
{
  freelist();
  if (NULL != Fin)  fclose(Fin);
  if (NULL != Fout) fclose(Fout);
  if (NULL != Ftmp) fclose(Ftmp);
  if (NULL != (Ftmp = fopen(tempfile, "rt")))
  {
    fclose(Ftmp);
    remove(tempfile);
  }
}

void disp_help(void)
{
  puts("This utility is used to process source files for the purpose");
  puts("of transmission through a FidoNet (tm) echo in such a manner");
  puts("as to circumvent over-size message problems.\n");
  puts("Syntax:\n");
  puts("Extract:  CSPLIT  /x  infile\n");
  puts("Split:    CSPLIT  [/tn]  outfile  src.ext  [ ... ]\n");
  puts("Where:         n - For TAB expansion, the number of spaces to");
  puts("                   replace each TAB character (defaults to 4)");
  puts("          infile - File name that contains the parts properly");
  puts("                   placed in consecutive order for extraction");
  puts("         outfile - Name of the output file(s).  The extension");
  puts("                   will be the sequential section/part number");
  puts("                   (e.g., outfile.001, outfile.002, etc. ...)");
#if !defined(__STDC__)
  puts("         src.ext - Source file(s)..etc.  (w/wildcard support)");
#else
  puts("         src.ext - Source file(s)..etc. (no wildcard support)");
#endif
}

int extract(char *ifn)
{
  static char line[(LENGTH+1)*2], line2[(LENGTH+1)*2];
  char outfile[FNAME+1], *s;
  int  i, in_section, key, lines,
       curpart, maxpart, pos_wrap,
       sepmax, seppart,
       sep_id_len = strlen(SEP_ID);
  unsigned short crc, sepcrc;

  if (NULL == (Fin = fopen(ifn, "rt")))
  {
    printf("Error opening input file:  %s\n", ifn);
    return(INFILE);
  }

  crc = curpart = maxpart = lines = 0;
  in_section = pos_wrap = FALSE;
  Fout = NULL;
  initcrctab();
  *line2 = 0;

  while (NULL != Fin)
  {
    s = fgets(line, LENGTH*2, Fin);   /* increase input size */
                                      /* Auke Reitsma */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -