phantasmal_dgd_v1/
phantasmal_dgd_v1/bin/
phantasmal_dgd_v1/doc/
phantasmal_dgd_v1/mud/doc/
phantasmal_dgd_v1/mud/doc/api/
phantasmal_dgd_v1/mud/doc/kernel/
phantasmal_dgd_v1/mud/doc/kernel/hook/
phantasmal_dgd_v1/mud/doc/kernel/lfun/
phantasmal_dgd_v1/mud/include/
phantasmal_dgd_v1/mud/include/kernel/
phantasmal_dgd_v1/mud/kernel/lib/
phantasmal_dgd_v1/mud/kernel/lib/api/
phantasmal_dgd_v1/mud/kernel/obj/
phantasmal_dgd_v1/mud/kernel/sys/
phantasmal_dgd_v1/mud/tmp/
phantasmal_dgd_v1/mud/usr/System/
phantasmal_dgd_v1/mud/usr/System/keys/
phantasmal_dgd_v1/mud/usr/System/obj/
phantasmal_dgd_v1/mud/usr/System/open/lib/
phantasmal_dgd_v1/mud/usr/common/data/
phantasmal_dgd_v1/mud/usr/common/lib/parsed/
phantasmal_dgd_v1/mud/usr/common/obj/telopt/
phantasmal_dgd_v1/mud/usr/common/obj/ustate/
phantasmal_dgd_v1/mud/usr/game/
phantasmal_dgd_v1/mud/usr/game/include/
phantasmal_dgd_v1/mud/usr/game/obj/
phantasmal_dgd_v1/mud/usr/game/object/
phantasmal_dgd_v1/mud/usr/game/object/stuff/
phantasmal_dgd_v1/mud/usr/game/sys/
phantasmal_dgd_v1/mud/usr/game/text/
phantasmal_dgd_v1/mud/usr/game/users/
phantasmal_dgd_v1/src/host/
phantasmal_dgd_v1/src/host/beos/
phantasmal_dgd_v1/src/host/mac/
phantasmal_dgd_v1/src/host/unix/
phantasmal_dgd_v1/src/host/win32/res/
phantasmal_dgd_v1/src/kfun/
phantasmal_dgd_v1/src/lpc/
phantasmal_dgd_v1/src/parser/
# include "dgd.h"
# include "str.h"
# include "array.h"
# include "object.h"
# include "data.h"
# include "interpret.h"


/*
 * DES encryption tailored to DGD, small but reasonably fast.
 */

static char Salt[256] = {
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,32,
     16,48, 8,40,24,56, 4,36,20,52,40,24,56, 4,36,20,
     52,12,44,28,60, 2,34,18,50,10,42,26,58, 6,38,22,
     54,14,46,30,62, 1,33,17,49, 9,41, 1,33,17,49, 9,
     41,25,57, 5,37,21,53,13,45,29,61, 3,35,19,51,11,
     43,27,59, 7,39,23,55,15,47,31,63, 0, 0, 0, 0, 0,
};

static char Rot[] = {
    0,1,1,1,1,1,1,0,1,1,1,1,1,1,0,0,
};

