Initial revision
diff --git a/radix.c b/radix.c
new file mode 100644
index 0000000..1c49794
--- /dev/null
+++ b/radix.c
@@ -0,0 +1,258 @@
+/*
+  radix.c
+
+  base-64 encoding pinched from lynx2-7-2, who pinched it from rpem.
+  Originally written by Mark Riordan 12 August 1990 and 17 Feb 1991
+  and placed in the public domain.
+
+  Dug Song <dugsong@UMICH.EDU>
+*/
+  
+#include "includes.h"
+
+#ifdef AFS
+#include <krb.h>
+
+char six2pr[64] = {
+    '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',
+    '0','1','2','3','4','5','6','7','8','9','+','/'
+};
+
+unsigned char pr2six[256];
+
+int uuencode(unsigned char *bufin, unsigned int nbytes, char *bufcoded)
+{
+  /* ENC is the basic 1 character encoding function to make a char printing */
+#define ENC(c) six2pr[c]
+  
+  register char *outptr = bufcoded;
+  unsigned int i;
+  
+  for (i=0; i<nbytes; i += 3) {
+    *(outptr++) = ENC(*bufin >> 2);            /* c1 */
+    *(outptr++) = ENC(((*bufin << 4) & 060) | ((bufin[1] >> 4) & 017)); /*c2*/
+    *(outptr++) = ENC(((bufin[1] << 2) & 074) | ((bufin[2] >> 6) & 03));/*c3*/
+    *(outptr++) = ENC(bufin[2] & 077);         /* c4 */
+    bufin += 3;
+  }
+  if (i == nbytes+1) {
+    outptr[-1] = '=';
+  } else if (i == nbytes+2) {
+    outptr[-1] = '=';
+    outptr[-2] = '=';
+  }
+  *outptr = '\0';
+  return(outptr - bufcoded);
+}
+
+int uudecode(const char *bufcoded, unsigned char *bufplain, int outbufsize)
+{
+  /* single character decode */
+#define DEC(c) pr2six[(unsigned char)c]
+#define MAXVAL 63
+  
+  static int first = 1;
+  int nbytesdecoded, j;
+  const char *bufin = bufcoded;
+  register unsigned char *bufout = bufplain;
+  register int nprbytes;
+  
+  /* If this is the first call, initialize the mapping table. */
+  if (first) {
+    first = 0;
+    for(j=0; j<256; j++) pr2six[j] = MAXVAL+1;
+    for(j=0; j<64; j++) pr2six[(unsigned char)six2pr[j]] = (unsigned char)j;
+  }
+  
+  /* Strip leading whitespace. */
+  while (*bufcoded==' ' || *bufcoded == '\t') bufcoded++;
+  
+  /* Figure out how many characters are in the input buffer.
+     If this would decode into more bytes than would fit into
+     the output buffer, adjust the number of input bytes downwards. */
+  bufin = bufcoded;
+  while (DEC(*(bufin++)) <= MAXVAL);
+  nprbytes = bufin - bufcoded - 1;
+  nbytesdecoded = ((nprbytes+3)/4) * 3;
+  if (nbytesdecoded > outbufsize)
+    nprbytes = (outbufsize*4)/3;
+  
+  bufin = bufcoded;
+  
+  while (nprbytes > 0) {
+    *(bufout++) = (unsigned char) (DEC(*bufin) << 2 | DEC(bufin[1]) >> 4);
+    *(bufout++) = (unsigned char) (DEC(bufin[1]) << 4 | DEC(bufin[2]) >> 2);
+    *(bufout++) = (unsigned char) (DEC(bufin[2]) << 6 | DEC(bufin[3]));
+    bufin += 4;
+    nprbytes -= 4;
+  }
+  if (nprbytes & 03) {
+    if (DEC(bufin[-2]) > MAXVAL)
+      nbytesdecoded -= 2;
+    else 
+      nbytesdecoded -= 1;
+  }
+  return(nbytesdecoded);
+}
+
+typedef unsigned char my_u_char;
+typedef unsigned int my_u_int32_t;
+typedef unsigned short my_u_short;
+
+/* Nasty macros from BIND-4.9.2 */
+
+#define GETSHORT(s, cp) { \
+	register my_u_char *t_cp = (my_u_char*)(cp); \
+	(s) = (((my_u_short)t_cp[0]) << 8) \
+	    | (((my_u_short)t_cp[1])) \
+	    ; \
+	(cp) += 2; \
+}
+
+#define GETLONG(l, cp) { \
+	register my_u_char *t_cp = (my_u_char*)(cp); \
+	(l) = (((my_u_int32_t)t_cp[0]) << 24) \
+	    | (((my_u_int32_t)t_cp[1]) << 16) \
+	    | (((my_u_int32_t)t_cp[2]) << 8) \
+	    | (((my_u_int32_t)t_cp[3])) \
+	    ; \
+	(cp) += 4; \
+}
+
+#define PUTSHORT(s, cp) { \
+	register my_u_short t_s = (my_u_short)(s); \
+	register my_u_char *t_cp = (my_u_char*)(cp); \
+	*t_cp++ = t_s >> 8; \
+	*t_cp   = t_s; \
+	(cp) += 2; \
+}
+
+#define PUTLONG(l, cp) { \
+	register my_u_int32_t t_l = (my_u_int32_t)(l); \
+	register my_u_char *t_cp = (my_u_char*)(cp); \
+	*t_cp++ = t_l >> 24; \
+	*t_cp++ = t_l >> 16; \
+	*t_cp++ = t_l >> 8; \
+	*t_cp   = t_l; \
+	(cp) += 4; \
+}
+
+#define GETSTRING(s, p, p_l) {			\
+    register char* p_targ = (p) + p_l;		\
+    register char* s_c = (s);			\
+    register char* p_c = (p);			\
+    while (*p_c && (p_c < p_targ)) {		\
+	*s_c++ = *p_c++;			\
+    }						\
+    if (p_c == p_targ) {			\
+	return 1;				\
+    }						\
+    *s_c = *p_c++;				\
+    (p_l) = (p_l) - (p_c - (p));		\
+    (p) = p_c;					\
+}
+
+
+int creds_to_radix(CREDENTIALS *creds, unsigned char *buf)
+{
+  char *p, *s;
+  int len;
+  char temp[2048];
+  
+  p = temp;
+  *p++ = 1; /* version */
+  s = creds->service;	while (*s) *p++ = *s++; *p++ = *s;
+  s = creds->instance;	while (*s) *p++ = *s++; *p++ = *s;
+  s = creds->realm;	while (*s) *p++ = *s++; *p++ = *s;
+
+  s = creds->pname;	while (*s) *p++ = *s++;   *p++ = *s;
+  s = creds->pinst;	while (*s) *p++ = *s++;   *p++ = *s;
+  /* Null string to repeat the realm. */
+  *p++ = '\0';
+
+  PUTLONG(creds->issue_date,p);
+  {
+    unsigned int	endTime ;
+    endTime = (unsigned int)krb_life_to_time(creds->issue_date,
+					      creds->lifetime);
+    PUTLONG(endTime,p);
+  }
+
+  memcpy(p,&creds->session, sizeof(creds->session));
+  p += sizeof(creds->session);
+  
+  PUTSHORT(creds->kvno,p);
+  PUTLONG(creds->ticket_st.length,p);
+  
+  memcpy(p,creds->ticket_st.dat, creds->ticket_st.length);
+  p += creds->ticket_st.length;
+  len = p - temp;
+
+  return(uuencode(temp, len, buf));
+}
+
+int radix_to_creds(const char *buf, CREDENTIALS *creds)
+{
+
+  char *p;
+  int len, tl;
+  char version;
+  char temp[2048];
+  
+  if (!(len = uudecode(buf, temp, sizeof(temp))))
+    return 0;
+  
+  p = temp;
+
+  /* check version and length! */
+  if (len < 1) return 0;
+  version = *p; p++; len--;
+
+  GETSTRING(creds->service, p, len);
+  GETSTRING(creds->instance, p, len);
+  GETSTRING(creds->realm, p, len);
+  
+  GETSTRING(creds->pname, p, len);
+  GETSTRING(creds->pinst, p, len);
+  /* Ignore possibly different realm. */
+  while (*p && len) p++, len--;
+  if (len == 0) return 0;
+  p++, len--;
+  
+  /* Enough space for remaining fixed-length parts? */
+  if (len < (4 + 4 + sizeof(creds->session) + 2 + 4))
+    return 0;
+  
+  GETLONG(creds->issue_date,p);
+  len -= 4;
+  {
+    unsigned int	endTime;
+    GETLONG(endTime,p);
+    len -= 4;
+    creds->lifetime = krb_time_to_life(creds->issue_date, endTime);
+  }
+
+  memcpy(&creds->session, p, sizeof(creds->session));
+  p += sizeof(creds->session);
+  len -= sizeof(creds->session);
+  
+  GETSHORT(creds->kvno,p);
+  len -= 2;
+  GETLONG(creds->ticket_st.length,p);
+  len -= 4;
+
+  tl = creds->ticket_st.length;
+  if (tl < 0 || tl > len || tl > sizeof(creds->ticket_st.dat))
+    return 0;
+  
+  memcpy(creds->ticket_st.dat, p, tl);
+  p += tl;
+  len -= tl;
+  
+  return 1;
+}
+
+#endif /* AFS */