#define NAME	 "xUp"
#define REVISION "2"

/* 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
*/

#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 = 1, suffix, len;
  STRPTR password = 0;

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

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

  if(i + 1 < argc && !strcmp(argv[i], "-p"))
    password = argv[++i], i++;

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

    {
      if((res = XpkUnpackTags(
	XPK_InName, (ULONG) argv[i],
	XPK_FileName, (ULONG) 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);
}