static Uint PC2[14][16] = { {
    0x00000000L, 0x00040000L, 0x00002000L, 0x00042000L,
    0x00000001L, 0x00040001L, 0x00002001L, 0x00042001L,
    0x02000000L, 0x02040000L, 0x02002000L, 0x02042000L,
    0x02000001L, 0x02040001L, 0x02002001L, 0x02042001L,
}, {
    0x00000000L, 0x00010000L, 0x00000010L, 0x00010010L,
    0x00000400L, 0x00010400L, 0x00000410L, 0x00010410L,
    0x01000000L, 0x01010000L, 0x01000010L, 0x01010010L,
    0x01000400L, 0x01010400L, 0x01000410L, 0x01010410L,
}, {
    0x00000000L, 0x00080000L, 0x08000000L, 0x08080000L,
    0x00000100L, 0x00080100L, 0x08000100L, 0x08080100L,
    0x00000000L, 0x00080000L, 0x08000000L, 0x08080000L,
    0x00000100L, 0x00080100L, 0x08000100L, 0x08080100L,
}, {
    0x00000000L, 0x00000020L, 0x00000800L, 0x00000820L,
    0x20000000L, 0x20000020L, 0x20000800L, 0x20000820L,
    0x00000002L, 0x00000022L, 0x00000802L, 0x00000822L,
    0x20000002L, 0x20000022L, 0x20000802L, 0x20000822L,
}, {
    0x00000000L, 0x00000004L, 0x00100000L, 0x00100004L,
    0x00000000L, 0x00000004L, 0x00100000L, 0x00100004L,
    0x10000000L, 0x10000004L, 0x10100000L, 0x10100004L,
    0x10000000L, 0x10000004L, 0x10100000L, 0x10100004L,
}, {
    0x00000000L, 0x04000000L, 0x00200000L, 0x04200000L,
    0x00000000L, 0x04000000L, 0x00200000L, 0x04200000L,
    0x00000200L, 0x04000200L, 0x00200200L, 0x04200200L,
    0x00000200L, 0x04000200L, 0x00200200L, 0x04200200L,
}, {
    0x00000000L, 0x00001000L, 0x00000008L, 0x00001008L,
    0x00020000L, 0x00021000L, 0x00020008L, 0x00021008L,
    0x00000000L, 0x00001000L, 0x00000008L, 0x00001008L,
    0x00020000L, 0x00021000L, 0x00020008L, 0x00021008L,
}, {
    0x00000000L, 0x00000001L, 0x08000000L, 0x08000001L,
    0x00002000L, 0x00002001L, 0x08002000L, 0x08002001L,
    0x00000002L, 0x00000003L, 0x08000002L, 0x08000003L,
    0x00002002L, 0x00002003L, 0x08002002L, 0x08002003L,
}, {
    0x00000000L, 0x00000004L, 0x00000000L, 0x00000004L,
    0x00020000L, 0x00020004L, 0x00020000L, 0x00020004L,
    0x00000200L, 0x00000204L, 0x00000200L, 0x00000204L,
    0x00020200L, 0x00020204L, 0x00020200L, 0x00020204L,
}, {
    0x00000000L, 0x00001000L, 0x00080000L, 0x00081000L,
    0x00000000L, 0x00001000L, 0x00080000L, 0x00081000L,
    0x04000000L, 0x04001000L, 0x04080000L, 0x04081000L,
    0x04000000L, 0x04001000L, 0x04080000L, 0x04081000L,
}, {
    0x00000000L, 0x00200000L, 0x00000000L, 0x00200000L,
    0x00000010L, 0x00200010L, 0x00000010L, 0x00200010L,
    0x20000000L, 0x20200000L, 0x20000000L, 0x20200000L,
    0x20000010L, 0x20200010L, 0x20000010L, 0x20200010L,
}, {
    0x00000000L, 0x00000100L, 0x02000000L, 0x02000100L,
    0x00000020L, 0x00000120L, 0x02000020L, 0x02000120L,
    0x00000400L, 0x00000500L, 0x02000400L, 0x02000500L,
    0x00000420L, 0x00000520L, 0x02000420L, 0x02000520L,
}, {
    0x00000000L, 0x10000000L, 0x00000800L, 0x10000800L,
    0x00000008L, 0x10000008L, 0x00000808L, 0x10000808L,
    0x00100000L, 0x10100000L, 0x00100800L, 0x10100800L,
    0x00100008L, 0x10100008L, 0x00100808L, 0x10100808L,
}, {
    0x00000000L, 0x00040000L, 0x01000000L, 0x01040000L,
    0x00000000L, 0x00040000L, 0x01000000L, 0x01040000L,
    0x00010000L, 0x00050000L, 0x01010000L, 0x01050000L,
    0x00010000L, 0x00050000L, 0x01010000L, 0x01050000L,
} };

