[comp.sources.wanted] Joiner for uuencoded file parts

acook@athena.mit.edu (Andrew R Cook) (05/30/91)

I got a bunch of responses asking for this code, so in the interest of sanity,
here it is: (code is pretty simple, please ignore if you have something better,
and no flames please):


*********************************************************************************
/* This is a rather simple way to clean up cat'ed uue files.  It
assumes standard uue format: begin ... Mdata(61 or 62 chars).. end.
A better way would be to test the number of chars in the line and see
if the first char is the correct one for the number of bytes represented.
This is explained in the formats section of any standard unix manual.

Places where errors will occur:
1) if data lines do not begin with 'M'.
2) if any other line beginning with 'M' (not data) also has 61 or 62
       chars in it.  This one is unavoidable in any case.

If you find other bugs, or make major improvements, I would appreciate
it if you would let me know.  I wrote this code to be helpful, so the
more useful it becomes, the better.

Written by:
    Andrew Cook
    acook@athena.mit.edu
    andy@ivana.mit.edu

typical usage:
    clean uuefile | uudecode
where uuefile is the cat'ed together uuencoded parts.

Distribute freely, use freely as long as this authorship notice remains
intact.
*/

#include <stdio.h>
#include <string.h>
#define INTERVAL 100

main(argc, argv)
int argc;
char **argv;
{
  int i, cnt=0, num=0, bflag=0, eflag=0;
  FILE *in;
  char buf[300], bufa[300], bufb[300], ff[100];

  if(argc != 2) {
    fprintf(stderr, "Usage: clean file\n");
    exit(0); }

  if((in = fopen(argv[1], "r")) == NULL) {
    fprintf(stderr, "Error: can't open \"%s\"\n", argv[1]);
    exit(0); }

  fprintf(stderr, "Cleaning catted uue file \"%s\" ", argv[1]);

  while(fgets(buf, 295, in) != NULL) {
    buf[strlen(buf)-1] = '\0';
    if(buf[0] == 'b') { /* begin */
      if(buf[1]=='e' && buf[2]=='g' && buf[3]=='i' && buf[4]=='n') {
	bflag = 1;
	if(puts(buf) == EOF) {
	  fprintf(stderr, "error on puts.\n");
	  exit(0); }
      }
    } else if(buf[0] == 'M' && bflag == 1 && (strlen(buf) == 61 || strlen(buf) == 62)) { /*uue stuff*/
      if(puts(buf) == EOF) {
	fprintf(stderr, "error on puts.\n");
	exit(0); }
      cnt++;
      num++;
      if(cnt == INTERVAL) {
	fprintf(stderr, ".");
	fflush(stderr);
	cnt = 0; }
    } else if(strcmp(buf, "end") == 0) { /* end */
	if(puts(bufb) ==  EOF) {
	  fprintf(stderr, "error on puts.\n");
	  exit(0); }
	if(puts(bufa) ==  EOF) {
	  fprintf(stderr, "error on puts.\n");
	  exit(0); }
	if(puts(buf) ==  EOF) {
	  fprintf(stderr, "error on puts.\n");
	  exit(0); }
	fprintf(stdout, "\n\n");
	eflag = 1;
	break;
    }
    strcpy(bufb, bufa);
    strcpy(bufa, buf);
  }

  if(bflag != 1) {
    fprintf(stderr, "Error: never found \"begin\" line.\n");
    exit(0) ; }
  if(eflag != 1) {
    fprintf(stderr, "Error: never found \"end\" line. num = %d\n", num);
    exit(0) ; }

  fclose(in);
  fprintf(stderr, " done.\nFound %d lines in file.\n", num);
}

w8sdz@rigel.acs.oakland.edu (Keith Petersen) (06/06/91)

Stefan Parmark's uucat works very well for joining uuencoded file parts.

Keith
--
Keith Petersen
Maintainer of the MSDOS, MISC and CP/M archives at SIMTEL20 [192.88.110.20]
Internet: w8sdz@WSMR-SIMTEL20.Army.Mil    or     w8sdz@vela.acs.oakland.edu
Uucp: uunet!umich!vela!w8sdz                          BITNET: w8sdz@OAKLAND


---Forwarded message:
From: d84sp@efd.lth.se (Stefan Parmark)
Subject: uucat - updated version
Date: 29 Sep 90 07:35:26 GMT

