X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ian/git?p=chiark-tcl.git;a=blobdiff_plain;f=base%2Fhook.c;h=0cb2f9d47961615e8dfde1af3966e2198401edcf;hp=08e055d6426379687d01c580a3e8caf6e099c121;hb=ca8b96bf81245f21fe3906c71dc2994bfc5e516f;hpb=2cf1bfc63e73a424f9f3899c204025a8346b38e0 diff --git a/base/hook.c b/base/hook.c index 08e055d..0cb2f9d 100644 --- a/base/hook.c +++ b/base/hook.c @@ -1,162 +1,126 @@ /* + * base code for various Tcl extensions + * Copyright 2006-2012 Ian Jackson + * + * 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 library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301, USA. */ -#include "hbytes.h" -#include "tables.h" +#include "chiark-tcl-base.h" -int staticerr(Tcl_Interp *ip, const char *m) { +int cht_staticerr(Tcl_Interp *ip, const char *m, const char *ec) { Tcl_SetResult(ip, (char*)m, TCL_STATIC); + if (ec) Tcl_SetObjErrorCode(ip, Tcl_NewStringObj(ec,-1)); return TCL_ERROR; } -void objfreeir(Tcl_Obj *o) { +int cht_posixerr(Tcl_Interp *ip, int errnoval, const char *m) { + const char *em; + + Tcl_ResetResult(ip); + errno= errnoval; + em= Tcl_PosixError(ip); + Tcl_AppendResult(ip, m, ": ", em, (char*)0); + return TCL_ERROR; +} + +int cht_newfdposixerr(Tcl_Interp *ip, int fd, const char *m) { + int e; + e= errno; + close(fd); + return cht_posixerr(ip,e,m); +} + +void cht_objfreeir(Tcl_Obj *o) { if (o->typePtr && o->typePtr->freeIntRepProc) o->typePtr->freeIntRepProc(o); o->typePtr= 0; } -int do_hbytes_rep_info(ClientData cd, Tcl_Interp *ip, - HBytes_Value v, Tcl_Obj **result) { - const char *tn; - int nums[3], i; - Tcl_Obj *objl[4]; +void cht_obj_updatestr_vstringls(Tcl_Obj *o, ...) { + va_list al; + char *p; + const char *part; + int l; + size_t pl; - memset(nums,0,sizeof(nums)); - nums[1]= hbytes_len(&v); + va_start(al,o); + for (l=0; (part= va_arg(al, const char*)); ) { + pl= va_arg(al, size_t); + assert(pl <= INT_MAX/2 - l); + l += pl; + } + va_end(al); - if (HBYTES_ISEMPTY(&v)) tn= "empty"; - else if (HBYTES_ISSENTINEL(&v)) tn= "sentinel!"; - else if (HBYTES_ISSIMPLE(&v)) tn= "simple"; - else { - HBytes_ComplexValue *cx= v.begin_complex; - tn= "complex"; - nums[0]= cx->prespace; - nums[2]= cx->avail - cx->len; + o->length= l; + o->bytes= TALLOC(l+1); + + va_start(al,o); + for (p= o->bytes; (part= va_arg(al, const char*)); p += pl) { + pl= va_arg(al, size_t); + memcpy(p, part, pl); } - - objl[0]= Tcl_NewStringObj((char*)tn,-1); - for (i=0; i<3; i++) objl[i+1]= Tcl_NewIntObj(nums[i]); - *result= Tcl_NewListObj(4,objl); - return TCL_OK; -} + va_end(al); -static void hbytes_t_dup(Tcl_Obj *src, Tcl_Obj *dup) { - objfreeir(dup); - hbytes_array(OBJ_HBYTES(dup), - hbytes_data(OBJ_HBYTES(src)), - hbytes_len(OBJ_HBYTES(src))); + *p= 0; } -static void hbytes_t_free(Tcl_Obj *o) { - hbytes_free(OBJ_HBYTES(o)); +void cht_obj_updatestr_string(Tcl_Obj *o, const char *str) { + cht_obj_updatestr_vstringls(o, str, strlen(str), (char*)0); } -static void hbytes_t_ustr(Tcl_Obj *o) { - int l; - char *str; - const Byte *byte; - - byte= hbytes_data(OBJ_HBYTES(o)); - l= hbytes_len(OBJ_HBYTES(o)); - str= o->bytes= TALLOC(l*2+1); - o->length= l*2; - while (l>0) { - sprintf(str,"%02x",*byte); - str+=2; byte++; l--; - } - *str= 0; -} - -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); - objfreeir(o); - - if (l & 1) return staticerr(ip, "hbytes: conversion from hex:" - " odd length in hex"); - - startbytes= bytes= hbytes_arrayspace(OBJ_HBYTES(o), l/2); - - cbuf[2]= 0; - while (l>0) { - cbuf[0]= *str++; - cbuf[1]= *str++; - *bytes++= strtoul(cbuf,&ep,16); - if (ep != cbuf+2) { - hbytes_free(OBJ_HBYTES(o)); - return staticerr(ip, "hbytes: conversion from hex:" - " bad hex digit"); - } - l -= 2; - } +#define URANDOM "/dev/urandom" - o->typePtr = &hbytes_type; - return TCL_OK; -} +int cht_get_urandom(Tcl_Interp *ip, Byte *buffer, int l) { + static FILE *urandom; -Tcl_ObjType hbytes_type = { - "hbytes", - hbytes_t_free, hbytes_t_dup, hbytes_t_ustr, hbytes_t_sfa -}; + int r, esave; -int do_hbytes_raw2h(ClientData cd, Tcl_Interp *ip, - Tcl_Obj *binary, HBytes_Value *result) { - const char *str; - int l; + if (!urandom) { + urandom= fopen(URANDOM,"rb"); + if (!urandom) return cht_posixerr(ip,errno,"open " URANDOM); + } + r= fread(buffer,1,l,urandom); + if (r==l) return 0; - str= Tcl_GetStringFromObj(binary,&l); - hbytes_array(result, str, l); - return TCL_OK; -} + esave= errno; + fclose(urandom); urandom=0; -int do_hbytes_h2raw(ClientData cd, Tcl_Interp *ip, - HBytes_Value hex, Tcl_Obj **result) { - *result= Tcl_NewStringObj(hbytes_data(&hex), hbytes_len(&hex)); - return TCL_OK; + if (ferror(urandom)) { + return cht_posixerr(ip,errno,"read " URANDOM); + } else { + assert(feof(urandom)); + return cht_staticerr(ip, URANDOM " gave eof!", 0); + } } -#if 0 -HC_DEFINE(pkcs5) { - static const PadKindInfo padkindinfos[0]= { - { "pa", 1, 1 }, - { "pn", 1, 0 }, - { "ua", 0, 1 }, - { "un", 0, 0 }, - { 0 } - }; - - HC_DECLS_HBV; - Tcl_Obj *v; - int blocksize; - const PadKindInfo *pk; - const BlockCipherInfo *bc; - - HC_ARG_ENUM(pk, padkindinfos); - HC_ARG_HBV; - if (!pk->algname) HC_ARG_INTRANGE(blocksize, 1,255); - else { HC_ARG_ENUM(bc, blockciphers); blocksize= bc->blocksize; } - HC_ARGS_E; - - /* do nothing :-) */ - - HC_FINI_HBV; -} -#endif +void cht_prepare__basic(Tcl_Interp *ip) { + static int prepared; -int do__hbytes(ClientData cd, Tcl_Interp *ip, - const HBytes_SubCommand *subcmd, - int objc, Tcl_Obj *const *objv) { - return subcmd->func(0,ip,objc,objv); + if (prepared) return; + Tcl_RegisterObjType(&cht_tabledataid_nearlytype); + Tcl_RegisterObjType(&cht_enum_nearlytype); + Tcl_RegisterObjType(&cht_enum1_nearlytype); + prepared= 1; } -int Hbytes_Init(Tcl_Interp *ip) { - Tcl_RegisterObjType(&hbytes_type); - Tcl_RegisterObjType(&enum_nearlytype); - Tcl_RegisterObjType(&enum1_nearlytype); - Tcl_CreateObjCommand(ip,"hbytes", pa__hbytes,0,0); - return TCL_OK; +void cht_setup__commands(Tcl_Interp *ip, const TopLevel_Command *cmds) { + const TopLevel_Command *cmd; + + for (cmd= cmds; + cmd->name; + cmd++) + Tcl_CreateObjCommand(ip, (char*)cmd->name, cmd->func, 0,0); }