static Uint SP[8][64] = { {
    0x00101040L, 0x00000000L, 0x00001000L, 0x40101040L,
    0x40101000L, 0x40001040L, 0x40000000L, 0x00001000L,
    0x00000040L, 0x00101040L, 0x40101040L, 0x00000040L,
    0x40100040L, 0x40101000L, 0x00100000L, 0x40000000L,
    0x40000040L, 0x00100040L, 0x00100040L, 0x00001040L,
    0x00001040L, 0x00101000L, 0x00101000L, 0x40100040L,
    0x40001000L, 0x40100000L, 0x40100000L, 0x40001000L,
    0x00000000L, 0x40000040L, 0x40001040L, 0x00100000L,
    0x00001000L, 0x40101040L, 0x40000000L, 0x00101000L,
    0x00101040L, 0x00100000L, 0x00100000L, 0x00000040L,
    0x40101000L, 0x00001000L, 0x00001040L, 0x40100000L,
    0x00000040L, 0x40000000L, 0x40100040L, 0x40001040L,
    0x40101040L, 0x40001000L, 0x00101000L, 0x40100040L,
    0x40100000L, 0x40000040L, 0x40001040L, 0x00101040L,
    0x40000040L, 0x00100040L, 0x00100040L, 0x00000000L,
    0x40001000L, 0x00001040L, 0x00000000L, 0x40101000L,
}, {
    0x08010802L, 0x08000800L, 0x00000800L, 0x00010802L,
    0x00010000L, 0x00000002L, 0x08010002L, 0x08000802L,
    0x08000002L, 0x08010802L, 0x08010800L, 0x08000000L,
    0x08000800L, 0x00010000L, 0x00000002L, 0x08010002L,
    0x00010800L, 0x00010002L, 0x08000802L, 0x00000000L,
    0x08000000L, 0x00000800L, 0x00010802L, 0x08010000L,
    0x00010002L, 0x08000002L, 0x00000000L, 0x00010800L,
    0x00000802L, 0x08010800L, 0x08010000L, 0x00000802L,
    0x00000000L, 0x00010802L, 0x08010002L, 0x00010000L,
    0x08000802L, 0x08010000L, 0x08010800L, 0x00000800L,
    0x08010000L, 0x08000800L, 0x00000002L, 0x08010802L,
    0x00010802L, 0x00000002L, 0x00000800L, 0x08000000L,
    0x00000802L, 0x08010800L, 0x00010000L, 0x08000002L,
    0x00010002L, 0x08000802L, 0x08000002L, 0x00010002L,
    0x00010800L, 0x00000000L, 0x08000800L, 0x00000802L,
    0x08000000L, 0x08010002L, 0x08010802L, 0x00010800L,
}, {
    0x80000020L, 0x00802020L, 0x00000000L, 0x80802000L,
    0x00800020L, 0x00000000L, 0x80002020L, 0x00800020L,
    0x80002000L, 0x80800000L, 0x80800000L, 0x00002000L,
    0x80802020L, 0x80002000L, 0x00802000L, 0x80000020L,
    0x00800000L, 0x80000000L, 0x00802020L, 0x00000020L,
    0x00002020L, 0x00802000L, 0x80802000L, 0x80002020L,
    0x80800020L, 0x00002020L, 0x00002000L, 0x80800020L,
    0x80000000L, 0x80802020L, 0x00000020L, 0x00800000L,
    0x00802020L, 0x00800000L, 0x80002000L, 0x80000020L,
    0x00002000L, 0x00802020L, 0x00800020L, 0x00000000L,
    0x00000020L, 0x80002000L, 0x80802020L, 0x00800020L,
    0x80800000L, 0x00000020L, 0x00000000L, 0x80802000L,
    0x80800020L, 0x00002000L, 0x00800000L, 0x80802020L,
    0x80000000L, 0x80002020L, 0x00002020L, 0x80800000L,
    0x00802000L, 0x80800020L, 0x80000020L, 0x00802000L,
    0x80002020L, 0x80000000L, 0x80802000L, 0x00002020L,
}, {
    0x10080200L, 0x10000208L, 0x10000208L, 0x00000008L,
    0x00080208L, 0x10080008L, 0x10080000L, 0x10000200L,
    0x00000000L, 0x00080200L, 0x00080200L, 0x10080208L,
    0x10000008L, 0x00000000L, 0x00080008L, 0x10080000L,
    0x10000000L, 0x00000200L, 0x00080000L, 0x10080200L,
    0x00000008L, 0x00080000L, 0x10000200L, 0x00000208L,
    0x10080008L, 0x10000000L, 0x00000208L, 0x00080008L,
    0x00000200L, 0x00080208L, 0x10080208L, 0x10000008L,
    0x00080008L, 0x10080000L, 0x00080200L, 0x10080208L,
    0x10000008L, 0x00000000L, 0x00000000L, 0x00080200L,
    0x00000208L, 0x00080008L, 0x10080008L, 0x10000000L,
    0x10080200L, 0x10000208L, 0x10000208L, 0x00000008L,
    0x10080208L, 0x10000008L, 0x10000000L, 0x00000200L,
    0x10080000L, 0x10000200L, 0x00080208L, 0x10080008L,
    0x10000200L, 0x00000208L, 0x00080000L, 0x10080200L,
    0x00000008L, 0x00080000L, 0x00000200L, 0x00080208L,
}, {
    0x00000010L, 0x00208010L, 0x00208000L, 0x04200010L,
    0x00008000L, 0x00000010L, 0x04000000L, 0x00208000L,
    0x04008010L, 0x00008000L, 0x00200010L, 0x04008010L,
    0x04200010L, 0x04208000L, 0x00008010L, 0x04000000L,
    0x00200000L, 0x04008000L, 0x04008000L, 0x00000000L,
    0x04000010L, 0x04208010L, 0x04208010L, 0x00200010L,
    0x04208000L, 0x04000010L, 0x00000000L, 0x04200000L,
    0x00208010L, 0x00200000L, 0x04200000L, 0x00008010L,
    0x00008000L, 0x04200010L, 0x00000010L, 0x00200000L,
    0x04000000L, 0x00208000L, 0x04200010L, 0x04008010L,
    0x00200010L, 0x04000000L, 0x04208000L, 0x00208010L,
    0x04008010L, 0x00000010L, 0x00200000L, 0x04208000L,
    0x04208010L, 0x00008010L, 0x04200000L, 0x04208010L,
    0x00208000L, 0x00000000L, 0x04008000L, 0x04200000L,
    0x00008010L, 0x00200010L, 0x04000010L, 0x00008000L,
    0x00000000L, 0x04008000L, 0x00208010L, 0x04000010L,
}, {
    0x02000001L, 0x02040000L, 0x00000400L, 0x02040401L,
    0x02040000L, 0x00000001L, 0x02040401L, 0x00040000L,
    0x02000400L, 0x00040401L, 0x00040000L, 0x02000001L,
    0x00040001L, 0x02000400L, 0x02000000L, 0x00000401L,
    0x00000000L, 0x00040001L, 0x02000401L, 0x00000400L,
    0x00040400L, 0x02000401L, 0x00000001L, 0x02040001L,
    0x02040001L, 0x00000000L, 0x00040401L, 0x02040400L,
    0x00000401L, 0x00040400L, 0x02040400L, 0x02000000L,
    0x02000400L, 0x00000001L, 0x02040001L, 0x00040400L,
    0x02040401L, 0x00040000L, 0x00000401L, 0x02000001L,
    0x00040000L, 0x02000400L, 0x02000000L, 0x00000401L,
    0x02000001L, 0x02040401L, 0x00040400L, 0x02040000L,
    0x00040401L, 0x02040400L, 0x00000000L, 0x02040001L,
    0x00000001L, 0x00000400L, 0x02040000L, 0x00040401L,
    0x00000400L, 0x00040001L, 0x02000401L, 0x00000000L,
    0x02040400L, 0x02000000L, 0x00040001L, 0x02000401L,
}, {
    0x00020000L, 0x20420000L, 0x20400080L, 0x00000000L,
    0x00000080L, 0x20400080L, 0x20020080L, 0x00420080L,
    0x20420080L, 0x00020000L, 0x00000000L, 0x20400000L,
    0x20000000L, 0x00400000L, 0x20420000L, 0x20000080L,
    0x00400080L, 0x20020080L, 0x20020000L, 0x00400080L,
    0x20400000L, 0x00420000L, 0x00420080L, 0x20020000L,
    0x00420000L, 0x00000080L, 0x20000080L, 0x20420080L,
    0x00020080L, 0x20000000L, 0x00400000L, 0x00020080L,
    0x00400000L, 0x00020080L, 0x00020000L, 0x20400080L,
    0x20400080L, 0x20420000L, 0x20420000L, 0x20000000L,
    0x20020000L, 0x00400000L, 0x00400080L, 0x00020000L,
    0x00420080L, 0x20000080L, 0x20020080L, 0x00420080L,
    0x20000080L, 0x20400000L, 0x20420080L, 0x00420000L,
    0x00020080L, 0x00000000L, 0x20000000L, 0x20420080L,
    0x00000000L, 0x20020080L, 0x00420000L, 0x00000080L,
    0x20400000L, 0x00400080L, 0x00000080L, 0x20020000L,
}, {
    0x01000104L, 0x00000100L, 0x00004000L, 0x01004104L,
    0x01000000L, 0x01000104L, 0x00000004L, 0x01000000L,
    0x00004004L, 0x01004000L, 0x01004104L, 0x00004100L,
    0x01004100L, 0x00004104L, 0x00000100L, 0x00000004L,
    0x01004000L, 0x01000004L, 0x01000100L, 0x00000104L,
    0x00004100L, 0x00004004L, 0x01004004L, 0x01004100L,
    0x00000104L, 0x00000000L, 0x00000000L, 0x01004004L,
    0x01000004L, 0x01000100L, 0x00004104L, 0x00004000L,
    0x00004104L, 0x00004000L, 0x01004100L, 0x00000100L,
    0x00000004L, 0x01004004L, 0x00000100L, 0x00004104L,
    0x01000100L, 0x00000004L, 0x01000004L, 0x01004000L,
    0x01004004L, 0x01000000L, 0x00004000L, 0x01000104L,
    0x00000000L, 0x01004104L, 0x00004004L, 0x01000004L,
    0x01004000L, 0x01000100L, 0x01000104L, 0x00000000L,
    0x01004104L, 0x00004100L, 0x00004100L, 0x00000104L,
    0x00000104L, 0x00004004L, 0x01000000L, 0x01004100L,
} };

