/*
From: jpsdiry@daimi.aau.dk          Article 3993 of alt.binaries.pictures.misc

xcchen@iastate.edu (Xiaoshan Chen) writes:

>Hi, there,
>Please re-post the eek.c on this group, because I found it easy to use and
>time-saving. I have recommended it to a friend of mine but I lost my source
>code.
>Thank you in advance !

eek2.c is better, and follows. If problems (anyone), email me, and I'll
email it instead. (There is an even later version, but I haven't tried
it out yet. If interested, email me.)

>-- 
>********************************************************************
>xcchen@iastate.edu; 294-3887 (O); 296-7917 (H)
>A volleyball lover

----------CUT----------CUT----------
*/
/*
 * This UNIX C program takes any number of uuencoded files
 * from <stdin>, extracts the good stuff, and feeds
 * each file one at a time to uudecode.
 *
 * To compile, "cc -o eek eek.c" should suffice.
 *
 * For example, if you want to extract images from news:
 *
 * From within "rn" (readnews), once in the pictures group,
 * you can hit "=" (equals sign) to get a listing of the
 * headers.  Here's an example of a few lines of the output:
 *
   3219 Marilyn Monroe 2 of 3
   3220 Marilyn Monroe 1 of 3
   3221 Marilyn Monroe 3 of 3
   3223 .zip and .gl files
   3224 Vibrators.gif (1/3)
   3225 Vibrators.gif (2/3)
   3226 Vibrators.gif (3/3)
   3227 Cindy.gif (1/1)
   3228 Blair.gif (1/1)
 *
 * From the prompt, you can use the 's' command like this:
 *
     [rn prompt from within the group] 3220,3219,3221,3224-3228 s ims
 *
 * If this is the first set of images this run, it will ask if you
 * want mailbox format, to which "n" (no) is the best response, though
 * it shouldn't make much difference.
 *
 * This will send four pictures to the file "ims".  Notice that when
 * the parts aren't in order, you have to specify the numbers in the
 * proper order -- but it can still be done on one line (in one command).
 *
 * Once out of "rn", the command
 *
     eek < ims
 *
 * will extract the four images into the current directory, at which point
 * you probably want to remove "ims" so you can start fresh next time.
 *
 * It will break if someone has junk lines starting with "end" or "begin #".
 * Probably in other ways too.  But heh, it's free.  Whaddya want?  If you
 * improve upon it, please send me a copy so I can use it too.
 *
 * If you find it useful, drop me a note so I can feel all warm inside.
 *
 *  - Brandyn (brandyn@apple.com), 1/25/90
 *
 * Ps. I've added a few trivial enhancements:
 *
 *    - If multiple archives are in one file, and one of them is corrupt
 *      and missing an "end" line, Eek will detect the "begin" line of the
 *      next archive and start a new extraction.  Before, it would loose
 *      the second file (actually, it would pack it onto the end of the
 *      corrupt one, not knowing any better).
 *
 *    - If the file to be extracted already exists, the name of the new
 *      file will have a "+" appended to it (or ++, +++, etc.. until it
 *      finds an unused name).  This is to insure that eek doesn't clobber
 *      any of your files.  Bug: Eek determines the existance of a file by
 *      trying to open it for reading.  If the file is not readable, eek
 *      will think it is not there and use the same name.  If it is writable,
 *      it will clobber it.  Cheap hack, obscure bug.  That's life.
 *
 *    - The mode of the extracted file will always be 600.  You can change
 *      the code if you want another default.  Some postings had obnoxious
 *      protection modes (like 0) so I found this useful.
 *
 *  -Brandyn - 1/17/92 (Two years! Boy do I feel old.)
 */

#include <ctype.h>
#include <stdio.h>

    /*
     * Current input line (which
     * may be held over from earlier):
     */
    static char curline[512];
    static int  heldover=0;

main()
{
    FILE *uu;
    int num;

    for (num=0; ; num++) {
        printf("Extracting file %d: ",num); fflush(stdout);
        uu  = popen("uudecode","w");
        if (CopyOne(stdin,uu))
            break;
        pclose(uu);
        /* printf("Done\n"); */
    }

    printf("oops, no more.\n");
    pclose(uu);
}

