/* arc.c - a 12 bit version 
   This has nothing to do with cryptography.
   Copyright (C) 1998 Paul Sheer

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

#include "mostincludes.h"
#include "parse.h"
#include "arc.h"
#include "diffie/compat.h"

#ifdef HAVE_BUILTIN_ARC
#define ARC_SWAP(a,b)			\
    {					\
	unsigned short __arc_temp = a;	\
	a = b;				\
	b = __arc_temp;			\
    }
#else

static char *load_file (char *f)
{
    char *r, *result;
    int fd;
    struct stat s;
    if (stat (f, &s))
	return 0;
    if (s.st_size < 3)
	return 0;
    result = r = malloc (s.st_size + 1);
    fd = open (f, O_RDONLY);
    result[s.st_size] = '\0';
    while (s.st_size > 0) {
	int count;
	count = read (fd, r, s.st_size);
	if (count < 0 && errno == EINTR)
	    continue;
	if (count <= 0)
	    break;
	s.st_size -= count;
	r += count;
    }
    close (fd);
    return result;
}

#endif

#ifdef HAVE_DL
void (*dl_arc_init) (Arc * arc, unsigned char *key, int key_size) = 0;
void (*dl_arc_encrypt) (Arc * arc, unsigned char *data, int len) = 0;
#endif

void arc_init (Arc * arc, unsigned char *key, int key_size)
{
#ifdef HAVE_BUILTIN_ARC
#include "arcinit.inc"
#else
    Value heap[16];
    void *c;
    char *f;
#ifdef HAVE_DL
    if (dl_arc_init) {
	(dl_arc_init) (arc, key, key_size);
	return;
    }
#endif
    memset (arc, 0, sizeof (Arc));
    arc->key = (char *) key;
    arc->key_size = key_size;
    parser_evaluate (c = parser_compile (f = load_file (ARC_INIT_SCRIPT), heap), arc);
    parser_free (c, heap);
    if (f)
	free (f);
    arc->c = parser_compile (f = load_file (ARC_ENCRYPT_SCRIPT), arc->heap);
    if (f)
	free (f);
    arc->initialised = 1;
#endif
}

void arc_shut (Arc * arc)
{
#ifndef HAVE_BUILTIN_ARC
    parser_free (arc->c, arc->heap);
#endif
    memset (arc, 0, sizeof (Arc));
}

void arc_encrypt (Arc * arc, unsigned char *data, int len)
{
#ifdef HAVE_BUILTIN_ARC
#include "arcencrypt.inc"
#else
#ifdef HAVE_DL
    if (dl_arc_encrypt) {
	(dl_arc_encrypt) (arc, data, len);
	return;
    }
#endif
    arc->data = (char *) data;
    arc->len = len;
    parser_evaluate (arc->c, arc->heap);
#endif
}

void arc_decrypt (Arc * arc, unsigned char *data, int len)
{
#ifdef HAVE_DL
    if (dl_arc_encrypt) {
	(dl_arc_encrypt) (arc, data, len);
	return;
    }
#endif
    arc_encrypt (arc, data, len);
}