static char out[64] = {
    '.', '/', '0', '1', '2', '3', '4', '5',
    '6', '7', '8', '9', 'A', 'B', 'C', 'D',
    'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L',
    'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
    'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b',
    'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
    'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r',
    's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 
};

# define EXG1(a, t, n, m)	((t) = (((a) >> (n)) ^ (a)) & (m), \
				 (a) ^= (t), (a) ^= ((t) << (n)))
# define EXG2(a, b, t, n, m)	((t) = (((a) >> (n)) ^ (b)) & (m), \
				 (b) ^= (t), (a) ^= (t) << (n))

/*
 * NAME:	P->setkey()
 * DESCRIPTION:	prepare a key for encryption or decryption
 */
static void P_setkey(keys, k)
register Uint *keys;
register char *k;
{
    register Uint L, R, A, B, T;
    register int i;

    L  = UCHAR(*k++ << 1); L <<= 8;
    L |= UCHAR(*k++ << 1); L <<= 8;
    L |= UCHAR(*k++ << 1); L <<= 8;
    L |= UCHAR(*k++ << 1);
    R  = UCHAR(*k++ << 1); R <<= 8;
    R |= UCHAR(*k++ << 1); R <<= 8;
    R |= UCHAR(*k++ << 1); R <<= 8;
    R |= UCHAR(*k << 1);

    /* PC1 */
    EXG2(R, L, T,  4, 0x0f0f0f0fL);
    EXG1(L,    T, 14,     0xccccL);
    EXG1(L,    T,  7,   0xaa00aaL);
    EXG1(L,    T,  4, 0x0f0f0f0fL);
    EXG1(L,    T,  2, 0x33333333L);
    EXG1(L,    T,  1, 0x55555555L);
    EXG1(R,    T, 18,     0x3333L);
    EXG1(R,    T,  9,   0x550055L);
    EXG1(R,    T,  4, 0x0f0f0f0fL);
    R = (R << 4) | (L & 0xf);
    L >>= 4;

    /* PC2 */
    for (i = 15; i >= 0; --i) {
	if (Rot[i] == 0) {
	    L = (L << 1) | (L >> 27);
	    R = (R << 1) | (R >> 27);
	} else {
	    L = (L << 2) | (L >> 26);
	    R = (R << 2) | (R >> 26);
	}
	L &= 0x0fffffff;
	R &= 0x0fffffff;

	A = PC2[ 0][ L >> 24       ] |
	    PC2[ 1][(L >> 20) & 0xf] |
	    PC2[ 2][(L >> 16) & 0xf] |
	    PC2[ 3][(L >> 12) & 0xf] |
	    PC2[ 4][(L >>  8) & 0xf] |
	    PC2[ 5][(L >>  4) & 0xf] |
	    PC2[ 6][ L        & 0xf];
	B = PC2[ 7][ R >> 24       ] |
	    PC2[ 8][(R >> 20) & 0xf] |
	    PC2[ 9][(R >> 16) & 0xf] |
	    PC2[10][(R >> 12) & 0xf] |
	    PC2[11][(R >>  8) & 0xf] |
	    PC2[12][(R >>  4) & 0xf] |
	    PC2[13][ R        & 0xf];
	EXG2(B, A, T, 16, 0x3f3fL);
	*keys++ = A;
	*keys++ = B;
    }
}

