#define NAME	 "xUp"
#define REVISION "3"

/* Programmheader

	Name:		xUp
	Author:		SDI (before 1.1 Urban Dominik Müller)
	Distribution:	PD
	Description:	General XPK file-to-file unpacker
	Compileropts:	-
	Linkeropts:	-l xpkmaster

 1.1   09.10.96 : fixed error with new 3.10 xpkmaster.library (A4 problem)
 1.2   29.11.96 : recompiled
 1.3   14.02.96 : corrected suffix removement
*/

#include "SDI_defines.h"
#define SDI_TO_ANSI
#include "SDI_ASM_STD_protos.h"
#include <pragma/exec_lib.h>
#include <pragma/dos_lib.h>
#include <pragma/xpkmaster_lib.h>

#ifdef __MAXON__
  #define __asm
  #define __saveds
#endif

struct Library *XpkBase = 0;

UBYTE errbuf[XPKERRMSGSIZE + 1];	/* +1 to make room for '\n'*/

ULONG __asm __saveds chunkfunc(register __a1 struct XpkProgress *prog)
{
  if(prog->xp_Type == XPKPROG_START)
    printf("\033[0 p");

  if(prog->xp_Type != XPKPROG_END)
    printf("\r%4s: %-8s (%3ld%% done, %2ld%% CF, %6ld cps) %s\033[K",
	   prog->xp_PackerName, prog->xp_Activity, prog->xp_Done,
	   prog->xp_CF, prog->xp_Speed, prog->xp_FileName);
  else
    printf("\r%4s: %-8s (%3ldK, %2ld%% CF, %6ld cps) %s\033[K\n",
	   prog->xp_PackerName, prog->xp_Activity, prog->xp_ULen >> 10,
	   prog->xp_CF, prog->xp_Speed, prog->xp_FileName);

  if(prog->xp_Type == XPKPROG_END)
    printf("\033[1 p");

  return SetSignal(0, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C;
}

struct Hook chunkhook = {{0}, (ULONG (*) ()) chunkfunc};

UBYTE namebuf[200];

STRPTR tempname(STRPTR name)
{
  ULONG i = strlen(name);
  CopyMem(name, namebuf, i);
  for(name = namebuf + i; name > namebuf; name--)
    if(name[-1] == '/' || name[-1] == ':')
      break;

  sprintf(name, "tmp%lx", &name);
  return namebuf;
}

void end(STRPTR text)
{
  if(text)	printf(text);
  if(XpkBase)	CloseLibrary(XpkBase);
  exit(text ? RETURN_ERROR : 0);
}

void main(int argc, char **argv)
{
  LONG res, i, suffix, len, sufmode = 0;
  STRPTR password = 0;

  if(!(XpkBase = OpenLibrary(XPKNAME, 0)))
    end("Cannot open " XPKNAME "\n");

  if(argc == 1 || !strcmp (argv[1], "?"))
    end("Usage: " NAME " [-s|-S] [-p password] files\n");

  for(i = 1; i + 1 < argc; ++i) // find params
  {
    if(!strcmp(argv[i], "-s"))
      sufmode = 1;
    else if(!strcmp(argv[i], "-S"))
      sufmode = 2;
    else if(!strcmp(argv[i], "-p"))
      password = argv[++i];
    else
      break;
  }

  for(; i < argc; i++)
  {
    tempname(argv[i]);
    len = strlen(argv[i]);
    suffix = 0;
    if(sufmode == 1 && len > 4 && !stricmp(argv[i] + len - 4, ".xpk"))
    {
      CopyMem(argv[i], namebuf, len-4);
      namebuf[len-4] = 0;
      suffix = 1;
    }
    else if(sufmode == 2 && len > 2)
    {
      char *end = argv[i] + len-1;

      while(end > argv[i])
      {
        if(*end == '.')
        {
	  CopyMem(argv[i], namebuf, end-argv[i]);
	  namebuf[end-argv[i]] = 0;
          suffix = 1; break;
        }
        --end;
      }
    }

    if((res = XpkUnpackTags(
	XPK_InName, (ULONG) argv[i],
	XPK_FileName, (suffix ? namebuf : argv[i]),
	XPK_OutName, (ULONG) namebuf,
	XPK_ChunkHook, (ULONG) &chunkhook,
	XPK_Password, (ULONG) password,
	XPK_GetError, (ULONG) errbuf,
	XPK_NoClobber, TRUE,
	TAG_DONE
    )) && res != XPKERR_NOTPACKED)
    {
      if(errbuf)
      {
        ULONG i = strlen(errbuf);
        errbuf[i++] = '\n';
        errbuf[i] = 0;
      }
      end(errbuf);
    }

    if(res)
    {
      printf("%s\n", errbuf);
      if(!DeleteFile(namebuf))
	end("Cannot delete outfile\n");
    }

    else if(!suffix)
    {
      if(!DeleteFile(argv[i]))
	end("Cannot delete input file\n");
      if(!Rename(namebuf, argv[i]))
	end("Cannot rename tempfile\n");
    }
  }
  end(0);
}
