#include #include #include #include #include "util.h" typedef struct priv_mem_w PRIV_MEM_W; struct priv_mem_w { char *b; int a; int l; char **sp; int *lp; } ; #ifdef LOG_UTIL static void foo(const char *, ...) __attribute__((__format__(__printf__,1,2))); static void foo(const char *fmt, ...) { va_list ap; char *txt; static FILE *df; static int initted = 0; if (initted < 0) return; if (initted == 0) { df = fopen("util.log","w"); if (df == 0) { initted = -1; return; } setlinebuf(df); initted = 1; } va_start(ap,fmt); vasprintf(&txt,fmt,ap); va_end(ap); fprintf(df,"%s\n",txt); free(txt); } #else #define foo(x...) do { } while (0) #endif static void mem_w_room(PRIV_MEM_W *p, int spc) { if (spc > p->a) { p->a = spc + 256; p->b = realloc(p->b,p->a); } } static int w_mem_w(void *pv, const char *buf, int len) { PRIV_MEM_W *p; p = pv; foo("w_mem_w: pv=%p buf=%p len=%d, current buf %p alloc %d len %d",pv,(const void *)buf,len,(void *)p->b,p->a,p->l); if (len < 1) return(len); if (p->sp) { mem_w_room(p,p->l+len+1); bcopy(buf,p->b+p->l,len); } p->l += len; return(len); } static int c_mem_w(void *pv) { PRIV_MEM_W *p; p = pv; foo("c_mem_w: pv=%p",pv); if (p->sp) { mem_w_room(p,p->l+1); p->b[p->l] = '\0'; *p->sp = p->b; foo("c_mem_w: wrote %p through %p",(void *)p->b,(void *)p->sp); } if (p->lp) { *p->lp = p->l; foo("c_mem_w: wrote %d through %p",p->l,(void *)p->lp); } free(p); return(0); } FILE *util_memopen_w(char **sp, int *lp) { PRIV_MEM_W *p; FILE *f; foo("util_memopen_w: sp=%p lp=%p",(void *)sp,(void *)lp); p = malloc(sizeof(PRIV_MEM_W)); if (! p) return(0); f = funopen(p,0,&w_mem_w,0,&c_mem_w); if (! f) { free(p); return(0); } p->b = 0; p->a = 0; p->l = 0; p->sp = sp; p->lp = lp; foo("util_memopen_w: returning %p, priv %p",(void *)f,(void *)p); return(f); } typedef struct priv_mem_r PRIV_MEM_R; struct priv_mem_r { const char *s; int l; int o; } ; static int r_mem_r(void *pv, char *buf, int len) { PRIV_MEM_R *p; int n; p = pv; foo("r_mem_r: pv=%p buf=%p len=%d, offset %d/%d",pv,(void *)buf,len,p->o,p->l); if (len < 1) return(len); n = p->l - p->o; if (n > len) n = len; if (n > 0) { bcopy(p->s+p->o,buf,n); p->o += n; } foo("r_mem_r: returning %d, offset now %d",n,p->o); return(n); } static int c_mem_r(void *pv) { foo("c_mem_r: pv=%p",pv); free(pv); return(0); } FILE *util_memopen_r(const char *text, int len) { PRIV_MEM_R *p; FILE *f; foo("util_memopen_r: text=%p len=%d",(const void *)text,len); p = malloc(sizeof(PRIV_MEM_R)); if (! p) return(0); f = funopen(p,&r_mem_r,0,0,&c_mem_r); if (! f) { free(p); return(0); } p->s = text; p->l = len; p->o = 0; foo("util_memopen_r: returning %p, priv %p",(void *)f,(void *)p); return(f); } typedef struct priv_tee_r PRIV_TEE_R; struct priv_tee_r { FILE *r; FILE *t; unsigned int flags; } ; static int r_tee_r(void *pv, char *buf, int len) { PRIV_TEE_R *p; int n; foo("r_tee_r: pv=%p buf=%p len=%d",pv,(void *)buf,len); if (len < 1) return(len); p = pv; n = fread(buf,1,len,p->r); foo("r_tee_r: read %d from %p, ferror now %d",n,(void *)p->r,ferror(p->r)); if (ferror(p->r)) return(-1); if (n > 0) { foo("r_tee_r: writing to %p",(void *)p->t); fwrite(buf,1,n,p->t); } foo("r_tee_r: returning %d",n); return(n); } static int c_tee_r(void *pv) { PRIV_TEE_R *p; p = pv; foo("c_tee_r: closing priv %p",pv); if (p->flags & TEE_F_CLOSE_R) { foo("c_tee_r: cascade closing %p",(void *)p->r); fclose(p->r); } if (p->flags & TEE_F_CLOSE_TEE) { foo("c_tee_r: cascade closing %p",(void *)p->t); fclose(p->t); } free(p); return(0); } FILE *util_teeopen_r(FILE *r, FILE *t, unsigned int flags) { PRIV_TEE_R *p; FILE *f; foo("util_teeopen_r: r=%p t=%p flags=%d",(void *)r,(void *)t,flags); if (flags & ~(TEE_F_CLOSE_R|TEE_F_CLOSE_TEE)) return(0); p = malloc(sizeof(PRIV_TEE_R)); if (! p) return(0); f = funopen(p,&r_tee_r,0,0,&c_tee_r); if (! f) { free(p); return(0); } p->r = r; p->t = t; p->flags = flags; foo("util_teeopen_r: returning %p, priv = %p",(void *)f,(void *)p); return(f); } typedef struct priv_tee_w PRIV_TEE_W; struct priv_tee_w { FILE *a; FILE *b; unsigned int flags; } ; static int w_tee_w(void *pv, const char *buf, int len) { PRIV_TEE_W *p; foo("w_tee_w: pv=%p buf=%p len=%d",pv,(const void *)buf,len); if (len < 1) return(len); p = pv; fwrite(buf,1,len,p->a); fwrite(buf,1,len,p->b); return(len); } static int c_tee_w(void *pv) { PRIV_TEE_W *p; p = pv; foo("c_tee_w: closing priv %p",pv); if (p->flags & TEE_F_CLOSE_A) { foo("c_tee_w: cascade closing %p",(void *)p->a); fclose(p->a); } if (p->flags & TEE_F_CLOSE_B) { foo("c_tee_w: cascade closing %p",(void *)p->b); fclose(p->b); } free(p); return(0); } FILE *util_teeopen_w(FILE *a, FILE *b, unsigned int flags) { PRIV_TEE_W *p; FILE *f; foo("util_teeopen_w: a=%p b=%p flags=%d",(void *)a,(void *)b,flags); if (flags & ~(TEE_F_CLOSE_A|TEE_F_CLOSE_B)) return(0); p = malloc(sizeof(PRIV_TEE_W)); if (! p) return(0); f = funopen(p,0,&w_tee_w,0,&c_tee_w); if (! f) { free(p); return(0); } p->a = a; p->b = b; p->flags = flags; foo("util_teeopen_w: returning %p, priv = %p",(void *)f,(void *)p); return(f); }