/*
 * NAME:	P->crypt()
 * DESCRIPTION:	Unix password encryption.
 */
char *P_crypt(passwd, salt)
char *passwd, *salt;
{
    static char result[14];
    register Uint L, R, T, X, *key;
    register int i, j;
    register char *p;
    Uint keys[32], E[2];

    /* fetch password data */
    memset(result, '\0', 8);
    strncpy(result, passwd, 8);
    P_setkey(keys, result);

    /* prepare salt */
    E[0] = UCHAR(Salt[UCHAR(result[0] = *salt++)]) << 8;
    E[1] = UCHAR(Salt[UCHAR(result[1] = *salt++)]) << 4;

    /* encrypt */
    L = 0;
    R = 0;
    for (i = 25; i > 0; --i) {
	key = keys;
	for (j = 7; j >= 0; --j) {
	    T = R ^ (R >> 16);
	    X = T & E[0];
	    X ^= (X << 16) ^ R ^ *key++;
	    L ^= SP[6][X & 0x3f]; X >>= 8;
	    L ^= SP[4][X & 0x3f]; X >>= 8;
	    L ^= SP[2][X & 0x3f]; X >>= 8;
	    L ^= SP[0][X & 0x3f];
	    X = T & E[1];
	    X ^= (X << 16) ^ R;
	    X = ((X << 4) | (X >> 28)) ^ *key++;
	    L ^= SP[7][X & 0x3f]; X >>= 8;
	    L ^= SP[5][X & 0x3f]; X >>= 8;
	    L ^= SP[3][X & 0x3f]; X >>= 8;
	    L ^= SP[1][X & 0x3f];
	    T = L ^ (L >> 16);
	    X = T & E[0];
	    X ^= (X << 16) ^ L ^ *key++;
	    R ^= SP[6][X & 0x3f]; X >>= 8;
	    R ^= SP[4][X & 0x3f]; X >>= 8;
	    R ^= SP[2][X & 0x3f]; X >>= 8;
	    R ^= SP[0][X & 0x3f];
	    X = T & E[1];
	    X ^= (X << 16) ^ L;
	    X = ((X << 4) | (X >> 28)) ^ *key++;
	    R ^= SP[7][X & 0x3f]; X >>= 8;
	    R ^= SP[5][X & 0x3f]; X >>= 8;
	    R ^= SP[3][X & 0x3f]; X >>= 8;
	    R ^= SP[1][X & 0x3f];
	}
	T = L;
	L = R;
	R = T;
    }
    L = (L << 3) | (L >> 29);
    R = (R << 3) | (R >> 29);

    /* FP */
    EXG2(L, R, T,  1, 0x55555555L);
    EXG2(R, L, T,  8,   0xff00ffL);
    EXG2(R, L, T,  2, 0x33333333L);
    EXG2(L, R, T, 16,     0xffffL);
    EXG2(L, R, T,  4, 0x0f0f0f0fL);

    /* put result in static buffer */
    p = result + 13;
    *p = '\0';
    *--p = out[(R << 2) & 0x3f]; R >>= 4;
    *--p = out[R & 0x3f]; R >>= 6;
    *--p = out[R & 0x3f]; R >>= 6;
    *--p = out[R & 0x3f]; R >>= 6;
    *--p = out[R & 0x3f]; R >>= 6;
    *--p = out[((L << 4) | R) & 0x3f]; L >>= 2;
    *--p = out[L & 0x3f]; L >>= 6;
    *--p = out[L & 0x3f]; L >>= 6;
    *--p = out[L & 0x3f]; L >>= 6;
    *--p = out[L & 0x3f]; L >>= 6;
    *--p = out[L & 0x3f];

    return result;
}

