X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ian/git?p=chiark-tcl.git;a=blobdiff_plain;f=base%2Fhook.c;h=6e4b3a102e4abe26cf48cdb26faad2066dd2d439;hp=cdcb246d2c742b945ad8444faad1cd1705529b01;hb=382dc154ad04e75c16d062af9e4ab49a82330ba0;hpb=5d466de467f28ae6f7125bef086d141a7734a4ce diff --git a/base/hook.c b/base/hook.c index cdcb246..6e4b3a1 100644 --- a/base/hook.c +++ b/base/hook.c @@ -1,17 +1,30 @@ /* + * 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, see . */ -#include +#include "chiark-tcl-base.h" -#include "hbytes.h" -#include "tables.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; } -int posixerr(Tcl_Interp *ip, int errnoval, const char *m) { +int cht_posixerr(Tcl_Interp *ip, int errnoval, const char *m) { const char *em; Tcl_ResetResult(ip); @@ -21,88 +34,32 @@ int posixerr(Tcl_Interp *ip, int errnoval, const char *m) { return TCL_ERROR; } -void objfreeir(Tcl_Obj *o) { +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, - Tcl_Obj *obj, Tcl_Obj **result) { - const char *tn; - int nums[3], i, lnl; - Tcl_Obj *objl[4]; - - if (obj->typePtr == &hbytes_type) { - HBytes_Value *v= OBJ_HBYTES(obj); - memset(nums,0,sizeof(nums)); - nums[1]= hbytes_len(v); - - 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; - } - lnl= 3; - } else { - tn= "other"; - lnl= 0; - } - - objl[0]= Tcl_NewStringObj((char*)tn,-1); - for (i=0; itypePtr= &hbytes_type; -} - -static void hbytes_t_free(Tcl_Obj *o) { - hbytes_free(OBJ_HBYTES(o)); -} - -void obj_updatestr_array_prefix(Tcl_Obj *o, const Byte *byte, - int l, const char *prefix) { - char *str; - int pl; - - pl= strlen(prefix); - o->length= l*2+pl; - str= o->bytes= TALLOC(o->length+1); - - memcpy(str,prefix,pl); - str += pl; - - while (l>0) { - sprintf(str,"%02x",*byte); - str+=2; byte++; l--; - } - *str= 0; -} - -void obj_updatestr_array(Tcl_Obj *o, const Byte *byte, int l) { - obj_updatestr_array_prefix(o,byte,l,""); -} - -void obj_updatestr_vstringls(Tcl_Obj *o, ...) { +void cht_obj_updatestr_vstringls(Tcl_Obj *o, ...) { va_list al; char *p; const char *part; - int l, pl; + int l; + size_t pl; va_start(al,o); - for (l=0; (part= va_arg(al, const char*)); ) - l+= va_arg(al, int); + 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); o->length= l; @@ -110,7 +67,7 @@ void obj_updatestr_vstringls(Tcl_Obj *o, ...) { va_start(al,o); for (p= o->bytes; (part= va_arg(al, const char*)); p += pl) { - pl= va_arg(al, int); + pl= va_arg(al, size_t); memcpy(p, part, pl); } va_end(al); @@ -118,230 +75,49 @@ void obj_updatestr_vstringls(Tcl_Obj *o, ...) { *p= 0; } -void obj_updatestr_string(Tcl_Obj *o, const char *str) { - obj_updatestr_vstringls(o, str, strlen(str), (char*)0); -} - -static void hbytes_t_ustr(Tcl_Obj *o) { - obj_updatestr_array(o, - hbytes_data(OBJ_HBYTES(o)), - hbytes_len(OBJ_HBYTES(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); - 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; - } - - o->typePtr = &hbytes_type; - return TCL_OK; -} - -Tcl_ObjType hbytes_type = { - "hbytes", - hbytes_t_free, hbytes_t_dup, hbytes_t_ustr, hbytes_t_sfa -}; - -int do_hbytes_raw2h(ClientData cd, Tcl_Interp *ip, - Tcl_Obj *binary, HBytes_Value *result) { - const unsigned char *str; - int l; - - str= Tcl_GetByteArrayFromObj(binary,&l); - hbytes_array(result, str, l); - return TCL_OK; -} - -int do_hbytes_h2raw(ClientData cd, Tcl_Interp *ip, - HBytes_Value hex, Tcl_Obj **result) { - *result= Tcl_NewByteArrayObj(hbytes_data(&hex), hbytes_len(&hex)); - return TCL_OK; -} - -int do_hbytes_length(ClientData cd, Tcl_Interp *ip, - HBytes_Value v, int *result) { - *result= hbytes_len(&v); - return TCL_OK; -} - -int do_hbytes_random(ClientData cd, Tcl_Interp *ip, - int length, HBytes_Value *result) { - Byte *space; - int rc; - - space= hbytes_arrayspace(result, length); - rc= get_urandom(ip, space, length); - if (rc) { hbytes_free(result); return rc; } - return TCL_OK; -} - -int do_hbytes_overwrite(ClientData cd, Tcl_Interp *ip, - HBytes_Var v, int start, HBytes_Value sub) { - int sub_l; - - sub_l= hbytes_len(&sub); - if (start < 0) - return staticerr(ip, "hbytes overwrite start -ve"); - if (start + sub_l > hbytes_len(v.hb)) - return staticerr(ip, "hbytes overwrite out of range"); - memcpy(hbytes_data(v.hb) + start, hbytes_data(&sub), sub_l); - return TCL_OK; -} - -int do_hbytes_trimleft(ClientData cd, Tcl_Interp *ip, HBytes_Var v) { - const Byte *o, *p, *e; - o= p= hbytes_data(v.hb); - e= p + hbytes_len(v.hb); - - while (p INT_MAX/sub_l) return staticerr(ip, "hbytes repeat too long"); - - data= hbytes_arrayspace(result, sub_l*count); - sub_d= hbytes_data(&sub); - while (count) { - memcpy(data, sub_d, sub_l); - count--; data += sub_l; - } - return TCL_OK; -} - -int do_hbytes_zeroes(ClientData cd, Tcl_Interp *ip, - int length, HBytes_Value *result) { - Byte *space; - space= hbytes_arrayspace(result, length); - memset(space,0,length); - return TCL_OK; -} - -int do_hbytes_compare(ClientData cd, Tcl_Interp *ip, - HBytes_Value a, HBytes_Value b, int *result) { - int al, bl, minl, r; - - al= hbytes_len(&a); - bl= hbytes_len(&b); - minl= al0) *result= +2; - else { - if (albl) *result= +1; - else *result= 0; - } - return TCL_OK; -} - -int do_hbytes_range(ClientData cd, Tcl_Interp *ip, - HBytes_Value v, int start, int size, - HBytes_Value *result) { - const Byte *data; - int l; - - l= hbytes_len(&v); - if (start<0 || size<0 || lfunc(0,ip,objc,objv); -} - -int do_toplevel_dgram_socket(ClientData cd, Tcl_Interp *ip, - const DgramSocket_SubCommand *subcmd, - int objc, Tcl_Obj *const *objv) { - return subcmd->func(0,ip,objc,objv); -} - -int do_toplevel_ulong(ClientData cd, Tcl_Interp *ip, - const ULong_SubCommand *subcmd, - int objc, Tcl_Obj *const *objv) { - return subcmd->func(0,ip,objc,objv); +void cht_obj_updatestr_string(Tcl_Obj *o, const char *str) { + cht_obj_updatestr_vstringls(o, str, strlen(str), (char*)0); } #define URANDOM "/dev/urandom" -int get_urandom(Tcl_Interp *ip, Byte *buffer, int l) { +int cht_get_urandom(Tcl_Interp *ip, Byte *buffer, int l) { static FILE *urandom; - int r, esave; + int r; if (!urandom) { urandom= fopen(URANDOM,"rb"); - if (!urandom) return posixerr(ip,errno,"open " URANDOM); + if (!urandom) return cht_posixerr(ip,errno,"open " URANDOM); } r= fread(buffer,1,l,urandom); if (r==l) return 0; - esave= errno; - fclose(urandom); urandom=0; - if (ferror(urandom)) { - return posixerr(ip,errno,"read " URANDOM); + r = cht_posixerr(ip,errno,"read " URANDOM); } else { assert(feof(urandom)); - return staticerr(ip, URANDOM " gave eof!"); + r = cht_staticerr(ip, URANDOM " gave eof!", 0); } + fclose(urandom); urandom=0; + return r; } -int Hbytes_Init(Tcl_Interp *ip) { - const TopLevel_Command *cmd; +void cht_prepare__basic(Tcl_Interp *ip) { + static int prepared; - Tcl_RegisterObjType(&hbytes_type); - Tcl_RegisterObjType(&blockcipherkey_type); - Tcl_RegisterObjType(&enum_nearlytype); - Tcl_RegisterObjType(&enum1_nearlytype); - Tcl_RegisterObjType(&sockaddr_type); - Tcl_RegisterObjType(&dgramsockid_type); - Tcl_RegisterObjType(&ulong_type); + if (prepared) return; + Tcl_RegisterObjType(&cht_tabledataid_nearlytype); + Tcl_RegisterObjType(&cht_enum_nearlytype); + Tcl_RegisterObjType(&cht_enum1_nearlytype); + prepared= 1; +} - for (cmd=toplevel_commands; +void cht_setup__commands(Tcl_Interp *ip, const TopLevel_Command *cmds) { + const TopLevel_Command *cmd; + + for (cmd= cmds; cmd->name; cmd++) - Tcl_CreateObjCommand(ip, cmd->name, cmd->func, 0,0); - - return TCL_OK; + Tcl_CreateObjCommand(ip, (char*)cmd->name, cmd->func, 0,0); }