home *** CD-ROM | disk | FTP | other *** search
/ Amiga Elysian Archive / AmigaElysianArchive.iso / compress / arcex20.lha / ArcEx.c < prev    next >
C/C++ Source or Header  |  1992-09-12  |  10KB  |  433 lines

  1. //:ts=8
  2. /////////////////////////////////////////////////////////////////////////////
  3. //
  4. // ArcEx V2.0 - V37+ only
  5. //
  6. // Mostly done for general 2.x practice ;-)
  7. //
  8. // Note: ArcEx is somewhat large, but notice that it checks everything,
  9. //       even small allocations which probably never fail.
  10. //
  11. //
  12. // Compile with Aztec C V5.2a
  13. //
  14. // 1> cc -il ArcEx
  15. // 2> ln ArcEx -lcl
  16. //
  17. /////////////////////////////////////////////////////////////////////////////
  18. //
  19. // This program and sourcecode is © 1992 Mark Cassidy
  20. //
  21. // You are allowed to distribute and modify this, as long as you always
  22. // distribute the original source along with it.  NO profit of any kind may
  23. // be made from any such distribution.
  24. //
  25. /////////////////////////////////////////////////////////////////////////////
  26. //
  27. // Notes:
  28. //
  29. // I do not use any non-constant global variables, and I beleive this is a
  30. // good example of good programming practise, unlike some sources I've seen
  31. // from a C=ompany whose name I won't mention here :-)
  32. // - However, the DOSBase is (at present time) somewhat impossible for me to
  33. //   get rid of, as this is initialized (as a global) by the startup-code.
  34. //
  35. // I use almost entirely V37 dos.library routines, not because I HAD to, but
  36. // because I began programming V37 only yesterday, so I needed some practice
  37. // in using them.
  38. //
  39. /////////////////////////////////////////////////////////////////////////////
  40. //
  41. // Many thanks must go to Klaus Seistrup#2:230/119.0 for his patience with
  42. // me during the development of this program.
  43. //
  44. // Also thanks to Jesper Kehlet#2:230/413.0 for helpfully providing me with
  45. // Klaus' source-codes :-)
  46. //
  47. /////////////////////////////////////////////////////////////////////////////
  48.  
  49.  
  50. /////////////////////////////////////////////////////////////////////////////
  51. // Includes.
  52. /////////////////////////////////////////////////////////////////////////////
  53. #include <exec/memory.h>
  54. #include <exec/types.h>
  55. #include <exec/libraries.h>
  56. #include <dos/dos.h>
  57. #include <dos/rdargs.h>
  58. #include <dos/dostags.h>
  59. #include <dos/dosasl.h>
  60. #include <pragmas/dos_lib.h>
  61.  
  62.  
  63. /////////////////////////////////////////////////////////////////////////////
  64. // User-defines.
  65. /////////////////////////////////////////////////////////////////////////////
  66. #define VERSION        20
  67. #define VERSIONSTR    "2.0"
  68. #define    MIN_DOSBASE    37
  69. #define    MIN_DOSBASESTR    "37"
  70.  
  71. #define    TEMPLATE "From/A/M,To"
  72. #define    OPT_FROM    0
  73. #define    OPT_TO        1
  74. #define OPT_COUNT    2
  75.  
  76. #define    ARC_LHA        0
  77. #define ARC_ARC        1
  78. #define ARC_ZOO        2
  79. #define ARC_ZIP        3
  80. #define    ARC_ARJ        4
  81. #define ARC_APE        5
  82. #define ARC_PP        6
  83. #define    ARC_NUMENT    7
  84. #define    ARC_UNKNOWN    -1
  85.  
  86.  
  87. /////////////////////////////////////////////////////////////////////////////
  88. // Global constant data
  89. /////////////////////////////////////////////////////////////////////////////
  90. const    char    *Version = "\0$VER: ArcEx "VERSIONSTR" ("__DATE__") © 1992 Wize Productions Denmark";
  91. const    char    *KS20    = "Sorry!, ArcEx needs Dos.library V"MIN_DOSBASESTR"+\n";
  92. const    char    *NameStr = "ArcEx "VERSIONSTR;
  93. const    char    *Poster  = "Finished! - Thanx for risking using ArcEx "VERSIONSTR" :-)\n";
  94.  
  95. extern    struct    Library    *DOSBase;
  96.  
  97.     struct ArcRec {
  98.         LONG    Offset;
  99.         LONG    ID;
  100.         LONG    Len;
  101.     };
  102.  
  103. const    struct ArcRec ArcRec[] = {
  104.         2, (LONG) '-lh\0', 3,        // LhA, LhArc
  105.         0, (LONG) 0x1a000000, 1,    // Arc
  106.         0, (LONG) 'ZOO\0', 3,        // Zoo
  107.         0, (LONG) 0x504b0304, 4,    // Zip
  108.         0, (LONG) 0x60ea0000, 2,    // Arj
  109.         0, (LONG) '$JPE', 4,        // APE
  110.         0, (LONG) 'PP\0\0', 2        // Power-'Packer'
  111.     };
  112.  
  113. const    char    *Extensions[] = { ".LHA", ".LZH", ".ARC", ".ZOO", ".ZIP", ".ARJ", ".APE", ".PP" };
  114.  
  115. const    char    *Extractors[] = {
  116.         "LhA -I -F -Qd -Qw -e -K -a -m -M x ",
  117.         "Arc xwn ",
  118.         "Zoo xO// ",
  119.         "UnZip -d ",
  120.         "UnArj x -y ",
  121.         "APE x ",
  122.         "Decrunch "
  123.     };
  124.  
  125.  
  126. /////////////////////////////////////////////////////////////////////////////
  127. // User-defined function prototypes.
  128. /////////////////////////////////////////////////////////////////////////////
  129. LONG    ArcEx(char *, char *, BOOL);
  130. LONG    WildArcEx(char *, char *);
  131. short    ArcType(char *);
  132.  
  133.  
  134. /////////////////////////////////////////////////////////////////////////////
  135. // Main module, overrides the normal Aztec startup-code/cli parsing.
  136. /////////////////////////////////////////////////////////////////////////////
  137. void _main(long alen, char *aptr)
  138. {
  139.     char        **FromFiles;
  140.     char        *To;
  141.     struct    RDArgs    *Args;
  142.     LONG        **Result;
  143.  
  144.     if (DOSBase->lib_Version < MIN_DOSBASE)
  145.     {
  146.         Write(Output(), KS20, strlen(KS20));
  147.         SetIoErr(ERROR_INVALID_RESIDENT_LIBRARY);
  148.         exit(RETURN_FAIL);
  149.     }
  150.  
  151.     if (!(Result = (LONG **)AllocVec(OPT_COUNT*sizeof(LONG), MEMF_ANY|MEMF_CLEAR)))
  152.     {
  153.         PrintFault(ERROR_NO_FREE_STORE, NameStr);
  154.         exit(RETURN_FAIL);
  155.     }
  156.  
  157.     if (Args = (struct RDArgs *)ReadArgs(TEMPLATE, Result, NULL))
  158.     {
  159.         Printf("%s\n\n", Version+7);
  160.  
  161.         FromFiles = (char **)Result[OPT_FROM];
  162.         To   = (char *)Result[OPT_TO];
  163.  
  164.         while(*FromFiles)
  165.         {
  166.             LONG    Ret;
  167.  
  168.             if (SetSignal(0,0) & SIGBREAKF_CTRL_C)
  169.             {
  170.                 SetSignal(0, SIGBREAKF_CTRL_C);
  171.                 PrintFault(ERROR_BREAK, NameStr);
  172.                 FreeVec(Result);
  173.                 exit(RETURN_WARN);
  174.             }
  175.  
  176.             if ( (Ret = WildArcEx(*(FromFiles++), To)) != RETURN_OK)
  177.             {
  178.                 FreeArgs(Args);
  179.                 FreeVec(Result);
  180.                 exit(Ret);
  181.             }
  182.         }
  183.  
  184.         FreeVec(Result);
  185.         FreeArgs(Args);
  186.     } else {
  187.         FreeVec(Result);
  188.         PrintFault(IoErr(), NameStr);
  189.         exit(RETURN_WARN);
  190.     }
  191.  
  192.     PutStr(Poster);
  193.     exit(RETURN_OK);
  194. }
  195.  
  196.  
  197. /////////////////////////////////////////////////////////////////////////////
  198. // The extract routine, extracts 1 file to destinaton.
  199. /////////////////////////////////////////////////////////////////////////////
  200. LONG ArcEx(char *From, char *To, BOOL WildScan)
  201. {
  202.     BPTR    FromLock;
  203.     BPTR    ToLock = 0;
  204.     BPTR    FileHandle;
  205.     BPTR    SaveDir = 0;
  206.     char    *FullName;
  207.     char    *SystemTagName;
  208.     char    *EnvBuf;
  209.     char    Buffer[6];
  210.     short    Type;
  211.     LONG    RetVal;
  212.  
  213.     if (!(FromLock = Lock(From, SHARED_LOCK)))
  214.     {
  215.         short    i;
  216.         char    *NewName = (char *)AllocVec(strlen(From)+5, MEMF_ANY);
  217.  
  218.         if (!NewName)
  219.         {
  220.             PrintFault(ERROR_NO_FREE_STORE, NameStr);
  221.             return(RETURN_FAIL);
  222.         }
  223.  
  224.         for(i=0; i<ARC_NUMENT; i++)
  225.         {
  226.             strcpy(NewName, From);
  227.             strcat(NewName, Extensions[i]);
  228.             FromLock = Lock(NewName, SHARED_LOCK);
  229.             if (FromLock)
  230.                 break;
  231.         }
  232.  
  233.         FreeVec(NewName);
  234.  
  235.         if ( (i==ARC_NUMENT) && (!WildScan) )
  236.         {
  237.             PrintFault(IoErr(), From);
  238.             return(RETURN_WARN);
  239.         }
  240.     }
  241.  
  242.     if (!(FullName = (char *)AllocVec(1024, MEMF_ANY)))
  243.     {
  244.         PrintFault(ERROR_NO_FREE_STORE, NameStr);
  245.         return(RETURN_FAIL);
  246.     }
  247.  
  248.     if(!(NameFromLock(FromLock, FullName, 1024L)))
  249.     {
  250.         PrintFault(IoErr(), NameStr);
  251.         FreeVec(FullName);
  252.         return(RETURN_ERROR);
  253.     }
  254.  
  255.     if(!(FileHandle = OpenFromLock(FromLock)))
  256.     {
  257.         PrintFault(IoErr(), NameStr);
  258.         UnLock(FromLock);
  259.         FreeVec(FullName);
  260.         return(RETURN_ERROR);
  261.     }
  262.  
  263.     Read(FileHandle, Buffer, 6);
  264.     Close(FileHandle);
  265.  
  266.     Type = ArcType(Buffer);
  267.  
  268.     if ( (Type == ARC_UNKNOWN) && (!WildScan) )
  269.     {
  270.         PrintFault(ERROR_OBJECT_WRONG_TYPE, FullName);
  271.         FreeVec(FullName);
  272.         return(RETURN_WARN);
  273.     }
  274.  
  275.     if (Type == ARC_UNKNOWN)
  276.     {
  277.         FreeVec(FullName);
  278.         return(RETURN_OK);
  279.     }
  280.  
  281.     if (To)
  282.     {
  283.         if(!(ToLock = Lock(To, SHARED_LOCK)))
  284.         {
  285.             PrintFault(IoErr(), To);
  286.             FreeVec(FullName);
  287.             return(RETURN_WARN);
  288.         }
  289.  
  290.         SaveDir = CurrentDir(ToLock);
  291.     }
  292.  
  293.     if (!(SystemTagName = (char *)AllocVec(1024, MEMF_ANY)))
  294.     {
  295.         PrintFault(ERROR_NO_FREE_STORE, NameStr);
  296.         return(RETURN_FAIL);
  297.     }
  298.  
  299.     strcpy(SystemTagName, Extractors[Type]);
  300.     strcat(SystemTagName, FullName);
  301.  
  302.     FreeVec(FullName);
  303.  
  304.     if (!(EnvBuf = (char *)AllocVec(256L, MEMF_ANY)))
  305.     {
  306.         PrintFault(ERROR_NO_FREE_STORE, NameStr);
  307.         return(RETURN_FAIL);
  308.     }
  309.  
  310.     if (GetVar("CUSTOMSHELL", EnvBuf, 256L, 0L) > 0)
  311.         RetVal = SystemTags(SystemTagName, SYS_CustomShell, EnvBuf, TAG_DONE, 0L);
  312.     else
  313.         RetVal = SystemTags(SystemTagName, SYS_UserShell, 0L, TAG_DONE, 0L);
  314.  
  315.     FreeVec(SystemTagName);
  316.     FreeVec(EnvBuf);
  317.  
  318.     if (ToLock)
  319.         UnLock(ToLock);
  320.     if (SaveDir)
  321.         CurrentDir(SaveDir);
  322.  
  323.     switch(RetVal)
  324.     {
  325.     case -1:
  326.         PrintFault(IoErr(), NameStr);
  327.         return(RETURN_WARN);
  328.         break;
  329.     case 0:
  330.         break;
  331.     default:
  332.         Printf("%s: Archiver returned %ld\n", NameStr, RetVal);
  333.         return(RETURN_WARN);
  334.     };
  335.  
  336.     return(RETURN_OK);
  337. }
  338.  
  339.  
  340. /////////////////////////////////////////////////////////////////////////////
  341. // The wildcard parser - this one calls ArcEx().
  342. /////////////////////////////////////////////////////////////////////////////
  343. LONG WildArcEx(char *Pat, char *To)
  344. {
  345.     struct    AnchorPath    *AnchorPath;
  346.     char            *FullName;
  347.     LONG            TheEnd = 0;
  348.  
  349.     if (!(FullName = (char *)AllocVec(1024L, MEMF_ANY)))
  350.     {
  351.         PrintFault(ERROR_NO_FREE_STORE, NameStr);
  352.         return(RETURN_FAIL);
  353.     }
  354.  
  355.     if (!(AnchorPath = (struct AnchorPath *)AllocVec(sizeof(struct AnchorPath), MEMF_ANY|MEMF_CLEAR)))
  356.     {
  357.         FreeVec(FullName);
  358.         PrintFault(ERROR_NO_FREE_STORE, NameStr);
  359.         return(RETURN_FAIL);
  360.     }
  361.  
  362.     AnchorPath->ap_BreakBits = SIGBREAKF_CTRL_C;
  363.  
  364.     if (MatchFirst(Pat, AnchorPath))
  365.     {
  366.         LONG    ErrorCode;
  367.  
  368.         FreeVec(FullName);
  369.         MatchEnd(AnchorPath);
  370.         FreeVec(AnchorPath);
  371.         if ( (ErrorCode = IoErr()) == ERROR_OBJECT_NOT_FOUND )
  372.             PrintFault(ErrorCode, Pat);
  373.         else
  374.             PrintFault(ErrorCode, NameStr);
  375.         return(RETURN_FAIL);
  376.     } else {
  377.         do {
  378.             if (AnchorPath->ap_Info.fib_DirEntryType < 0)
  379.             {
  380.                 LONG            Ret;
  381.  
  382.                 NameFromLock(AnchorPath->ap_Last->an_Lock, FullName, 1024L);
  383.                 AddPart(FullName, AnchorPath->ap_Info.fib_FileName, 1024L);
  384.  
  385.                 if ( (Ret = ArcEx(FullName, To, ((AnchorPath->ap_Flags & APF_ITSWILD) == APF_ITSWILD) )) != RETURN_OK )
  386.                 {
  387.                     FreeVec(FullName);
  388.                     MatchEnd(AnchorPath);
  389.                     FreeVec(AnchorPath);
  390.                     return(Ret);
  391.                 }
  392.             }
  393.  
  394.             if (MatchNext(AnchorPath))
  395.             {
  396.                 LONG    ErrorCode;
  397.  
  398.                 TheEnd = 1;
  399.  
  400.                 if ( ERROR_NO_MORE_ENTRIES != (ErrorCode = IoErr()) )
  401.                 {
  402.                     PrintFault(ErrorCode, NameStr);
  403.                     FreeVec(FullName);
  404.                     MatchEnd(AnchorPath);
  405.                     FreeVec(AnchorPath);
  406.                     return(RETURN_FAIL);
  407.                 }
  408.             }
  409.         } while (!TheEnd);
  410.     }
  411.  
  412.     FreeVec(FullName);
  413.     MatchEnd(AnchorPath);
  414.     FreeVec(AnchorPath);
  415.  
  416.     return(RETURN_OK);
  417. }
  418.  
  419.  
  420. /////////////////////////////////////////////////////////////////////////////
  421. // The archive-recognition routine.
  422. /////////////////////////////////////////////////////////////////////////////
  423. short ArcType(char *Header)
  424. {
  425.     COUNT    i;
  426.  
  427.     for(i=0; i<ARC_NUMENT; i++)
  428.         if(!memcmp(Header+ArcRec[i].Offset, &ArcRec[i].ID, ArcRec[i].Len))
  429.             return(i);
  430.  
  431.     return(ARC_UNKNOWN);
  432. }
  433.