/*
 * NAME:	P->encrypt_des_key()
 * DESCRIPTION:	return a DES key prepared for encryption
 */
string *P_encrypt_des_key(f, keystr)
frame *f;
string *keystr;
{
    register Uint k, *key;
    register char *p;
    register int i;
    Uint keys[32];
    string *str;

    if (keystr->len != 8) {
	error("Wrong key length");
    }
    i_add_ticks(f, 60);

    P_setkey(keys, keystr->text);
    str = str_new((char *) NULL, 32L * sizeof(Uint));
    p = str->text;
    key = keys;
    for (i = 31; i >= 0; --i) {
	k = *key++;
	*p++ = k >> 24;
	*p++ = k >> 16;
	*p++ = k >> 8;
	*p++ = k;
    }

    return str;
}

/*
 * NAME:	P->decrypt_des_key()
 * DESCRIPTION:	return a DES key prepared for decryption
 */
string *P_decrypt_des_key(f, keystr)
frame *f;
string *keystr;
{
    register Uint k, *key;
    register char *p;
    register int i;
    Uint keys[32];
    string *str;

    if (keystr->len != 8) {
	error("Wrong key length");
    }
    i_add_ticks(f, 60);

    P_setkey(keys, keystr->text);
    str = str_new((char *) NULL, 32L * sizeof(Uint));
    p = str->text;
    key = keys + 32;
    for (i = 15; i >= 0; --i) {
	key -= 2;
	k = key[0];
	*p++ = k >> 24;
	*p++ = k >> 16;
	*p++ = k >> 8;
	*p++ = k;
	k = key[1];
	*p++ = k >> 24;
	*p++ = k >> 16;
	*p++ = k >> 8;
	*p++ = k;
    }

    return str;
}