/*
 * Throws the input stream <from> away until
 * it finds "begin ...", then copies
 * all uuencode type lines to <to> until
 * it finds "end ..." at which point it may
 * reintroduce the last one or two "rejected"
 * lines to account for uuencode's funny endings.
 *
 * Returns TRUE on EOF.
 */
CopyOne(from,to)
FILE *from,*to;
{
    int len;
    char new[250];
    char a[250],b[250];
    char *res;

    /*
     * Find the begin line, or use
     * the heldover one:
     */
    if (!heldover) {

        while (res = fgets(curline,250,from))
            if (strncmp(curline,"begin ",6)==0 && isdigit(curline[6]))
                break;

        if (!res)
            return(1);

    } else
        heldover=0;

    RewriteHeader(curline,new);
    printf(" %s",new); fflush(stdout);
    fputs(new,to);

    while (res = fgets(curline,250,from)) {

        if (!strncmp(curline,"end",3))
            break;

        len = strlen(curline);

        if (curline[0] != 'M' ||
            len < 60      ||
            len > 70      ||
            (strncmp(curline,"Message-ID",10)==0)) {

                /*
                 * Check for nested "begin" line:
                 */
                if (strncmp(curline,"begin ",6)==0 && isdigit(curline[6])) {
                    heldover++;
                    fprintf(stderr,"Eek! Found a nested begin line!\n");
                    fputs("end\n",to);
                    return(0);
                }

                /* fprintf(stderr,"Rejecting \"%s\"\n",curline); */
                strcpy(b,a);
                strcpy(a,curline);
                continue;

        }
        a[0] = '\0';
        b[0] = '\0';
        fputs(curline,to);
    }

    if (!res) {
        fprintf(stderr,
            "Warning: hit end of file without ever finding \"end\"\n");
        exit(0);
    }

    if (b[0]) {
        /* fprintf(stderr,"Restoring \"%s\"\n",b); */
        fputs(b,to);
    }

    if (a[0]) {
        /* fprintf(stderr,"Restoring \"%s\"\n",a); */
        fputs(a,to);
    }
    fputs(curline,to);

    return(0);
}

RewriteHeader(old,new)
char *old;
char *new;
{
    char fname[256];

    if (ExtractFileName(old,fname,250)) {
        strcpy(new,old);
        fprintf(stderr,"[can't parse header!!]");
        fflush(stderr);
        return;
    }

    while (Isafile(fname))
        strcat(fname,"+");

    sprintf(new,"begin 600 %s\n",fname);
}

Isafile(fn)
char *fn;
{
    FILE *fp;

    if (fp = fopen(fn,"r")) {
        fclose(fp);
        return(1);
    }
    return(0);
}

/*
 * I don't know, maybe I was tired when
 * I wrote this.  But you must admit it's
 * robust?  I know, I know -- use sscanf.
 * I must have had a reason to do it this
 * way... (ehem).
 */
ExtractFileName(header,fname,len)
char *header,*fname;
int len;
{
    int i,j;

    for (j=5; header[j]==' '; j++)
        ;
    for (; header[j] && header[j]!=' '; j++)
        ;
    for (; header[j]==' '; j++)
        ;
    for (i=0; i<len; i++) {
        fname[i] = header[i+j];
        if (fname[i] == ' '  ||
            fname[i] == '\t' ||
            fname[i] == '\n' ||
            fname[i] == '\0')
            break;
    }
    fname[i] = '\0';

    if (!i)
        return(1);

    return(0);
}

/*
----------CUT----------CUT----------
--
Joern Poulsen, jpsdiry@daimi.aau.dk | "...no more deals Kirsty. It's your flesh we   
   Institute of mathematics and     | want to experience, not your skill of bargening
         computer science.          | ...trick us again child, and your suffering    
  University of Aarhus, Denmark.    | will be legendary, even in Hell..." (Hellbound)
*/
