From 568dfce1d3c4b7b3bc4fc1503469a35b5e21734f Mon Sep 17 00:00:00 2001 From: short <> Date: Sun, 16 Jan 2000 16:11:42 +0000 Subject: [PATCH] Initial import, non-compilable, stripped down m1d/common.[ch] version. --- vblib.c | 985 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ vblib.h | 181 ++++++++++++ 2 files changed, 1166 insertions(+) create mode 100644 vblib.c create mode 100644 vblib.h diff --git a/vblib.c b/vblib.c new file mode 100644 index 0000000..61017c7 --- /dev/null +++ b/vblib.c @@ -0,0 +1,985 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "common.h" +#include "dataserv.h" + +const int safesigs[]={SIGQUIT,SIGINT,SIGTERM,SIGIOT,SIGALRM,-1}; //SIGCHLD->childsignal anyway +char vbnexact; +const char *upsc_sshpath="/usr/bin/ssh"; /* upsetupconn()... */ +const char *upsc_dstport=DS_PORT; + +void chk(const void *p) +{ + vbsanity(); + if (p) return; + FATAL(CRIT,"NULL-check failure, memory exhausted? FATAL: %m"); +} + +#ifndef NDEBUG +static void *vbchecknull=NULL; +static struct varbuf *vbcheckhead=(struct varbuf *)&vbchecknull; +static unsigned vbchecknum; +#ifdef FATALSIG_INSANE +static char vbcheckno; +#else +#define vbcheckno (0) +#endif +pthread_mutex_t vbcheckmx=PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP; + +static void vbchecklock (void) +{ if (pthread_mutex_lock (&vbcheckmx)) FATAL(CRIT,"Mutex ""lock on vbcheck mx"); } +static void vbcheckunlock(void) +{ if (pthread_mutex_unlock(&vbcheckmx)) FATAL(CRIT,"Mutex unlock on vbcheck mx"); } + +static char vbchecklist(struct varbuf *vb) +{ +struct varbuf *vbs; +unsigned tot=0; + + vbchecklock(); + assert(!vbchecknull); + assert(!!vb); + for (vbs=vbcheckhead;vbs;vbs=vbs->checknext,tot++) + if (vb==vbs) break; + if (!vbs) { + vbcheckunlock(); + return(0); + } + assert(vb->checknext); + while (tot++,(vbs=vbs->checknext)!=vbchecknull) assert(vb!=vbs); + assert(tot==vbchecknum+1); + vbcheckunlock(); + return(1); +} + +void vbcheck(struct varbuf *vb) +{ +struct varbufnode *vbn; +char *s; +volatile char touch; + + if (vbcheckno) return; vbchecklock(); + assert(vbchecklist(vb)); + if (vb->done) assert(!!vb->f); + if (vb->free) assert(!!vb->l); + assert((!vb->f)==(!vb->f)); + for (vbn=vb->f;vbn;vbn=vbn->next) { + if (vbn==vb->f) assert(vb->done<=vbn->size); + if (vbn==vb->l) assert(vb->free<=vbn->size); + for (s=vbn->buf;sbuf+vbn->size;s++) touch=*s; + } + vbcheckunlock(); +} + +void vbsanity(void) +{ +struct varbuf *vb; + dbg("vbsanity()\n"); + if (vbcheckno) return; vbchecklock(); + assert(!vbchecknull); + for (vb=vbcheckhead;vb!=(struct varbuf *)&vbchecknull;vb=vb->checknext) vbcheck(vb); + vbcheckunlock(); +} +#endif + +#ifdef VBDEBUG +void vbdebug(struct varbuf *vb,const char *msg) +{ +struct varbufnode *vbn; + fprintf(stderr,"vbdebug(%s): vb=%p",msg,vb); + vbcheck(vb); + if (!vb) { + fprintf(stderr,"\n"); + return; + } + fprintf(stderr,", first=%p, last=%p, done=%u, free=%u\n",vb->f,vb->l,vb->done,vb->free); + for (vbn=vb->f;vbn;vbn=vbn->next) { +size_t i; + fprintf(stderr," *VBN: %p: size=%u, buf:",vbn,vbn->size); + for (i=0;isize;i++) { +char c=vbn->buf[i]; + if (isprint(c)) fprintf(stderr," '%c'",c); + else fprintf(stderr," %02x",(unsigned char)c); + } + fprintf(stderr,"\n"); + } + fprintf(stderr,"vbdebug(%s): finishing...\n",msg); +} +#endif + +struct varbufnode *vbnnew(size_t sugsize) +{ +struct varbufnode *r; + if (!vbnexact && sugsizenext=NULL; + r->size=sugsize; + return(r); +} + +void vbgrow(struct varbuf *vb,size_t sugsize) +{ +struct varbufnode *vbn; + vbdebug(vb,"vbgrow"); + assert(!vb->free); + if (!vbnexact) { + if (vb->l && vb->l->size>sugsize) sugsize=vb->l->size; + if (sugsize*2<=VB_MAXSIZE) sugsize*=2; + else if (sugsizel) vb->l->next=vbn; + else vb->f=vbn; + vb->l=vbn; + vb->free=vbn->size; +} + +void vbinit(struct varbuf *vb) +{ +#ifndef NDEBUG + if (!vbcheckno) assert(!vbchecklist(vb)); +#endif + bzero(vb,sizeof(*vb)); +#ifndef NDEBUG + vbchecklock(); + vb->checknext=vbcheckhead; + vbcheckhead=vb; + vbchecknum++; + vbcheckunlock(); +#endif + vbcheck(vb); +} + +struct varbufnode *vbremone(struct varbuf *vb) +{ +struct varbufnode *r; + vbdebug(vb,"vbremone"); + assert(vb->f); + r=vb->f->next; + free(vb->f); + vb->done=0; + if (!(vb->f=r)) { + vb->l=NULL; + vb->free=0; + } + return(r); +} + +void vbclear(struct varbuf *vb) +{ + vbdebug(vb,"vbclear"); + while (vb->f) vbremone(vb); +} + +void vbrem(struct varbuf *vb) +{ +#ifndef NDEBUG +struct varbuf **vbp; +#endif + + vbdebug(vb,"vbrem"); + vbclear(vb); +#ifndef NDEBUG + vbchecklock(); + assert(vbchecknum>0); + for (vbp=&vbcheckhead;*vbp;vbp=&(*vbp)->checknext) + if (*vbp==vb) break; + *vbp=vb->checknext; + vbchecknum--; + bzero(vb,sizeof(*vb)); + vbcheckunlock(); +#endif +} + +size_t vbsize(struct varbuf *vb,size_t maxsize) +{ +size_t size=0; +struct varbufnode *vbn=vb->f; + + vbdebug(vb,"vbsize"); + while (vbn && (!maxsize || sizenext; + } + return(size); +} + +#define GENVARBUFC(argmid) \ + void vbput##argmid(struct varbuf *vb,const argmid arg) \ + { vbwrite(vb,&arg,sizeof(arg)); } \ + char vbget##argmid(struct varbuf *vb,argmid *argp) \ + { if (sizeof(*argp)>1 && !VBCHKSIZE(vb,sizeof(*argp))) return(0); \ + return(vbread(vb,argp,sizeof(*argp))); } + +#ifndef INLINE_PUTGETCHAR +GENVARBUFC(char) +#endif +GENVARBUFC(short) +GENVARBUFC(int) + +#undef GENVARBUFC + +void vbwrite(struct varbuf *vb,const void *buf,size_t count) +{ +size_t now; + + vbdebug(vb,"vbwrite"); + if (!count) return; + if (vb->free) { + assert(vb->l); + memcpy(vb->l->buf+VBNSIZEL(vb,vb->l),buf,(now=min(vb->free,count))); + count-=now; + vb->free-=now; + if (!count) return; + buf+=now; + } + vbgrow(vb,count); + assert(vb->free>=count); + assert(vb->l&&vb->l->size==vb->free); + memcpy(vb->l->buf,buf,count); + vb->free-=count; + assert(vb->free>=0); +} + +extern size_t vbputstring(struct varbuf *vb,const char *s) +{ +size_t l=strlen(s); + vbwrite(vb,s,l); + return(l); +} + +ssize_t vbwritefd(struct varbuf *vb,int fd) +{ +ssize_t now,got=0; + + vbdebug(vb,"vbwritefd"); + for (;;) { + if (!vb->free) vbgrow(vb,0); + now=read(fd,vb->l->buf+vb->l->size-vb->free,vb->free); + dbg("vbwritefd: now=%d\n",now); + if (now<0) { + if (errno==EAGAIN) break; + return(now); + } + if (!now) { + errno=ENODATA; + return(-1); + } + vb->free-=now; + assert(vb->free>=0); + } + return(got); +} + +size_t vbpeek(struct varbuf *vb,ssize_t offs,void *buf,size_t count) +{ +size_t got=0,now,size; +char doread; +struct varbufnode *vbn=vb->f; + + vbdebug(vb,"vbpeek"); + if ((doread=(offs==-1))) offs=0; + offs+=vb->done; + while (vbn && count) { + size=VBNSIZEL(vb,vbn); + if (offsbuf+offs,(now=min(count,size-offs))); + buf+=now; + count-=now; + got+=now; + offs+=now; + if (doread) { + assert(vbn==vb->f); + vb->done+=now; + } + } + offs-=size; + if (!VBNSIZE(vb,vb->f)) { + assert(doread); + vbremone(vb); + vbn=vb->f; + } + else vbn=vbn->next; + } + return(got); +} + +ssize_t vbchrn(struct varbuf *vb,ssize_t offs,char c,char dir) +{ +struct vbl { + struct vbl *next; + struct varbufnode *vbn; + } *vbl=NULL,*vbl2; +struct varbufnode *vbn; +ssize_t distoffs=0,size=vbsize(vb,0); + + assert(!!dir); + if (offs==-1 || offs>=size) { + if (dir>0) return(-1); + else offs=size-1; + } + if (offs<0) return(-1); + vbn=vb->f; + offs+=vb->done; + distoffs=-vb->done; + while (vbn && offs>=vbn->size) { + if (dir<0) { + chk(vbl2=alloca(sizeof(*vbl2))); + vbl2->next=vbl; + vbl2->vbn=vbn; + vbl=vbl2; + } + offs-=vbn->size; + assert(offs>=0); + distoffs+=vbn->size; + vbn=vbn->next; + } + if (dir<0) for (;;) { + if (vbn && offssize=%u\n",start,offs,vbn->size); + while (offs>=start&&vbn->buf[offs]!=c) offs--; + if (offs>=start) return(distoffs+offs); + } + if (!vbl) break; + vbn=vbl->vbn; + vbl=vbl->next; + distoffs-=vbn->size; + offs=vbn->size-1; + assert(offs>=0); + } + if (dir>0) while (vbn) { +size_t size=VBNSIZEL(vb,vbn); +char *s; + dbg("vbn=%p,offs=%d,size=%d\n",vbn,offs,size); + assert(offs<=size); + if ((s=memchr(vbn->buf+offs,c,size-offs))) + return(distoffs+(s-vbn->buf)); + distoffs+=vbn->size; + vbn=vbn->next; + offs=0; + } + return(-1); +} + +ssize_t vbreadfd(struct varbuf *vb,int fd) +{ +ssize_t now,got=0; + + vbdebug(vb,"vbreadfd"); + dbg("entering vbreadfd(fd=%d)\n",fd); + while (vb->f) { +size_t size=VBNSIZE(vb,vb->f); + now=write(fd,vb->f->buf+vb->done,size); + dbg("vbreadfd: now=%d\n",now); + if (now<0 && errno!=EAGAIN) return(now); + if (now<=0) return(got); + vb->done+=now; + assert(vb->done<=size); + got+=now; + if (!VBNSIZE(vb,vb->f)) + vbremone(vb); + } + return(got); +} + +char quiet_null; + +static void fixupnulls(char *s,size_t len,const char *fname) +{ +unsigned tot=0; +char *d; + + for (d=s;(d=memchr(d,'\0',s+len-d));) { *d++=' '; tot++; } + if (tot) logmsg((quiet_null?MYLOG_DEBUG:MYLOG_ERR), + "%s() replaced %u '\\0's by ' ' in: %.*s",fname,tot,(int)len,s); +} + +char *vbgetline(struct varbuf *vb,char term) +{ +size_t len,r; +char *s; + + if (!(len=vbchrn(vb,0,term,1)+1)) return(NULL); + assert(len>0); + chk(s=malloc(len)); + r=vbread(vb,s,len); assert(r==len); + assert(s[len-1]==term); + s[len-1]='\0'; + fixupnulls(s,len-1,"vbgetline"); + return(s); +} + +size_t chkvsprintf(char **sp,const char *fmt,va_list ap) +{ +size_t bufsize=VB_DEFSIZE; +int i; + + for (*sp=NULL;;) { + chk(*sp=realloc(*sp,bufsize)); + i=vsnprintf(*sp,bufsize,fmt,ap); + dbg("chkvsprintf: bufsize=%u,i=%d,fmt:%s\n",bufsize,i,fmt); + if (i>=0&&i=0); + return(i); +} + +size_t vbvprintf(struct varbuf *vb,const char *fmt,va_list ap,char remlf) +{ +char *buf=NULL; +size_t len; + + len=chkvsprintf(&buf,fmt,ap); + if (remlf) { +char *s,c; + for (s=buf;(c=*s);s++) { + if (c<0 || (c>=' '&&c!='\\')) { + vbputchar(vb,c); + continue; + } + vbputchar(vb,'\\'); + switch (c) { + case '\n' : vbputchar(vb,'n'); break; + case '\r' : vbputchar(vb,'r'); break; + case 1 ... 9: //FALLTHRU + case 11 ... 12: //FALLTHRU + case 14 ... 31: vbprintf(vb,"x%02X",c); break; + case '\\' : vbputchar(vb,'\\'); break; + default: assert(0); + } + } + } + else vbwrite(vb,buf,len); + free(buf); + return(len); +} + +size_t vbprintf(struct varbuf *vb,const char *fmt,...) //stub +{ +va_list ap; +size_t r; + + va_start(ap,fmt); + r=vbvprintf(vb,fmt,ap,0); + va_end(ap); + return(r); +} + +#ifdef PSTR_16BIT +#define PSTR_MAX 65535 +#define PSTR_TYPE short +#else +#define PSTR_MAX 255 +#define PSTR_TYPE char +#endif + +#define PSTR_PUTLEN2(vb,len,type) vbput##type((vb),(type)(len)) +#define PSTR_PUTLEN1(vb,len,type) PSTR_PUTLEN2(vb,len,type) +#define PSTR_PUTLEN(vb,len) PSTR_PUTLEN1((vb),(len),PSTR_TYPE) + +void vbpstrputstring(struct varbuf *vb,const char *s) +{ +size_t len=strlen(s); + if (len>PSTR_MAX) { + LOG(CRIT,"String longer (%u) than PSTRing max (%u)",len,PSTR_MAX); + len=PSTR_MAX; + dbg("vbpstrputstring-longer than MAX: \"%s\"\n",s); + } + PSTR_PUTLEN(vb,len); + vbwrite(vb,s,len); +} + +size_t vbpstrcopy(struct varbuf *vbd,struct varbuf *vbs,ssize_t len) +{ +size_t size,was; + if (len==-1) len=vbsize(vbs,0); + else if ((size=vbsize(vbs,len))PSTR_MAX) { + LOG(CRIT,"String longer (%u) than PSTRing max (%u)",len,PSTR_MAX); + len=PSTR_MAX; + vbdebug(vbs,"vbpstrputstring-longer than MAX"); + } + PSTR_PUTLEN(vbd,len); + vbcopy(vbd,vbs,len); + if (was!=len) vbdrop(vbs,was-len); + return(was); +} + +void vbpstrprintf(struct varbuf *vb,const char *fmt,...) +{ +va_list ap; +char buf[PSTR_MAX+1]; +int i; + + va_start(ap,fmt); + i=vsnprintf(buf,sizeof(buf),fmt,ap); + va_end(ap); + if (i==-1) { + LOG(CRIT,"Buffer overflow (max=%u) during PSTR printf",PSTR_MAX); + i=PSTR_MAX; + } + assert(i>=0 && i<=PSTR_MAX && !buf[i]); + vbpstrputstring(vb,buf); +} + +char *vbpstrread(struct varbuf *vb) +{ +unsigned PSTR_TYPE len,scan,chgd=0; +char *buf; +size_t r; + + if (!vbpeek(vb,0,&len,sizeof(len))) return(NULL); + if (!VBCHKSIZE(vb,1+len)) return(NULL); + chk(buf=malloc(len+1)); + vbdrop(vb,sizeof(len)); + r=vbread(vb,buf,len); assert(r==len); + buf[len]='\0'; + for (scan=0;scangot) count=got; + else got=count; + dbg("got=%u, vbd->free=%u, count=%d\n",got,vbd->free,count); + if (!count) return(got); + if (vbd->free) { + dbg("vbd->free=%d path\n",vbd->free); + vbdebug(vbd,"vbd->free-s:vbd"); + assert(vbd->f && vbd->l); + r=vbread(vbs,vbd->l->buf+VBNSIZEL(vbd,vbd->l),(now=min(count,vbd->free))); assert(r==now); + dbg("now=%u,vbd->free=%u,count=%u\n",now,vbd->free,count); + vbd->free-=now; + count-=now; + vbdebug(vbd,"vbd->free-e:vbd"); + if (!count) return(got); + assert(!vbd->free); + } + dbg("vbs->done=%u\n",vbs->done); + assert(!vbd->free); + assert(!VBEMPTY(vbs)); + if (vbs->done) { + dbg("vbs->done=%d path\n",vbs->done); + vbdebug(vbs,"vbs->done-s:vbs"); + vbdebug(vbd,"vbs->done-s:vbd"); + vbnexact=1; + vbgrow(vbd,(now=min(count,VBNSIZE(vbs,vbs->f)))); + vbnexact=0; + assert(vbd->l && vbd->l->size==now && vbd->free==now); + r=vbread(vbs,vbd->l->buf,now); assert(r==now); + vbd->free=0; + count-=now; + assert(count>=0); + dbg("in vbs->done: count=%d, now=%u\n",count,now); + vbdebug(vbs,"vbs->done-e:vbs"); + vbdebug(vbd,"vbs->done-e:vbd"); + if (!count) return(got); + } + assert(!vbs->done); + vbdebug(vbs,"relink:vbs"); + vbdebug(vbd,"relink:vbd"); + while (count && VBNSIZEL(vbs,vbs->f)<=count) { +struct varbufnode *vbn=vbs->f; + assert(!vbd->free); + if (!(vbs->f=vbn->next)) { + vbs->l=NULL; + count+=(vbd->free=vbs->free); + vbs->free=0; + } + count-=vbn->size; + if (vbd->l) { + vbd->l->next=vbn; + vbd->l=vbn; + } + else { + assert(!vbd->f); + vbd->f=vbd->l=vbn; + } + vbn->next=NULL; + } + if (!count) return(got); + assert(!vbd->free); + vbdebug(vbs,"final:vbs"); + vbdebug(vbd,"final:vbd"); + vbgrow(vbd,count); + assert(vbd->l && vbd->l->size>=count && vbd->free==vbd->l->size); + vbread(vbs,vbd->l->buf,count); + vbd->free-=count; + assert(vbd->free>=0); + return(got); +} + +unsigned short vbxsum(struct varbuf *vb) +{ +unsigned short xsum=0; +size_t offs; +struct varbufnode *vbn; + + vbdebug(vb,"vbxsum"); + vbn=vb->f; + offs=vb->done; + while (vbn) { +size_t size=VBNSIZEL(vb,vbn); + assert(offsbuf[offs]; + if (++offs>=size) { + vbn=vbn->next; + offs=0; + } + } + dbg("vbxsum=%u\n",(unsigned)xsum); + return(xsum); +} + +char vbremlast(struct varbuf *vb) +{ +struct varbufnode *vbn; + + vbdebug(vb,"vbremlast"); + if (VBEMPTY(vb)) return(0); + assert(vb->l&&vb->free<=vb->l->size); + if (vb->freel->size) { + vb->free++; + vbdebug(vb,"vbremlast-stdend"); + return(1); + } + assert(vb->f!=vb->l); + for (vbn=vb->f;vbn->next!=vb->l;vbn=vbn->next) + assert(vbn->next); + vbn->next=NULL; + free(vb->l); + vb->l=vbn; + assert(vb->l->size); + vb->free=1; + vbdebug(vb,"vbremlast-blasting-end"); + return(1); +} + +void vbdrop(struct varbuf *vb,size_t len) +{ +struct varbufnode *vbn; + + assert(VBCHKSIZE(vb,len)); + vb->done+=len; + while (vb->f&&vb->done>=VBNSIZEL(vb,vb->f)) { + vb->done-=VBNSIZEL(vb,vb->f); + vbn=vb->f; + if (!(vb->f=vbn->next)) { + assert(vbn==vb->l); + vb->l=NULL; + vb->free=0; + } + free(vbn); + } + if (!vb->f) assert(!vb->done&&!vb->free&&!vb->l); +} + +void vbgetlinef(struct varbuf *vb,FILE *f) +{ +char buf[LOGF_FGETS_BUF],*s; + + dbg("vbgetlinef(), tell=0x%lx\n",ftell(f)); + for (;;) { + if (!fgets(buf,sizeof(buf),f)) { + dbg("vbgetlinef: fgets=NULL\n"); + if (feof(f)) return; + FATAL(ERR,"linereading fail: %m"); + } + dbg("vbgetlinef: fgets: %s\n",buf); + if ((s=strchr(buf,'\n'))) break; + vbputstring(vb,buf); + } + vbwrite(vb,buf,s-buf); + dbg("vbgetlinef(f), ftell=0x%lx\n",ftell(f)); +} + +ssize_t vbcopyline(struct varbuf *vbd,struct varbuf *vbs) +{ +ssize_t len,r; + if ((len=vbchrn(vbs,0,'\n',1))==-1) return(-1); + r=vbcopy(vbd,vbs,len); assert(r==len); + vbdrop(vbs,1); + return(len); +} + +char vbdropline(struct varbuf *vb) +{ +ssize_t len; + if ((len=vbchrn(vb,0,'\n',1))==-1) return(0); + vbdrop(vb,len+1); + return(1); +} + +char *vbmemorize(struct varbuf *vb,unsigned flg,size_t *sizep) +{ +ssize_t len=vbsize(vb,0),r; +char *s; + if (sizep) *sizep=len; + chk(s=malloc(len+!!(flg&VBMEM_ZERO))); + r=vbpeek(vb,(flg&VBMEM_REM?-1:0),s,len); assert(r==len); + if (flg&VBMEM_ZERO) { + s[len]='\0'; + fixupnulls(s,len,"vbmemorize"); + } + if (flg&VBMEM_REM) assert(VBEMPTY(vb)); + return(s); +} + +char *vbstringify(struct varbuf *vb,char rem) +{ return vbmemorize(vb,VBMEM_ZERO|(rem?VBMEM_REM:0),NULL); } + +const char *signames[]={ + "HUP", "INT", "QUIT", "ILL", "TRAP", "ABRT", "IOT", "BUS", "FPE", "KILL", + "USR1", "SEGV", "USR2", "PIPE", "ALRM", "TERM", "STKFLT", "CHLD", "CONT", + "STOP", "TSTP", "TTIN", "TTOU", "URG", "XCPU", "XFSZ", "VTALRM", "PROF", + "WINCH", "IO", "PWR", "UNUSED" }; + +void abortsignal(int signo) +{ //no reinstall! (deadlock!) +#ifdef FATALSIG_INSANE + vbcheckno=1; +#endif + signal(signo,SIG_DFL); + dbg("Got signal %d\n",signo); + exit(EXIT_FAILURE); +} + +struct varbuf *chat_vbout; +int chat_cmdpar; +char *chat_cmdpars[CHAT_CMD_MAXPARS]; + +static void chatfn_help(void); + +static const struct chat_cmdtab chat_cmdint[]={ + {"help" ,0,chatfn_help ,"This help"}, + {"quit" ,0,chatfn_quit ,"Close connection"}, + {"exit" ,0,chatfn_quit ,"Close connection"}, +}; + +static void chatfn_help(void) +{ +int i; +const struct chat_cmdtab *cmd,*cmdt; + + vbputstring(chat_vbout,"000 Available commands:\n"); + cmdt=chat_cmdtable; + for (i=0;iname) cmd=cmdt++; + else cmd=&chat_cmdint[i++]; + vbprintf(chat_vbout,"000 %-10s[%d] - %s\n",cmd->name,(int)cmd->npars,cmd->help); + } + vbputstring(chat_vbout,"102 Help end.\n"); +} + +static inline void chat_parsepars(char *s) +{ +char c,*d,quote; + + chat_cmdpar=0; + if (*s) for (*s++='\0';*s&&isspace(*s);s++); + for (c=*s;c&&chat_cmdparname) cmd=cmdt++; + else cmd=&chat_cmdint[i++]; + assert(cmd->npars<=CHAT_CMD_MAXPARS); + if (!strcmp(cmd->name,cmds)) break; + } + if (inpars!=chat_cmdpar) + vbprintf(chat_vbout,"205 %d parameter%s found, %d expected!\n",chat_cmdpar,(chat_cmdpar==1?"":"s"),cmd->npars); + else { + vbprintf(chat_vbout,"001 Running command: %s\n",cmds); + LOG(DEBUG,"%s is executing user command \"%s\"",who,cmds); + (*cmd->fnc)(); + } + } + else vbprintf(chat_vbout,"206 Unknown command \"%s\"!\n",cmds); +} + +void crfilter(char *sr) +{ +char *sw; + for (sw=sr;*sr;sr++) + if (*sr!='\r') *sw++=*sr; + *sw='\0'; +} + +static void tzchange(const char *tz) +{ +static char *otz=NULL; + + if (tz) { + free(otz); + if ((otz=getenv("TZ"))) chk(otz=strdup(otz)); + setenv("TZ",tz,1); + } + else { + if (otz) { + setenv("TZ",otz,1); + free(otz); otz=NULL; + } + else unsetenv("TZ"); + } + tzset(); +} + +char *gmctime(time_t tm) +{ +char *r,*s; + + tzchange("GMT"); + r=ctime(&tm); + tzchange(NULL); + if ((s=strchr(r,'\n'))) + *s='\0'; + chk(r=strdup(r)); + return(r); +} + +unsigned char *bitshuffle(unsigned char *dst,unsigned char dstb,const unsigned char *src,unsigned char srcb,size_t bits,char lr) +{ +unsigned char dstrem,*dstp,srcrem,now; +const unsigned char *srcp; + + if (!dst) chk(dst=malloc((bits+dstb-1)/dstb)); + dstrem=0; dstp=dst-1; + srcrem=0; srcp=src-1; + while (bits) { + if (!dstrem) { + *++dstp=0; + dstrem=dstb; + } + if (!srcrem) { + srcp++; + srcrem=srcb; + } + dbg("dstrem=%u,srcrem=%u,bits=%u\n",dstrem,srcrem,bits); + assert(dstrem&&srcrem); + now=min(dstrem,srcrem); + assert(bits>=now); + dbg("1:*dstp=0x%02x,*srcp=0x%02x,dstrem=%u,srcrem=%u,now=%u\n",*dstp,*srcp,dstrem,srcrem,now); + *dstp|=((*srcp>>(lr?srcrem-now:srcb-srcrem))&((1U< +#include +#include +#include +#include +#include +#include +#include + +/******************************** + * Configuration section follows + */ + +//#define PSTR_16BIT +#define INLINE_PUTGETCHAR +//#define FATALSIG_INSANE + +#define VB_DEFSIZE 256 //>=min of n in vsnprintf() +#define VB_MAXSIZE 128*1024 //recommended limit, not hard (probably) + +#define CHAT_CMD_MAXPARS 10 + +/* + * Configuration section ends + ****************************/ + +#define strncpydst(d,s) strncpy(d,s,sizeof(d)) +#ifdef NDEBUG +#undef DEBUG +#endif +#ifdef DEBUG +#define dbg(msg...) fprintf(stderr, ##msg) +#else +#define dbg(msg...) +#endif + +#ifndef max +#define max(a,b) ((a)>(b)?(a):(b)) +#endif +#ifndef min +#define min(a,b) ((a)<(b)?(a):(b)) +#endif +#ifndef __NORETURN +#define __NORETURN __attribute__((__noreturn__)) +#endif + +#define NELEM(a) (sizeof((a))/sizeof(*(a))) +#define XRAWDIGITI(n) ((n)-'0'-((n)>='A'?'A'-('9'+1):0)) +#define XRAWDIGITO(n) ((n)+'0'+((n)>=0xA?'A'-('9'+1):0)) +#define PK __attribute__((packed)) + +extern const int safesigs[]; + +struct varbufnode { + struct varbufnode *next; + size_t size; + char buf[0]; + }; +struct varbuf { +#ifndef NDEBUG + struct varbuf *checknext; //MUST be first in the struct +#endif + struct varbufnode *f,*l; + size_t done,free; + }; + +#define VBNSIZEL(vb,vbn) ((vbn)->size-((vb)->l==(vbn)?(vb)->free:0)) +#define VBNSTART(vb,vbn) ((vb)->f==(vbn)?(vb)->done:0) +#define VBNSIZE(vb,vbn) (VBNSIZEL((vb),(vbn))-VBNSTART((vb),(vbn))) + +#define VBEMPTY(vb) (!(vb)->f || ((vb)->l==(vb)->f&&(vb)->l->size==(vb)->free)) + +#ifndef NDEBUG +extern void vbcheck(struct varbuf *vb); +extern void vbsanity(void); +#else +#define vbcheck(vb) +#define vbsanity() +#endif + +#ifdef VBDEBUG +extern void vbdebug(struct varbuf *vb,const char *msg); +#else +#define vbdebug(vb,msg) vbcheck(vb) +#endif + +struct chat_cmdtab { + const char *name; + const unsigned char npars; + void (*fnc)(void); + const char *help; +}; + +#define VBMEM_REM (1<<0) +#define VBMEM_ZERO (1<<1) + +extern void chk(const void *p); + +extern struct varbufnode *vbnnew(size_t sugsize); +extern void vbgrow(struct varbuf *vb,size_t sugsize); +extern void vbinit(struct varbuf *vb); +extern struct varbufnode *vbremone(struct varbuf *vb); +extern void vbclear(struct varbuf *vb); +extern void vbrem(struct varbuf *vb); +extern size_t vbsize(struct varbuf *vb,size_t maxsize); +extern void vbwrite(struct varbuf *vb,const void *buf,size_t count); +extern size_t vbputstring(struct varbuf *vb,const char *s); +extern ssize_t vbwritefd(struct varbuf *vb,int fd); +extern size_t vbpeek(struct varbuf *vb,ssize_t offs,void *buf,size_t count); +#define vbread(vbp,buf,count) vbpeek(vbp,-1,buf,count) +extern ssize_t vbchrn(struct varbuf *vb,ssize_t offs,char c,char dir); +extern ssize_t vbreadfd(struct varbuf *vb,int fd); +extern char *vbgetline(struct varbuf *vb,char term); +extern size_t chkvsprintf(char **sp,const char *fmt,va_list ap); +extern size_t vbvprintf(struct varbuf *vb,const char *fmt,va_list ap,char remlf) __attribute__((format(printf,2,0))); +extern size_t vbprintf(struct varbuf *vb,const char *fmt,...) __attribute__((format(printf,2,3))); +extern void vbpstrputstring(struct varbuf *vb,const char *s); +extern void vbpstrprintf(struct varbuf *vb,const char *fmt,...) __attribute__((format(printf,2,3))); +extern char *vbpstrread(struct varbuf *vb); +extern size_t vbcopy(struct varbuf *vbd,struct varbuf *vbs,ssize_t count); +extern unsigned short vbxsum(struct varbuf *vb); +extern char vbremlast(struct varbuf *vb); +extern void vbdrop(struct varbuf *vb,size_t len); +extern void vbgetlinef(struct varbuf *vb,FILE *f); +extern ssize_t vbcopyline(struct varbuf *vbd,struct varbuf *vbs); +extern char vbdropline(struct varbuf *vb); +extern char *vbmemorize(struct varbuf *vb,unsigned flg,size_t *sizep); +extern char *vbstringify(struct varbuf *vb,char rem); +extern void chat_proccmd(const char *who,char *buf); +extern void crfilter(char *sr); +extern char *gmctime(time_t tm); +extern unsigned char *bitshuffle(unsigned char *dst,unsigned char dstb,const unsigned char *src,unsigned char srcb,size_t bits,char lr); +extern char *enbase64(char *dst,const unsigned char *src,size_t bits); +extern unsigned char *debase64(unsigned char *dst,const char *src,size_t *dstlp); + +extern char vbnexact,quiet_null; + +extern struct varbuf *chat_vbout; +extern int chat_cmdpar; +extern char *chat_cmdpars[CHAT_CMD_MAXPARS]; +extern const struct chat_cmdtab chat_cmdtable[]; + +extern const char *signames[]; +extern void abortsignal(int signo); + +#define VBCHKSIZE(vb,size) (vbsize((vb),(size))>=(size)) + +#define GENVARBUFP(argmid) \ + extern void vbput##argmid(struct varbuf *vb,const argmid arg); \ + extern char vbget##argmid(struct varbuf *vb,argmid *argp); + +#ifndef INLINE_PUTGETCHAR +GENVARBUFP(char) +#endif +GENVARBUFP(short) +GENVARBUFP(int) + +#undef GENVARBUFP + +#ifdef INLINE_PUTGETCHAR +static inline void vbputchar(struct varbuf *vb,const char arg) __attribute__((unused)); +static inline void vbputchar(struct varbuf *vb,const char arg) +{ + vbcheck(vb); + if (vb->free) vb->l->buf[vb->l->size-(vb->free--)]=arg; + else vbwrite(vb,&arg,sizeof(arg)); +} + +static inline char vbgetchar(struct varbuf *vb,char *argp) __attribute__((unused)); +static inline char vbgetchar(struct varbuf *vb,char *argp) +{ + vbcheck(vb); + if (vb->f && vb->done+1f)) { *argp=vb->f->buf[vb->done++]; return(1); } + else return vbread(vb,argp,sizeof(*argp)); +} +#endif + +#endif /* !_M1D_COMMON_H */ -- 1.8.3.1