home *** CD-ROM | disk | FTP | other *** search
/ Amiga ISO Collection / AmigaUtilCD1.iso / Cruncher / XPK416SR.LHA / xpk_Source / shell / xPK.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-09-06  |  8.6 KB  |  399 lines

  1. #define NAME        "xPK"
  2. #define DISTRIBUTION    "(Freeware) "
  3. #define REVISION    "3"
  4.  
  5. /* Programmheader
  6.  
  7.     Name:        xPK
  8.     Author:        SDI (before 1.2 Urban Dominik Müller)
  9.     Distribution:    Freeware
  10.     Description:    General XPK file-to-file packer/unpacker
  11.     Compileropts:    -
  12.     Linkeropts:    -l xpkmaster
  13.  
  14.  1.0    : first public release
  15.  1.1    : docs written, version string added
  16.  1.2   19.10.96 : fixed an recursion error
  17.  1.3   29.11.96 : recompiled
  18. */
  19.  
  20. #include "SDI_defines.h"
  21. #define SDI_TO_ANSI
  22. #include "SDI_ASM_STD_protos.h"
  23. #include <proto/exec.h>
  24. #include <proto/dos.h>
  25. #include <proto/xpkmaster.h>
  26. #include <exec/memory.h>
  27.  
  28. #ifdef __MAXON__
  29.   #define __asm
  30.   #define __saveds
  31. #endif
  32.  
  33. #define lines[1000]
  34.  
  35. ULONG __asm __saveds chunkfunc(register __a1 struct XpkProgress *);
  36. STRPTR tempname(STRPTR);
  37. STRPTR basename(STRPTR);
  38. void   doarg(STRPTR);
  39. STRPTR dofile(STRPTR, struct FileInfoBlock *);
  40. void   end(STRPTR);
  41. LONG   isexecutable(STRPTR);
  42.  
  43. struct Hook         chunkhook    = {{0}, (ULONG (*) ()) chunkfunc};
  44. struct Library         *XpkBase    = 0;
  45. UBYTE            errbuf[300],
  46.             *err        = 0,
  47.             namebuf[200],
  48.             PrevName[100],
  49.             strbuf[200];
  50. struct FileInfoBlock     *fib        = 0;
  51.  
  52. UBYTE usage[] =
  53. "Usage: XPK [-efrsux] [-m method] [-p password] files\n"
  54. "       -e = extract files (same as -u)\n"
  55. "       -f = force packing of already packed files\n"
  56. "       -m = four letter packing method name\n"
  57. "       -p = encrypt/decrypt using password\n"
  58. "       -r = recursively (un)pack files in dir\n"
  59. "       -s = add suffix and don't delete original\n"
  60. "       -x = pack executables only\n";
  61.  
  62. UBYTE    suffix = 0, force = 0, unpack = 0, recurse = 0, depth = 0, executables = 0;
  63. STRPTR  password = 0, method = 0;
  64.  
  65. void main(int argc, char **argv)
  66. {
  67.   STRPTR c;
  68.   LONG i = 1;
  69.  
  70.   if(!(XpkBase = OpenLibrary(XPKNAME, 0)) ||
  71.   !(fib = (struct FileInfoBlock *) AllocMem(sizeof(struct FileInfoBlock), MEMF_ANY|MEMF_CLEAR)))
  72.     end("Cannot open " XPKNAME "\n");
  73.  
  74.   if(stricmp(basename(argv[0]), "XPK"))
  75.     method = basename(argv[0]);
  76.   else if(argc < 2 || !strcmp (argv[1], "?"))
  77.     end(usage);
  78.  
  79.   for(; *argv[i] == '-'; i++)
  80.     for(c = argv[i] + 1; *c; c++)
  81.     {
  82.       switch (*c)
  83.       {
  84.       case 'p': password = argv[++i]; break;
  85.       case 'm': method = argv[++i]; break;
  86.       case 's': suffix = 1; break;
  87.       case 'f': force = 1; break;
  88.       case 'e':
  89.       case 'u':    unpack = 1; break;
  90.       case 'r': recurse = 1; break;
  91.       case 'x':    executables = 1; break;
  92.       default: end(usage);
  93.       }
  94.       if(i >= argc)
  95.     end(usage);
  96.     }
  97.  
  98.   if(!method && !unpack)
  99.     end("Need a packing method, use -m\n");
  100.  
  101.   if(i == argc)
  102.     end(usage);
  103.  
  104.   for(; i < argc && !err; i++)
  105.     doarg(argv[i]);
  106.  
  107.   end(err);
  108. }
  109.  
  110. void iprint(STRPTR s)
  111. {
  112.   ULONG out = Output(), i;
  113.   for(i = depth; i; --i)
  114.     Write(out, "  ", 2);
  115.   Write(out, s, strlen(s));
  116. }
  117.  
  118. void doarg(STRPTR name)
  119. {
  120.   ULONG lock;
  121.  
  122.   if(*name == 0xFF)
  123.     return;
  124.  
  125.   if(!(lock = Lock(name, ACCESS_READ)))
  126.   {
  127.     sprintf(err = errbuf, "Error %ld reading %s\n", IoErr(), name);
  128.     return;
  129.   }
  130.  
  131.   if(!Examine(lock, fib))
  132.   {
  133.     UnLock(lock);
  134.     sprintf(err = errbuf, "Error %ld reading %s\n", IoErr(), name);
  135.     return;
  136.   }
  137.  
  138.   if(fib->fib_DirEntryType < 0)
  139.   {
  140.     UnLock(lock);
  141.     dofile(name, fib);
  142.   }
  143.   else if(recurse)
  144.   {
  145.     ULONG prev;
  146.  
  147.     sprintf(strbuf, "Directory %s\n", name);
  148.     iprint(strbuf);
  149.     prev = CurrentDir(lock);
  150.     *PrevName = 0xFF;
  151.  
  152.     while(ExNext(lock, fib) && !err)
  153.     {
  154.       if(SetSignal(0, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C)
  155.     err = " *** Break";
  156.       else
  157.       {
  158.         STRPTR thisname;
  159.     ULONG i = strlen(fib->fib_FileName) + 1;
  160.  
  161.         if(!(thisname = (STRPTR) AllocMem(i, MEMF_ANY)))
  162.         {
  163.           Write(Output(), "Not enough memory\n", 18);
  164.           break;
  165.         }
  166.     CopyMem(fib->fib_FileName, thisname, i);
  167.     depth++;
  168.     doarg(PrevName);
  169.     depth--;
  170.     strcpy(PrevName, thisname);
  171.     FreeMem(thisname, i);
  172.       }
  173.     }
  174.     depth++;
  175.     doarg(PrevName);
  176.     depth--;
  177.     *PrevName = 0xFF;
  178.  
  179.     UnLock(CurrentDir(prev));
  180.   }
  181. }
  182.  
  183. STRPTR dofile(STRPTR filename, struct FileInfoBlock *fib)
  184. {
  185.   struct XpkFib xfib;
  186.   UBYTE buf[100];
  187.   LONG len;
  188.  
  189.   if(!force || unpack)
  190.   {
  191. #ifdef __MAXON__            /* Maxon has no tagcall pragma now */
  192.       struct TagItem t[] = {        /* and I don't want to use a link */
  193. #else                    /* library */
  194.       if(XpkExamineTags(&xfib,
  195. #endif
  196.     XPK_InName, (ULONG) filename,
  197.     TAG_DONE
  198. #ifdef __MAXON__
  199.       , 0 };
  200.       if(XpkExamine(&xfib, t
  201. #endif
  202.     ))
  203.     {
  204.       sprintf(buf, "Error examining %s\n", filename);
  205.       iprint(buf);
  206.       return 0;
  207.     }
  208.   }
  209.  
  210.   tempname(filename);
  211.   if(!unpack)
  212.   {
  213.     if(!force && xfib.xf_Type != XPKTYPE_UNPACKED)
  214.     {
  215.       sprintf(buf, "Skipping (already packed) %s\n", filename);
  216.       iprint(buf);
  217.       return 0;
  218.     }
  219.  
  220.     if(executables && !isexecutable(filename))
  221.       return 0;
  222.  
  223.     if(suffix)
  224.       sprintf(namebuf, "%s.xpk", filename);
  225.  
  226.     {
  227. #ifdef __MAXON__            /* Maxon has no tagcall pragma now */
  228.       struct TagItem t[] = {        /* and I don't want to use a link */
  229. #else                    /* library */
  230.       if(XpkPackTags(
  231. #endif
  232.         XPK_InName, (ULONG) filename,
  233.     XPK_OutName, (ULONG) namebuf,
  234.     XPK_ChunkHook, (ULONG) &chunkhook,
  235.     XPK_GetError, (ULONG) errbuf,
  236.     XPK_PackMethod, (ULONG) method,
  237.     XPK_Password, (ULONG) password,
  238.     XPK_NoClobber, TRUE,
  239.     TAG_DONE
  240. #ifdef __MAXON__
  241.       , 0 };
  242.       if(XpkPack(t
  243. #endif
  244.       ))
  245.       {
  246.         ULONG i = strlen(errbuf);
  247.         errbuf[i] = '\n'; errbuf[i+1] = '\0';
  248.         return err = errbuf;
  249.       }
  250.     }
  251.   }
  252.   else
  253.   {
  254.     if(xfib.xf_Type != XPKTYPE_PACKED)
  255.     {
  256.       sprintf(buf, "Skipping (already unpacked) %s\n", filename);
  257.       iprint(buf);
  258.       return 0;
  259.     }
  260.  
  261.     len = strlen(filename);
  262.     suffix = 0;
  263.     if(len > 4 && !stricmp(filename + len - 5, ".xpk"))
  264.     {
  265.       strcpy(namebuf, filename);
  266.       namebuf[len - 5] = 0;
  267.       suffix = 1;
  268.     }
  269.  
  270.     {
  271. #ifdef __MAXON__            /* Maxon has no tagcall pragma now */
  272.       struct TagItem t[] = {        /* and I don't want to use a link */
  273. #else                    /* library */
  274.       if(XpkUnpackTags(
  275. #endif
  276.     XPK_InName, (ULONG) filename,
  277.     XPK_FileName, (ULONG) filename,
  278.     XPK_OutName, (ULONG) namebuf,
  279.     XPK_ChunkHook, (ULONG) &chunkhook,
  280.     XPK_Password, (ULONG) password,
  281.     XPK_GetError, (ULONG) errbuf,
  282.     XPK_NoClobber, TRUE,
  283.     TAG_DONE
  284. #ifdef __MAXON__
  285.       , 0 };
  286.       if(XpkUnpack(t
  287. #endif
  288.       ))
  289.       {
  290.         ULONG i = strlen(errbuf);
  291.         errbuf[i] = '\n'; errbuf[i+1] = '\0';
  292.         return err = errbuf;
  293.       }
  294.     }
  295.   }
  296.  
  297.   if(!suffix)
  298.   {
  299.     if(!DeleteFile(filename))
  300.       return err = "Cannot delete input file\n";
  301.     if(!Rename(namebuf, filename))
  302.       return err = "Cannot rename tempfile\n";
  303.     if(*fib->fib_Comment && !SetComment(filename, fib->fib_Comment))
  304.       return err = "Cannot set original comment\n";
  305.     if(fib->fib_Protection && !SetProtection(filename, fib->fib_Protection))
  306.       return err = "Cannot set original protection bits\n";
  307.   }
  308. }
  309.  
  310. ULONG __asm __saveds chunkfunc(register __a1 struct XpkProgress *prog)
  311. {
  312.   ULONG out = Output();
  313.   UBYTE buf[180];
  314.  
  315.   if(prog->xp_Type == XPKPROG_START)
  316.     Write(out, "\033[0 p", 5);
  317.  
  318.   if(prog->xp_Type != XPKPROG_END)
  319.     sprintf(buf,
  320.          "%4s: %-8s (%3ld%% done, %2ld%% CF, %6ld cps) %s\033[K\r",
  321.          prog->xp_PackerName, prog->xp_Activity, prog->xp_Done,
  322.          prog->xp_CF, prog->xp_Speed, prog->xp_FileName);
  323.   else
  324.     sprintf(buf,
  325.          "%4s: %-8s (%3ldK, %2ld%% CF, %6ld cps) %s\033[K\n",
  326.          prog->xp_PackerName, prog->xp_Activity, prog->xp_ULen / 1024,
  327.          prog->xp_CF, prog->xp_Speed, prog->xp_FileName);
  328.  
  329.   iprint(buf);
  330.  
  331.   if(prog->xp_Type == XPKPROG_END)
  332.     Write(out, "\033[1 p", 5);
  333.  
  334.   return SetSignal(0, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C;
  335. }
  336.  
  337. STRPTR tempname(STRPTR name)
  338. {
  339.   strcpy(namebuf, name);
  340.   for(name = namebuf + strlen (namebuf); name > namebuf; name--)
  341.     if(name[-1] == '/' || name[-1] == ':')
  342.       break;
  343.   sprintf(name, "tmp%lx", &name);
  344.   return namebuf;
  345. }
  346.  
  347. LONG isexecutable(STRPTR name)
  348. {
  349.   ULONG fh;
  350.   BPTR buf[5];
  351.   UBYTE msg[100];
  352.   LONG len;
  353.  
  354.   if(!(fh = Open(name, MODE_OLDFILE)))
  355.   {
  356.     sprintf(msg, "Cannot open %s\n", name);
  357.     iprint(msg);
  358.     return 0;
  359.   }
  360.   len = Read(fh, (void *) buf, 20);
  361.   Close(fh);
  362.  
  363.   if(len < 20 || buf[0] != 0x3f3 || buf[1] != 0)
  364.   {
  365.     sprintf(msg, "%s not executable\n", name);
  366.     iprint(msg);
  367.     return 0;
  368.   }
  369.  
  370.   if(buf[3] != 0 || buf[4] + 1 != buf[2])
  371.   {
  372.     sprintf(msg, "%s overlayed\n", name);
  373.     iprint(msg);
  374.     return 0;
  375.   }
  376.   return 1;
  377. }
  378.  
  379. STRPTR basename(STRPTR name)
  380. {
  381.   STRPTR ret = name;
  382.  
  383.   for(; *name; ++name)
  384.   {
  385.     if(*name == ':' || *name == '/')
  386.       ret = name + 1;
  387.   }
  388.   return ret;
  389. }
  390.  
  391. void end(STRPTR text)
  392. {
  393.   if(text)    Write(Output(), text, strlen(text));
  394.   if(XpkBase)    CloseLibrary(XpkBase);
  395.   if(fib)    FreeMem(fib, sizeof(struct FileInfoBlock));
  396.  
  397.   exit(text ? 10 : 0);
  398. }
  399.