I'm glad my program uucat.c was appreciated, and is used by
many of you out there.  So I decided to post an updated version.
For those who don't know what uucat is, here's a description:

You use it to uudecode multi-part uuencoded files.  It has worked
for all newsgroups I have tested so far.  It saves you the effort
of having to edit the files.  To compile it, extract everything
between the two lines which say 'CUT HERE', and save it as uucat.c.
To compile it on a Unix machine, type

> cc -o uucat uucat.c

On other machines, the C compiler is called something else.

In order to decode files, type

> uucat file1 file2 ... filen | uudecode
or

> cat file1 file2 ... filen | uucat | uudecode

or, if you already have concatenated them into one file

> uucat file | uudecode

Uucat is placed in the public domain, and I assume no responsibility
for its usage.

I would like to add the fact that some news readers have this function
built-in.. nn has, but rn, which I use, hasn't.

/Stefan
-- 
------------------------------------------------------------------
Stefan Parmark		d84sp@efd.lth.se
------------------------------------------------------------------

---CUT HERE---

/* uucat.c */

#include <stdio.h>
#include <string.h>

#define TRUE	1
#define FALSE	0

#define LENGTH	150

extern void uuread();


void main(argc, argv)
int argc;
char *argv[];
{
  int error, argno;
  FILE *infile;

  if (argc < 2)
    uuread(stdin);
  else
  {
    error = FALSE;
    for (argno = 1; !error && argno < argc; argno++)
    {
      if ((infile = fopen(argv[argno], "r")) == NULL)
      {
	error = TRUE;
	fprintf(stderr, "uucat: Can't open '%s' for input.\n", argv[argno]);
      }
      else
      {
	uuread(infile);
	fclose(infile);
      }
    }
  }

  exit(0);
}


void uuread(infile)
FILE *infile;
{
  char *s2, *s1, *s0, *tmp_s;
  int length;
  static char s[3 * (LENGTH + 1)];
  static int echo_on = FALSE, started = FALSE, just_finished = FALSE;
  static int line_length = 0, lines_to_go = 0;

  s0 = s;
  s1 = s0 + (LENGTH + 1);
  s2 = s1 + (LENGTH + 1);

  s0[0] = s1[0] = s2[0] = '\0';  /* Clear strings */

  while (fgets(s0, LENGTH, infile) != NULL)
  {
    s0[LENGTH] = '\0';  /* Make sure string is terminated */

    if (just_finished)
    {
      if (strncmp(s0, "size ", 5) == 0)
      {
	fputs(s0, stdout);
	s0[0] = '\0';
      }
      just_finished = FALSE;
    }

    if (!started)
    {
      if (strncmp(s0, "begin ", 6) == 0)
      {
	started = echo_on = TRUE;
	line_length = 0;
	lines_to_go = 0;
      }
    }
    else  /* started */
    {
      length = strlen(s0);
      if (line_length == 0)
	line_length = length;

      if (echo_on)
      {
	lines_to_go = 0;
	if (s0[0] != 'M' || length != line_length)
	{
	  echo_on = FALSE;
	  lines_to_go = 2;  /* Lines to go before 'end' is expected */
	  if (s0[0] == ' ' || s0[0] == '`')
	    lines_to_go = 1;
	}
      }
      else  /* !echo_on */
      {
	if (s0[0] == 'M' && length == line_length)
	  echo_on = TRUE;
	else if (lines_to_go > 0)
	{
	  if (lines_to_go == 2)
	  {
	    if (s0[0] == ' ' || s0[0] == '`')
	      lines_to_go = 1;
	    else
	      lines_to_go = 0;  /* Unexpected line, so break off */
	  }
	  else if (lines_to_go == 1)
	  {
	    if (strcmp(s0, "end\n") == 0)
	    {
	      fputs(s2, stdout);
	      fputs(s1, stdout);
	      fputs(s0, stdout);
	      lines_to_go = 0;  /* Done. Break off */
	      just_finished = TRUE;
	      started = FALSE;
	    }
	    else
	      lines_to_go = 0;  /* Unexpected line, so break off */
	  }
	}
      }
    }

    if (echo_on)
    {
      fputs(s0, stdout);
      s0[0] = '\0';
    }

    tmp_s = s2;
    s2 = s1;
    s1 = s0;
    s0 = tmp_s;
  }
}

---CUT HERE---