home *** CD-ROM | disk | FTP | other *** search
/ Amiga MA Magazine 1998 #6 / amigamamagazinepolishissue1998.iso / packery / xpk_source / shell / xpk.c < prev    next >
C/C++ Source or Header  |  1996-11-12  |  9KB  |  393 lines

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