chiark / gitweb /
Builds a working plugin.
authorian <ian>
Thu, 29 Aug 2002 00:36:25 +0000 (00:36 +0000)
committerian <ian>
Thu, 29 Aug 2002 00:36:25 +0000 (00:36 +0000)
base/chiark-tcl.h [new file with mode: 0644]
base/enum.c [new file with mode: 0644]
base/troglodyte-Makefile
hbytes/hbytes.c [new file with mode: 0644]
hbytes/hbytes.h [new file with mode: 0644]

diff --git a/base/chiark-tcl.h b/base/chiark-tcl.h
new file mode 100644 (file)
index 0000000..5aca162
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ */
+/*
+ *
+ *  hbytes bin VAR                               => binary string
+ *  hbytes bin VAR VALUE                         => set
+ *
+ *  hbytes prefix VAR [VALUE ...]         = set VAR [concat VALUE ... $VAR]
+ *  hbytes append VAR [VALUE ...]         = set VAR [concat $VAR VALUE ...]
+ *  hbytes concat VAR [VALUE ...]         = set VAR [concat VALUE ...]
+ *  hbytes unprepend VAR PREFIXLENGTH            => prefix (removed from VAR)
+ *  hbytes unappend VAR SUFFIXLENGTH             => suffix (removed from VAR)
+ *  hbytes chopto VAR NEWVARLENGTH               => suffix (removed from VAR)
+ *                                                  (too short? error)
+ *
+ *  hbytes pkcs5 pv|uv VAR ALG                   => worked?  (always 1 for p)
+ *  hbytes pkcs5 pn|un VAR BLOCKSIZE             => worked?  (always 1 for p)
+ *  hbytes blockcipher e|d VAR ALG MODE [IV]     => IV
+ *  hbytes hash ALG VALUE                        => hash
+ *  hbytes hmac ALG VALUE KEY [MACLENGTH]        => mac
+ *
+ * Refs: HMAC: RFC2104
+ */
+
+#ifndef HBYTES_H
+#define HBYTES_H
+
+#include <assert.h>
+#include <stdlib.h>
+
+#include <tcl.h>
+
+typedef unsigned char Byte;
+
+/* from hbytes.c */
+
+typedef struct {
+  Byte *start, *end; /* always allocated dynamically */
+} HBytes_Value; /* overlays internalRep */
+
+extern Tcl_ObjType hbytes_type;
+
+int staticerr(Tcl_Interp *ip, const char *m);
+void objfreeir(Tcl_Obj *o);
+
+Tcl_Obj *hbytes_set(Tcl_Obj *overwrite, const Byte *array, int l);
+
+/* from enum.c */
+
+extern Tcl_ObjType enum_nearlytype;
+
+const void *enum_lookup_cached_func(Tcl_Interp *ip, Tcl_Obj *o,
+                                   size_t entrysize, const void *firstentry,
+                                   const char *what);
+#define enum_lookup_cached(ip,o,table,what)                    \
+    (enum_lookup_cached_func((ip),(o),                         \
+                            sizeof((table)[0]),&(table)[0],    \
+                            (what)))
+  /* table should be a pointer to an array of structs of size
+   * entrysize, the first member of which should be a const char*.
+   * The table should finish with a null const char *.
+   * On error, 0 is returned and the ip->result will have been
+   * set to the error message.
+   */
+
+/* useful macros */
+
+#define HBYTES(o) ((HBytes_Value*)&(o)->internalRep.twoPtrValue)
+#define HBYTES_LEN(o) (HBYTES((o))->end - HBYTES((o))->start)
+
+#define TALLOC(s) ((void*)Tcl_Alloc((s)))
+#define TFREE(f) (Tcl_Free((void*)(f)))
+
+#endif /*HBYTES_H*/
diff --git a/base/enum.c b/base/enum.c
new file mode 100644 (file)
index 0000000..1a66aa3
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ *
+ */
+
+#include "hbytes.h"
+
+static void enum_nt_dup(Tcl_Obj *src, Tcl_Obj *dup) {
+  dup->internalRep= src->internalRep;
+}
+
+static void enum_nt_ustr(Tcl_Obj *o) {
+  abort();
+}
+
+static int enum_nt_sfa(Tcl_Interp *ip, Tcl_Obj *o) {
+  abort();
+}
+
+Tcl_ObjType enum_nearlytype = {
+  "enum-nearly",
+  0, enum_nt_dup, enum_nt_ustr, enum_nt_sfa
+};
+
+const void *enum_lookup_cached_func(Tcl_Interp *ip, Tcl_Obj *o,
+                                   size_t entrysize, const void *firstentry,
+                                   const char *what) {
+  const char *supplied, *found;
+  const char *ep;
+  
+  if (o->typePtr == &enum_nearlytype &&
+      o->internalRep.twoPtrValue.ptr1 == firstentry)
+    return o->internalRep.twoPtrValue.ptr2;
+
+  supplied= Tcl_GetStringFromObj(o,0);  assert(supplied);
+  for (ep= firstentry;
+       (found= *(const char*const*)ep) && strcmp(supplied,found);
+       ep += entrysize);
+
+  if (found) {
+    objfreeir(o);
+    o->typePtr= &enum_nearlytype;
+    o->internalRep.twoPtrValue.ptr1= (void*)firstentry;
+    o->internalRep.twoPtrValue.ptr2= (void*)ep;
+    return ep;
+  }
+
+  Tcl_ResetResult(ip);
+  Tcl_AppendResult(ip, "invalid ",what," - must be one of:",(char*)0);
+  for (ep= firstentry;
+       (found= *(const char*const*)ep);
+       ep += entrysize)
+    Tcl_AppendResult(ip, " ",found,(char*)0);
+  return 0;
+}
index 2ae36d57338b4e5101ad7d1ed9799a38845a0d5c..765d5e45997366f09822f31b3f8e60aa728d88ba 100644 (file)
@@ -1,20 +1,19 @@
-OBJS=  forwarder.o \
-       main.o \
-       misc.o \
-       intr-sigio.o \
-       bget/bget.o
+OBJS=          hbytes.o \
+               enum.o
 