/*
 * NAME:	P->encrypt_des()
 * DESCRIPTION:	encrypt (or decrypt) a string
 */
string *P_encrypt_des(f, keystr, mesg)
frame *f;
string *keystr, *mesg;
{
    register Uint L, R, T, *key;
    register char *p, *q;
    register int i;
    register ssizet len;
    Uint keys[32];
    string *str;

    if (keystr->len != 32 * sizeof(Uint)) {
	error("Wrong key length");
    }
    i_add_ticks(f, mesg->len * 5L);
    if (f->rlim->ticks < 0) {
	if (f->rlim->noticks) {
	    f->rlim->ticks = 0x7fffffffL;
	} else {
	    error("Out of ticks");
	}
    }
    str = str_new((char *) NULL, (long) (mesg->len + 7) & ~7);

    p = keystr->text;
    key = keys;
    for (i = 31; i >= 0; --i) {
	T  = UCHAR(*p++); T <<= 8;
	T |= UCHAR(*p++); T <<= 8;
	T |= UCHAR(*p++); T <<= 8;
	T |= UCHAR(*p++);
	*key++ = T;
    }

    p = mesg->text;
    q = str->text;

    for (len = mesg->len; len >= 8; len -= 8) {
	L  = UCHAR(*p++); L <<= 8;
	L |= UCHAR(*p++); L <<= 8;
	L |= UCHAR(*p++); L <<= 8;
	L |= UCHAR(*p++);
	R  = UCHAR(*p++); R <<= 8;
	R |= UCHAR(*p++); R <<= 8;
	R |= UCHAR(*p++); R <<= 8;
	R |= UCHAR(*p++);

	/* IP */
	EXG2(L, R, T,  4, 0x0f0f0f0fL);
	EXG2(L, R, T, 16,     0xffffL);
	EXG2(R, L, T,  2, 0x33333333L);
	EXG2(R, L, T,  8,   0xff00ffL);
	EXG2(L, R, T,  1, 0x55555555L);

	key = keys;
	L = (L >> 3) | (L << 29);
	R = (R >> 3) | (R << 29);
	for (i = 7; i >= 0; --i) {
	    T = R ^ *key++;
	    L ^= SP[6][T & 0x3f]; T >>= 8;
	    L ^= SP[4][T & 0x3f]; T >>= 8;
	    L ^= SP[2][T & 0x3f]; T >>= 8;
	    L ^= SP[0][T & 0x3f];
	    T = ((R << 4) | (R >> 28)) ^ *key++;
	    L ^= SP[7][T & 0x3f]; T >>= 8;
	    L ^= SP[5][T & 0x3f]; T >>= 8;
	    L ^= SP[3][T & 0x3f]; T >>= 8;
	    L ^= SP[1][T & 0x3f];
	    T = L ^ *key++;
	    R ^= SP[6][T & 0x3f]; T >>= 8;
	    R ^= SP[4][T & 0x3f]; T >>= 8;
	    R ^= SP[2][T & 0x3f]; T >>= 8;
	    R ^= SP[0][T & 0x3f];
	    T = ((L << 4) | (L >> 28)) ^ *key++;
	    R ^= SP[7][T & 0x3f]; T >>= 8;
	    R ^= SP[5][T & 0x3f]; T >>= 8;
	    R ^= SP[3][T & 0x3f]; T >>= 8;
	    R ^= SP[1][T & 0x3f];
	}
	L = (L << 3) | (L >> 29);
	R = (R << 3) | (R >> 29);

	/* FP */
	EXG2(R, L, T,  1, 0x55555555L);
	EXG2(L, R, T,  8,   0xff00ffL);
	EXG2(L, R, T,  2, 0x33333333L);
	EXG2(R, L, T, 16,     0xffffL);
	EXG2(R, L, T,  4, 0x0f0f0f0fL);

	*q++ = R >> 24;
	*q++ = R >> 16;
	*q++ = R >> 8;
	*q++ = R;
	*q++ = L >> 24;
	*q++ = L >> 16;
	*q++ = L >> 8;
	*q++ = L;
    }

    if (len != 0) {
	char buffer[8];

	memset(buffer, '\0', 8);
	memcpy(buffer, p, len);
	p = buffer;

	L  = UCHAR(*p++); L <<= 8;
	L |= UCHAR(*p++); L <<= 8;
	L |= UCHAR(*p++); L <<= 8;
	L |= UCHAR(*p++);
	R  = UCHAR(*p++); R <<= 8;
	R |= UCHAR(*p++); R <<= 8;
	R |= UCHAR(*p++); R <<= 8;
	R |= UCHAR(*p++);

	/* IP */
	EXG2(L, R, T,  4, 0x0f0f0f0fL);
	EXG2(L, R, T, 16,     0xffffL);
	EXG2(R, L, T,  2, 0x33333333L);
	EXG2(R, L, T,  8,   0xff00ffL);
	EXG2(L, R, T,  1, 0x55555555L);

	key = keys;
	L = (L >> 3) | (L << 29);
	R = (R >> 3) | (R << 29);
	for (i = 7; i >= 0; --i) {
	    T = R ^ *key++;
	    L ^= SP[6][T & 0x3f]; T >>= 8;
	    L ^= SP[4][T & 0x3f]; T >>= 8;
	    L ^= SP[2][T & 0x3f]; T >>= 8;
	    L ^= SP[0][T & 0x3f];
	    T = ((R << 4) | (R >> 28)) ^ *key++;
	    L ^= SP[7][T & 0x3f]; T >>= 8;
	    L ^= SP[5][T & 0x3f]; T >>= 8;
	    L ^= SP[3][T & 0x3f]; T >>= 8;
	    L ^= SP[1][T & 0x3f];
	    T = L ^ *key++;
	    R ^= SP[6][T & 0x3f]; T >>= 8;
	    R ^= SP[4][T & 0x3f]; T >>= 8;
	    R ^= SP[2][T & 0x3f]; T >>= 8;
	    R ^= SP[0][T & 0x3f];
	    T = ((L << 4) | (L >> 28)) ^ *key++;
	    R ^= SP[7][T & 0x3f]; T >>= 8;
	    R ^= SP[5][T & 0x3f]; T >>= 8;
	    R ^= SP[3][T & 0x3f]; T >>= 8;
	    R ^= SP[1][T & 0x3f];
	}
	L = (L << 3) | (L >> 29);
	R = (R << 3) | (R >> 29);

	/* FP */
	EXG2(R, L, T,  1, 0x55555555L);
	EXG2(L, R, T,  8,   0xff00ffL);
	EXG2(L, R, T,  2, 0x33333333L);
	EXG2(R, L, T, 16,     0xffffL);
	EXG2(R, L, T,  4, 0x0f0f0f0fL);

	*q++ = R >> 24;
	*q++ = R >> 16;
	*q++ = R >> 8;
	*q++ = R;
	*q++ = L >> 24;
	*q++ = L >> 16;
	*q++ = L >> 8;
	*q++ = L;
    }

    return str;
}