---[  Phrack Magazine   Volume 8, Issue 52 January 26, 1998, article 20 of 20


-------------------------[  Phrack Magzine Extraction Utility


--------[  Phrack Staff


   Added to the list of extraction variants this time is a version in AWK,
   and a version in sh.  Also, the C version has ben spruced up to accept
   file name globs.  Keep `em coming...


---------------------8<------------CUT-HERE----------->8---------------------

<++> PEU/extract2.c
/*  extract.c by Phrack Staff and sirsyko
*
*  (c) Phrack Magazine, 1997
*      1.8.98 rewritten by route:
*          - aesthetics
*          - now accepts file globs
*      todo:
*          - more info in tag header (file mode, checksum)
*  Extracts textfiles from a specially tagged flatfile into a hierarchical
*  directory strcuture.  Use to extract source code from any of the articles
*  in Phrack Magazine (first appeared in Phrack 50).
*
*  gcc -o extract extract.c
*
*  ./extract file1 file2 file3 ...
*/


#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <string.h>
#include <dirent.h>

#define BEGIN_TAG   "<++> "
#define END_TAG     "<-->"
#define BT_SIZE     strlen(BEGIN_TAG)
#define ET_SIZE     strlen(END_TAG)

struct f_name
{
   u_char name[256];
   struct f_name *next;
};

int
main(int argc, char **argv)
{
   u_char b[256], *bp, *fn;
   int i, j = 0;
   FILE *in_p, *out_p = NULL;
   struct f_name *fn_p = NULL, *head = NULL;

   if (argc < 2)
   {
       printf("Usage: %s file1 file2 ... filen\n", argv[0]);
       exit(0);
   }

   /*
    *  Fill the f_name list with all the files on the commandline (ignoring
    *  argv[0] which is this executable).  This includes globs.
    */
   for (i = 1; (fn = argv[i++]); )
   {
       if (!head)
       {
           if (!(head = (struct f_name *)malloc(sizeof(struct f_name))))
           {
               perror("malloc");
               exit(1);
           }
           strncpy(head->name, fn, sizeof(head->name));
           head->next = NULL;
           fn_p = head;
       }
       else
       {
           if (!(fn_p->next = (struct f_name *)malloc(sizeof(struct f_name))))
           {
               perror("malloc");
               exit(1);
           }
           fn_p = fn_p->next;
           strncpy(fn_p->name, fn, sizeof(fn_p->name));
           fn_p->next = NULL;
       }
   }
   /*
    *  Sentry node.
    */
   if (!(fn_p->next = (struct f_name *)malloc(sizeof(struct f_name))))
   {
       perror("malloc");
       exit(1);
    }
   fn_p = fn_p->next;
   fn_p->next = NULL;

   /*
    *  Check each file in the f_name list for extraction tags.
    */
   for (fn_p = head; fn_p->next; fn_p = fn_p->next)
   {
       if (!(in_p = fopen(fn_p->name, "r")))
       {
           fprintf(stderr, "Could not open input file %s.\n", fn_p->name);
           continue;
       }
       else fprintf(stderr, "Opened %s\n", fn_p->name);
       while (fgets(b, 256, in_p))
       {
           if (!strncmp (b, BEGIN_TAG, BT_SIZE))
           {
               b[strlen(b) - 1] = 0;           /* Now we have a string. */
               j++;

               if ((bp = strchr(b + BT_SIZE + 1, '/')))
               {
                   while (bp)
                   {
                       *bp = 0;
                       mkdir(b + BT_SIZE, 0700);
                       *bp = '/';
                       bp = strchr(bp + 1, '/');
                   }
               }
               if ((out_p = fopen(b + BT_SIZE, "w")))
               {
                   printf("- Extracting %s\n", b + BT_SIZE);
               }
               else
               {
                   printf("Could not extract '%s'.\n", b + BT_SIZE);
                   continue;
               }
           }
           else if (!strncmp (b, END_TAG, ET_SIZE))
           {
               if (out_p) fclose(out_p);
               else
               {
                   fprintf(stderr, "Error closing file %s.\n", fn_p->name);
                   continue;
               }
           }
           else if (out_p)
           {
               fputs(b, out_p);
           }
       }
   }
   if (!j) printf("No extraction tags found in list.\n");
   else printf("Extracted %d file(s).\n", j);
   return (0);
}

/* EOF */
<-->
<++> PEU/extract.pl
# Daos <[email protected]>
#!/bin/sh -- # -*- perl -*- -n
eval 'exec perl $0 -S ${1+"$@"}' if 0;

$opening=0;

if (/^\<\+\+\>/) {$curfile = substr($_ , 5); $opening=1;};
if (/^\<\-\-\>/) {close ct_ex; $opened=0;};
if ($opening) {
       chop $curfile;
       $sex_dir= substr( $curfile, 0, ((rindex($curfile,'/'))) ) if ($curfile =~ m/\//);
       eval {mkdir $sex_dir, "0777";};
       open(ct_ex,">$curfile");
       print "Attempting extraction of $curfile\n";
       $opened=1;
}
if ($opened && !$opening) {print ct_ex $_};
<-->

<++> PEU/extract.awk
#!/usr/bin/awk -f
#
# Yet Another Extraction Script
# - <sirsyko>
#
/^\<\+\+\>/ {
       ind = 1
       File = $2
       split ($2, dirs, "/")
       Dir="."
       while ( dirs[ind+1] ) {
               Dir=Dir"/"dirs[ind]
               system ("mkdir " Dir" 2>/dev/null")
               ++ind
       }
       next
}
/^\<\-\-\>/ {
       File = ""
       next
}
File { print >> File }
<-->

<++> PEU/extract.sh
#!/bin/sh
# exctract.sh : Written 9/2/1997 for the Phrack Staff by <sirsyko>
#
# note, this file will create all directories relative to the current directory
# originally a bug, I've now upgraded it to a feature since I dont want to deal
# with the leading / (besides, you dont want hackers giving you full pathnames
# anyway, now do you :)
# Hopefully this will demonstrate another useful aspect of IFS other than
# haxoring rewt
#
# Usage: ./extract.sh <filename>

cat $* | (
Working=1
while [ $Working ];
do
       OLDIFS1="$IFS"
       IFS=
       if read Line; then
               IFS="$OLDIFS1"
               set -- $Line
               case "$1" in
               "<++>") OLDIFS2="$IFS"
                       IFS=/
                       set -- $2
                       IFS="$OLDIFS2"
                       while [ $# -gt 1 ]; do
                               File=${File:-"."}/$1
                               if [ ! -d $File ]; then
                                       echo "Making dir $File"
                                       mkdir $File
                               fi
                               shift
                       done
                       File=${File:-"."}/$1
                       echo "Storing data in $File"
               ;;
               "<-->") if [ "x$File" != "x" ]; then
                               unset File
                       fi ;;
               *)      if [ "x$File" != "x" ]; then
                                       IFS=
                                       echo "$Line" >> $File
                                       IFS="$OLDIFS1"
                       fi
               ;;
               esac
               IFS="$OLDIFS1"
       else
               echo "End of file"
               unset Working
       fi
done
)
<-->

----[  EOF