-HDRS=  misc.h \
-       forwarder.h \
-       intr.h
+HDRS=          hbytes.h
 
-CFLAGS=        -g -Wall
+TARGETS=       hbytes.so
 
-fvpn:          $(OBJS)
-               $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(OBJS) $(LDLIBS)
+CFLAGS=        -g -Wall -O
+
+all:           $(TARGETS)
+
+hbytes.so:     $(OBJS)
+               $(CC) $(CFLAGS) $(LDFLAGS) -o $@ -shared $(OBJS) $(LDLIBS)
 
 %.o:           %.c $(HDRS)
                $(CC) $(CFLAGS) $(CPPFLAGS) -o $@ -c $<
 
 clean:
-               rm -f $(OBJS) *~ ./#*#
+               rm -f $(OBJS) $(TARGETS) *~ ./#*#
diff --git a/hbytes/hbytes.c b/hbytes/hbytes.c
new file mode 100644 (file)
index 0000000..99bddfe
--- /dev/null
@@ -0,0 +1,165 @@
+/*
+ *
+ */
+
+#include "hbytes.h"
+
+int staticerr(Tcl_Interp *ip, const char *m) {
+  Tcl_SetResult(ip, (char*)m, TCL_STATIC);
+  return TCL_ERROR;
+}
+
+static void hbytes_setintern(Tcl_Obj *o, const Byte *array, int l) {
+  Byte *np;
+    
+  HBYTES(o)->start= np= l ? TALLOC(l) : 0;
+  memcpy(np, array, l);
+  HBYTES(o)->end= np + l;
+  o->typePtr = &hbytes_type;
+}
+
+static void hbytes_t_dup(Tcl_Obj *src, Tcl_Obj *dup) {
+  hbytes_setintern(src, HBYTES(src)->start, HBYTES_LEN(src));
+}
+
+Tcl_Obj *hbytes_set(Tcl_Obj *overwrite, const Byte *array, int l) {
+  if (!overwrite) overwrite= Tcl_NewObj();
+  objfreeir(overwrite);
+  Tcl_InvalidateStringRep(overwrite);
+  hbytes_setintern(overwrite, array, l);
+  return overwrite;
+}
+
+static void hbytes_t_free(Tcl_Obj *o) {
+  TFREE(HBYTES(o)->start);
+}
+
+static void hbytes_t_ustr(Tcl_Obj *o) {
+  int l;
+  char *str;
+  const Byte *byte;
+
+  l= HBYTES_LEN(o);
+  byte= HBYTES(o)->start;
+  str= o->bytes= TALLOC(l*2+1);
+  o->length= l*2;
+  while (l>0) {
+    sprintf(str,"%02x",*byte);
+    str+=2; byte++; l--;
+  }
+}
+
+void objfreeir(Tcl_Obj *o) {
+  if (o->typePtr && o->typePtr->freeIntRepProc)
+    o->typePtr->freeIntRepProc(o);
+}  
+
+static int hbytes_t_sfa(Tcl_Interp *ip, Tcl_Obj *o) {
+  char *str, *ep, *os;
+  Byte *startbytes, *bytes;
+  int l;
+  char cbuf[3];
+
+  os= str= Tcl_GetStringFromObj(o,&l);  assert(str);
+  if (l & 1) return staticerr(ip, "hbytes: conversion from hex:"
+                             " odd length in hex");
+
+  startbytes= bytes= l ? TALLOC(l*2) : 0;
+  cbuf[2]= 0;
+  while (l>0) {
+    cbuf[0]= *str++;
+    cbuf[1]= *str++;
+    *bytes++= strtoul(cbuf,&ep,16);
+    if (ep != cbuf+2) {
+      TFREE(startbytes);
+fprintf(stderr,">%d|%s|%s<\n",l,os,cbuf);
+      return staticerr(ip, "hbytes: conversion from hex:"
+                      " bad hex digit");
+    }
+    l -= 2;
+  }
+  objfreeir(o);
+
+  HBYTES(o)->start= startbytes;
+  HBYTES(o)->end= bytes;
+  o->typePtr = &hbytes_type;
+  return TCL_OK;
+}
+
+Tcl_ObjType hbytes_type = {
+  "hbytes",
+  hbytes_t_free, hbytes_t_dup, hbytes_t_ustr, hbytes_t_sfa
+};
+
+static Tcl_Obj *hb_getvar(Tcl_Interp *ip, Tcl_Obj *varname) {
+  int ec;
+  Tcl_Obj *value;
+  
+  value= Tcl_ObjGetVar2(ip,varname,0,TCL_LEAVE_ERR_MSG);
+  if (!value) return 0;
+
+  ec= Tcl_ConvertToType(ip,value,&hbytes_type);
+  if (ec) return 0;
+
+  return value;
+}
+
+static int hc_bin(ClientData cd, Tcl_Interp *ip, int objc,
+                 Tcl_Obj *const *objv) {
+  Tcl_Obj *varname, *value, *result;
+  const char *str;
+  int l;
+
+  varname= objv[0];
+  switch (objc) {
+  case 1:
+    value= hb_getvar(ip,varname);  if (!value) return TCL_ERROR;
+    result= Tcl_NewStringObj(HBYTES(value)->start, HBYTES_LEN(value));
+    assert(result);
+    Tcl_SetObjResult(ip,result);
+    return TCL_OK;
+  case 2:
+    value= objv[1];
+    str= Tcl_GetStringFromObj(value,&l);
+    value= hbytes_set(0,str,l);
+    value= Tcl_ObjSetVar2(ip,varname,0, value, TCL_LEAVE_ERR_MSG);
+    if (!value) return TCL_ERROR;
+    Tcl_ResetResult(ip);
+    return TCL_OK;
+  }
+  abort();
+}
+
+typedef struct {
+  const char *name;
+  int minargs, maxargs;
+  Tcl_ObjCmdProc *func;
+} SubCommand;
+
+static const SubCommand subcommands[] = {
+  { "bin", 1, 2, hc_bin },
+  { 0 }
+};
+
+static int hb_proc(ClientData cd, Tcl_Interp *ip, int objc,
+                  Tcl_Obj *const *objv) {
+  const SubCommand *sc;
+
+  if (objc<2) return staticerr(ip, "hbytes: need subcommand");
+  sc= enum_lookup_cached(ip,objv[1],subcommands,"hbytes subcommand");
+  if (!sc) return TCL_ERROR;
+  objc -= 2;
+  objv += 2;
+  if (objc < sc->minargs)
+    return staticerr(ip, "too few args");
+  if (sc->maxargs >=0 && objc > sc->maxargs)
+    return staticerr(ip,"too many args");
+  return sc->func((void*)sc,ip,objc,objv);
+}
+
+int Hbytes_Init(Tcl_Interp *ip) {
+  Tcl_RegisterObjType(&hbytes_type);
+  Tcl_RegisterObjType(&enum_nearlytype);
+  Tcl_CreateObjCommand(ip,"hbytes", hb_proc,0,0);
+  return TCL_OK;
+}
diff --git a/hbytes/hbytes.h b/hbytes/hbytes.h
new file mode 100644 (file)
index 0000000..5aca162
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ */
+/*
+ *
+ *  hbytes bin VAR                               => binary string
+ *  hbytes bin VAR VALUE                         => set
+ *
+ *  hbytes prefix VAR [VALUE ...]         = set VAR [concat VALUE ... $VAR]
+ *  hbytes append VAR [VALUE ...]         = set VAR [concat $VAR VALUE ...]
+ *  hbytes concat VAR [VALUE ...]         = set VAR [concat VALUE ...]
+ *  hbytes unprepend VAR PREFIXLENGTH            => prefix (removed from VAR)
+ *  hbytes unappend VAR SUFFIXLENGTH             => suffix (removed from VAR)
+ *  hbytes chopto VAR NEWVARLENGTH               => suffix (removed from VAR)
+ *                                                  (too short? error)
+ *
+ *  hbytes pkcs5 pv|uv VAR ALG                   => worked?  (always 1 for p)
+ *  hbytes pkcs5 pn|un VAR BLOCKSIZE             => worked?  (always 1 for p)
+ *  hbytes blockcipher e|d VAR ALG MODE [IV]     => IV
+ *  hbytes hash ALG VALUE                        => hash
+ *  hbytes hmac ALG VALUE KEY [MACLENGTH]        => mac
+ *
+ * Refs: HMAC: RFC2104
+ */
+
+#ifndef HBYTES_H
+#define HBYTES_H
+
+#include <assert.h>
+#include <stdlib.h>
+
+#include <tcl.h>
+
+typedef unsigned char Byte;
+
+/* from hbytes.c */
+
+typedef struct {
+  Byte *start, *end; /* always allocated dynamically */
+} HBytes_Value; /* overlays internalRep */
+
+extern Tcl_ObjType hbytes_type;
+
+int staticerr(Tcl_Interp *ip, const char *m);
+void objfreeir(Tcl_Obj *o);
+
+Tcl_Obj *hbytes_set(Tcl_Obj *overwrite, const Byte *array, int l);
+
+/* from enum.c */
+
+extern Tcl_ObjType enum_nearlytype;
+
+const void *enum_lookup_cached_func(Tcl_Interp *ip, Tcl_Obj *o,
+                                   size_t entrysize, const void *firstentry,
+                                   const char *what);
+#define enum_lookup_cached(ip,o,table,what)                    \
+    (enum_lookup_cached_func((ip),(o),                         \
+                            sizeof((table)[0]),&(table)[0],    \
+                            (what)))
+  /* table should be a pointer to an array of structs of size
+   * entrysize, the first member of which should be a const char*.
+   * The table should finish with a null const char *.
+   * On error, 0 is returned and the ip->result will have been
+   * set to the error message.
+   */
+
+/* useful macros */
+
+#define HBYTES(o) ((HBytes_Value*)&(o)->internalRep.twoPtrValue)
+#define HBYTES_LEN(o) (HBYTES((o))->end - HBYTES((o))->start)
+
+#define TALLOC(s) ((void*)Tcl_Alloc((s)))
+#define TFREE(f) (Tcl_Free((void*)(f)))
+
+#endif /*HBYTES_H*/