/* MLH/MH library of special calls - general, Mike Harrelson */ /* version 3.2.2 revision 9-28-09*/ /* Copyright (C) 1996-2009 Mike Harrelson The MLH Library 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, or (at your option) any later version. The MLH Library 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. The GNU General Public License is often shipped with GNU software, and is generally kept in a file called COPYING or LICENSE. If you do not have a copy of the license, write to the Free Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ /* libmlh.c | libmh.c */ /*#define _REENTRANT *you may want to comment this out*/ #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 #include #include #include #include "libmlh.h" #ifdef __sun /*Is it SVR4 or just Solaris? Why be different? sigh...*/ #include int gethostname(char*,int); int usleep(unsigned int); #endif #ifdef linux #include #endif #ifdef __osf__ /*not used from unistd.h on Digital Unix 4.0 for some reason*/ int usleep(unsigned int); #endif /*Internal prototypes*/ static int N_lockf(int, char, char); static char N_getformat(char**, char*, int*); static unsigned int N_hashfunction(char*, unsigned int,char); static unsigned char *N_lib_scramble(unsigned char*, int, long, short); static int N_grow_dlist(struct dlist_type*, int); static int N_strcmp(char*, char*, int); static int N_strmatch(char*, char*, char, int*, char); static int N_strcharcmp(char, char, char); static int N_qstrcmp(const void*, const void*); static int N_qstrcasecmp(const void*, const void*); /*libmlh internal additions*/ int N_parse_dn(unsigned char*, unsigned char*, short); int N_parse_drec(unsigned char*, short, short, unsigned char*); #define HFUNC 7 /*see N_hashfunc() and lib_checksum() */ /**********************************/ /* BEGIN STRING FUNCTIONS SECTION */ /**********************************/ int lib_strtoint(char *val, int *stat) /*function converts a string to int, kind of like atoi() but with an optional status flag returned, if _stat_ is NULL we ignore it*/ { int x,signval=0,v=0,start=0,size; if ((size=strlen(val))==0) { /*sanity check*/ if (stat!=NULL) *stat=0; return(0); } while(isspace((int)val[start])) start++; /*skip the white space*/ if (val[start]=='-') {signval=-1; start++;} else if (val[start]=='+') start++; for (x=start;x'9' || val[x]<'0') { x=size+1; if (stat!=NULL) *stat=-1; return(0); } else v=v*10 + val[x]-48; } if (signval==-1) v=-v; if (stat!=NULL) *stat=1; return(v); } /*end lib_strtoint()*/ char *lib_inttostr(int inval, char *outval) /*function converts an int to a string*/ { sprintf(outval,"%d",inval); return(outval); } /*end lib_inttostr()*/ double lib_strtofloat(char *input, int *stat) /*convert a string to floating point, store status in _stat_ if not NULL, similar to a reverse gconvert()*/ { double a=0.0, b=0.0, divisor=1.0; int size,start=0, sign=0,x; char *ptr, astr[32], bstr[32]; /*some sanity checks*/ if (stat!=NULL) *stat=-1; if ((size=strlen(input))>32) return(0.0); ptr=astr; for (x=0;x='0' && ptr[x]<='9') a=(a*10)+(float)(ptr[x]-48); else { if (stat!=NULL) *stat=-1; return(0.0); } } if ((size=strlen(bstr))==0) b=0.0; else for (x=0;x='0' && bstr[x]<='9') b=(b*10)+(float)(bstr[x]-48); else { if (stat!=NULL) *stat=-1; return(0.0); } } /*now bring them together in the form b.a */ for (x=0;x=len) return(0); if (howmany<0 || start<0) return(-1); if ((start+hm) > len) hm=len-start; pos=start+hm; while (pos<=len) string[start++]=string[pos++]; return(hm); } /*end lib_bstrip()*/ int lib_strip_nonalphanum(char *string, char stripnum, char *adds) /*removes all non-alphabetic and (maybe) non-numeric characters*/ { int x=0,y=0; char foo=0; if (adds==NULL) adds=&foo; if (stripnum!=0) { /*stip numbers*/ while (string[x]!='\0') { if (toupper((int)string[x]) <= 'Z' && toupper((int)string[x]) >= 'A') { /*dey good*/ string[y]=string[x]; y++; } else if (strchr(adds,string[x])!=NULL) { string[y++]=string[x]; } x++; } string[y]='\0'; /*cut 'em off*/ } else { while (string[x]!='\0') { /*don't strip numbers*/ if ((string[x] <= '9' && string[x] >= '0') || (toupper((int)string[x]) <= 'Z' && toupper((int)string[x]) >= 'A')) { string[y]=string[x]; y++; } else if (strchr(adds,string[x])!=NULL) { string[y++]=string[x]; } x++; } string[y]='\0'; /*cut 'em off*/ } return(y); } /*end lib_strip_nonalphanum()*/ int lib_chomp(char *string) /*remove linefeeds/CRs at end of a string terminating the string at that point*/ { int x=0; if (string==NULL) return(-1); while (string[x]!=0) { if (string[x]=='\n' || string[x]=='\r') { string[x]='\0'; return(1); } else x++; } return(0); } /*end lib_chomp()*/ char *lib_chop(char *string, int size) /* chop characters off end of string*/ { int cutpos,len; if (size<0) return(NULL); len=strlen(string); if (size>=len || len==0) { string[0]=0; return(string); } cutpos=len-size; string[cutpos]=0; return(string); } /*end lib_chop()*/ char *lib_getsubstr(char *string, short start, short end, char *sub) /* return a substring from within a string */ { int x,pos=0; /*sanity checks*/ if (endstrlen(string)) return(NULL); if (start+len < strlen(string)) len--; for (x=start;x<=(len+start);x++) string[x]=replacement[pos++]; return(string); } /*end lib_strsub()*/ char *lib_insertstr(char *string, char *insertion, short where) /* insert a string into another string */ { char *tmp, *tmp2; int x,len=strlen(string),pos=0; /*sanity checks*/ if (where > len || where <0) return(NULL); if (insertion==NULL || strlen(insertion)==0) return(NULL); /*allocate memory for tmp variables*/ if ((tmp=(char*)malloc(len))==NULL) return(NULL); if ((tmp2=(char*)malloc(where+1))==NULL) { free(tmp); return(NULL); } for (x=where;x<=len;x++) tmp[pos++]=string[x]; string[where]=0; strcpy(tmp2,string); /*now rebuild the string with the insertion*/ sprintf(string,"%s%s%s",tmp2,insertion,tmp); free(tmp); free(tmp2); return(string); } /*end lib_insertstr()*/ char *lib_insertfiller(char *string, char filler, short size) /*insert or append filler characters into a string*/ { int x,len,h; char *newstring; len=strlen(string); if (abs(size)<=len) return(string); h=abs(size)-len; if ((newstring=(char*)malloc(abs(size)))==NULL) return(NULL); for (x=0;x0) while (line[x]!='\0') { /*start from left*/ if (line[x]==capch) { c++; if (c==which) { line[x]='\0'; return(1); } } x++; } else { /*_which_ is negative, start from the right*/ int len=strlen(line); which=-which; /*make _which_ positive*/ for (x=len-1;x>=0;x--) if (line[x]==capch) { c++; if (c==which) { line[x]='\0'; return(1); } } } return(0); } /*end lib_strcap()*/ int lib_strip_whitespace(char *line, char how) /*strip leading/trailing white space, return number of chars stripped*/ /*_how_: 1=leading, -1=trailing, 0=both*/ /*whitespace= space, tab, carriage return, newline*/ { int count=0, spos, len, x; if (how<1) { /*strip trailing white space*/ len=strlen(line); x=len-1; while (len>=0) { if (line[x]==' ' || line[x]=='\t' || line[x]=='\r' || line[x]=='\n') { line[x]='\0'; x--; count++; } else break; } if (x<0 || count==len) return(count); /*all gone*/ } if (how>=0) { /*strip leading white space*/ x=spos=0; while (line[x]!='\0') { if (line[x]==' ' || line[x]=='\t' || line[x]=='\r' || line[x]=='\n') { count++; x++; } else break; } if (x==0) return(count); /*nothing to do*/ while (line[x]!='\0') { line[spos]=line[x]; spos++; x++; } line[spos]='\0'; } return(count); } /*end lib_strip_whitespace()*/ int lib_strip_8bit(unsigned char *line) /*strip 8 bit characters from a string*/ { int spos=0, x=0; /*sanity check*/ if (line==NULL) return(-1); /*strip tease time*/ while (line[x]!='\0') { if (line[x]<128) { if (spos!=x) line[spos]=line[x]; spos++; } x++; } line[spos]='\0'; return(x-spos); /*return number of characters stripped*/ } /*end lib_strip_8bit()*/ int lib_strip_unprintable(char *line) /*strip unprintable/uncertain characters from a string*/ { int spos=0, x=0; /*sanity checks*/ if (line==NULL) return(-1); /*now for the strip tease*/ while (line[x]!='\0') { if (line[x]<127 && line[x]>31) { if (spos!=x) line[spos]=line[x]; spos++; } x++; } line[spos]='\0'; return(x-spos); /*return number of characters stripped*/ } /*end lib_strip_unprintable()*/ int lib_stripendchars(char *line, char begin, char end) /*strips leading or trailing chars*/ /*returns 2: trailing only removed, 1 leading only removed, 3 if both leading and trailing removed, 0 if neither removed*/ { int x, len, fl=0; if (line==NULL) return(-1); len=strlen(line); if (line[len-1]==end) { line[len-1]='\0'; len--; fl=2; } if (line[0]==begin) { for (x=0;x'F') continue; if (hex[1]<'0' || hex[1]>'F') continue; if (hex[0]>'9' && hex[0]<'A') continue; if (hex[1]>'9' && hex[1]<'A') continue; /*convert to base values*/ if (hex[0]>='A' && hex[0]<='F') hex[0]=hex[0]-55; if (hex[1]>='A' && hex[1]<='F') hex[1]=hex[1]-55; if (hex[0]>='0' && hex[0]<='9') hex[0]=hex[0]-48; if (hex[1]>='0' && hex[1]<='9') hex[1]=hex[1]-48; aval=(hex[0]<<4) | hex[1]; line[npos]=aval; /*replace '%' with ascii value*/ cpos+=2; /*skip over hex values*/ } } line[npos]='\0'; /*terminate new string*/ return(line); } /*end lib_stringhex_conv()*/ char *lib_2hex_transform(unsigned char *instring, short sflag, char *outstr) /*converts unprintable characters to hex %## equivs*/ { int len, x, cpos=0; char *newstring=NULL, tflag; unsigned char val; /*sanity checks and initialization*/ if (instring==NULL) return(NULL); len=strlen((char*)instring); if (outstr==NULL) { newstring=(char*)malloc((len<<1)+len); /*3xlen*/ if (newstring==NULL) return(NULL); } else newstring=outstr; newstring[0]='\0'; if ((len=strlen((char*)instring))==0) return(newstring); for (x=0;x125) sflag=1; else if (instring[x]=='%') sflag=1; else if (instring[x]==' ' && sflag==1) sflag=1; if (tflag==0) { /*ok as is*/ newstring[cpos]=instring[x]; cpos++; continue; } /*need to transform, first left val*/ newstring[cpos++]='%'; val=instring[x]>>4; if (val>9) val=val+55; else val=val+48; newstring[cpos++]=val; /*now right val*/ val=instring[x]&15; if (val>9) val=val+55; else val=val+48; newstring[cpos++]=val; } return(newstring); } /*end lib_2hex_transform()*/ unsigned char *lib_quote_convert(unsigned char *instring, char *pat) /*converts specified quoted strings into 8 bit version values*/ { int len, x, qmode=0; char testpat[256]; /*sanity checks*/ if (instring==NULL) return(NULL); if ((len=strlen((char*)instring))==0) return(instring); if (pat!=NULL) { if (strlen(pat)==0) strcpy(testpat," \r\n\t"); /*convert whitespace*/ else strncpy(testpat,pat,255); testpat[255]='\0'; } else testpat[0]='\0'; for (x=0;testpat[x]!='\0';x++) /*pattern cannot include quotes*/ if (testpat[x]=='"') return(NULL); /*whaddya tryin' to pull?!*/ /*down to business*/ for (x=0;x127) instring[x]=instring[x]&127; } } } return(instring); } /*end lib_quote_convert()*/ int lib_grep(char *pat, char *teststr, char cflag, char eflag) /*return true if pat found in teststr*/ /*cflag=1, insenstive, 0=sensitive, *+? may not be in teststr*/ /* *=match anything, ?=match any character, all others match exactly*/ { int st, tlen, len, testpos, strpos; char match=1, sflag=1, *tstr, *tptr, *sptr; /*sanity checking*/ if (pat==NULL || teststr==NULL) return(-1); len=strlen(pat); if (len==0) return(1); /*empty pattern string always matches*/ if (strcmp(pat,"*")==0) return(1); /*matches all*/ if (strlen(teststr)==0) return(0); /*empty test string unmatchable*/ /*quick check for no astrick*/ if ((tptr=strstr(pat,"*"))==NULL) { /*must be an exact match*/ st=N_strmatch(teststr,pat,cflag,NULL,eflag); if (st==2) return(0); /*no exact match*/ else return(st); } /*main parsing loop - assumes '*' exists in pattern*/ tstr=strdup(pat); if (tstr==NULL) return(-1); match=1; /*test to true to start*/ strpos=0; /*start position in test string*/ sptr=&pat[0]; /*set to beginning of pattern*/ /*loop through string, testing for match with pattern*/ /*we split the string up on '*' and scan the pieces*/ while (tptr!=NULL) { /*while we have an '*' at or coming up*/ if (sflag==1 && tptr==sptr) { /* * at beginning, skipover*/ sflag=0; /* no longer at start */ sptr++; /*skip to position after '*' */ tptr=strstr(sptr,"*"); /*scan for next '*' */ continue; } if (sflag) { /*at the beginning of pattern section -pre'*'*/ tlen=tptr-sptr; /*calculate length of section*/ strncpy(tstr,sptr,tlen); /*copy section length*/ tstr[tlen]='\0'; /*test section to see if contains match*/ if ((st=N_strmatch(teststr,tstr,cflag,&testpos,eflag))<1) { free(tstr); return(0); /*doesn't contain pattern, fail*/ } if (st==2 && testpos!=0) { /*check if at beginning*/ free(tstr); return(0); /*not at beginning, fail*/ } sflag=0; /*no longer at the beginning*/ sptr=tptr+1; /*position just after the 1st '*' */ strpos=strpos+tlen; /*after partially matched string*/ tptr=strstr(sptr,"*"); /*get next '*', if any*/ continue; } /*at this point we are dealing with middle sections*/ tlen=tptr-sptr; /*get length of next pattern section*/ strncpy(tstr,sptr,tlen); /*copy next pattern section*/ tstr[tlen]='\0'; /*check pattern section- must contain match*/ st=N_strmatch(&teststr[strpos],tstr,cflag,&testpos,eflag); if (st<1) { free(tstr); return(0); /*no match*/ } strpos=strpos+tlen; /*setup for next section*/ sptr=tptr+1; /*new starting point beyond last '*' */ tptr=strstr(sptr,"*"); /*scan for next '*' */ } free(tstr); /*no more '*' in pattern at this point - test end string*/ if (sptr[0]=='\0') { /*nul after last '*' heading for home*/ return(1); /*we're good, It's Miller Time(tm)!*/ } tlen=strlen(sptr); /*verify match on last section - must simply contain*/ st=N_strmatch(&teststr[strpos],sptr,cflag,&testpos,eflag); if (st<1) { /*test if in last pattern block*/ return(0); /*darn, so close*/ } /*since N_strmatch can't match exact length, we have to test for end*/ if (teststr[strpos+testpos+tlen]!='\0') return(0); /*darn, not at end*/ return(match); } /*end lib_grep()*/ char *lib_get_match_str(char *text, char *pattern, char cflag, char *lastpos, unsigned char chomp) /*return 1st instance if pattern is found in teststr*/ { int patlen, textlen, plen, tlen, ppos=0, tpos=0, matchflag=0; int nexttpos=0, st, smatchpos=-1; char *fmatchstr=NULL, *pteststr=NULL, *naptr=NULL; char term1=0, term2=0; /*sanity checks + quickies*/ if (text==NULL || pattern==NULL) return(NULL); if ((patlen=strlen(pattern))<1) return(NULL); if ((textlen=strlen(text))<1) return(NULL); if (strcmp(pattern,"*")==0) { /*easy*/ fmatchstr=strdup(text); if (lastpos!=NULL) lastpos=&text[textlen]; return(fmatchstr); } if (patlen>2) { term1=(chomp&2)>>1; /*opening delimiter*/ term2=(chomp&1); /*closing delimiter*/ } if (strstr(pattern,"*")==NULL) { /*no '*', handle as is*/ st=N_strmatch(text,pattern,cflag,&nexttpos,1); if (st<1) return(NULL); /*not there*/ fmatchstr=(char*)malloc(patlen+1); if (fmatchstr==NULL) return(NULL); /*memory error*/ nexttpos=nexttpos+term1; /*adjust for any delimiter*/ patlen=patlen-term1-term2; /*calculate new patlen*/ strncpy(fmatchstr,&text[nexttpos],patlen); fmatchstr[patlen]='\0'; if (lastpos!=NULL) lastpos=&text[nexttpos+patlen]; return(fmatchstr); } /*at this point, there is at least one '*' in pattern*/ if (pattern[0]=='*') { /*start matching at beginning*/ matchflag=1; ppos=1; /*skip past initial '*' */ smatchpos=0; /*match position will be from start of text*/ term1=0; /*no delimit in this case*/ } for (;;) { /*loop through remaining pattern sections*/ naptr=strstr(&pattern[ppos],"*"); /*get position of next '*'*/ if (naptr==NULL) /*no more '*', and no '*' at end*/ plen=patlen-ppos; else /*length of next pattern sec tion*/ plen=naptr-&pattern[ppos]; pteststr=(char*)malloc(plen+1); if (pteststr==NULL) return(NULL); /*memory error, bail*/ strncpy(pteststr,&pattern[ppos],plen); /*copy pattern section*/ pteststr[plen]='\0'; st=N_strmatch(&text[tpos],pteststr,cflag,&nexttpos,1); free(pteststr); if (st<1) { /*not found in initial test, bail*/ if (lastpos!=NULL) lastpos=&text[textlen]; return(NULL); } matchflag=1; nexttpos=nexttpos+tpos; /*nexttpos is relative*/ if (smatchpos==-1) smatchpos=nexttpos; /*first match pos*/ tpos=nexttpos+plen; /*next text pos after last match*/ ppos=ppos+plen; if (naptr) ppos++; /*move 1 spot past next '*' */ if (pattern[ppos]=='\0') { /*oh look...we're done :) */ if (pattern[ppos-1]=='*') { /*set tpos to end of text*/ tpos=textlen; term2=0; /*don't delimit in this case*/ } if (lastpos!=NULL) lastpos=&text[tpos-term2]; tlen=tpos-smatchpos-term2; /*how big is match?*/ fmatchstr=(char*)malloc(tlen+1); if (fmatchstr==NULL) return(NULL); smatchpos=smatchpos+term1; strncpy(fmatchstr,&text[smatchpos],tlen-term1); fmatchstr[tlen-term1]='\0'; return(fmatchstr); } }; return(NULL); /*should never get here*/ } /*end of lib_get_match_str() */ char *lib_case_strstr(char *bstr, char *tstr) /*case insensitive version of strstr()*/ { int x, pos, tlen, blen; char *ibstr, *itstr, *ptr; /*sanity checks*/ if (tstr==NULL || bstr==NULL) return(NULL); if ((blen=strlen(bstr))==0) return(NULL); /*not findable*/ if ((tlen=strlen(tstr))==0) return(bstr); if (tlen>blen) return(NULL); /*s2 longer than s1*/ /*set up workstrings*/ ibstr=strdup(bstr); if (ibstr==NULL) return(NULL); itstr=strdup(tstr); if (itstr==NULL) { free(ibstr); return(NULL); } for (x=0;x=0;x--) { if (isspace((int)nstr1[x])) nstr1[x]='\0'; else break; } for (x=len2-1;x>=0;x--) { if (isspace((int)nstr2[x])) nstr2[x]='\0'; else break; } /*do final check and return*/ if (icase) x=strcasecmp(nstr1,nstr2); else x=strcmp(nstr1,nstr2); free(nstr1); free(nstr2); if (x!=0) x=1; return(x); } /*end of lib_fstrcmp()*/ /*********************************/ /* BEGIN INPUT FUNCTIONS SECTION */ /*********************************/ int lib_getastr(char *text, char *strbuf, int size) /*get a fixed size string, size includes terminating null */ { int x; char *buff; /*sanity checks*/ if (strbuf==NULL || text==NULL || size < 0) return(-1); if (size==0) { strbuf[0]=0; return(0); } /*now down to business*/ if (text[0]!='\0') { /*skip unless there is something to print*/ fprintf(stdout,"%s",text); fflush(stdout); } fflush(stdin); if ((buff=(char*)malloc(size+2))==NULL) return(-1); fgets(buff,size+1,stdin); /*+1 to hold the newline*/ for (x=0;x0) { write(fileno(stdout),buf,3); buff[--pos]=0; } } else { if (c!='\n') write(fileno(stdout),"*",1); if (pos<(size)) buff[pos]=c; pos++; } } while (c!='\n'); if (possize) pos=size; return(strlen(buff)); } /*end lib_gethstr()*/ int lib_getvstr(char *text, char *buff, int size, char *pattern) /*get a string only allowing certain (valid) characters*/ { char c,buf[3]={8,32,8}; int pos=0,ch; struct termios current, initial; /*sanity check*/ if (size<2) { buff[0]=0; return(0); } /*set terminal to no echo*/ tcgetattr(0, &initial); current=initial; current.c_cc[VMIN]=1; current.c_cc[VTIME]=0; current.c_lflag &= ~ICANON & ~ECHO; tcsetattr(0, TCSANOW, ¤t); /*print _text_*/ if (text[0]!='\0') { /*only print _text_ if not empty*/ printf("%s",text); fflush(stdout); } /*collect input, only outputing good characters*/ do { if ((ch=getchar())==EOF) break; /*what the!? Bail out*/ c=(char)ch; if (c==8 || c==127) { /*handle backspace and delete key*/ if (pos>0) { write(fileno(stdout),buf,3); buff[--pos]=0; } } else if ((strchr(pattern,c)!=NULL || pattern[0]==0) && pos<(size-1)) { write(fileno(stdout),&c,1); if (pos<(size-1)) buff[pos]=c; pos++; } } while (c!='\n'); /*end of do-while loop*/ if (possize) pos=size; return(pos); } /*end lib_getvstr()*/ char *lib_dfgets(FILE *fp,int buffsize, short extra, int *ssize) /*dynamically allocated fgets() like function*/ { char *buffer, *new=NULL; int size=0, addsize; /*sanity check*/ if (buffsize<1 || extra <0) return(NULL); if ((buffer=(char*)malloc(buffsize+1))==NULL) return(NULL); while (1) { /*start reading characters until return or break*/ if (fgets(buffer,buffsize+1,fp)==NULL) { if (new==NULL) { free(buffer); return(NULL); } break; } size=size+(addsize=strlen(buffer)); if (new!=NULL) { /*allocate more space*/ new=realloc(new,size+extra+1); strncat(new,buffer,addsize); new[size]=0; } else { /*new allocation */ if ((new=malloc(size+extra+1))==NULL) { /*failed!*/ free(buffer); return(NULL); } strncpy(new,buffer,addsize); /*copy what we have*/ new[addsize]=0; /*terminate for next copy*/ } if (buffer[addsize-1]=='\n') break; } new[size]=0; free(buffer); if (ssize!=NULL) *ssize=size; return(new); } /*end lib_dfgets()*/ char *lib_getdelim(FILE *fp, char *termpat, int wsize, int maxsize) /*like lib_dfgets() but allows for other terminators besides newlines*/ { int st, plen, rsize=0; char *tstr, rch; unsigned int gfactor=256; /*sanity checks and setup*/ if (fp==NULL || termpat==NULL) return(NULL); plen=strlen(termpat); if (plen==0) return(NULL); if (wsize<=0) wsize=256; /*set default size*/ if (wsize>16777216) wsize=16777216; /*be reasonable*/ tstr=(char*)malloc(wsize); if (tstr==NULL) return(NULL); if (maxsize<=0) maxsize=1073741824; /*gotta start somewhere*/ else if (maxsize=plen) { st=strncmp(&tstr[rsize-plen],termpat,plen); if (st==0) { tstr[rsize]='\0'; return(tstr); } } if (rsize>=(wsize-1)) { /*need to grow buffer*/ char *ntstr; ntstr=realloc(tstr,wsize+gfactor); if (ntstr==NULL) { free(tstr); return(NULL); /*memory failure, bail*/ } tstr=ntstr; wsize=wsize+gfactor; if (gfactor<65536) gfactor=gfactor<<1; /*double it*/ } if (rsize>=maxsize) break; /*too large*/ } /*end while(rch)*/ /*reached eof, close up shop, give 'em what we have*/ tstr[rsize]='\0'; if (rsize==0) return(NULL); /*must have termpat or something*/ return(tstr); } /*end of lib_getdelim()*/ char lib_getvch(char *pattern, char not, char echo) /*get a character only if it is valid input, no echo*/ { struct termios current, initial; int c; char retval=0; /*clear buffers*/ fflush(stdin); fflush(stdout); /*set terminal to no echo and no delay*/ tcgetattr(0, &initial); current=initial; current.c_cc[VMIN]=1; current.c_cc[VTIME]=0; current.c_lflag &= ~ICANON & ~ECHO; tcsetattr(0, TCSANOW, ¤t); /*get input*/ while (retval==0) { if ((c=getchar())==EOF) return(0); if (strchr(pattern,c)==NULL && not!=0) retval=(char)c; else if (strchr(pattern,c)!=NULL && not==0) retval=(char)c; } tcsetattr(0, TCSANOW, &initial); /*restore terminal*/ if (echo!=0) { printf("%c",retval); fflush(stdout); } return(retval); } /*end lib_getvch()*/ char lib_getvchar(char *pattern, char not) /*get only a valid character, with echo*/ { char c,cb[2],buf[3]={8,32,8}, valid; struct termios current, initial; int pos=0,ch; /*clear buffers*/ fflush(stdin); fflush(stdout); /*set no echo and no delay on terminal*/ tcgetattr(0, &initial); current=initial; current.c_cc[VMIN]=1; current.c_cc[VTIME]=0; current.c_lflag &= ~ICANON & ~ECHO; tcsetattr(0, TCSANOW, ¤t); /*get input*/ do { if ((ch=getchar())==EOF) break; c=(char)ch; if (c==8 || c==127) { if (pos>0) { write(fileno(stdout),buf,3); cb[--pos]=0; } continue; } if ((strchr(pattern,c)!=NULL && not==0) || pattern[0]==0 || (strchr(pattern,c)==NULL && not!=0)) valid=1; else valid=0; if ( valid==1 && pos==0 ) { write(fileno(stdout),&c,1); cb[pos]=c; pos++; } } while (c!='\n' || pos==0); tcsetattr(0, TCSANOW, &initial); /*restore terminal*/ return(cb[0]); } /*end lib_getvchar()*/ char lib_getch(void) /*get a character from stdin and return immediately*/ { struct termios current, initial; int c; char retval; /*set terminal mode to no echo, no delay*/ tcgetattr(0, &initial); current=initial; current.c_cc[VMIN]=1; current.c_cc[VTIME]=0; current.c_lflag &= ~ICANON & ~ECHO; tcsetattr(0, TCSANOW, ¤t); /*get input*/ if ((c=getchar())==EOF) retval=0; else retval=(char)c; tcsetattr(0, TCSANOW, &initial); /*restore terminal*/ return(retval); } /*end lib_getch()*/ char lib_getche(void) /*get a character from stdin, echo it and return immediately*/ { struct termios current, initial; int c; char retval; /*set terminal to no delay*/ tcgetattr(0, &initial); current=initial; current.c_cc[VMIN]=1; current.c_cc[VTIME]=0; current.c_lflag &= ~ICANON; current.c_lflag |= ECHO; tcsetattr(0,TCSANOW, ¤t); if ((c=getchar())==EOF) retval=0; else retval=(char)c; tcsetattr(0,TCSANOW, &initial); /*restore terminal*/ return(retval); } /*end lib_getche()*/ short lib_keypressed(int interval) /*returns 1 & value if a key is being pressed*/ { struct timeval tv; fd_set read_fd; struct termios current, initial; int retval=0, s=0,i=100000; /*set terminal to no delay*/ tcgetattr(0, ¤t); initial=current; current.c_cc[VMIN]=0; current.c_cc[VTIME]=0; current.c_lflag &= ~ICANON; current.c_lflag &= ~ECHO; tcsetattr(0, TCSANOW, ¤t); if (interval>1) { /*interval is in tenth or deciseconds*/ s=interval/10; /*seconds*/ i=(interval%10)*100000; /*microseconds*/ } /*set wait interval*/ tv.tv_sec=s; tv.tv_usec=i; /*check for keypress*/ ioctl(0,TCFLSH,0); FD_ZERO(&read_fd); FD_SET(0, &read_fd); if (select(1, &read_fd, NULL, NULL, &tv) == -1) retval=-1; else retval=(FD_ISSET(0, &read_fd) ? 1: 0); tcsetattr(0, TCSANOW, &initial); /*restore terminal*/ return(retval); } /*end lib_keypressed()*/ char lib_readkey(void) /*read a key if one has been pressed - nonblocking*/ { struct termios current, initial; char ch,c; /*set terminal to non-buffered input*/ tcgetattr(0, &initial); current=initial; current.c_cc[VMIN]=0; current.c_cc[VTIME]=0; current.c_lflag &= ~ICANON & ~ECHO; tcsetattr(0, TCSANOW, ¤t); fflush(stdin); ch=read(fileno(stdin),&c,1); tcsetattr(0, TCSANOW, &initial); /*restore terminal*/ if (ch==1) return(c); return(ch); } /*end lib_readkey()*/ int lib_noecho(void) /*turn off terminal echo*/ { struct termios current; tcgetattr(0, ¤t); current.c_lflag &= ~ECHO; if (tcsetattr(0, TCSANOW, ¤t)<0) return(-1); return(1); } /*end lib_noecho()*/ int lib_echo(void) /*turn on terminal echo*/ { struct termios current; tcgetattr(0, ¤t); current.c_lflag |= ECHO; if (tcsetattr(0, TCSANOW, ¤t)<0) return(-1); return(1); } /*end lib_echo()*/ int lib_linebufferctl(char flag) /*if flag=0:restore line buffering, -x=no echo, +x = echo*/ { static struct termios initial; struct termios current; int st; if (!flag) { /*flag is zero, restore previous state*/ /*if _initial_ has never been set by a previous call, */ /*then woe unto you for your sin has caught up with you! */ /*explicitly set line buffering and echo*/ initial.c_lflag|=ICANON|ECHO; st=tcsetattr(0, TCSANOW,&initial); if (st<0) return(-1); else return(0); /*0 for restored*/ } /*else flag!=0, set state: no echo, no line buffering*/ tcgetattr(0, &initial); /*save current settings*/ current=initial; current.c_cc[VMIN]=1; current.c_cc[VTIME]=0; if (flag<0) current.c_lflag &= ~ICANON & ~ECHO; /*no echo*/ else current.c_lflag &= ~ICANON; /*echo*/ if (tcsetattr(0, TCSANOW, ¤t)<0) return(-1); return(1); /*1 for special seting success*/ } /*end lib_linebufferctl()*/ int lib_rwpoll(int fd, int wait) /*polls a single fd for all ops: rd/wr/err*/ { struct pollfd polly; int st, ret=0; if (fd<0) return(-1); if (wait<0) wait=-1; /*set to INFTIM if negative*/ polly.fd=fd; polly.revents=0; polly.events=POLLIN|POLLOUT; st=poll(&polly,1,wait); if (st<0) { if (errno==EINTR) return(-2); else return(-1); } if (st==0) return(0); /*timeout*/ if (polly.revents&POLLIN) ret=1; if (polly.revents&POLLOUT) ret=ret|2; if (polly.revents&POLLERR) ret=ret|4; return(ret); } /*end lib_rwpoll()*/ int lib_readpoll(int fd, int wait) /*returns 1 if _fd_ is ready for read, 0 if not, -1 on error*/ { struct pollfd polly; int st; if (fd<0) return(-1); if (wait<0) wait=-1; /*set to INFTIM if negative*/ polly.fd=fd; polly.events=POLLIN; polly.revents=0; st=poll(&polly,1,wait); if (st<0) { if (errno==EINTR) return(-2); else return(-1); } if (st==0) return(0); if (polly.revents&(POLLIN|POLLERR)) return(1); /*return 1 even on err*/ return(-1); /*still here? poll failed: return -1*/ } /*end lib_readpoll()*/ int lib_readpoll2(int fd1, int fd2, int wait) /*check readability of 2 file descriptors: returns -1 on error, 0 if none, 1 if first is ready, 2 if second is ready, 3 if both*/ { struct pollfd polly[2]; int st; if (fd1<0 || fd2<0) return(-1); if (wait<0) wait=-1; /*set to INFTIM if negative*/ polly[0].fd=fd1; polly[1].fd=fd2; polly[0].events=polly[1].events=POLLIN; polly[0].revents=polly[1].revents=0; st=poll(polly,2,wait); if (st<0) { if (errno==EINTR) return(-2); else return(-1); /*poll failed*/ } if (st==0) return(0); /*neither has read data*/ st=0; if (polly[0].revents&(POLLIN|POLLERR)) st=1; if (polly[1].revents&(POLLIN|POLLERR)) st=st|2; return(st); } /*end lib_readpoll2()*/ int lib_mknonblockfd(int fd) /*make a file descriptor non-blocking, returns 1 if successful*/ /*0 if already nonblocking, or -1 on error*/ { int flags; if (fd<0) return(-1); if ((flags=fcntl(fd, F_GETFL,0))<0) return(-1); if ((flags&O_NONBLOCK)!=0) return(0); /*already nonblocking*/ if (fcntl(fd, F_SETFL, flags|O_NONBLOCK)<0) return(-1); return(1); /*done*/ } /*end lib_mknonblockfd()*/ int lib_mkblockfd(int fd) /*make a file descriptor blockable, returns 1 if successful, */ /*0 if already blockable, -1 on error*/ { int flags; if (fd<0) return(-1); if ((flags=fcntl(fd, F_GETFL,0))<0) return(-1); if ((flags&O_NONBLOCK)==0) return(0); /*already blocking mode*/ if (fcntl(fd, F_SETFL, flags & ~O_NONBLOCK)<0) return(-1); return(1); /*done*/ } /*end lib_mkblockfd()*/ /********************************/ /* BEGIN FILE FUNCTIONS SECTION */ /********************************/ FILE *lib_fopenlock(char *path,char *mode, char wait) /*fopen and lock a file with an advisory lock*/ /* if wait > 0, keep trying if file already locked */ /* if wait = 0, return with error if file is already locked */ /* locks will be refused if any error occurs*/ { int FLAGS=-1,fd,stat=0; FILE *fp; /*set mode flags with which to open the file*/ if (strcmp(mode,"r")==0) FLAGS = O_RDONLY; else if (strcmp(mode,"r+")==0) FLAGS = O_RDWR | O_CREAT; else if (strcmp(mode,"w")==0) FLAGS = O_WRONLY | O_TRUNC | O_CREAT; else if (strcmp(mode,"w+")==0) FLAGS = O_RDWR | O_TRUNC | O_CREAT; else if (strcmp(mode,"a")==0) FLAGS = O_WRONLY | O_APPEND | O_CREAT; else if (strcmp(mode,"a+")==0) FLAGS = O_RDWR | O_APPEND | O_CREAT; if (FLAGS==-1) return(NULL); if ((fd=open(path,FLAGS,0666))==-1) return(NULL); if (FLAGS==O_RDONLY) stat=N_lockf(fd,1,wait); /*internal lock funct*/ else stat=N_lockf(fd,2,wait); /*use internal lock function*/ if (stat==-1) { /*error, bail out*/ close(fd); return(NULL); } fp=fdopen(fd,mode); if (fp==NULL) { /*error, bail out*/ N_lockf(fd,0,0); /*use interal lock function*/ close(fd); return(NULL); } return(fp); } /*end lib_fopenlock()*/ int lib_fcloselock(FILE *fp) /*close a preveously locked file opened with lib_fopenlock()*/ { int fd; if (fp==NULL) return(-1); fd=fileno(fp); N_lockf(fd, 0, 0); fclose(fp); return(1); } /*end lib_fcloselock()*/ int lib_sflock(char *lockfile, int timeout) /*create semefore lock file (symlink)*/ /*positive value=success, 0=locked/exists, -1=error*/ { int len, t=0, sum=0; extern int errno; unsigned char link[1024], host[128]; time_t tm,tm2; /*sanity checking*/ if (lockfile==NULL) return(-1); if ((len=strlen(lockfile))==0) return(-1); if (len>768) return(-1); /*too long!*/ tm=time(NULL); /*get number of seconds since the epoch*/ gethostname((char*)host,127); len=sprintf((char*)link,"%s:%ld:%ld",host,(long)getpid(),tm); /*host:pid:time*/ while ((symlink((char*)link,lockfile)<0) && (errno==EEXIST)) { if (timeout>=0) { /*limited timeout, retry until exhausted*/ tm2=time(NULL); /*get current time*/ if (tm2-tm >= timeout) return(0); /*locked*/ } usleep(250000); /*retry every 1/4 second*/ } for (t=0;t3) return(-1); for (x=0;x7) return(-1); x=(p[0]*64)+(p[1]*8)+p[2]; if(umask(x)==(mode_t)x) return(0); return(1); } /*end lib_setumask()*/ int lib_log(char *logfile, char *fmt,...) /*log a line to a logfile, open/close case*/ { va_list ap; char *p; long lval; void *pval; int ival, count=0,size,scount, fd; double dval; char buff[32], type, format[8]; va_start(ap, fmt); for (p=fmt;*p; p++) { if (*p!='%') { count++; continue; } p++; if (*p=='%') { count++; continue; } type=N_getformat(&p,format,&size); switch (type) { case 's' : count=(scount=strlen(va_arg(ap, char*)))+count; if (scount(sbuf.st_blocks*512)) { /*is size > allocated?*/ sparsefile=1; /*we have a sparse file!*/ bsize=512; /*use 512 bytes at a time in lseeks for now*/ } if (stat(dest,&sbuf)!=-1) { if (inode==sbuf.st_ino && dev==sbuf.st_dev) return(sbuf.st_size); mode=sbuf.st_mode; } if ((ifd=open(source,O_RDONLY))==-1) return(-1); if ((ofd=open(dest,O_WRONLY | O_CREAT,0600))==-1) { close(ifd); return(-1); } if (lock) { /*wait for clear, then set lock*/ if (N_lockf(ifd,1,1)<0) { /*abort if locks cannot be had*/ close(ifd); close(ofd); return(-2); } if (N_lockf(ofd,2,1)<0) { /*abort if locks cannot be had*/ N_lockf(ifd,0,0); close(ifd); close(ofd); return(-2); } } /*If we have a sparse file and _dest_ exists, then we could run into a interesting situation in which the src file has all 0's in a block but the dest file doesn't, thus we would lseek() through the block without changing the existing bytes in the dest file to 0's. Truncating the file to 0 length works around this little problem*/ if (sparsefile) ftruncate(ofd,0L); while ((bufsize=read(ifd,buffer,bsize))>0) { if (sparsefile) { nonzero=FALSE; for (x=0;x=0) ftruncate(ofd,lseek(ofd,0,SEEK_CUR)); if (lock) { /*unlock the files if needed*/ N_lockf(ifd,0,0); N_lockf(ofd,0,0); } close(ofd); close(ifd); if (bufsize==-1) return(-1); if (chmod(dest,mode)==-1) return(-1); return(bwt); } /*end lib_fcopy()*/ long lib_ftrans(FILE *from, FILE *to) /*move data from one open file to another via stdio*/ { int cr; char buff[768]; short bw; long bwt=0; /*reset file pointers*/ if (fseek(from, 0L, SEEK_SET)<0) return(-1); if (fseek(to, 0L, SEEK_SET)<0) return(-1); /*nuke data in destination file*/ while ((cr=fread(buff,1,768,from))>0) { bw=fwrite(buff,1,cr,to); bwt+=bw; } fflush(to); /*write out any buffered data*/ ftruncate(fileno(to),ftell(to)); /*truncate file to new length*/ rewind(from); rewind(to); return(bwt); } /*end lib_ftrans()*/ long lib_fdtrans(int from, int to) /*move data from one open file to another*/ { char buff[4096]; int cr; short bw; long bwt=0; /*reset file pointers*/ if (lseek(from,0,SEEK_SET)<0) return(-1); if (lseek(to,0,SEEK_SET)<0) return(-1); /*nuke data in destination file*/ while ((cr=read(from,buff,4096))>0) { bw=write(to,buff,cr); bwt+=bw; } if (ftruncate(to,lseek(to,0,SEEK_CUR))<0) return(-1); lseek(from,0,SEEK_SET); lseek(to,0,SEEK_SET); return(bwt); } /*end lib_fdtrans()*/ int lib_append(char *from, char *to, char lock, char truncat) /*append one file to another*/ { char buff[4096]; int st,in,out; /*open files*/ if ((in=open(from,O_RDWR))==-1) return(-1); if ((out=open(to,O_RDWR | O_APPEND | O_CREAT, 0666))==-1) { close(in); return(-1); } if (lock!=0) { /*set the lock if specified*/ N_lockf(in,2,1); N_lockf(out,2,1); } while ((st=read(in,buff,4096))>0) write(out,buff,st); if (truncat!=0) ftruncate(in,0L); if (lock!=0) { /*unlock*/ N_lockf(in,0,0); N_lockf(out,0,0); } close(in); close(out); return(1); } /*end lib_append()*/ int lib_fappend(int from, int to) /*append one open file to another open file*/ { char buff[4096]; int st; /*set file positions*/ if (lseek(from, 0L, SEEK_SET)==-1) return(-1); if (lseek(to, 0L, SEEK_END)==-1) return(-1); /*transfer data*/ while ((st=read(from,buff,4096))>0) write(to,buff,st); lseek(from, 0L, SEEK_SET); return(1); } /*end lib_fappend()*/ int lib_flock(int fd, char locktype, int wait) /*place an advisory lock on an open file*/ /* wait: 0=nowait,1=wait; locktype: 0=unlock, 1=read, 2=write*/ /* flock() implementation on fcntl()*/ { struct flock fl; if (locktype==0) fl.l_type=F_UNLCK; else if (locktype==1) fl.l_type=F_RDLCK; else if (locktype==2) fl.l_type=F_WRLCK; else return(-1); fl.l_whence=0; fl.l_len=0; fl.l_start=0; if (wait==0) wait=F_SETLK; else wait=F_SETLKW; return(fcntl(fd, wait, &fl)); } /*end lib_flock()*/ char *lib_getfilename(char *path) /*return filename from a path*/ { int x,len; if (path==NULL) return(NULL); if ((len=strlen(path))==0) return(NULL); for (x=len-1;x>=0;x--) if (path[x]=='/') { if (strlen(&path[x+1])==0) return(NULL); return(&path[x+1]); } return(path); } /*end lib_getfilename()*/ char *lib_last_path_element(char *path, char *element) /*return last element in a given path*/ { int x,len, emarker=0, flag=0; if (path==NULL || element==NULL) return(NULL); element[0]='\0'; if ((len=strlen(path))==0) return(element); /*empty, just return*/ x=len-1; /*set to first char before nul*/ while (x>=0) { if (path[x]=='/') { if (flag==0) { /*flag=0 means we're slashing*/ x--; /*go to the next char*/ continue; } else { x++; /*leading slash - done, stop*/ break; } } else if (flag==0) { flag=1; /*non-slash, set flag*/ emarker=x; /*mark end point*/ } x--; } if (x<0) x=0; if (emarker>=x) { /*emarker should never be < x, but...*/ len=emarker-x+1; strncpy(element, &path[x], len); element[len]='\0'; } return(element); } /*end lib_last_path_element()*/ char *lib_getpathdir(char *path, char *dirpath) /*return just the path directory portion without the last element*/ { int x,len; char *p; if (path==NULL || dirpath==NULL) return(NULL); dirpath[0]='\0'; if ((len=strlen(path))==0) return(dirpath); /*empty, just return*/ if (len==1) { /*just a slash*/ if (path[0]=='/') strcpy(dirpath,path); return(dirpath); } p=path; x=len-1; /*set to first char before nul*/ while (p[x]=='/' && x>0) x--; /*skip multiple trailing /'s */ while (x>=0) { if (p[x]=='/') break; x--; } if (x<=0) { /*no patch to print*/ if (path[0]=='/') strcpy(dirpath,"/"); return(dirpath); } strncpy(dirpath,p,x); dirpath[x]='\0'; return(dirpath); } /*end lib_getpathdir()*/ int lib_condense_path(char *path, char trflag) /*clean up a path by condensing redundant slashes*/ { int lp=0, np=0, dflag=0; if (path==NULL) return(-1); if (path[0]=='\0') return(0); if (path[1]=='\0') return(1); while (path[lp]!='\0') { if (path[lp]=='/') { if (!dflag) { path[np]=path[lp]; np++; dflag=1; } } else { path[np]=path[lp]; np++; dflag=0; } lp++; } path[np]='\0'; /*null terminate new position*/ if (trflag==0) { if (np>0) if (path[np-1]=='/') { np--; path[np]='\0'; /*nuke trailing slash*/ } } return(np); } /*end lib_condense_path()*/ int lib_get_file_ext(char *file, char *ext) /*retrieve trailing file extension and return its length*/ { int len, x, c=0; char sflag=0; if (file==NULL || ext==NULL) return(-1); ext[0]='\0'; x=(len=strlen(file))-1; if (len==0) return(0); x=len-1; while (x>0) { if (file[x]=='.') { sflag=1; break; } x--; } if (sflag==0) return(0); x++; /*skip the . */ while (file[x]!='\0') ext[c++]=file[x++]; ext[c]='\0'; return(c); } /*end lib_get_file_ext()*/ int lib_match_inode(char *path1, char *path2) /*check if identical objects, 1:yes, 0:no, -1:error*/ { struct stat sbuff1, sbuff2; /*sanity checks*/ if (path1==NULL || path2==NULL) return(-1); if (path1[0]=='\0' || path2[0]=='\0') return(-1); if (lstat(path1,&sbuff1)<0) return(-1); if (lstat(path2,&sbuff2)<0) return(-1); if (sbuff1.st_ino!=sbuff2.st_ino) return(0); /*inode is different*/ if (sbuff1.st_dev!=sbuff2.st_dev) return(0); /*device is different*/ return(1); /*still here? must be the same!*/ } /*end lib_match_inode()*/ int lib_match_fs(char *path1, char *path2) /*check if on filessystems, 1:yes, 0:no, -1:error*/ { struct stat sbuff1, sbuff2; /*sanity checks*/ if (path1==NULL || path2==NULL) return(-1); if (path1[0]=='\0' || path2[0]=='\0') return(-1); if (lstat(path1,&sbuff1)<0) return(-1); if (lstat(path2,&sbuff2)<0) return(-1); if (sbuff1.st_dev!=sbuff2.st_dev) return(0); /*different file systems*/ return(1); } /*end lib_match_fs()*/ int lib_getfiletype(char *path) /*return file type of a file system object*/ { struct stat sbuff; if (path==NULL) return(-1); if (path[0]=='\0') return(-1); if (lstat(path,&sbuff)<0) return(-1); sbuff.st_mode=sbuff.st_mode&0xF000; if (sbuff.st_mode==S_IFREG) return(1); /*regular file*/ if (sbuff.st_mode==S_IFDIR) return(2); /*directory*/ if (sbuff.st_mode==S_IFLNK) return(3); /*symlink*/ if (sbuff.st_mode==S_IFBLK) return(4); /*block device*/ if (sbuff.st_mode==S_IFCHR) return(5); /*char device*/ if (sbuff.st_mode==S_IFIFO) return(6); /*named pipe*/ if (sbuff.st_mode==S_IFSOCK) return(7); /*socket*/ return(0); /*dunno, but it exists*/ } /*end lib_getfiletype()*/ int lib_compare_filenodes(char *path1, char *path2) /*compare main attributes of two inodes for equality*/ { struct stat sbuff1, sbuff2; int ret=0, lfl=0; /*sanity checks*/ if (path1==NULL || path2==NULL) return(-1); if (path1[0]=='\0' || path2[0]=='\0') return(-1); if (lstat(path1,&sbuff1)<0) return(-1); if (lstat(path2,&sbuff2)<0) return(-1); if ((sbuff1.st_mode&0xF000) != (sbuff2.st_mode&0xF000)) ret=ret|1; /*different file types*/ if ((sbuff1.st_mode&0x0FFF) != (sbuff2.st_mode&0x0FFF)) ret=ret|2; /*different perms*/ if (sbuff1.st_uid != sbuff2.st_uid) ret=ret|4; /*different UID*/ if (sbuff1.st_gid != sbuff2.st_gid) ret=ret|8; /*different GID*/ if (sbuff1.st_size != sbuff2.st_size) ret=ret|16; if (!(ret&1)) { /*same type, check if symlink*/ if ((sbuff1.st_mode&0xF000)==S_IFLNK) { char rd1[1048], rd2[1048]; int s1, s2; rd2[0]=rd1[0]='\0'; if ((s1=readlink(path1,rd1,1024))<0) s1=0; if ((s2=readlink(path2,rd2,1024))<0) s2=0; rd2[s2]=rd1[s1]='\0'; if (strcmp(rd1,rd2)!=0) ret=ret|64; lfl=1; } } if (!lfl) /*check mtimes unless BOTH objects are symlinks*/ if (sbuff1.st_mtime != sbuff2.st_mtime) ret=ret|32; return(ret); /*if ret==0, then identical, at least in appearance*/ } /*end lib_compare_filenodes()*/ int lib_compare_filecontent(char *path1, char *path2) /*compare the file contents of two files*/ { struct stat sbuff1, sbuff2; FILE *fp1, *fp2; int ch1, ch2, ret=0; if (path1==NULL || path2==NULL) return(-1); if (path1[0]=='\0' || path2[0]=='\0') return(-1); if (stat(path1,&sbuff1)<0) return(-1); /*use stat to follow symlinks*/ if (stat(path2,&sbuff2)<0) return(-1); /*use stat to follow symlinks*/ if ((sbuff1.st_mode&0xF000) != S_IFREG && (sbuff2.st_mode&0xF000) != S_IFREG) return(-1); /*not reg files*/ if (sbuff1.st_size!=sbuff2.st_size) return(1); /*have different sizes, they CANNOT be equal*/ if ((fp1=fopen(path1,"r"))==NULL) return(-1); if ((fp2=fopen(path2,"r"))==NULL) { fclose(fp1); return(-1); } for (;;) { ch1=fgetc(fp1); ch2=fgetc(fp2); if (ch1!=ch2) { ret=1; break; } if (ch1==EOF || ch2==EOF) break; } fclose(fp1); fclose(fp2); return(ret); } /*end lib_compare_filecontent()*/ int lib_is_sparsefile(char *path) /*checks to see if a file is sparse or not*/ { struct stat sbuff; /*sanity checks*/ if (path==NULL) return(-1); if (path[0]=='\0') return(-1); if (stat(path,&sbuff)<0) return(-1); /*follow symlink, using stat()*/ if ((sbuff.st_mode&0xF000) != S_IFREG) return(-1); /*not a reg file*/ if ((512*sbuff.st_blocks) < sbuff.st_size) return(1); return(0); /*not a sparsefile*/ } /*end lib_is_sparsefile()*/ int lib_fcat(char *filename, int output) /*outputs an entire file, returns #bytes read/written*/ { FILE *fptr; unsigned char buff[1024]; int crw, tot=0; /*sanity checks*/ if (filename==NULL || output<0) return(-1); if (strlen(filename)==0) return(-1); fptr=fopen(filename,"r"); if (fptr==NULL) return(-1); while ((crw=fread(buff,1,1024,fptr))>0) { if (write(output,buff,crw)<0) { fclose(fptr); return(-1); } if (tot>=0) tot=tot+crw; } fclose(fptr); if (crw<0) return(-1); /*some error occurred on read*/ if (tot<0) return(0); /*size probably too big*/ return(tot); } /*end lib_fcat()*/ int lib_diffstat(char *path, struct stat *inbuf, struct stat *outbuf) /*return 1 on different, 0 if not, -1 on error*/ { int st; struct stat cbuf; /*sanity checks*/ if (path==NULL || inbuf==NULL) return(-1); if (strlen(path)==0) return(-1); /*get current stat*/ st=lstat(path,&cbuf); if (st<0) return(-1); if (outbuf!=NULL) bcopy(inbuf,outbuf,sizeof(struct stat)); /*compare*/ if (cbuf.st_mtime!=inbuf->st_mtime) return(1); /*modified?*/ if (cbuf.st_size!=inbuf->st_size) return(1); /*changed size?*/ if (cbuf.st_ctime!=inbuf->st_ctime) return(1); /*inode attr change?*/ if (cbuf.st_mode!=inbuf->st_mode) return(1); /*perms changed?*/ if (cbuf.st_ino!=inbuf->st_ino) return(1); /*inode changed?*/ if (cbuf.st_uid!=inbuf->st_uid) return(1); /*uid changed?*/ if (cbuf.st_gid!=inbuf->st_gid) return(1); /*gid changed?*/ if (cbuf.st_blocks!=inbuf->st_blocks) return(1); /*#blocks changed?*/ if (cbuf.st_dev!=inbuf->st_dev) return(1); /*device changed?*/ return(0); } /*end lib_diffstat()*/ long lib_getfilesize(char *path, unsigned int *blocks) /*return file size in bytes or blocks*/ /*may require special compile time flags for largefile operations*/ { struct stat buf; int st; /*sanity checks*/ if (path==NULL) return(-1); if (strlen(path)==0) return(-1); st=lstat(path,&buf); if (st<0) { #ifndef __osf__ /*tru64 is 64 bit, this errno doesn't exist for it */ if (errno==EOVERFLOW) return(-2); #endif return(-1); } if (blocks!=NULL) *blocks=buf.st_blocks; /* # of 512 byte blocks*/ return(buf.st_size); } /*end lib_getfilesize()*/ int lib_getfileguid(char *path, int *gid) /*get UID/GID of a file*/ { struct stat buf; int st; /*sanity checks*/ if (path==NULL) return(-1); if (strlen(path)==0) return(-1); if ((st=lstat(path,&buf))<0) return(-1); if (gid!=NULL) *gid=buf.st_gid; return(buf.st_uid); } /*end lib_getfileguid()*/ int lib_getfileperms(char *path) /*get file permissions including type*/ { struct stat buf; int st; /*sanity checks*/ if (path==NULL) return(-1); if (strlen(path)==0) return(-1); if ((st=lstat(path,&buf))<0) return(-1); return(buf.st_mode); } /*end lib_getfileperms()*/ int lib_getfilesize2(char *filename, int *remainder) /*return the size of a file in Kbytes + bytes*/ /*may require compile flags for 64bit file operations*/ { struct stat buf; int st; unsigned int size; st=stat(filename,&buf); if (st<0) return(-1); size=(buf.st_size>>10); /*total base Kbytes*/ if (remainder!=NULL) /*bytes remaining*/ *remainder=(int)( buf.st_size - (size<<10) ); else { if (buf.st_size&1023) size++; /*increment for overflow*/ } return(size); } /*end lib_getfilesize2()*/ int lib_isfileopen(char *file) /*see if a file is open - may require root for /proc processing*/ /*known only to work on Linux and Solaris*/ { struct stat base, test; int st, len, x; struct dirent *direntp, *direntfd; DIR *dirp, *dirfd; char path[1024], wpath[1280]; st=lstat(file,&base); if (st<0) return(-1); dirp=opendir("/proc"); if (dirp==NULL) return(-1); rewinddir(dirp); while ((direntp=readdir(dirp))!=NULL) { len=strlen(direntp->d_name); for (x=0;xd_name[x])==0) continue; /*if still here, got a PID*/ snprintf(path,1024,"/proc/%s/fd",direntp->d_name); path[1023]='\0'; /*sorry if this is too short*/ dirfd=opendir(path); if (dirfd==NULL) continue; /*gone now, next*/ rewinddir(dirfd); while ((direntfd=readdir(dirfd))!=NULL) { snprintf(wpath,1279,"%s/%s",path,direntfd->d_name); wpath[1279]='\0'; st=stat(wpath,&test); if (st<0) continue; /*no longer there, skip*/ if (test.st_ino==base.st_ino && test.st_dev==base.st_dev) { closedir(dirfd); closedir(dirp); return(1); } } closedir(dirfd); } closedir(dirp); /*still here, not found*/ return(0); } /*end lib_isfileopen()*/ /*************************************/ /*BEGIN IPC/NETWORK FUNCTIONS SECTION*/ /*************************************/ int lib_open_tcp_connection(char *host, int port) /* open an internet socket stream*/ /* may not be thread safe unless IP address*/ { int sd; struct hostent *hp; struct sockaddr_in sin; /*sanity checks*/ if (port < 1 || host==NULL) return(-1); if (strlen(host)==0) return(-1); bzero((char *) &sin,sizeof(sin)); if (inet_addr(host)!=(in_addr_t)(-1)) { /*just a plain ol IP address*/ sin.sin_addr.s_addr=inet_addr(host); } else { /*not an IP address, use resolver (may not be thread safe)*/ if ((hp=gethostbyname(host))==NULL) return(-1); /*no address*/ bcopy(hp->h_addr,(char *) &sin.sin_addr,hp->h_length); } sin.sin_family=AF_INET; sin.sin_port=htons(port); if ((sd=socket(AF_INET,SOCK_STREAM,0))<0) return(-2); /*??*/ if (connect(sd,(struct sockaddr*)&sin,sizeof(sin))==-1) { close(sd); return(-3); /*connection refused*/ } return(sd); } /*end lib_open_tcp_connection()*/ int lib_init_tcp_connection(char *host, int port, int *status) /*initiat a connection, but not wait for it to finish*/ /*function returns the socket or -1 on error. */ { int flags,sd; struct hostent *hp; struct sockaddr_in sin; /*sanity checks*/ if (port < 1 || host==NULL) return(-1); if (strlen(host)==0) return(-1); bzero((char *) &sin,sizeof(sin)); if (inet_addr(host)!=(in_addr_t)(-1)) { /*just a plain ol IP address*/ sin.sin_addr.s_addr=inet_addr(host); } else { /*not an IP address, use resolver (may not be thread safe)*/ if ((hp=gethostbyname(host))==NULL) return(-1); /*no address*/ bcopy(hp->h_addr,(char *) &sin.sin_addr,hp->h_length); } sin.sin_family=AF_INET; sin.sin_port=htons(port); if ((sd=socket(AF_INET,SOCK_STREAM,0))<0) return(-2); /*??*/ flags=fcntl(sd, F_GETFL,0); if (flags<0) { close(sd); return(-1); } if (fcntl(sd, F_SETFL, flags|O_NONBLOCK)<0) { close(sd); return(-1); } if (connect(sd, (struct sockaddr*)&sin,sizeof(sin))<0) { if (errno!=EINPROGRESS) { close(sd); return(-1); } if (status!=NULL) *status=1; /*in progress*/ return(sd); } /*still here, then it completed*/ if (status!=NULL) *status=0; /*completed*/ return(sd); } /*end lib_init_tcp_connection()*/ int lib_make_tcp_socket(int port, short backlog, long ip) /*create local socket and bind to a TCP port*/ { int sd,n=1; struct sockaddr_in sin; /*sanity checks*/ if (port<1 || backlog<1 || ip<-1) return(-1); if (ip==0) ip=htonl(INADDR_ANY); bzero((char *) &sin,sizeof(sin)); sin.sin_addr.s_addr=ip; /* _ip_ is assumed to be in network order*/ sin.sin_port=htons(port); sin.sin_family=AF_INET; if ((sd=socket(AF_INET,SOCK_STREAM,0)) < 0) return(-2); /*??*/ setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, (char *) &n, sizeof(int)); if (bind(sd,(struct sockaddr*)&sin,sizeof(sin))<0) return(-3); listen(sd,backlog); return(sd); } /*end lib_make_tcp_socket()*/ int lib_acceptconnect(int sd, int *nsd, char nowait) /*accept an incoming connection from the network*/ /*may not be thread safe*/ { int ret=0,old=0,addrlen=sizeof(struct sockaddr); struct sockaddr peer; if (sd<0) return(*nsd=-1); memset(&peer,0,sizeof(struct sockaddr)); /*set nonblocking if specified*/ if (nowait) fcntl(sd,F_SETFL,((old=fcntl(sd,F_GETFL)) | O_NONBLOCK)); if ((*nsd=accept(sd,&peer,(socklen_t*)&addrlen))<0) { if (errno==EWOULDBLOCK) ret=0; else if (errno==EINTR) ret=-2; else ret=-1; } else ret=1; if (nowait) { /*restore socket setting if nonblocking was set*/ fcntl(sd,F_SETFL,old); if (ret==1) fcntl(*nsd,F_SETFL,old); } return(ret); } /*end lib_acceptconnect()*/ int lib_gethostinfo(int sd, char *ipaddress, char *hostname) /*return host data (IP and hostname) of peer on an open socket*/ /*may not be thread safe*/ { struct sockaddr_in name; struct hostent *h; int namelen=sizeof(struct sockaddr); if (sd<0) return(-1); if (getpeername(sd, (struct sockaddr*)&name,(socklen_t*)&namelen)<0) return(-1); strcpy(ipaddress,inet_ntoa(name.sin_addr)); if (hostname==NULL) return(0); hostname[0]=0; h=gethostbyaddr((char *)&(name.sin_addr),sizeof(struct in_addr), name.sin_family); if (h==NULL) { strcpy(hostname,ipaddress); return(0); } strcpy(hostname,h->h_name); return(1); } /*end lib_gethostinfo()*/ int lib_make_udp_socket(unsigned long ip, int port) /*create a server-side udp socket*/ { int sd, siz; struct sockaddr_in servaddr; /*first create the socket*/ if (ip<0 || port<0) return(-1); if ((sd=socket(AF_INET, SOCK_DGRAM, 0))<0) return(-2); /*populate the sockaddr_in struct*/ if (ip==0) ip=htonl(INADDR_ANY); siz=sizeof(struct sockaddr); bzero(&servaddr,siz); servaddr.sin_family=AF_INET; servaddr.sin_addr.s_addr=ip; /*assumed to be in network order*/ servaddr.sin_port=htons(port); /*actually bind to the socket*/ if (bind(sd, (struct sockaddr*)&servaddr,siz)<0) { close(sd); return(-3); } return(sd); } /*end lib_make_udp_socket()*/ int lib_make_udp_addr(struct sockaddr_in *sock, unsigned long ip, int port) /*populate a sockaddr_in struct for UDP operations*/ { /*sanity checks*/ if (ip==0) ip=INADDR_ANY; if (port<0 || ip==-1 || sock==NULL) return(-1); /*populate with the necessities of life*/ bzero(sock,sizeof(struct sockaddr)); sock->sin_family=AF_INET; sock->sin_port=htons(port); sock->sin_addr.s_addr=(long)ip; /*assumed to be in network order*/ return(1); } /*end lib_make_udp_addr()*/ int lib_open_unix_socket(char *name) /*open a connection to a local Unix socket*/ { struct sockaddr sock; int sd; /*sanity checks-name limited to < 14 characters*/ if (strlen(name)>13 || name[0]==0) return(-1); sock.sa_family=AF_UNIX; strcpy(sock.sa_data,name); if ((sd=socket(AF_UNIX,SOCK_STREAM,0))<0) return(-2); if (connect(sd,&sock,sizeof(sock))==-1) { close(sd); return(-3); } return(sd); } /*end lib_open_unix_socket()*/ int lib_make_unix_socket(char *name, int backlog) /*create a local Unix socket to accept connections*/ { struct sockaddr sock; int sd,n=1; /*sanity checks - name limited to <14 characters*/ if (strlen(name)>13 || name[0]=='\0') return(-1); if ((sd=socket(AF_UNIX,SOCK_STREAM,0))<0) return(-2); sock.sa_family=AF_UNIX; strcpy(sock.sa_data,name); setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, (char*)&n, sizeof(int)); if (bind(sd,&sock,sizeof(sock))==-1) { close(sd); return(-3); } listen(sd,backlog); return(sd); } /*end lib_make_unix_socket()*/ int lib_nslookup(char *hostname, char *ipaddress) /*DNS lookup by hostname*/ /*may not be thread safe unless IP address*/ { struct hostent *h; struct in_addr *a; int n,s=0; struct tms buffer; double f; /*sanity checks*/ if (hostname==NULL) return(-1); if (strlen(hostname)==0) return(-1); /*save some time if already an IP address*/ if (hostname[0]>='0' && hostname[0]<='9') { if (inet_addr(hostname)!=(in_addr_t)(-1)) { if (ipaddress!=NULL) strcpy(ipaddress, hostname); return(1); } } h=NULL; /*initialize*/ if ((h=gethostbyname(hostname))==NULL) { if (h_errno==NO_DATA) return(0); /*exists, but no IP*/ if (h_errno==HOST_NOT_FOUND) return(-2); /*nonexistant*/ if (h_errno==TRY_AGAIN) return(-3); /*no response*/ if (h_errno==NO_RECOVERY) return(-4); /*DNS error*/ return(-1); /*whatever else, bail*/ } for (n = 0; h->h_addr_list[n] != NULL; n++); if (n>1) { srand48(abs(times(&buffer)-lrand48())); f=drand48(); s=(int)(f*((float)n)); } a=(struct in_addr*) h->h_addr_list[s]; if (ipaddress!=NULL) strcpy(ipaddress,inet_ntoa(*a)); return(n); } /*end lib_nslookup()*/ int lib_dnslookup(char *hostname, struct ip_type *ip) /*DNS lookup on a hostname returning all IPs*/ /*may not be thread safe unless IP address*/ { struct hostent *h; struct in_addr *a; int n; /*sanity checks*/ if (hostname==NULL || ip==NULL) return(-1); if (strlen(hostname)==0) return(-1); /*save our breath if its already an IP address*/ if (hostname[0]>='0' && hostname[0]<='9') { /*might be an IP addr*/ if (inet_addr(hostname)!=(in_addr_t)(-1)) { /*it is!*/ strcpy(ip->address[0],hostname); return(ip->size=1); } } h=NULL; if ((h=gethostbyname(hostname))==NULL) { if (h_errno==NO_DATA) return(0); /*exists, but no IP*/ if (h_errno==HOST_NOT_FOUND) return(-2); /*nonexistant*/ if (h_errno==TRY_AGAIN) return(-3); /*no response*/ if (h_errno==NO_RECOVERY) return(-4); /*DNS error*/ return(-1); /*dunno, just fail*/ } for (n = 0; h->h_addr_list[n] != NULL; n++) { a=(struct in_addr *) h->h_addr_list[n]; strcpy(ip->address[n],inet_ntoa(*a)); if (n+1 >= 32) break; /*32 is the limit in struct ip_type*/ } ip->size=n; return(n); } /*end lib_dnslookup() */ int lib_revnslookup(char *ipaddress, char *hostname) /*reverse DNS lookup by IP address*/ /*may not be thread safe*/ { struct hostent *h; unsigned long a; /*sanity checks*/ if (ipaddress==NULL) return(-1); if (strlen(ipaddress)==0) return(-1); a=inet_addr(ipaddress); /*recognize dot notation only*/ if ((long)a == -1) return(-1); h=gethostbyaddr((char *)&a,sizeof(struct in_addr),AF_INET); if (hostname!=NULL) hostname[0]='\0'; if (h==NULL) return(0); if (hostname!=NULL) strncpy(hostname,h->h_name,63); hostname[63]='\0'; /*cap at 64 chars*/ return(1); } /*end lib_revnslookup()*/ int lib_check_cidr(char *ipaddress, char *cidr) /*check if an IP addresses matches a cidr block*/ /*returns 1 if match, 0 if not, -1 on error*/ { long ip, nip; int bitcnt=0, x, len; unsigned int bit, uip, nid, mask; char *tbuffnet, *tbuffmask, *sptr; /*sanity checks*/ if (ipaddress==NULL || cidr==NULL) return(-1); if (strlen(ipaddress)==0 || (len=strlen(cidr))==0) return(-1); if ((sptr=strchr(cidr,'/'))==NULL) return(-1); ip=(long)inet_network(ipaddress); if (ip==-1) return(-1); /*we don't handle 255.255.255.255*/ tbuffnet=(char*)malloc(len+1); tbuffmask=(char*)malloc(len+1); if (tbuffnet==NULL || tbuffmask==NULL) return(-1); strcpy(tbuffnet,cidr); x=0; while (tbuffnet[x]!='/') x++; tbuffnet[x]='\0'; nip=(long)inet_network(tbuffnet); if (nip==-1) { leave: free(tbuffnet); free(tbuffmask); return(-1); } sptr=&sptr[1]; /*skip past the / character*/ len=strlen(sptr); if (len==0 || len>2) { goto leave; } bitcnt=atoi(sptr); if (bitcnt<=0 || bitcnt>32) goto leave; free(tbuffnet); free(tbuffmask); mask=0; bit=(1<<31); for (x=0;x>1)|bit; nid=(unsigned long)nip; uip=(unsigned long)ip; if ((uip&mask)==nid) return(1); /*netid's match*/ return(0); /*still here?, didn't match*/ } /*end lib_check_cidr()*/ int lib_gen_tocidr(char *ipaddr, char *nmask, char *cidr) /*generate cidr address from ip address and netmask*/ { int ilen, nlen, x; long ip, nip; unsigned long u_ip, u_nip, u_cip, tmp; unsigned int bit; unsigned short o1, o2, o3, o4; /*sanity checks*/ if (ipaddr==NULL || nmask==NULL || cidr==NULL) return(-1); ilen=strlen(ipaddr); if (ilen<7 || ilen>15) return(-1); nlen=strlen(nmask); if (nlen<7 || nlen>15) return(-1); ip=inet_network(ipaddr); if (ip==-1) { if (strcmp(ipaddr,"255.255.255.255")==0) { u_ip=(65535<<16)|65535; } else return(-1); /*bad address*/ } else u_ip=(unsigned long)ip; nip=inet_network(nmask); if (nip==-1) { if (strcmp(nmask,"255.255.255.255")==0) { u_nip=(65535<<16)|65535; } else return(-1); /*bad netmask*/ } else u_nip=(unsigned long)nip; /*need to check u_nip to verify validity : contigious 1s+0s*/ if (nip!=-1) { for (x=0,tmp=0;x<32;x++) { if ((u_nip&1)==0 && tmp==1) return(-1); /*bad boy*/ if ((u_nip&1)==1) tmp=1; u_nip=u_nip>>1; } u_nip=(unsigned long)nip; /*reset u_nip*/ } u_cip=(u_ip & u_nip); tmp=u_nip; for (x=0;x<32;x++) { bit=tmp&1; if (bit==1) break; tmp=tmp>>1; } bit=32-x; /*shouldn't be less than 0 or more than 32, in theory :) */ if (bit>32) bit=0; /*screw 'em*/ o1=(u_cip>>24) & 255; o2=(u_cip>>16) & 255; o3=(u_cip>>8) & 255; o4=u_cip & 255; sprintf(cidr,"%d.%d.%d.%d/%d",o1,o2,o3,o4,bit); return(1); } /*end lib_gen_tocidr()*/ int lib_gen_fromcidr(char *nmask, char *cidr) /*generate netmask from cidr address*/ { int nlen, clen; unsigned long nip=0; char *s; unsigned short o1, o2, o3, o4; /*sanity checks*/ if (nmask==NULL || cidr==NULL) return(-1); clen=strlen(cidr); if (clen<9 || clen>18) return(-1); if ((s=strchr(cidr,'/'))==NULL) return(-1); s++; /*skip the / */ nlen=atoi(s); if (nlen>32 || nlen<=0) return(-1); for (clen=0;clen>24) & 255; o2=(nip>>16) & 255; o3=(nip>>8) & 255; o4=nip & 255; sprintf(nmask,"%d.%d.%d.%d",o1,o2,o3,o4); return(1); } /*end lib_gen_fromcidr()*/ int lib_check_ipblock(char *ip, char *range) /*check IP block using string compares*/ { int leni, lenr; /*sanity checks*/ if (ip==NULL || range==NULL) return(-1); if ((leni=strlen(ip))<7) return(-1); /*too small for ip*/ if ((lenr=strlen(range))==0) return(-1); /*too small for range*/ if (leni>15 || lenr>15) return(-1); /*too big*/ if (inet_addr(ip)==-1) return(-1); if (inet_addr(range)==-1) return(-1); if (lenr>leni) return(0); /*range can't be larger than IP*/ /*down to bizzness*/ if (strcmp(ip,range)==0) return(1); /*exact match, return*/ if (strncmp(ip,range,lenr)!=0) return(0); /*don't match for sure*/ if (ip[lenr]=='.') return(1); /*yep, good to go*/ /*still here? must be bad*/ return(0); } /*end lib_check_ipblock()*/ int lib_check_fqdn_match(char *hostname, char *domain) /*check if a hostname has a specified domain*/ { int hlen, dlen, x; char rhost[128], rdomain[128]; /*sanity checks*/ if (hostname==NULL || domain==NULL) return(-1); if ((hlen=strlen(hostname))==0) return(-1); if ((dlen=strlen(domain))==0) return(-1); if (hlen>127 || dlen>127) return(-1); if (strcasecmp(hostname,domain)==0) return(1); /*identical*/ if (dlen>=hlen) return(0); /*impossible to match*/ /*reverse the strings*/ for (x=0;x4) return(-1); if (retran<1) retran=0; /*set minimum standards*/ if (retry<1) retry=1; /*set minimum standards*/ /*initialize stuff*/ res_init(); sin=_res.nsaddr_list[0]; tmout=_res.retrans; /*save this*/ sretry=_res.retry; /*save this*/ nscount=_res.nscount; /*save this*/ if (nip!=NULL) { /*only specify NS if nip is NULL*/ _res.nsaddr_list[0].sin_addr.s_addr=inet_addr(nip); if (_res.nsaddr_list[0].sin_addr.s_addr==-1) return(-1); _res.nscount=1; } _res.retry=retry; /*retry interval timeout*/ _res.retrans=retran; /*retrancmit tries*/ for (x=0;x<32;x++) rrec->ip[x][0]='\0'; rrec->itype=rrec->icount=0; /*convert types: 0=T_A, 1=T_PTR, 2=T_CNAME, 3=T_NS, 4=T_MX */ if (type==0) type=T_A; else if (type==1) { unsigned char tbuf[8]; type=T_PTR; if ((long)(addr=inet_addr(fn))==-1) return(-1); tbuf[3]=addr & 255; tbuf[2]=(addr>>8)&255; tbuf[1]=(addr>>16)&255; tbuf[0]=(addr>>24)&255; tbuf[4]=0; sprintf((char*)lbuf,"%d.%d.%d.%d.in-addr.arpa",tbuf[3],tbuf[2],tbuf[1],tbuf[0]); } else if (type==2) type=T_CNAME; else if (type==3) type=T_NS; else if (type==4) type=T_MX; if (type!=T_PTR) strcpy((char*)lbuf,fn); /*down to business*/ siz=res_search((char*)lbuf,C_IN,type,buffer,4096); if (siz<0) { herror("res_search"); _res.retrans=tmout; _res.retry=sretry; _res.nscount=nscount; _res.nsaddr_list[0]=sin; return(-1); } reply=buffer; rrec->icount=(reply[6]<<8)|reply[7]; /*record count*/ rrec->itype=(reply[28]<<8)|reply[29]; /*record type asked for*/ if (type==T_A) aflag=1; /*A record*/ else if (type==T_MX) mxflag=1; /*MX record*/ ppos=12; /*skip header*/ while (reply[ppos]>0 && reply[ppos]<192) ppos++; if (reply[ppos]>=192) ppos+=2; /*skip ptr*/ else ppos++; /*skip \0 */ ppos+=4; /*skip flags*/ while (rrnumicount) { /*parse records*/ /*skip header junk*/ while (reply[ppos]>0 && reply[ppos]<192) ppos++; if (reply[ppos]>=192) ppos+=2; /*skip ptr*/ else ppos++; /*skip \0 */ if (reply[ppos+1]==1) ipflag=1; /*if type==1, IP address*/ ppos+=8; nlen=ppos+((reply[ppos]<<8)|reply[ppos+1])+2; ppos+=2; /*skip length stuff*/ if (mxflag) { /*need to pull and skip weights*/ rrec->wt[rrnum]=(reply[ppos]<<8)|reply[ppos+1]; ppos+=2; } N_parse_drec(reply,ppos,ipflag,hptr); strcpy((char*)rrec->ip[rrnum],(char*)hptr); rrnum++; ppos=nlen; } /*restore old values*/ _res.retrans=tmout; _res.retry=sretry; _res.nscount=nscount; _res.nsaddr_list[0]=sin; return(rrnum); } /*end lib_dns_query()*/ int lib_tcp_ping(char *ipaddr, int pwait, unsigned short port) /*uses TCP to determine if an IP is there or not*/ { int slen, st, sd, flags, ret=-1; struct sockaddr_in sin; struct pollfd polly; /*sanity checks*/ if (ipaddr==NULL) return(-1); slen=strlen(ipaddr); if (slen<8 || slen>15) return(-1); if (pwait<1) pwait=1; /*be reasonable*/ if (pwait>60000) pwait=60000; /*can't wait forever*/ if (port==0) port=6; /*we use the unassigned port 6 by default*/ if (inet_addr(ipaddr)==(in_addr_t)(-1)) return(-1); /*now for the setup*/ bzero((char *) &sin,sizeof(sin)); sin.sin_addr.s_addr=inet_addr(ipaddr); sin.sin_family=AF_INET; sin.sin_port=htons(port); if ((sd=socket(AF_INET,SOCK_STREAM,0))<0) return(-2); /*local failure*/ flags=fcntl(sd, F_GETFL,0); if (flags<0) { close(sd); return(-1); } if (fcntl(sd, F_SETFL, flags|O_NONBLOCK)<0) { close(sd); return(-1); } if ((st=connect(sd, (struct sockaddr*)&sin,sizeof(sin)))<0) { if (errno!=EINPROGRESS) { if (errno==ECONNREFUSED) ret=1; /*they is there*/ close(sd); return(ret); } } /*if still here either it worked, or is in progress*/ if (st==0) { close(sd); return(1); /*yep, they is there*/ } /*if still here, then its in progress*/ polly.fd=sd; polly.events=POLLIN; polly.revents=0; st=poll(&polly,1,pwait); close(sd); if (st<0) { if (errno==EINTR) return(-2); else return(-1); } if (st==0) return(0); /*hmmm, they ain't there or be too slow*/ if (polly.revents&(POLLIN|POLLERR)) return(1); /*they is there*/ return(-1); /*unknown error, fail it*/ } /*end of lib_tcp_ping()*/ /*************************************/ /* BEGIN TIME/DATE FUNCTIONS SECTION */ /*************************************/ char lib_gettime(int *hour, int *min, int *sec, char mil) /* get current time */ /* mil =0 if military time, 1 if civilian */ { struct tm *t; time_t clockt=time(NULL); char pm='a'; t=localtime(&clockt); if (min!=NULL) *min=t->tm_min; if (sec!=NULL) *sec=t->tm_sec; if (t->tm_hour >= 12) pm='p'; if (mil!=0) { if (t->tm_hour == 0) t->tm_hour=12; if (t->tm_hour > 12) t->tm_hour=t->tm_hour-12; } if (hour!=NULL) *hour=t->tm_hour; return(pm); } /*end lib_gettime()*/ char *lib_getdate(int *mon, int *day, int *year, char *dayofwk, char *month, int offset) /* get the current day and date (or a relative date)*/ { struct tm *t; time_t clockt=time(NULL); clockt=clockt+(86400*offset); t=localtime(&clockt); if (mon!=NULL) *mon=t->tm_mon+1; if (day!=NULL) *day=t->tm_mday; if (year!=NULL) *year=t->tm_year+1900; if (dayofwk!=NULL) switch (t->tm_wday) { case 0: strcpy(dayofwk,"Sunday"); break; case 1: strcpy(dayofwk,"Monday"); break; case 2: strcpy(dayofwk,"Tuesday"); break; case 3: strcpy(dayofwk,"Wednesday"); break; case 4: strcpy(dayofwk,"Thursday"); break; case 5: strcpy(dayofwk,"Friday"); break; case 6: strcpy(dayofwk,"Saturday"); break; default: dayofwk[0]=0; } if (month==NULL) return(dayofwk); switch (t->tm_mon+1) { case 1: strcpy(month,"January"); break; case 2: strcpy(month,"February"); break; case 3: strcpy(month,"March"); break; case 4: strcpy(month,"April"); break; case 5: strcpy(month,"May"); break; case 6: strcpy(month,"June"); break; case 7: strcpy(month,"July"); break; case 8: strcpy(month,"August"); break; case 9: strcpy(month,"September"); break; case 10: strcpy(month,"October"); break; case 11: strcpy(month,"November"); break; case 12: strcpy(month,"December"); break; default: strcpy(month,""); } return(dayofwk); } /*end lib_getdate()*/ char *lib_timestamp(char *title, char *buffer) /*return a formated string with current date and a message*/ { time_t clk; char tbuff[48]; if (title==NULL || buffer==NULL) return(NULL); clk=time(NULL); strcpy(tbuff,ctime(&clk)); tbuff[strlen(tbuff)-1]=0; sprintf(buffer,"%s: %s[%d]: ",tbuff,title, (int)getpid()); return(buffer); } /*end lib_timestamp()*/ char *lib_value_to_month(int mon, char *month, char shsized) /*convert a month value to a text proper name*/ { char monstr[12]; if (month==NULL) return(NULL); switch (mon) { case 1: strcpy(monstr,"January"); break; case 2: strcpy(monstr,"February"); break; case 3: strcpy(monstr,"March"); break; case 4: strcpy(monstr,"April"); break; case 5: strcpy(monstr,"May"); break; case 6: strcpy(monstr,"June"); break; case 7: strcpy(monstr,"July"); break; case 8: strcpy(monstr,"August"); break; case 9: strcpy(monstr,"September"); break; case 10: strcpy(monstr,"October"); break; case 11: strcpy(monstr,"November"); break; case 12: strcpy(monstr,"December"); break; default: return(NULL); } if (shsized) monstr[3]='\0'; month[0]='\0'; strcpy(month,monstr); return(month); } /*end lib_value_to_month()*/ int lib_month_to_value(char *mo) /*validate a given month and return its value*/ { if (mo==NULL) return(-1); if ((strcasecmp(mo,"Jan")==0) || (strcasecmp(mo,"January")==0)) return(1); if ((strcasecmp(mo,"Feb")==0) || (strcasecmp(mo,"February")==0)) return(2); if ((strcasecmp(mo,"Mar")==0) || (strcasecmp(mo,"March")==0)) return(3); if ((strcasecmp(mo,"Apr")==0) || (strcasecmp(mo,"April")==0)) return(4); if ((strcasecmp(mo,"May")==0) || (strcasecmp(mo,"May")==0)) return(5); if ((strcasecmp(mo,"Jun")==0) || (strcasecmp(mo,"June")==0)) return(6); if ((strcasecmp(mo,"Jul")==0) || (strcasecmp(mo,"July")==0)) return(7); if ((strcasecmp(mo,"Aug")==0) || (strcasecmp(mo,"August")==0)) return(8); if ((strcasecmp(mo,"Sep")==0) || (strcasecmp(mo,"September")==0)) return(9); if ((strcasecmp(mo,"Oct")==0) || (strcasecmp(mo,"October")==0)) return(10); if ((strcasecmp(mo,"Nov")==0) || (strcasecmp(mo,"November")==0)) return(11); if ((strcasecmp(mo,"Dec")==0) || (strcasecmp(mo,"December")==0)) return(12); return(-1); } /*end lib_month_to_value()*/ char *lib_value_to_dayofwk(int day, char *dayofwk, char shsized) /*convert a day of the week value to a text proper name*/ { char dstr[12]; if (dayofwk==NULL) return(NULL); if (day==1) strcpy(dstr,"Sunday"); else if (day==2) strcpy(dstr,"Monday"); else if (day==3) strcpy(dstr,"Tuesday"); else if (day==4) strcpy(dstr,"Wednesday"); else if (day==5) strcpy(dstr,"Thursday"); else if (day==6) strcpy(dstr,"Friday"); else if (day==7) strcpy(dstr,"Saturday"); else return(NULL); if (shsized) dstr[3]='\0'; dayofwk[0]='\0'; strcpy(dayofwk,dstr); return(dayofwk); } /*end lib_value_to_dayofwk()*/ int lib_dayofwk_to_value(char *day) /*validate a given day of the week and return its value*/ { if (day==NULL) return(-1); if ((strcasecmp(day,"Sun")==0) || (strcasecmp(day,"Sunday")==0)) return(1); if ((strcasecmp(day,"Mon")==0) || (strcasecmp(day,"Monday")==0)) return(2); if ((strcasecmp(day,"Tue")==0) || (strcasecmp(day,"Tuesday")==0)) return(3); if ((strcasecmp(day,"Wed")==0) || (strcasecmp(day,"Wednesday")==0)) return(4); if ((strcasecmp(day,"Thu")==0) || (strcasecmp(day,"Thursday")==0)) return(5); if ((strcasecmp(day,"Fri")==0) || (strcasecmp(day,"Friday")==0)) return(6); if ((strcasecmp(day,"Sat")==0) || (strcasecmp(day,"Saturday")==0)) return(7); return(-1); } /*end lib_dayofwk_to_value()*/ long lib_days_from_epoch(int year, int month, int dayofmonth) /*calculate number of days for a date from the epoch*/ { struct tm timeptr; time_t t; /*sanity checks*/ if (month<1 || month>12) return(-1); if (year<70 || year>2037) return(-1); /*head 'em off at the pass!*/ if (year>137 && year <1970) return(-1); /*the other pass!*/ if (dayofmonth<1 || dayofmonth>31) return(-1); if (year>1900) year=year-1900; timeptr.tm_sec=0; timeptr.tm_min=0; timeptr.tm_hour=0; timeptr.tm_mday=dayofmonth; timeptr.tm_mon=month-1; /*months in range of 0-11, not 1-12*/ timeptr.tm_year=year; timeptr.tm_wday=0; timeptr.tm_yday=0; timeptr.tm_isdst=-1; t=mktime(&timeptr); t=(time_t)(t/(24*3600)); return(t); } /*end lib_days_from_epoch()*/ unsigned int lib_seconds2units(unsigned int s, int *w, int *d, int *h, int *m) /*convert seconds to days ane/or hours, etc, return remaining seconds*/ { unsigned int sec, rem=0; sec=s; if (w!=NULL) { /*include weeks in stats*/ rem=sec%604800; if (rem!=sec) *w=sec/604800; else *w=0; /*secs < 1 week*/ sec=rem; } if (d!=NULL) { /*include days in stats*/ rem=sec%86400; if (rem!=sec) *d=sec/86400; else *d=0; /*secs < 1 day*/ sec=rem; } if (h!=NULL) { /*include hours in stats*/ rem=sec%3600; if (rem!=sec) *h=sec/3600; else *h=0; /*secs < 1 hour*/ sec=rem; } if (m!=NULL) { /*include minutes in stats*/ rem=sec%60; if (rem!=sec) *m=sec/60; else *m=0; sec=rem; } return(sec); } /*end lib_seconds2units()*/ char *lib_print_datetime(char *buff) /*return date and time string*/ { time_t clk; static char buf[48]; char *tbuff; clk=time(NULL); if (buff==NULL) tbuff=buf; else tbuff=buff; strcpy(tbuff,ctime(&clk)); tbuff[strlen(tbuff)-1]='\0'; /*nuke the newline*/ return(tbuff); } /*end lib_print_datetime()*/ /****************************************/ /* BEGIN MISC/PROCESS FUNCTIONS SECTION */ /****************************************/ void lib_die(int exitval, char *diestr, ...) /*print a message and exit*/ { va_list ap; if (diestr==NULL) exit(exitval); va_start(ap,diestr); vfprintf(stderr,diestr,ap); va_end(ap); fprintf(stderr,"\n"); exit(exitval); } /*end lib_die()*/ int lib_exitstat(int pid) /*get exit status of a child process*/ { int stat; if (pid < 2) pid=-1; waitpid(pid, &stat,0); if (WIFEXITED(stat)==0) return(-1); return(WEXITSTATUS(stat)); } /*end lib_exitstat()*/ void lib_do_nothing(int nothing) /* Do nothing function */ { return; } /*end lib_do_nothing()*/ int lib_timer(int start) /* stop watch function, get elapsed time in centi-seconds*/ /*note: the wrap fix may be broken on some 64bit systems*/ { struct tms buff; long t, c, ret; t=times(&buff); /*time measured in clock-ticks*/ if (start==0) return(t); /*value _t_ is relative if _start_ is 0*/ c=sysconf(_SC_CLK_TCK); if (start>t) /*wrap occurred*/ ret=2147483647-start+t; /*wrap occurred*/ else ret=t-start; ret=ret*(100.0/(float)c); /*float for best accuracy*/ return(ret); } /*end lib_timer()*/ int lib_checkpid(int pid) /*check the validity of a process ID*/ { int st; st=kill(pid,0); /*signal 0 does nothing*/ if (st==0) return(1); if (errno==EPERM && st==-1) return(0); else if (errno==ESRCH) return(-1); return(-2); } /*end lib_checkpid()*/ int lib_daemonize(int exitval) /*daemonize a process and make its parent exit*/ { switch (fork()) { case -1: return(-1); /*error*/ case 0: break; /*child*/ default: exit(exitval); /*parent*/ } setsid(); /* become session leader */ /* chdir("/"); */ /*close initial I/O's, redirect from /dev/null?*/ fclose(stdin); fclose(stdout); fclose(stderr); return((int)getpid()); } /*end lib_daemonize()*/ int lib_read_pidfile(char *path) /*read pid from a pidfile*/ { FILE *fp; char data[64]; int x, len; /*sanity checks*/ if (path==NULL) return(-1); if (strlen(path)==0) return(-1); if ((fp=fopen(path,"r"))==NULL) return(-1); if (fgets(data,12,fp)==NULL) { fclose(fp); return(-1); } data[11]='\0'; len=strlen(data); for (x=0;x'9') { data[x]='\0'; break; } } fclose(fp); x=atoi(data); /*re-using x */ if (x<1) return(-1); return(x); } /*end lib_read_pidfile()*/ int lib_makepidfile(char *path, char overwr) /*create pid file*/ { int fd, crw, st; char pidstr[16]; /*sanity checks*/ if (path==NULL || overwr<0) return(-1); if (strlen(path)==0) return(-1); /*open and/or create pid file*/ if (overwr!=0) { /*ignore any existing pid file*/ fd=open(path,O_RDWR | O_TRUNC | O_CREAT,0644); if (fd<0) return(-1); } else { fd=open(path,O_RDWR | O_CREAT | O_TRUNC | O_EXCL,0644); if (fd<0) { if (errno==EEXIST) return(-2); else return(-1); /*unknown error*/ } } /*write out the new pid*/ crw=sprintf(pidstr,"%ld\n",(long)getpid()); st=write(fd,pidstr,crw); if (st<0) { /*write failed, bail out!*/ unlink(path); close(fd); return(-1); } close(fd); return(1); } /*end lib_makepidfile()*/ int lib_free(void *ptr) /*safety free() w/ variable clearance*/ { void **rptr; if (ptr==NULL) return(-1); rptr=(void**)ptr; if (*rptr==NULL) return(0); free(*rptr); /*sigh, free() doesn't return a value*/ *rptr=NULL; /*reset variable to reflect*/ return(1); } /*end lib_free() */ int lib_freeall(void *ptr, ...) /*multiple free() calls in one for ordinal/simple data types*/ { void **rptr; va_list ap; if (ptr==NULL) return(0); rptr=(void**)ptr; if (*rptr!=NULL) free(*rptr); *rptr=NULL; va_start(ap,ptr); for (;;) { rptr=va_arg(ap,void*); if (rptr==NULL) break; if (*rptr!=NULL) { free(*rptr); *rptr=NULL; } } va_end(ap); return(0); } /*end of lib_freeall() */ /********************************/ /* BEGIN MATH FUNCTIONS SECTION */ /********************************/ double lib_random_float(long mix) /* returns a random number without having to provide a seed*/ { struct tms buffer; srand48(mix^(times(&buffer)-time(0)+lrand48())); srand48(lrand48()); return(drand48()); } /*end lib_random_float()*/ unsigned char lib_random_byte(long mix) /*returns a random number in the range 0 - 255 */ { unsigned char t; struct tms buffer; srand48(mix ^ (times(&buffer)-time(0)+lrand48())); t=(unsigned char)(lrand48()>>16)&255; return(t); } /*end lib_random_byte()*/ long lib_random_long(long mix) /*return a random 32 big signed value*/ { struct tms buffer; srand48(mix ^ (times(&buffer)-time(0)+lrand48())); srand48(lrand48()); return(lrand48()); } /*end lib_random_long()*/ long lib_pwr(int x, int y) /*integer version of pow()*/ { long z=1; short t; if (y==0) return(1); if (x==0 || y<0) return(0); for (t=0;t '7' || in[x] < '0') return(-1); else t=(t*8) + in[x++]-48; } if (t > 32767) return(-1); return(t); } /*end lib_octaltodec()*/ int lib_dectoctal(int x) /*convert a decimal back to octal coded decimal*/ /*up to 5 digits*/ { int u=0; if (x==0) return(0); if (x>4095 || x<0) return(-1); u=(((x&28672)/4096)*10000)+ (((x&3584)/512)*1000)+(((x&448)/64)*100)+ (((x&56)/8)*10)+(x&7); return(u); } /*end lib_dectoctal()*/ char *lib_delimitint(int val, char *string) /*take an integer and produce a comma delimited value*/ /*_string_ should be at least 16 bytes*/ { char tmp[32]; int len,x, cc, pos; if (string==NULL) return(NULL); sprintf(tmp,"%d",val); len=strlen(tmp); cc=len/3; /*cc is comma count*/ string[cc+len]='\0'; /*nul terminate*/ pos=cc+len-1; for (cc=0,x=len-1;x>=0;x--) { string[pos]=tmp[x]; pos--; cc++; if (cc==3) { string[pos]=','; cc=0; pos--; } } return(string); } /*end lib_delimitint()*/ long lib_round(double x, double *f) /*round off the x putting leftover fraction in f*/ { double y; long z; if (x>=2147483647.0) return(-1); /*too big - 31 bits only*/ if (x < 0.0) return(-1); /*we only work with positives*/ y=x-(double)((long)x); /*strip off int part*/ z=(long)x; /*bye bye fraction*/ if (y>=0.5) z++; /*round up*/ if (f!=NULL) *f=y; /*return fraction if requested*/ return(z); } /*end lib_round()*/ int lib_setbit(unsigned int *bits, char which, unsigned char what) /*set or clear a particular bit*/ { unsigned int t=1; if (bits==NULL) return(-1); if (which>31 || which<0) return(-1); if (what) { /*if _what_ is 1 */ t=t<31 || which <0) return(-1); t=(bits>>which)&1; return((int)t); } /*end lib_getbit()*/ unsigned int lib_nextpowerof2(unsigned int val) /*returns the next power of two larger than or equal to _val_*/ { int x=0; unsigned int wval; /*quick cases*/ if (val==0) return(0); if (val==1) return(2); wval=val; while (wval>1) { /*nuke the crufty bits*/ wval=wval>>1; x++; } wval=1; wval=wval<wval) wval=wval<<1; /*up 1 bit to next level*/ return(wval); } /*end of lib_nextpowerof2()*/ int lib_prime(unsigned long x) /*determine primeness of a number*/ { unsigned long f, sqd; /*sanity checks*/ if (x<1) return(-1); if (x<=3) return(1); if (!(x&1)) return(0); /*even number*/ sqd=(unsigned long)(sqrt((double)x)) + 1; for (f=3;f<=sqd;f+=2) if ((x%f)==0) return(0); return(1); /*if still here, then prime*/ } /*end lib_prime() */ unsigned long lib_nextprime(unsigned long x) /*determine the next prime number from some value, 0 returned on err*/ { unsigned long f, sqd; char stop=0; /*sanity/quick checks*/ if (x<=3) return(x); /*1,2, & 3 are all odd*/ if (!(x&1)) x++; /*make it an odd number*/ for (;;) { /*loop until we find a prime number*/ sqd=(unsigned long)(sqrt((double)x)) + 1; for (f=3;f<=sqd;f+=2) if ((x%f)==0) { /*not prime, next!*/ stop=TRUE; break; } if (stop==FALSE) return(x); /*we got a prime!*/ x+=2; /*not prime, goto the next odd number*/ if (x<1) return(0); /*if wrapped, return an error*/ stop=FALSE; /*reset for the next loop*/ } /*NEXT!*/ return(0); /*dummy return*/ } /*end lib_nextprime() */ /********************************/ /* BEGIN HASH FUNCTIONS SECTION */ /********************************/ struct hashtable *lib_create_hashtable(int tablesize, int hash) /*creates an empty hash table */ /*returns a pointer to the hash table or NULL on error*/ { int x,hsize; struct hashtable *table; /*a small sanity check*/ if (tablesize < 1) return(NULL); /*malloc space for the table core structure*/ table=(struct hashtable*)malloc(sizeof(struct hashtable)); if (table==NULL) return(NULL); table->array=NULL; /*malloc space for _tablesize_ table elements*/ hsize=tablesize*sizeof(void*); table->array=(void*)malloc(hsize); /*if there is a problem bail out*/ if (table->array == NULL) { free(table); return(NULL); } /*else initialize the elements to NULL*/ for (x=0;xarray[x]=NULL; /*initialize the rest*/ table->hashsize=tablesize; table->count=0; table->first=table->last=NULL; table->bcollisions=table->usedbuckets=0; if (hash<=1) table->hashfunc=1; else if (hash>=HFUNC) table->hashfunc=HFUNC; else table->hashfunc=hash; /*everything is ready, return a pointer to our table*/ return(table); } /*end lib_create_hashtable()*/ int lib_delete_hashtable(struct hashtable *table) /*deletes a hash table and everything in it */ /*returns 1 on success, -1 on failure*/ { Hashentry *nextptr, *delptr; /*check for sane values in table*/ if (table==NULL) return(-1); if (table->count<0) return(-1); /*first we have to find all elements, if any, and free them*/ if (table->count > 0) { /*must free elements*/ delptr=table->first; while (delptr!=NULL) { nextptr=delptr->listn; if (delptr->data!=NULL) free(delptr->data); free(delptr->key); free(delptr); delptr=nextptr; } } /*now free up the core*/ free(table->array); free(table); return(1); } /*end lib_delete_hashtable()*/ int lib_clear_hashtable(struct hashtable *table) /*deletes a hash table's contents, leaves table intact*/ /*returns, number of deleted items or -1 if an error occurs*/ { Hashentry *nextptr, *delptr; int x, dc=0; /*check for sane values in table*/ if (table==NULL) return(-1); if (table->count<0) return(-1); if (table->count==0) return(0); /*first we have to find all elements, if any, and free them*/ delptr=table->first; while (delptr!=NULL) { nextptr=delptr->listn; if (delptr->data!=NULL) free(delptr->data); free(delptr->key); free(delptr); delptr=nextptr; dc++; } /*reset everything*/ for (x=0;xhashsize;x++) table->array[x]=NULL; table->bcollisions=0; table->count=0; table->usedbuckets=0; table->first=NULL; table->last=NULL; return(dc); /*return number of deleted items*/ } /*end of lib_clear_hashtable()*/ int lib_add_hashrecord(struct hashtable *table, char *key, void *data, int dsize, int type) /*adds an entry to a hash table */ /*returns 1 on success, 0 if already exists, -1 on error*/ { int hashvalue,bc; Hashentry *newptr, *tmp=NULL, *tmp2=NULL; /*some sanity checks*/ if (dsize<0 || table==NULL) return(-1); if (table->hashsize < 1 || table->count < 0 ) return(-1); if (data==NULL && dsize>0) return(-1); if (key==NULL) return(-1); /*first calculate the hashvalue*/ hashvalue=N_hashfunction(key, table->hashsize,table->hashfunc); bc=table->bcollisions; /*next find location for new record*/ if ((tmp=table->array[hashvalue])!=NULL) while (tmp!=NULL) { if (strcmp(key,tmp->key)==0) return(0); /*key exists*/ tmp2=tmp; tmp=tmp->next; bc++; } /*allocate space for the new record and initialize*/ newptr=(Hashentry*)malloc(sizeof(Hashentry)); if (newptr==NULL) return(-1); if (dsize>0) { newptr->data=(void*)malloc(dsize); if (newptr->data==NULL) { free(newptr); return(-1); } bcopy(data,newptr->data,dsize); } else newptr->data=data; /*just store the pointer*/ newptr->datasize=dsize; /*should be 0 for a pointer only*/ newptr->type=type; /*user defined value*/ if ((newptr->key=strdup(key))==NULL) { if (dsize>0) free(newptr->data); free(newptr); return(-1); } /*add to the bucket chain - at the front*/ newptr->prev=NULL; tmp2=table->array[hashvalue]; if (tmp2==NULL) { table->usedbuckets++; newptr->next=NULL; } else { tmp2->prev=newptr; newptr->next=tmp2; } table->array[hashvalue]=newptr; /*update linear list and table structure, return*/ newptr->listn=NULL; newptr->listp=table->last; if ((tmp=newptr->listp)!=NULL) tmp->listn=newptr; table->last=newptr; if (table->first==NULL) table->first=table->last; table->count++; table->bcollisions=bc; return(1); } /*end lib_add_hashrecord() */ int lib_edit_hashrecord(struct hashtable *table, char *key, void *data, int dsize, int type) /*replaces an entry in the hash table */ /*returns 1 for success, 0 for not found, -1 on error*/ { int hashvalue; Hashentry *ptr; void *tptr; /*some sanity checks*/ if (dsize<0 || table==NULL) return(-1); if (table->hashsize < 1 || table->count < 0 ) return(-1); if (data==NULL && dsize>0) return(-1); if (key==NULL) return(-1); /*first calculate the hashvalue*/ hashvalue=N_hashfunction(key,table->hashsize,table->hashfunc); /*next find the wanted record*/ ptr=table->array[hashvalue]; while (ptr!=NULL) { if (strcmp(key,ptr->key)==0) { if (ptr->datasize==0) { /*previously pointer only*/ ptr->type=type; if (dsize==0) { /*new is ptr too - replace*/ ptr->data=data; return(1); /*weesa done!*/ } /*else not ptr - allocate*/ tptr=malloc(dsize); if (tptr==NULL) return(-1); ptr->data=tptr; bcopy(data,ptr->data,dsize); ptr->datasize=dsize; return(1); /*our work is done*/ } /*if here, then previous data wasn't just ptr*/ if (dsize==0) { /*new data is ptr*/ if (ptr->data!=NULL) free(ptr->data); ptr->data=data; ptr->datasize=0; ptr->type=type; return(1); } /*neither ptr->data nor data are just pointers*/ if ((ptr->data=realloc(ptr->data,dsize))==NULL) return(-1); /*couldn't get the memory*/ bcopy(data,ptr->data,dsize); ptr->datasize=dsize; ptr->type=type; return(1); /*our work is done*/ } else ptr=ptr->next; } /*not found*/ return(0); } /*end lib_edit_hashrecord()*/ int lib_get_hashrecord(struct hashtable *table, char *key, void **d, int *dsize, int *type) /*retrieves an entry from the hash table */ /*returns 1 if present, 0 if not, -1 if an error, record put in _d_*/ { int hashvalue; Hashentry *ptr=NULL; /*some sanity checks*/ if (table==NULL) return(-1); if (table->hashsize < 1 || table->count < 0 ) return(-1); if (key==NULL) return(-1); /*find hashvalue*/ hashvalue=N_hashfunction(key,table->hashsize,table->hashfunc); /*find the record and return*/ ptr=table->array[hashvalue]; while (ptr!=NULL) { if (strcmp(ptr->key,key)==0) { if (dsize!=NULL) *dsize=ptr->datasize; if (d!=NULL) *d=(void*)ptr->data; if (type!=NULL) *type=ptr->type; return(1); } ptr=ptr->next; } return(0); } /*end lib_get_hashrecord()*/ int lib_delete_hashrecord(struct hashtable *table, char *key) /*deletes an entry from the hash table */ /*returns -1 on error, 0 if not found, 1 if successful*/ { int hashvalue; Hashentry *prev, *next, *tmp, *tmp2; /*some sanity checks*/ if (table==NULL) return(-1); if (table->hashsize < 1 || table->count < 0 ) return(-1); if (key==NULL) return(-1); /*find hashvalue*/ hashvalue=N_hashfunction(key,table->hashsize,table->hashfunc); /*find and delete the record*/ tmp=table->array[hashvalue]; while (tmp!=NULL) { if (strcmp(tmp->key,key)==0) { /*delete it*/ if (tmp==table->array[hashvalue]) { table->array[hashvalue]=tmp->next; if (table->array[hashvalue]==NULL) table->usedbuckets--; } next=tmp->next; prev=tmp->prev; if (prev!=NULL) prev->next=next; if (next!=NULL) next->prev=prev; if (tmp->data!=NULL) free(tmp->data); free(tmp->key); /*update linear list and table count*/ if (table->first==tmp) table->first=tmp->listn; if (table->last==tmp) table->last=tmp->listp; if (tmp->listn!=NULL) { tmp2=tmp->listn; tmp2->listp=tmp->listp; } if (tmp->listp!=NULL) { tmp2=tmp->listp; tmp2->listn=tmp->listn; } table->count--; /*free tmp and return*/ free(tmp); return(1); /*done*/ } else tmp=tmp->next; /*go try the next one*/ } /*if still here then not found, return emtpy*/ return(0); /*we should probably try to update collisions, but we don't - TODO*/ } /*end lib_delete_hashrecord()*/ int lib_get_hashcount(struct hashtable *table, int *bcoll, int *used, int *bucks, int *alg) /*returns the number of entries currently in the hash table */ /*return number of recs in hashtable, else -1 on error*/ { /*some sanity checks*/ if (table==NULL) return(-1); if (table->hashsize < 1 || table->count < 0 ) return(-1); /*okay, looks good, return the count*/ if (bcoll!=NULL) *bcoll=table->bcollisions; if (used!=NULL) *used=table->usedbuckets; if (alg!=NULL) *alg=(int)table->hashfunc; if (bucks!=NULL) *bucks=table->hashsize; return(table->count); } /*end lib_get_hashcount()*/ int lib_get_bucketcount(struct hashtable *table, char *key, int *loc) /*Return the number of entries in a single hash bucket*/ { int where, count=0; struct hashentry *ptr; /*sanity checks*/ if (table==NULL || key==NULL) return(-1); if (table->hashsize < 1 || table->count < 0 ) return(-1); if (strlen(key)==0) return(-1); /*find the array position and walk the walk*/ if (loc!=NULL) *loc=-1; where=N_hashfunction(key,table->hashsize,table->hashfunc); ptr=table->array[where]; while (ptr!=NULL) { if (loc!=NULL) if (strcmp(ptr->key,key)==0) *loc=count; count++; ptr=ptr->next; } return(count); } /*end lib_get_bucketcount()*/ int lib_get_hashvalue(struct hashtable *table, char *key) /*DEBUG: return the hashvalue for a given key*/ { if (table==NULL || key==NULL) return(-1); if (strlen(key)==0) return(-1); return(N_hashfunction(key, table->hashsize,table->hashfunc)); } /*end lib_get_hashvalue()*/ int lib_get_hashlinear_ptrs(struct hashtable *table, void **first, void **last) /*get first and last record pointers in a hash table */ { if (table==NULL) return(-1); if (table->count<0) return(-1); if (first!=NULL) *first=table->first; if (last!=NULL) *last=table->last; if (table->count==0) return(0); return(1); } /*end lib_get_hashlinear_ptrs()*/ void *lib_get_hashlinear_rec(void *which, void **prev, void **next, int *dsize, char **key, int *type) /*return hashed data from a pointer to a hash record */ { Hashentry *hashrec=which; if (which==NULL) return(NULL); if (next!=NULL) *next=hashrec->listn; if (prev!=NULL) *prev=hashrec->listp; if (dsize!=NULL) *dsize=hashrec->datasize; if (key!=NULL) *key=strdup(hashrec->key); if (type!=NULL) *type=hashrec->type; return(hashrec->data); } /*end lib_get_hashlinear_rec()*/ struct hashtable *lib_rehashtable(struct hashtable *table, int tablesize, int func) /*builds and new and rehashed hash table from an existing hash table*/ { int x, hsize, hashvalue; struct hashtable *newtable; Hashentry *nextptr, *prevptr, *newptr, *tmp; /*sanity check*/ if (tablesize<0 || table==NULL) return(NULL); if (table->count<0 || table->hashfunc<1) return(NULL); if (tablesize==0) tablesize=table->hashsize; /*allocate space for new table and initialize it*/ newtable=(struct hashtable*)malloc(sizeof(struct hashtable)); if (newtable==NULL) return(NULL); newtable->array=NULL; /*malloc space for _tablesize_ table elements*/ hsize=tablesize*sizeof(void*); newtable->array=(void*)malloc(hsize); /*if there is a problem bail out*/ if (newtable->array==NULL) { free(newtable); return(NULL); } hsize=sizeof(Hashentry); /*initialize new table*/ for (x=0;xarray[x]=NULL; /*initialize the rest*/ newtable->hashsize=tablesize; newtable->count=0; newtable->first=newtable->last=NULL; newtable->bcollisions=newtable->usedbuckets=0; if (func==0) newtable->hashfunc=table->hashfunc; else if (func<0) newtable->hashfunc=1; else if (func>=HFUNC) newtable->hashfunc=HFUNC; else newtable->hashfunc=func; if (table->count==0) return(newtable); /*nothing to do*/ /*go through old table and rehash it's elements into the new one*/ for (prevptr=table->first;prevptr!=NULL;prevptr=prevptr->listn) { /*calculate new hash value*/ hashvalue=N_hashfunction(prevptr->key,tablesize,newtable->hashfunc); /*allocate new hashentry structure*/ newptr=(Hashentry*)malloc(hsize); if (newptr==NULL) { /*crap, back up out of here!*/ /*clean up what we've made so far*/ error: for (prevptr=newtable->first;prevptr!=NULL;prevptr=nextptr) { nextptr=prevptr->listn; if (prevptr->data!=NULL) free(prevptr->data); free(prevptr->key); free(prevptr); } free(newtable->array); free(newtable); return(NULL); } /*allocate and set new data pointers or clean up on errors*/ if (prevptr->datasize>0) { newptr->data=(void*)malloc(prevptr->datasize); if (newptr->data==NULL) { /*crap, back up out of here*/ free(newptr); goto error; /*the evil goto makes this short*/ } bcopy(prevptr->data,newptr->data,prevptr->datasize); } else newptr->data=NULL; newptr->datasize=prevptr->datasize; newptr->type=prevptr->type; newptr->key=strdup(prevptr->key); if (newptr->key==NULL) { /*crap, back up out of here!*/ if (newptr->data!=NULL) free(newptr->data); free(newptr); goto error; /*no reason to duplicate code*/ } /*insert new entry into new table and set pointers*/ if ((tmp=newtable->array[hashvalue])==NULL) { newtable->usedbuckets++; newptr->prev=NULL; newtable->array[hashvalue]=newptr; } else { newtable->bcollisions++; while (tmp->next!=NULL) { newtable->bcollisions++; tmp=tmp->next; } tmp->next=newptr; newptr->prev=tmp; } newptr->next=NULL; /*update linear list & table count*/ newptr->listn=NULL; newptr->listp=newtable->last; if ((tmp=newptr->listp)!=NULL) tmp->listn=newptr; newtable->last=newptr; if (newtable->first==NULL) newtable->first=newtable->last; newtable->count++; } /*next item in linear linked list of old table*/ /*should be all done, return pointer to the new table*/ return(newtable); } /*end lib_rehashtable()*/ int lib_reposition_item(struct hashtable *table, char *key, int se) /*Reposition within the hash bucket, negative at back, else front*/ { int where; struct hashentry *cptr, *sent, *lent, *tptr; /*sanity checks*/ if (table==NULL || key==NULL) return(-1); if (table->hashsize < 1 || table->count < 0 ) return(-1); if (strlen(key)==0) return(-1); /*find the array position and walk the walk*/ where=N_hashfunction(key,table->hashsize,table->hashfunc); cptr=table->array[where]; sent=cptr; while (cptr->next!=NULL) cptr=cptr->next; lent=cptr; /*at the end*/ cptr=sent; /*reset to beginning*/ while (cptr!=NULL) { if (strcmp(cptr->key,key)==0) { /*found him*/ if (cptr==lent && cptr==sent) return(1); /*only item*/ if (se<0 && cptr==lent) return(1); /*already there*/ if (se>=0 && cptr==sent) return(1); /*already there*/ if (se<0) { /*put at end*/ lent->next=cptr; tptr=cptr->next; tptr->prev=cptr->prev; tptr=cptr->prev; if (tptr==NULL) /*move from beginning*/ table->array[where]=cptr->next; else tptr->next=cptr->next; cptr->next=NULL; cptr->prev=lent; } else { /*put at front*/ sent->prev=cptr; table->array[where]=cptr; tptr=cptr->prev; tptr->next=cptr->next; tptr=cptr->next; if (tptr!=NULL) tptr->prev=cptr->prev; cptr->next=sent; cptr->prev=NULL; } return(1); /*done*/ } cptr=cptr->next; } return(0); /*if we get here, wasn't found*/ } /*end lib_reposition_item()*/ int lib_rekey_hashitem(struct hashtable *table, char *key, char *newkey) /*change key for exisiting hash table item*/ { struct hashentry *cptr, *tptr=NULL, *lptr=NULL, *fptr=NULL; int hashvalue1, hashvalue2; char *tmpptr; /*sanity checks*/ if (table==NULL || key==NULL || newkey==NULL) return(-1); if (table->hashsize < 1 || table->count < 0) return(-1); if (strlen(key)==0 || strlen(newkey)==0) return(-1); if (strcmp(key,newkey)==0) return(0); /*calculate hashes*/ hashvalue1=N_hashfunction(key,table->hashsize,table->hashfunc); hashvalue2=N_hashfunction(newkey,table->hashsize,table->hashfunc); /*check to see if key exists*/ cptr=table->array[hashvalue1]; while (cptr!=NULL) { if (strcmp(cptr->key,key)==0) { fptr=cptr; break; } cptr=cptr->next; } if (fptr==NULL) return(-1); /*key doesn't exist*/ /*check to see if newkey already exists*/ cptr=table->array[hashvalue2]; while (cptr!=NULL) { /*cycle through new bucket to find newkey*/ if (strcmp(cptr->key,newkey)==0) return(-1); /*exists*/ if (cptr->next==NULL) lptr=cptr; /*at the end, record*/ cptr=cptr->next; } /*re-key*/ tmpptr=strdup(newkey); if (tmpptr==NULL) return(-1); /*out of memory*/ free(fptr->key); fptr->key=tmpptr; /*check if in same bucket*/ if (hashvalue1==hashvalue2) return(1); /*same bucket, we're done!*/ /*remove from old spot*/ tptr=fptr->next; if (tptr!=NULL) tptr->prev=fptr->prev; tptr=fptr->prev; if (tptr!=NULL) tptr->next=fptr->next; else table->array[hashvalue1]=fptr->next; /*was at front*/ /*put in new bucket*/ if (lptr==NULL) { /*empty bucket*/ table->array[hashvalue2]=fptr; fptr->prev=NULL; fptr->next=NULL; } else { /*append at end*/ lptr->next=fptr; fptr->prev=lptr; fptr->next=NULL; } return(1); /*done*/ } /*end lib_rekey_hashitem() */ int lib_move_hashrecord(struct hashtable *stable, struct hashtable *dtable, char *key) /*moves an entry from one hash table to another*/ /*returns 1 on success, 0 if already exists, -1 on error*/ { int hashvals,bc, hashvald, bcc=0; Hashentry *stmp=NULL, *dtmp=NULL, *dtmp2=NULL, *match; /*some sanity checks*/ if (dtable==NULL || stable==NULL) return(-1); if (stable->hashsize < 1 || stable->count < 0 ) return(-1); if (dtable->hashsize < 1 || dtable->count < 0 ) return(-1); if (key==NULL) return(-1); if (dtable==stable) return(0); /*nice try*/ /*first calculate the hashvalue*/ hashvals=N_hashfunction(key, stable->hashsize,stable->hashfunc); hashvald=N_hashfunction(key, dtable->hashsize,dtable->hashfunc); bc=dtable->bcollisions; /*first, find in source table*/ if ((stmp=stable->array[hashvals])==NULL) return(-1); /*bad key*/ while (stmp!=NULL) { if (strcmp(key,stmp->key)==0) break; stmp=stmp->next; } if (stmp==NULL) return(-1); /*not found*/ match=stmp; while (stmp!=NULL) { stmp=stmp->next; bcc++; } /*next find location for new record*/ if ((dtmp=dtable->array[hashvald])!=NULL) while (dtmp!=NULL) { if (strcmp(key,dtmp->key)==0) return(0); /*key exists*/ dtmp2=dtmp; /*save previous*/ dtmp=dtmp->next; bc++; } /*remove match from the source table*/ stmp=match->prev; if (stmp==NULL) stable->array[hashvals]=match->next; /*1st item*/ else stmp->next=match->next; stmp=match->next; if (stmp!=NULL) stmp->prev=match->prev; match->prev=match->next=NULL; if (stable->first==match) stable->first=match->listn; if (stable->last==match) stable->last=match->listp; stmp=match->listn; if (stmp!=NULL) stmp->listp=match->listp; stmp=match->listp; if (stmp!=NULL) stmp->listn=match->listn; match->listn=match->listp=NULL; stable->bcollisions=-bcc; /*adjust collision count*/ stable->count--; if (stable->array[hashvals]==NULL) stable->usedbuckets--; /*now add to destination table - at the front of the bucket chain*/ dtmp2=dtable->array[hashvald]; if (dtmp2==NULL) { /*simple case*/ dtable->array[hashvald]=match; if (dtable->first==NULL) dtable->first=match; if (dtable->last==NULL) dtable->last=match; dtable->count++; dtable->usedbuckets++; return(1); } stmp=dtable->last; /*reusing stmp*/ stmp->listn=match; match->listp=stmp; dtable->last=match; dtable->bcollisions=bc; dtable->array[hashvald]=match; match->next=dtmp2; dtmp2->prev=match; dtable->count++; return(1); } /*end lib_move_hashrecord() */ int lib_freeall_hashtable(struct hashtable **ptr, ...) /*multiple destroy calls in one for hashtable data types*/ { struct hashtable **rptr, *aptr; Hashentry *he, *next; va_list ap; if (ptr==NULL) return(0); rptr=ptr; aptr=*rptr; if (aptr!=NULL) { if (aptr->array!=NULL) { he=aptr->first; while (he!=NULL) { next=he->listn; if (he->key!=NULL) free(he->key); if (he->datasize>0 && he->data!=NULL) free(he->data); free(he); he=next; } free(aptr->array); } free(aptr); *rptr=NULL; } va_start(ap,ptr); for (;;) { rptr=va_arg(ap,struct hashtable**); if (rptr==NULL) break; aptr=*rptr; if (aptr!=NULL) { if (aptr->array!=NULL) { he=aptr->first; while (he!=NULL) { /*free hashentry*/ next=he->listn; if (he->key!=NULL) free(he->key); if (he->datasize>0 && he->data!=NULL) free(he->data); free(he); /*free entry*/ he=next; } free(aptr->array); } free(aptr); /*free the hash array*/ *rptr=NULL; } } va_end(ap); return(0); } /*end of lib_freeall_hashtable()*/ int lib_dlist2hashtable(struct hashtable *table, struct dlist_type *dlist) /*store a dlist into hash table as keys (no data)*/ { int hashvalue, bc, x; Hashentry *newptr, *tmp=NULL, *tmp2=NULL; char *key, bflag=0; /*sanity checks*/ if (dlist==NULL || table==NULL) return(-1); if (dlist->maxlistsize<0 || dlist->size<0 || dlist->size>dlist->maxlistsize) return(-1); if (dlist->item==NULL) return(-1); if (table->hashsize < 1 || table->count < 0 ) return(-1); if (dlist->size==0) return(0); /*nothing to do*/ for (x=0;xsize;x++) { key=dlist->item[x]; /*first calculate the hashvalue*/ hashvalue=N_hashfunction(key,table->hashsize,table->hashfunc); bc=table->bcollisions; bflag=0; /*next find location for new record*/ if ((tmp=table->array[hashvalue])!=NULL) while (tmp!=NULL) { if (strcmp(key,tmp->key)==0) { /*exists!*/ bflag=1; break; } tmp2=tmp; tmp=tmp->next; bc++; } if (bflag) continue; /*allocate space for the new record and initialize*/ newptr=(Hashentry*)malloc(sizeof(Hashentry)); if (newptr==NULL) return(-1); /*out of memory*/ newptr->data=NULL; /*no data to store, just keys*/ newptr->datasize=0; newptr->type=0; if ((newptr->key=strdup(key))==NULL) { free(newptr); return(-1); } /*add to the bucket chain - at the front*/ newptr->prev=NULL; tmp2=table->array[hashvalue]; if (tmp2==NULL) { table->usedbuckets++; newptr->next=NULL; } else { tmp2->prev=newptr; newptr->next=tmp2; } table->array[hashvalue]=newptr; /*update linear list and table structure*/ newptr->listn=NULL; newptr->listp=table->last; if ((tmp=newptr->listp)!=NULL) tmp->listn=newptr; table->last=newptr; if (table->first==NULL) table->first=table->last; table->count++; table->bcollisions=bc; } return(table->count); } /*end of lib_dlist2hashtable()*/ /********************************/ /* BEGIN SCREEN FUNCTIONS SECTION */ /********************************/ void lib_sclear(int out) /*clear the screen*/ { char clr[10]= { 27, 91, 59, 72, 27, 91, 50, 74, 8, 0}; if (out>=0) write(out,clr,9); else { printf("%s",clr); fflush(stdout); } } /*end lib_sclear()*/ void lib_shome(int out) /*home the cursor*/ { char buf[13]={033,'[','5',';','1','H',033,'[','1',';','1','H',0}; if (out>=0) write(out,buf,12); else { printf("%s",buf); fflush(stdout); } } /*end lib_shome()*/ void lib_screen_reset(int out) /*restores terminal to sane settings*/ { char textmode[64]={ 27, 91, 72, 27, 91, 74, 15, 27, 91,109, 27, 91,109, 27, 62, 27, 91, 63, 51,108, 27, 91, 63, 52, 108, 27, 91, 63, 53,108, 27, 91, 63, 55,104, 27, 91, 63, 56,104, 27, 99, 13, 0}; if (out<0) out=fileno(stdout); write(out,textmode,43); return; } /*end lib_screen_reset()*/ void lib_beep(int out) { char buff[2]={7,0}; if (out<0) out=fileno(stdout); write(out,buff,1); return; } /*end lib_beep()*/ /****************************************/ /* BEGIN DYNAMIC LIST FUNCTIONS SECTION */ /****************************************/ struct dlist_type* lib_create_dlist(int size) /*allocate memory for malloc'd dlist structure*/ { struct dlist_type *dl; int x; /*sanity check*/ if (size<0) return(NULL); dl=(struct dlist_type*)malloc(sizeof(struct dlist_type)); if (dl==NULL) return(NULL); dl->size=0; dl->item=NULL; dl->maxlistsize=size; if (size==0) return(dl); dl->item=(char**)malloc(sizeof(char*)*size); if (dl->item==NULL) { free(dl); return(NULL); } for (x=0;xitem[x]=NULL; dl->gfactor=16; /*initial growth scale*/ return(dl); } /*end lib_create_dlist()*/ int lib_destroy_dlist(struct dlist_type *dl) /*frees all memory in a malloc'd dlist struct*/ { int x; /*sanity checks*/ if (dl==NULL) return(-1); if (dl->maxlistsize<0 || dl->size<0 || dl->size>dl->maxlistsize) return(-1); if (dl->item==NULL && dl->maxlistsize!=0) return(1); /*free items*/ if (dl->item!=NULL) { if (dl->size>0) { for (x=0;xsize;x++) if (dl->item[x]!=NULL) free(dl->item[x]); } free(dl->item); dl->item=NULL; } free(dl); dl=NULL; return(1); } /*end lib_destroy_dlist()*/ int lib_clear_dlist(struct dlist_type *dlist) /*frees memory used by list items and re-initalizes list structures*/ { int x; /*some sanity checks*/ if (dlist==NULL) return(-1); if (dlist->maxlistsize<1 || dlist->size<0 || dlist->size>dlist->maxlistsize) return(-1); if (dlist->item==NULL) return(-1); /*free any items and NULLify them*/ for (x=0;xsize;x++) { free(dlist->item[x]); dlist->item[x]=NULL; } /*set an empty state for the list*/ dlist->size=0; dlist->gfactor=16; /*reset scalar*/ return(1); } /*end lib_clear_dlist()*/ char *lib_dfsplit(char *s, struct dlist_type *dlist, char *strt, char *end, char inc) /*stores in dlist first element separated by a patterns start & end*/ { char *sptr, *lptr, *nptr, *new; int len; /*some sanity checks*/ if (dlist==NULL) return(NULL); if (dlist->size<0 || dlist->item==NULL) return(NULL); if (dlist->maxlistsize<1 || dlist->size>dlist->maxlistsize) return(NULL); if (s==NULL || strt==NULL || end==NULL) return(NULL); /*setup initial positions and pointers*/ if (strlen(strt)==0) sptr=s; /*ignore starting separtor*/ else if ((sptr=strstr(s,strt))==NULL) return(NULL); nptr=sptr+strlen(strt); if (inc==0) sptr=nptr; if (strlen(end)==0) lptr=&s[strlen(s)]; else { if ((lptr=strstr(nptr,end))==NULL) lptr=&s[strlen(s)]; else if (inc!=0) lptr=lptr+strlen(end); } /*now lets malloc and insert the string*/ len=(int)(lptr-sptr); if ((new=(char*)malloc(len+1))==NULL) return(NULL); strncpy(new,sptr,len); new[len]=0; if (dlist->size>=dlist->maxlistsize) /*out of room, grow dlist*/ if (N_grow_dlist(dlist,0)<0) { /*oops, outta memory, bail*/ free(new); return(NULL); } dlist->item[dlist->size]=new; dlist->size++; if (lptr==&s[strlen(s)]) return(lptr); else if (inc==0) lptr=lptr+strlen(end); return(lptr); } /*end lib_dfsplit()*/ int lib_dsplit(char *string, struct dlist_type *i, char *separator) /*dynamically splits up a string into parts separated by a pattern*/ { char *cptr,*lptr=string,*new=NULL; int len,slen=strlen(separator); /* a quick check to see if we can be lazy*/ if (string==NULL || separator==NULL) return(-1); if ((len=strlen(string))==0) return(0); /*sanity checks*/ if (i==NULL) return(-1); if (i->item==NULL) return(-1); if (i->size<0 || i->maxlistsize<1 || i->size>i->maxlistsize) return(-1); /*now down to business*/ if ((cptr=strstr(string,separator))==NULL) { /*hmm, not found*/ if ((new=(char*)malloc(len+1))==NULL) return(-1); if (i->size>=i->maxlistsize) /*no room, grow dlist*/ if (N_grow_dlist(i,0)<0) { /*oops, outta memory*/ free(new); return(-1); } i->item[i->size]=new; strncpy(new,string,len); new[len]=0; i->item[i->size]=new; i->size++; return(i->size); } /*okay, we got at least one instance of it*/ while (cptr!=NULL) { /*process this current instance*/ len=(int)(cptr-lptr); /*how long is this one?*/ /*copy it into list*/ if ((new=(char*)malloc(len+1))==NULL) return(-1); strncpy(new,lptr,len); new[len]=0; if (i->size>=i->maxlistsize) /*no room, grow dlist*/ if (N_grow_dlist(i,0)<0) { /*oops, outta memory*/ free(new); return(-1); } i->item[i->size++]=new; /*update position pointers*/ lptr=cptr+slen; cptr=strstr(lptr,separator); } if (i->size>=i->maxlistsize) /*no room, grow dlist*/ if (N_grow_dlist(i,0)<0) { /*oops, outta memory*/ free(new); return(-1); } if (strlen(lptr)==0) { /*last item is empty*/ if ((new=(char*)malloc(1))==NULL) return(-1); new[0]=0; i->item[i->size++]=new; } else { /*handle the last item*/ len=strlen(lptr); if ((new=malloc(len+1))==NULL) return(-1); strcpy(new,lptr); i->item[i->size++]=new; } return(i->size); } /*end lib_dsplit()*/ int lib_dlist_replace(struct dlist_type *dlist, int which, char *new) /*replace an item in the list with a new string*/ { char *newptr; int len; /*sanity checks*/ if (dlist==NULL || new==NULL) return(-1); if (dlist->size<0 || dlist->size>dlist->maxlistsize) return(-1); if (dlist->maxlistsize<1 || dlist->item==NULL) return(-1); if (which>=dlist->size || which <0 ) return(-1); if (new==NULL) return(-1); /*realloc and copy new one into list*/ len=strlen(new); if ((newptr=realloc(dlist->item[which],len+1))==NULL) return(-1); strcpy(newptr,new); dlist->item[which]=newptr; return(dlist->size); } /*end lib_dlist_replace()*/ int lib_dlist_add(struct dlist_type *dlist, char *new) /*append/add a new string to the dynamic list*/ { char *newptr; int len; /*sanity checks*/ if (dlist==NULL) return(-1); if (dlist->item==NULL || dlist->maxlistsize<1) return(-1); if (dlist->size<0 || dlist->size>dlist->maxlistsize) return(-1); if (new==NULL) return(-1); /*allocate memory for and add new item to the end of the list*/ len=strlen(new); if ((newptr=(char*)malloc(len+1))==NULL) return(-1); strcpy(newptr,new); if (dlist->size>=dlist->maxlistsize) /*out of room, grow dlist*/ if (N_grow_dlist(dlist,0)<0) { /*oops, outta memory*/ free(newptr); return(-1); } dlist->item[dlist->size++]=newptr; return(dlist->size); } /*end lib_dlist_add()*/ char *lib_dlist_join(char *str, struct dlist_type *i, char *separator) /*join items in a dynamic list into a string with separators*/ { int x, len=0; char *string; /*sanity checks*/ if (i==NULL || separator==NULL) return(NULL); /*_i_ doesn't look sane, return error*/ if (i->item==NULL) return(NULL); if (i->size<0 || i->maxlistsize<1 || i->size>i->maxlistsize) return(NULL); /*allocate memory if string is NULL*/ string=str; if (string==NULL) { /*no storage passed in, allocate some*/ for (x=0;xsize;x++) { if (i->item[x]==NULL) return(NULL); len=len+strlen(i->item[x]); } /*safety space via extra separator length*/ len=len+(strlen(separator)*i->size); string=(char*)malloc(len); if (string==NULL) return(NULL); } string[0]='\0'; if (i->size==0) return(string); /*build string from items*/ strcpy(string,i->item[0]); for (x=1;xsize;x++) { strcat(string,separator); strcat(string,i->item[x]); } return(string); } /*end lib_dlist_join()*/ int lib_dlist_delete(struct dlist_type *i, int which) /*delete an item from the dynamic list*/ { int x; /*sanity check*/ if (i==NULL) return(-1); if (i->item==NULL) return(-1); if (i->size<1 || i->maxlistsize<1 || i->size>i->maxlistsize) return(-1); if (which <0 || which >= i->size) return(-1); /*delete memory for this item*/ free(i->item[which]); /*move everything afterwards up one position*/ for (x=which;xsize-1;x++) i->item[x]=i->item[x+1]; i->size--; i->item[i->size]=NULL; return(i->size); } /*end lib_dlist_delete()*/ int lib_dlist_insert(struct dlist_type *i, char *what, int where) /*insert an item into the list*/ { int x,len; char *new; /*sanity checks*/ if (i==NULL || what==NULL) return(-1); if (i->item==NULL) return(-1); if (i->size<0 || i->maxlistsize<1 || i->size>i->maxlistsize) return(-1); if (where > i->size || where<0) return(-1); /*allocate space for new entry*/ len=strlen(what); if ((new=(char*)malloc(len+1))==NULL) return(-1); /*move everything in list from that position onwards up one position*/ if (i->size>=i->maxlistsize) /*out of room, grow dlist*/ if (N_grow_dlist(i,0)<0) { /*oops, outta memory*/ free(new); return(-1); } for (x=i->size;x>where;x--) i->item[x]=i->item[x-1]; /*insert new item at that position*/ strcpy(new,what); i->item[where]=new; i->size++; return(i->size); } /*end lib_dlist_insert()*/ int lib_dparse(char *string, struct dlist_type *list, char *seps, char strict) /*parse a line of text and return its items in a dlist*/ { int spos=0,x,len=strlen(string); short stat=0; char *nseps, *new; /*sanity checks*/ if (list==NULL || string==NULL || seps==NULL) return(-1); if ((len=strlen(string))==0) return(0); if (list->item==NULL) return(-1); if (list->size<0 || list->maxlistsize<1 || list->size>list->maxlistsize) return(-1); /*set initial status values*/ if ((nseps=(char*)malloc(strlen(seps)+5))==NULL) return(-1); if (strlen(seps)==0) strcpy(nseps," \t\r\n"); else strcpy(nseps,seps); if (strict==0) stat=1; /*allocate memory for new entry*/ if ((new=(char*)malloc(len+1))==NULL) { free(nseps); return(-1); } /*parse the string, adding parsed items to the list*/ for (x=0;xsize>=list->maxlistsize) /*grow list*/ if (N_grow_dlist(list,0)<0) { free(nseps); free(new); return(-1); } list->item[list->size]=(char*)malloc(strlen(new)+1); if (list->item[list->size]==NULL) { free(nseps); free(new); return(-1); } strcpy(list->item[list->size++],new); spos=0; if (strict==0) stat=1; } } else { new[spos++]=string[x]; stat=0; } } free(nseps); /*special handling of last item parsed*/ new[spos]='\0'; if (list->size>=list->maxlistsize) /*no more space, grow list*/ if (N_grow_dlist(list,0)<0) { /*oops outta memory*/ free(new); return(-1); } if (strict==0) { if (strlen(new)>0) { list->item[list->size]=(char*)malloc(strlen(new)+1); if (list->item[list->size]==NULL) { free(new); return(-1); } strcpy(list->item[list->size++],new); } } else { list->item[list->size]=(char*)malloc(strlen(new)+1); if (list->item[list->size]==NULL) { free(new); return(-1); } strcpy(list->item[list->size++],new); } free(new); /*we don't need this guy anymore*/ return(list->size); } /*end lib_dparse()*/ int lib_dlist_getdir(struct dlist_type *dl, char *dir, char dotflag) /*retrieve the contents of a directory and put in a dynamic list*/ { DIR *dirp; struct dirent *direntp; char *new; /*sanity checks*/ if (dl==NULL || dir==NULL) return(-1); if (dl->item==NULL); if (dl->size<0 || dl->maxlistsize<1 || dl->size>dl->maxlistsize) return(-1); /*now down to business*/ if (strlen(dir)==0) dirp=opendir("."); else dirp=opendir(dir); if (dirp==NULL) return(-1); /*hmmm, can't open*/ rewinddir(dirp); while ((direntp=readdir(dirp))!=NULL) { if (!dotflag && direntp->d_name[0]=='.') continue; if (dotflag==1 && (strcmp(direntp->d_name,".")==0 || strcmp(direntp->d_name,"..")==0)) continue; if ((new=strdup(direntp->d_name))==NULL) { closedir(dirp); return(-1); } if (dl->size>=dl->maxlistsize) /*no room, grow dlist*/ if (N_grow_dlist(dl,0)<0) { /*oops, outta memory*/ free(new); return(-1); } dl->item[dl->size++]=new; } closedir(dirp); return(dl->size); } /*end lib_dlist_getdir()*/ int lib_dlist_sort(struct dlist_type *dl, char icase) /*sort the items in a dynamic list*/ { char *tmp; int workdone=0, x,y , midpt, cval; double delta, rmidpt; /*sanity checks*/ if (dl==NULL) return(-1); if (dl->item==NULL); if (dl->size<0 || dl->maxlistsize<1 || dl->size>dl->maxlistsize) return(-1); if (dl->size<=1) return(0); /*nothing done*/ /*now down to business*/ for (x=1;xsize;x++) { cval=N_strcmp(dl->item[x],dl->item[x-1],icase); if (cval>=0) continue; /*already bigger or equal*/ else { /*must find where to insert*/ delta=rmidpt=(double)x/2; /*cut in half*/ midpt=(int)rmidpt; cval=0; do { /*re-use cval*/ cval=N_strcmp(dl->item[x],dl->item[midpt],icase); delta=delta/2; if (cval==0) { /*exact match*/ delta=0.0; break; } if (cval<0) rmidpt=rmidpt-delta; /*before*/ else rmidpt=rmidpt+delta; /*after*/ midpt=(int)rmidpt; } while (delta>=1.0); if (delta>0.0) { /*rmidpt is within 2 positions*/ /*at this point we should be at or just before*/ for (y=midpt;yitem[x],dl->item[y],icase); if (cval<0) break; /*found the spot*/ if (cval==0) { y++; /*equal, put just after*/ break; } } midpt=y; } /*end if delta*/ } /*make space and insert - midpt now is the insert point*/ tmp=dl->item[x]; /*save current ptr at x */ for (y=x;y>midpt;y--) dl->item[y]=dl->item[y-1]; dl->item[midpt]=tmp; workdone=1; } return(workdone); } /*end lib_dlist_sort()*/ int lib_dlist_qsort(struct dlist_type *dl, char icase) /*use the quick sort library function*/ { /*sanity checks*/ if (dl==NULL) return(-1); if (dl->size<0 || dl->item==NULL || dl->maxlistsize<0) return(-1); if (dl->size>dl->maxlistsize) return(-1); if (dl->size==0) return(0); if (icase) qsort(dl->item,dl->size,sizeof(dl->item[0]),N_qstrcasecmp); else qsort(dl->item,dl->size,sizeof(void*),N_qstrcmp); return(0); } /*end of lib_dlist_qsort()*/ int lib_dlist_exec(struct dlist_type *dl) /*process a dlist and pass its items as args to exec()*/ { /*sanity checks*/ if (dl==NULL) return(-1); if (dl->size<2 || dl->item==NULL || dl->maxlistsize<2) return(-1); if (dl->size>dl->maxlistsize) return(-1); if (dl->item[0]==NULL || dl->item[1]==NULL) return(-1); return(execvp(dl->item[0],&dl->item[1])); } /*end lib_dlist_exec()*/ int lib_getdlistcount(struct dlist_type *dl) /*return the number of items on the dynamic list*/ { if (dl==NULL) return(-1); if (dl->item==NULL); if (dl->size<0 || dl->maxlistsize<1 || dl->size>dl->maxlistsize) return(-1); return(dl->size); } /*end lib_getdlistcount()*/ int lib_getdlistsize(struct dlist_type *dl) /*return maximum number of bytes the dynamic list holds*/ { int count=0,x; if (dl==NULL) return(-1); if (dl->item==NULL) return(-1); if (dl->size<0 || dl->size>dl->maxlistsize || dl->maxlistsize<1) return(-1); for (x=0;xsize;x++) count+=strlen(dl->item[x]); return(count); } /*end lib_getdlistsize()*/ int lib_dlist_blkdelete(struct dlist_type *dl, int which, int quant, char how) /* - delete before, + after, 0 before & after*/ /*return number of items that were deleted*/ { int nuked=0, x, nc=0, c=0; /*sanity checks*/ if (dl==NULL) return(-1); if (dl->item==NULL) return(-1); if (dl->size<0 || dl->size>dl->maxlistsize || dl->maxlistsize<1) return(-1); if (which>=dl->size || which <0) return(-1); if (quant<=0) quant=2147483647; /*now down to bidness*/ if (how>=0) { /*nuke _quant_ after _which_*/ for (x=which+1;xsize;x++) { free(dl->item[x]); dl->item[x]=NULL; nuked++; if (nuked>=quant) break; } } if (how<=0) { /*nuke _quant_ before*/ for (x=which-1;x>=0;x--) { free(dl->item[x]); dl->item[x]=NULL; nuked++; c++; if (c>=quant) break; } } if (nuked==0) return(0); /*nothing else to do*/ /*now reposition, fill in the vacancies*/ for (x=0;xsize;x++) { /*find first empty spot*/ if (dl->item[x]==NULL) { c=x; /*first empty spot*/ break; } } for (x=c+1;xsize;x++) { /*find first non-empty spot*/ if (dl->item[x]!=NULL) { nc=x; /*first non-empty spot*/ break; } } if (x>=dl->size) { /*deleted items all at the end*/ dl->size=c; return(nuked); } /*now move'em up*/ for (x=nc;xsize;x++) { if (dl->item[x]!=NULL) { dl->item[c]=dl->item[x]; dl->item[x]=NULL; c++; } } dl->size=c; return(nuked); /*return number of deleted items*/ } /*end lib_dlist_blkdelete()*/ int lib_dlist_from_hashkeys(struct hashtable *table, struct dlist_type *dlist) /*retrieve keys out of hashtable and put them into a dlist*/ /*key data is strdup'd for consistancy, wasteful- but much safer*/ { int tsize, lpos, st; char *p=NULL; void *h; struct hashentry *hashent; /*sanity checks*/ if (table==NULL || dlist==NULL) return(-1); if (table->count<0 || table->hashfunc<1) return(-1); if (dlist->size<0 || dlist->maxlistsize<0 || dlist->item==NULL) return(-1); if (table->count==0) return(dlist->size); /*nothing to do*/ /*initialize everything and prep dlist*/ tsize=dlist->size+table->count; /*new dlist size will need to be at least this as the dlist could already contain entries*/ if (tsize > dlist->maxlistsize) { st=N_grow_dlist(dlist, 4+tsize-dlist->maxlistsize); if (st<0) return(-1); } lpos=dlist->size; hashent=table->first; /*go through the hashtable keys duping them into the dlist*/ while (hashent!=NULL) { if (hashent->key!=NULL) p=strdup(hashent->key); if (p==NULL) return(-1); /*oops, we outta memory or key=NULL*/ else dlist->item[lpos]=p; lpos++; /*lpos should never hit maxlistsize in theory*/ dlist->size++; h=(void*)hashent->listn; /*next!*/ hashent=(struct hashentry*)h; p=NULL; /*reset p*/ } return(dlist->size); } /*end lib_dlist_from_hashkeys()*/ int lib_dlist_swap(struct dlist_type *dlist, int first, int second) /*swap two elements in a dlist*/ { char *tmp; /*sanity checking*/ if (dlist==NULL) return(-1); if (dlist->size<0 || dlist->maxlistsize<0 || dlist->item==NULL) return(-1); if (first<0 || second<0) return(-1); if (first>=dlist->size || second>=dlist->size) return(-1); /*swap*/ tmp=dlist->item[first]; dlist->item[first]=dlist->item[second]; dlist->item[second]=tmp; return(0); } /*end lib_dlist_swap()*/ int lib_dlist_reverse(struct dlist_type *dlist) /*reverse the order of elements in a dlist*/ { char *tptr; int x,y; /*sanity checks*/ if (dlist==NULL) return(-1); if (dlist->size<0 || dlist->maxlistsize<0 || dlist->item==NULL) return(-1); if (dlist->size>dlist->maxlistsize) return(-1); if (dlist->size<=1) return(0); /*nothing to do*/ x=0; y=dlist->size-1; while (xitem[x]; dlist->item[x]=dlist->item[y]; dlist->item[y]=tptr; y--; x++; } return(0); } /*end lib_dlist_reverse()*/ int lib_dlist_cgiparse(struct dlist_type *dlist, char *input) /* parse CGI GET input, +=space, & separator*/ { int x=0, start=0, pos=0, len; char *str; char stop=0; /*sanity checks*/ if (dlist==NULL || input==NULL) return(-1); if (dlist->size<0 || dlist->maxlistsize<0 || dlist->item==NULL) return(-1); if (dlist->size>dlist->maxlistsize) return(-1); if (strlen(input)==0) return(dlist->size); /*empty*/ for (;;) { if (input[pos]=='&' || input[pos]=='\0' || input[pos]=='=') { /*end of field*/ x=0; if (input[pos]=='\0') stop=1; /*EOL*/ len=pos-start; str=(char*)malloc(len+2); if (str==NULL) return(-1); while (xsize>=dlist->maxlistsize) if (N_grow_dlist(dlist,0)<0) { free(str); return(-1); } dlist->item[dlist->size++]=str; if (stop==1) break; pos++; start=pos; } else pos++; } return(dlist->size); } /*end lib_dlist_cgiparse()*/ int lib_grep_dlist(struct dlist_type *src,struct dlist_type *res, char *pat, short icase) /*grep for the existance of a string pattern in a dynamic list*/ /*bit1: 0=caseless,1=caseful ; bit2: 0=include,1=exclude*/ { int x, cnt; char *dupstr, *duppat, *ptr; /*sanity checks*/ if (src==NULL || res==NULL || pat==NULL) return(-1); if (strlen(pat)==0) return(0); if (src->item==NULL || res->item==NULL) return(-1); if (src->size<0 || res->size<0 || src->size>src->maxlistsize || res->size>res->maxlistsize) return(-1); if (res->maxlistsize<1 || src->maxlistsize<1) return(-1); cnt=src->size; if ((icase & 1)==0) { /*case sensitive*/ for (x=0;xitem[x],pat); if (ptr==NULL && (icase & 2)==0) continue; if (ptr!=NULL && (icase & 2)==2) continue; if (res->size>=res->maxlistsize) { if (N_grow_dlist(res,0)<0) return(-1); /*we gotta problem*/ } /*okay, gotta match at this point*/ dupstr=strdup(src->item[x]); if (dupstr==NULL) return(-1); res->item[res->size]=dupstr; res->size++; dupstr=NULL; } } else { /*case insensitve, more work to do*/ int len, y; /*create an all uppercase pattern*/ duppat=strdup(pat); if (duppat==NULL) return(-1); len=strlen(duppat); for (x=0;xitem[x]); if (dupstr==NULL) { free(duppat); return(-1); } len=strlen(dupstr); for (y=0;yitem[x]); /*should be safe*/ if (res->size>=res->maxlistsize) { if (N_grow_dlist(res,0)<0) { free(duppat); free(dupstr); return(-1); /*we gotta problem*/ } } res->item[res->size]=dupstr; res->size++; dupstr=NULL; } free(duppat); } return(res->size); } /*end lib_grep_dlist()*/ int lib_egrep_dlist(struct dlist_type *sdl, struct dlist_type *rdl, char *pat, short flags, char *regx) /*flag=1 case-insensitive, flag=2 means exclude*/ { int slen, plen, cflag=flags&1, eflag=flags&2, x, y; char match, function, *str, *dupstr; int rpos, lpos; /*sanity checks*/ plen=strlen(pat); if (plen==0) return(-2); if (strcmp(regx,"$")==0) function=0; /*exact match*/ else if (strcmp(regx,"$*")==0) function=1; /*start of string*/ else if (strcmp(regx,"*$")==0) function=2; /*end of string*/ else if (strcmp(regx,"*$*")==0) function=3; /*middle of string*/ else if (strcmp(regx,"*")==0) function=4; /*match anything but*/ else return(-3); /*invalid pattern*/ for (x=0;xsize;x++) { /*outer loop*/ match=0; /*reset everything*/ lpos=rpos=-1; /*reset to bogus values*/ if (sdl->item[x]==NULL) return(rdl->size); /*eh? bail!*/ /*quick check for possible presence*/ slen=strlen(sdl->item[x]); if (slenitem[x]; for (y=0;y<=(slen-plen);y++) { if (cflag==0) { /*case sensitive*/ if (strncmp(&str[y],pat,plen)==0) { match=1; lpos=y; break; } } else { /*case-insensitive, cflag!=0 */ if (strncasecmp(&str[y],pat,plen)==0) { match=1; lpos=y; break; } } } /*end of inner loop*/ /*check what we have, match means we found pattern*/ /*special handling for "*" case here*/ if (match==0) { nomatch: if (function==4) { if (eflag) continue; /*nothing here*/ } else if (eflag==0) continue; /*if still here, add da mutha*/ dupstr=strdup(sdl->item[x]); if (dupstr==NULL) return(-1); /*problem houston*/ if (rdl->size>=rdl->maxlistsize) { if (N_grow_dlist(rdl,0)<0) { free(dupstr); return(-4); /*we gotta problem*/ } } rdl->item[rdl->size]=dupstr; rdl->size++; dupstr=NULL; continue; /*NEXT candidate!*/ } /*at this point match==1 */ /*determine how to handle match based on flags+regx*/ rpos=lpos+plen; match=0; /*reset*/ if (function==3) { /*in the middle*/ if (lpos>0 && rpos0 && rpos==slen) { /*it matches*/ if (eflag) /*negation, next!*/ continue; } else { /*no match*/ if (eflag==0) /*no negation, next!*/ continue; } match=1; } else if (function==0) { /*exact match?*/ if (lpos==0 && rpos==slen) { /*it matches exactly*/ if (eflag) /*negation, next!*/ continue; } else { /*no match*/ if (eflag==0) /*no negation, next!*/ continue; } match=1; } else if (function==4) { /*match anything but pattern*/ if (eflag==0) /*negation means include here*/ continue; match=1; } if (match==0) continue; /*shouldn't get here*/ /*at this point add it*/ dupstr=strdup(sdl->item[x]); if (dupstr==NULL) return(-1); /*problem houston*/ if (rdl->size>=rdl->maxlistsize) { if (N_grow_dlist(rdl,0)<0) { free(dupstr); return(-5); /*we gotta problem*/ } } rdl->item[rdl->size]=dupstr; rdl->size++; dupstr=NULL; } /*NEXT! candidate*/ return(rdl->size); } /*end lib_egrep_dlist()*/ int lib_nuparse(char *string, char *format, struct dlist_type *dlist, char *m) /*parse based on seperator pairs, white space is special*/ { int x, y, flen, copylen, icount; int sspos, cpos, fpos, savepos; char *nsptr=string, nsep, mat[3]={'*','?','\0'}; /*sanity checks*/ if (string==NULL || format==NULL || dlist==NULL) return(-1); if (dlist->maxlistsize<1 || dlist->size<0 || dlist->size>dlist->maxlistsize) return(-1); if (dlist->item==NULL) return(-1); if (m!=NULL) { flen=strlen(m); if (flen!=0 && flen!=2) return(-1); if (flen==2) { if (m[0]==' ' || m[0]=='\t' || m[1]==' ' || m[1]=='\t') return(-1); /*invalid match characters*/ if (m[0]==m[1]) return(-1); /*also invalid*/ strncpy(mat,m,2); } /*else flen==0, just use default for mat*/ } /*handle simple cases*/ if (strlen(string)==0) return(dlist->size); /*nothing there*/ if ((flen=strlen(format))==0) return(dlist->size); /*nothing specified*/ for (x=0,icount=0;xsize); /*nothing there to parse*/ if (flen==1) { /*handle simple case here*/ if (format[0]==mat[0]) { nsptr=strdup(string); if (nsptr==NULL) return(-1); /*no memory*/ if (dlist->size>=dlist->maxlistsize) /*no room, grow!*/ if (N_grow_dlist(dlist,0)<0) { free(nsptr); return(-1); } dlist->item[dlist->size]=nsptr; dlist->size++; return(dlist->size); } else return(dlist->size); /*no valid format specs, bail*/ } /*initialize baseline*/ sspos=0; /*current string start position*/ cpos=0; /*check position in string*/ fpos=0; /*format position*/ nsptr=NULL; /*reset*/ savepos=dlist->size; /*first position to start stuff*/ /*main loop until we reach the end of a string*/ for (x=0;xsize>=dlist->maxlistsize) if (N_grow_dlist(dlist,0)<0) { free(nsptr); return(-1); } strncpy(nsptr,&string[sspos],copylen); nsptr[copylen]='\0'; dlist->item[dlist->size]=nsptr; dlist->size++; } if (string[cpos]=='\0') { /*done? check conditions*/ /*check icount*/ if (dlist->size-savepos!=icount) { bailnu: for (y=dlist->size-1;y>=savepos;y--) { free(dlist->item[y]); dlist->item[y]=NULL; } dlist->size=savepos; return(dlist->size); } /*check end of format, if we reach end of string before end of format, bail*/ if (nsep!='\0') goto bailnu; /*more format*/ return(dlist->size); /*good deal, return*/ } sspos=cpos; /*update start pos*/ } /*end copy match*/ else { /*find next field, skipping dup space block*/ /*handle white space*/ if (isspace((int)format[x])) { /*white space*/ if (isspace((int)format[x+1])!=0) { /*bad format bail*/ goto bailnu; } /*find string whitespace and skip over*/ while (isspace((int)string[cpos])) { if (string[cpos]=='\0') { /*fat lady sings - return*/ return(dlist->size); } cpos++; } sspos=cpos; /*update start pos*/ } else { /*handle anything else exactly*/ while (string[cpos]!=format[x]) { if (string[cpos]=='\0') { /*no more string, return*/ return(dlist->size); } cpos++; } cpos++; /*move beyond matching char*/ sspos=cpos; /*update start pos*/ } } /*end skipping block*/ } return(dlist->size); } /*end lib_nuparse()*/ int lib_dlist_sorted_uniq(struct dlist_type *dlist, char igncase) /*eliminate duplicated items in a (assummed sorted) dynamic list*/ { int delcount=0, tpos, chpos, npos, st; /*sanity checks*/ if (dlist==NULL) return(-1); if (dlist->size<0 || dlist->maxlistsize<0 || dlist->item==NULL) return(-1); if (dlist->size>dlist->maxlistsize) return(-1); if (dlist->size<2) return(0); /*nothing to do*/ /*loop through all items, marking deletes with NULL*/ for (tpos=0;tpossize;tpos++) { if (dlist->item[tpos]==NULL) continue; chpos=tpos+1; while (chpossize) { if (dlist->item[chpos]==NULL) break; /*what the!?*/ if (igncase) st=strcasecmp(dlist->item[tpos],dlist->item[chpos]); else st=strcmp(dlist->item[tpos],dlist->item[chpos]); if (st!=0) break; /*if still here, nuke and try next item*/ free(dlist->item[chpos]); dlist->item[chpos]=NULL; delcount++; chpos++; } } if (delcount==0) return(0); /*first find 1st NULL slot*/ npos=-1; for (tpos=1;tpossize;tpos++) { if (dlist->item[tpos]==NULL) { npos=tpos; break; } } if (npos==-1) return(0); /*nothing found..why are we here?*/ /*clean 'em out, filling in the space*/ for (chpos=npos;chpossize;chpos++) { if (dlist->item[chpos]==NULL) continue; /*empty, just skip*/ dlist->item[npos]=dlist->item[chpos]; /*move down*/ dlist->item[chpos]=NULL; /*clear it*/ npos++; } dlist->size=dlist->size-delcount; return(delcount); } /*end lib_dlist_sorted_uniq()*/ int lib_dlist_uniq(struct dlist_type *dlist, char igncase) /*eliminate duplicated items in an unsorted dynamic list*/ { int delcount=0, tpos, chpos, npos, st; /*sanity checks*/ if (dlist==NULL) return(-1); if (dlist->size<0 || dlist->maxlistsize<0 || dlist->item==NULL) return(-1); if (dlist->size>dlist->maxlistsize) return(-1); if (dlist->size<=1) return(0); /*nothing to do*/ /*cycle through looking for dups - expensive for unsorted*/ for (tpos=0;tpossize;tpos++) { if (dlist->item[tpos]==NULL) continue; for (chpos=tpos+1;chpossize;chpos++) { if (dlist->item[chpos]==NULL) continue; if (igncase) st=strcasecmp(dlist->item[tpos],dlist->item[chpos]); else st=strcmp(dlist->item[tpos],dlist->item[chpos]); if (st!=0) continue; /*if still here, nuke*/ free(dlist->item[chpos]); dlist->item[chpos]=NULL; delcount++; } } if (delcount==0) return(0); /*first find 1st NULL slot*/ npos=-1; for (tpos=1;tpossize;tpos++) { if (dlist->item[tpos]==NULL) { npos=tpos; break; } } if (npos==-1) return(0); /*nothing found..why are we here?*/ /*clean 'em out, filling in the space*/ for (chpos=npos;chpossize;chpos++) { if (dlist->item[chpos]==NULL) continue; /*empty, just skip*/ dlist->item[npos]=dlist->item[chpos]; /*move down*/ dlist->item[chpos]=NULL; /*clear it*/ npos++; } dlist->size=dlist->size-delcount; return(delcount); } /*end lib_dlist_uniq()*/ int lib_dlist_compare(struct dlist_type *l1, struct dlist_type *l2, char igncase, char sorted) /*compare 2 dlists - must be sorted and/or uniqued*/ { int st, pos1,pos2, match; /*sanity checks*/ if (l1==NULL || l2==NULL) return(-1); if (l1->size<0 || l1->maxlistsize<0 || l1->item==NULL) return(-1); if (l2->size<0 || l2->maxlistsize<0 || l2->item==NULL) return(-1); if (l1->size>l1->maxlistsize || l2->size>l2->maxlistsize) return(-1); /*easy checks*/ if (l1->size==0 && l2->size==0) return(0); /*nothing to do*/ if (l1->size!=l2->size) return(1); /*definitely not the same*/ /*unsorted case*/ if (!sorted) { /*must be all unique items if not sorted, otherwise matches on duplicated items can throw us off*/ for (pos1=0;pos1size;pos1++) { match=0; for (pos2=0;pos2size;pos2++) { if (igncase) st=strcasecmp(l1->item[pos1],l2->item[pos2]); else st=strcmp(l1->item[pos1],l2->item[pos2]); if (st==0) { match=1; break; } } if (!match) return(1); /*no match found, not equal*/ } return(0); /*if still here, probably equal, return as so*/ } /*end of not sorted case*/ /*check for sorted case*/ for (pos1=0;pos1size;pos1++) { if (igncase) st=strcasecmp(l1->item[pos1],l2->item[pos1]); else st=strcmp(l1->item[pos1],l2->item[pos1]); if (st!=0) return(1); /*mismatch, not equal*/ } return(0); /*if still here, must be equal*/ } /*end of lib_dlist_compare()*/ int lib_dlist_append(struct dlist_type *l1, struct dlist_type *l2, char copy) /*append one dynamic list to another*/ { int x, y; char *nitem; /*sanity checks*/ if (l1==NULL || l2==NULL) return(-1); if (l1->size<0 || l1->maxlistsize<0 || l1->item==NULL) return(-1); if (l2->size<0 || l2->maxlistsize<0 || l2->item==NULL) return(-1); if (l1->size>l1->maxlistsize || l2->size>l2->maxlistsize) return(-1); if (l2->size==0) return(l1->size); /*nothing to do*/ /*adjust size of l1 as needed*/ if (l1->maxlistsize-l1->size < l2->size) { /*grow l1*/ if (N_grow_dlist(l1,l2->size)<0) { /*oops, outta memory*/ return(-2); } } /*loop through l2, adding elements to l1*/ if (copy) { /*duplicate*/ for (x=0;xsize;x++) { nitem=strdup(l2->item[x]); if (nitem==NULL) { for (y=0;yitem[l1->size+y]); return(-2); /*out of memory*/ } l1->item[l1->size+x]=nitem; } l1->size=l1->size+l2->size; } else { /*move*/ for (x=0;xsize;x++) { l1->item[l1->size+x]=l2->item[x]; l2->item[x]=NULL; } l1->size=l1->size+l2->size; l2->size=0; } return(l1->size); } /*end lib_dlist_append()*/ int lib_dlist_merge(struct dlist_type *l1, struct dlist_type *l2, char cse) /*merge list2 with list1, assumed sorted order for both*/ /*list2 will be empty afterwards*/ { int nsize, x, lone=0,ltwo=0; char **newlist; /*sanity checks*/ if (l1==NULL || l2==NULL) return(-1); if (l1->size<0 || l1->maxlistsize<0 || l1->item==NULL) return(-1); if (l2->size<0 || l2->maxlistsize<0 || l2->item==NULL) return(-1); if (l1->size>l1->maxlistsize || l2->size>l2->maxlistsize) return(-1); if (l2->size==0) return(l1->size); /*nothing to do*/ /*create new combined list of appropriate size*/ nsize=l1->size+l2->size+4; /*add 4 for growth*/ newlist=(char**)malloc(sizeof(char*)*nsize); if (newlist==NULL) return(-2); /*no mo' memory*/ for (x=0;xsize+l2->size; for (x=0;xitem[lone]==NULL) { /*at end of list1*/ newlist[x]=l2->item[ltwo]; ltwo++; continue; } if (l2->item[ltwo]==NULL) { /*at end of list2*/ newlist[x]=l1->item[lone]; lone++; continue; } /*there are still items on both lists*/ if (cse) { /*case insensitive*/ if (strcasecmp(l1->item[lone],l2->item[ltwo])<0) { newlist[x]=l1->item[lone]; lone++; } else { newlist[x]=l2->item[ltwo]; ltwo++; } continue; } /*at this point, we're case sensitive*/ if (strcmp(l1->item[lone],l2->item[ltwo])<0) { newlist[x]=l1->item[lone]; lone++; } else { newlist[x]=l2->item[ltwo]; ltwo++; } } /*clean up list2 and list1*/ for (x=0;xsize;x++) l2->item[x]=NULL; l2->size=0; l1->size=nsize; l1->maxlistsize=nsize; free(l1->item); /*free old array*/ l1->item=newlist; return(l1->size); } /*end of lib_dlist_merge()*/ int lib_dlist_copy(struct dlist_type *list1, struct dlist_type *list2) /*copy all items in list1 to list2, discarding existing list2 items*/ { char **newlist, *nptr; int nsize, x, y; /*sanity checks*/ if (list1==NULL || list2==NULL) return(-1); if (list1->size<0 || list1->maxlistsize<0 || list1->item==NULL) return(-1); if (list2->size<0 || list2->maxlistsize<0 || list2->item==NULL) return(-1); if (list1->size>list1->maxlistsize || list2->size>list2->maxlistsize) return(-1); if (list1->size==0 && list2->size==0) return(0); /*nothing to do*/ /*allocate memory for new list so if we have a memory failure, nothing is alterned and we can bail*/ nsize=list1->size+4; /*+4 for growth*/ newlist=(char**)malloc(sizeof(char*)*nsize); if (newlist==NULL) return(-2); /*no memory*/ for (x=0;xsize;x++) { nptr=strdup(list1->item[x]); if (nptr==NULL) { /*oops, no mo' memory, clean up and bail*/ for (y=0;ysize;x++) { if (list2->item[x]!=NULL) free(list2->item[x]); list2->item[x]=NULL; } /*transfer new list array, freeing the old*/ free(list2->item); list2->item=newlist; list2->size=list1->size; list2->maxlistsize=nsize; /*set new maxlistsize*/ return(list2->size); } /*end of lib_dlist_copy() */ int lib_freeall_dlist(struct dlist_type **ptr, ...) /*multiple destroy calls in one for dlist_type data types*/ { struct dlist_type **rptr, *aptr; va_list ap; int x; if (ptr==NULL) return(0); rptr=ptr; aptr=*rptr; if (aptr!=NULL) { if (aptr->item!=NULL) { for (x=0;xsize;x++) if (aptr->item[x]!=NULL) free(aptr->item[x]); free(aptr->item); } free(aptr); *rptr=NULL; } va_start(ap,ptr); for (;;) { rptr=va_arg(ap,struct dlist_type**); if (rptr==NULL) break; aptr=*rptr; if (aptr!=NULL) { if (aptr->item!=NULL) { for (x=0;xsize;x++) if (aptr->item[x]!=NULL) free(aptr->item[x]); free(aptr->item); } free(aptr); *rptr=NULL; } } va_end(ap); return(0); } /*end lib_freeall_dlist()*/ int lib_dlist_readtxtfile(struct dlist_type *dlist, char *path, char strip) /*read a text file into a dynamic list*/ { FILE *fp; int size=0, len; char buffer[256], *new=NULL; /*sanity checks*/ if (dlist==NULL) return(-1); if (dlist->maxlistsize<0 || dlist->size<0 || dlist->size>dlist->maxlistsize) return(-1); if (dlist->item==NULL) return(-1); if (path==NULL) return(-1); if (strlen(path)==0) return(-1); /*begin reading*/ fp=fopen(path,"r"); if (fp==NULL) return(-1); while (fgets(buffer,255,fp)!=NULL) { len=strlen(buffer); if (len<255 || buffer[len-1]=='\n') { /*at the end*/ if (new==NULL) { new=(char*)malloc(len+1); if (new==NULL) { fclose(fp); return(-1); } } if (strip!=0 && buffer[len-1]=='\n') buffer[len-1]='\0'; /*remove newline*/ strcpy(new,buffer); /*add to dlist*/ if (dlist->size>=dlist->maxlistsize) if (N_grow_dlist(dlist,0)<0) { free(new); fclose(fp); return(-1); } dlist->item[dlist->size++]=new; new=NULL; size=0; continue; } /*append to running buffer in _new_*/ size=(size+len+1); /*calculate new size*/ if (new!=NULL) { /*allocate more space*/ new=realloc(new,size); strcat(new,buffer); /*should be safe*/ } else { /*new allocation*/ if ((new=malloc(size))==NULL) { /*failed!*/ fclose(fp); return(-1); } strcpy(new,buffer); /*copy what we have*/ } } /*end while*/ if (new!=NULL) { /*handle buffered data*/ /*add to dlist*/ if (dlist->size>=dlist->maxlistsize) if (N_grow_dlist(dlist,0)<0) { free(new); fclose(fp); return(-1); } dlist->item[dlist->size++]=new; } fclose(fp); return(dlist->size); } /*end of lib_dlist_readtxtfile()*/ /**********************************/ /* BEGIN QSTACK FUNCTIONS SECTION */ /**********************************/ struct qstack *lib_create_qstack(void) /*create and initialize a new qstack*/ { struct qstack *qstak; if ((qstak=(struct qstack*)malloc(sizeof(struct qstack)))==NULL) return(NULL); qstak->first=NULL; qstak->last=NULL; qstak->size=0; qstak->bsize=0; qstak->maxitems=2147483647; /*effectively unlimited*/ return(qstak); } /*end lib_create_qstack()*/ int lib_delete_qstack(struct qstack *qstak) /*destroy a qstack*/ { struct linklist_item *llist; void *pptr; if (qstak==NULL) return(-1); llist=qstak->last; while (llist!=NULL) { pptr=llist->prev; free(llist->data); free(llist); llist=pptr; } free(qstak); return(1); } /*end lib_delete_qstack()*/ int lib_clear_qstack(struct qstack *qstak) /*delete all items in a qstack*/ { struct linklist_item *llist; void *pptr; if (qstak==NULL) return(-1); llist=qstak->last; while (llist!=NULL) { pptr=llist->prev; free(llist->data); free(llist); llist=pptr; } qstak->first=NULL; qstak->last=NULL; qstak->size=0; qstak->bsize=0; return(1); } /*end lib_clear_qstack()*/ int lib_qstack_push(struct qstack *qstak, void *data, int datasize, int typ) /*insert an item at the back of the queue or the top of the stack*/ { void *new; struct linklist_item *lptr, *nlptr; if (data==NULL || datasize<1) return(0); lptr=qstak->last; nlptr=(struct linklist_item*)malloc(sizeof(struct linklist_item)); if (nlptr==NULL) return(-1); if ((new=(void*)malloc(datasize))==NULL) { free(nlptr); return(-1); } /*initialize new llist item*/ bcopy(data,new,datasize); nlptr->dsize=datasize; nlptr->next=NULL; nlptr->prev=lptr; nlptr->data=new; nlptr->type=typ; /*update qstack*/ qstak->last=nlptr; if (lptr==NULL) qstak->first=nlptr; else lptr->next=nlptr; qstak->size++; qstak->bsize+=datasize; if (qstak->size>qstak->maxitems) { lptr=qstak->first; if (lptr==NULL) return(1); if (lptr->data!=NULL) free(lptr->data); qstak->bsize-=lptr->dsize; qstak->first=lptr->next; free(lptr); lptr=qstak->first; if (lptr!=NULL) lptr->prev=NULL; qstak->size--; } return(1); } /*end lib_qstack_push()*/ int lib_qstack_press(struct qstack *qstak, void *data, int datasize, int typ) /*insert an item at the front of the queue or bottom of the stack*/ { void *new; struct linklist_item *fptr, *nfptr; if (data==NULL || datasize<1) return(0); fptr=qstak->first; nfptr=(struct linklist_item*)malloc(sizeof(struct linklist_item)); if (nfptr==NULL) return(-1); if ((new=(void*)malloc(datasize))==NULL) { free(nfptr); return(-1); } /*initialize new llist item*/ bcopy(data,new,datasize); nfptr->dsize=datasize; nfptr->next=fptr; nfptr->prev=NULL; nfptr->data=new; nfptr->type=typ; /*update qstack*/ qstak->first=nfptr; if (fptr==NULL) qstak->last=nfptr; else fptr->prev=nfptr; qstak->size++; qstak->bsize+=datasize; if (qstak->size>qstak->maxitems) { fptr=qstak->last; if (fptr==NULL) return(1); if (fptr->data!=NULL) free(fptr->data); qstak->bsize-=fptr->dsize; qstak->last=fptr->prev; free(fptr); fptr=qstak->last; if (fptr!=NULL) fptr->next=NULL; qstak->size--; } return(1); } /*end lib_qstack_press()*/ void *lib_qstack_pop(struct qstack *qstak, int *dsize, int *typ) /*retrieve an item at the back of the queue or the top of the stack*/ { struct linklist_item *lptr, *pptr; void *datap; if (qstak==NULL) return(NULL); if (qstak->size<1) return(NULL); lptr=qstak->last; if (qstak->first==lptr) qstak->first=NULL; if (dsize!=NULL) *dsize=lptr->dsize; if (typ!=NULL) *typ=lptr->type; qstak->bsize-=lptr->dsize; pptr=lptr->prev; if (pptr!=NULL) pptr->next=NULL; datap=lptr->data; free(lptr); qstak->size--; qstak->last=pptr; return(datap); } /*end lib_qstack_pop()*/ void *lib_qstack_vpop(struct qstack *qstak, int *dsize, int *typ) /*retrieves an item at the back of the queue or the top of the stack but doesn't remove it from the qstack*/ { struct linklist_item *lptr; void *datap; if (qstak==NULL) return(NULL); if (qstak->size<1) return(NULL); lptr=qstak->last; if (dsize!=NULL) *dsize=lptr->dsize; if (typ!=NULL) *typ=lptr->type; datap=lptr->data; return(datap); } /*end lib_qstack_vpop()*/ void *lib_qstack_pull(struct qstack *qstak, int *dsize, int *typ) /*retrieve an item at the front of the queue or the bottom of stack*/ { struct linklist_item *fptr, *nptr; void *datap; if (qstak==NULL) return(NULL); if (qstak->size<1) return(NULL); fptr=qstak->first; if (qstak->last==fptr) qstak->last=NULL; if (dsize!=NULL) *dsize=fptr->dsize; if (typ!=NULL) *typ=fptr->type; qstak->bsize-=fptr->dsize; nptr=fptr->next; if (nptr!=NULL) nptr->prev=NULL; datap=fptr->data; free(fptr); qstak->size--; qstak->first=nptr; return(datap); } /*end lib_qstack_pull()*/ void *lib_qstack_vpull(struct qstack *qstak, int *dsize, int *typ) /*retrieves an item at the front of the queue or the bottom of stack but doesn't remove it from the qstack*/ { struct linklist_item *fptr; void *datap; if (qstak==NULL) return(NULL); if (qstak->size<1) return(NULL); fptr=qstak->first; if (dsize!=NULL) *dsize=fptr->dsize; if (typ!=NULL) *typ=fptr->type; datap=fptr->data; return(datap); } /*end lib_qstack_vpull()*/ int lib_qstack_pointers(struct qstack *qstak, void **first, void **last) /*grab pointers to the first and last items in a Qstack */ { if (qstak==NULL) return(-1); if (first!=NULL) *first=qstak->first; if (last!=NULL) *last=qstak->last; return(1); } /*end lib_qstack_pointers()*/ void *lib_qstack_getlistptrs(void *item, void **prev, void **next, int *dsize, int *typ) /*return pointers/info for an item in the Qstack's linked list*/ { struct linklist_item *i; i=item; if (i==NULL) return(NULL); if (prev!=NULL) *prev=i->prev; if (next!=NULL) *next=i->next; if (dsize!=NULL) *dsize=i->dsize; if (typ!=NULL) *typ=i->type; return(i->data); } /*end lib_qstack_getlistptrs()*/ int lib_qstack_insert(struct qstack *qstak, void *i, char how, void *data, int datasize, int typ) /*insert or replace an item in the qstack, size limits are NOT enforced with this call*/ { void *p; struct linklist_item *new, *item=i; short lsize=sizeof(struct linklist_item); if (data==NULL || item==NULL || datasize<1 || qstak==NULL) return(-1); if (how==0) { /*replace _item_ */ if ((p=(void*)realloc(item->data,datasize))==NULL) return(-1); bcopy(data,p,datasize); item->data=p; item->type=typ; return(1); } /*insert _item_ */ /*first initialize the new item*/ if ((new=(struct linklist_item*)malloc(lsize))==NULL) return(-1); if ((new->data=(void*)malloc(datasize))==NULL) { /*ouch, bail*/ free(new); return(-1); } bcopy(data,new->data,datasize); new->dsize=datasize; new->type=typ; /*now where to insert the new item*/ if (how<0) { /*insert in back of (after) _item_ in queue*/ new->prev=item; new->next=item->next; item->next=new; p=new->next; if (p!=NULL) ((struct linklist_item*)p)->prev=new; else qstak->last=new; } else if (how>0) { /*insert in front of (before) _item_ */ new->next=item; new->prev=item->prev; item->prev=new; p=new->prev; if (p!=NULL) ((struct linklist_item*)p)->next=new; else qstak->first=new; } qstak->size++; return(1); } /*end lib_qstack_insert()*/ int lib_qstack_remove(struct qstack *qstak,void *i) /*remove an item within a qstack*/ { struct linklist_item *lptr, *item=i; if (qstak==NULL || item==NULL) return(-1); if (qstak->size==0) return(-1); if (item==qstak->first) qstak->first=item->next; if (item==qstak->last) qstak->last=item->prev; if ((lptr=item->prev)!=NULL) lptr->next=item->next; if ((lptr=item->next)!=NULL) lptr->prev=item->prev; qstak->bsize-=item->dsize; free(item->data); free(item); qstak->size--; return(1); } /*end lib_qstack_remove()*/ int lib_qstack_size(struct qstack *qstak, int *bytes) /*return the number of items currently on the qstack*/ { if (qstak==NULL) return(-1); if (bytes!=NULL) *bytes=qstak->bsize; return(qstak->size); } /*end lib_qstack_size()*/ int lib_qstack_setmaxsize(struct qstack *qstak, int size) /*set maxitems count*/ { /*sanity checks*/ if (qstak==NULL) return(-1); if (qstak->size<0 || qstak->bsize<0) return(-1); if (size==0) qstak->maxitems=2147483647; else if (size>0) qstak->maxitems=size; return(qstak->maxitems); } /*end lib_qstack_setmaxsize()*/ void *lib_qstack_returnitem(struct qstack *qstak, int which, int *size, int *typ) /*return pointer to data within qstack*/ /*0 = bottom/front/first of stack/queue/last - press/pull end*/ { struct linklist_item *lptr, *nptr; int x, inc, start; /*sanity checks*/ if (size!=NULL) *size=-1; /*initialize to error state*/ if (qstak==NULL) return(NULL); if (qstak->size<=0 || qstak->bsize<=0) return(NULL); if (which>=qstak->size || which < 0) return(NULL); /*optimize starting point*/ if (which >= (qstak->size<<1)) { lptr=qstak->last; inc=-1; start=qstak->size-1; /*adjust for 1st=0 vs 1*/ } else { lptr=qstak->first; inc=1; start=0; } /*start loop, counting items*/ for (x=start;x!=which;x=x+inc) { if (inc<0) nptr=lptr->prev; else nptr=lptr->next; lptr=nptr; } if (size!=NULL) *size=lptr->dsize; if (typ!=NULL) *typ=lptr->type; return(lptr->data); } /*end lib_qstack_returnitem()*/ int lib_freeall_qstack(struct qstack **ptr,...) /*multiple destroy calls in one for qstack data types*/ { struct qstack **rptr, *aptr; struct linklist_item *lc, *ln; va_list ap; if (ptr==NULL) return(0); rptr=ptr; aptr=*rptr; if (aptr!=NULL) { lc=aptr->first; while (lc!=NULL) { ln=lc->next; if (lc->data!=NULL) free(lc->data); free(lc); lc=ln; } free(aptr); *rptr=NULL; } va_start(ap,ptr); for (;;) { rptr=va_arg(ap,struct qstack**); if (rptr==NULL) break; aptr=*rptr; if (aptr!=NULL) { lc=aptr->first; while (lc!=NULL) { ln=lc->next; if (lc->data!=NULL) free(lc->data); free(lc); lc=ln; } free(aptr); *rptr=NULL; } } va_end(ap); return(0); } /*end of lib_freeall_qstack()*/ /************************************/ /* BEGIN ENCODING FUNCTIONS SECTION */ /************************************/ char *lib_encode(char *key, char *data, int dsize, int *esize, short cycles) /*encode a string of bytes using a symetric key, reversible*/ { unsigned char ascii[256],*new, *tnew; unsigned char lhigh; unsigned int skeyf1,skeyb1,skeyf2,skeyb2; /*needs to be 4 bytes*/ unsigned char dkeyf1,dkeyf2,dkeyb1,dkeyb2; /*needs to be 1 byte*/ int x=0,y, ksize; unsigned int h=0,g,a,seed; /*need to be 4 bytes, IMPORTANT!*/ unsigned char carry, of, cy; /*sanity checks*/ if (key==NULL || data==NULL) return(NULL); if ((ksize=strlen(key))<1 || dsize<1 || dsize>256) return(NULL); if (cycles<1) cycles=2; else cycles++; /*add 1 cycle for initial mapping*/ /*key forward hash #1 and #2 */ for (seed=1,x=0;key[x]!='\0';x++) { h=(h<<4)+key[x]; if ((g=h&0xf0000000)!=0) h=(h^(g>>24))^g; seed=(seed*((key[x]*3)+x))+1; } y=x-1; /*y holds the position of the last key character*/ skeyf1=h; skeyf2=seed; /*key backward hash #1 and #2 */ for (seed=0,h=0,x=y,a=31415;x>=0;x--,a=(a*27183)%2147483646) { h=(h<<4)+key[x]; if ((g=h&0xf0000000)!=0) h=(h^(g>>24))^g; seed=((a*seed)+key[x])%2147483647; } skeyb1=h; skeyb2=seed; /*generate dkey forward #1 and #2 */ for (seed=0,h=0,x=0;x>24))^g; seed=(251*seed + data[x])%2147483647; } dkeyf1=(h%256); dkeyf2=(seed%256); /*generate dkey backward #1 and #2*/ for (seed=0,h=0,x=dsize-1;x>=0;x--) { h=(h<<4)+data[x]; if ((g=h&0xf0000000)!=0) h=(h^(g>>24))^g; seed=((seed<<4)^data[x])^(seed>>27); } dkeyb1=(h%256); dkeyb2=(seed%256); /*generate initial ASCII array*/ for (x=1;x<255;x++) ascii[x]=x; ascii[0]=255; ascii[255]=0; /*scramble the array at least 4 times with various keys & cycles*/ /*1st scramble: 1-3 cyles*/ seed=skeyf1+(dkeyf1*ksize); if ((cy=dkeyf1&3)==0) cy=1; if ((new=N_lib_scramble(ascii,256,seed,cy))==NULL) { srand48(0); /*clear the internal seed*/ return(NULL); } /*2nd scramble: 1-3 cycles*/ tnew=new; seed=(skeyb2*dkeyb2+1)^lrand48(); if ((cy=(dkeyb1^cycles)&3)==0) cy=1; if ((new=N_lib_scramble(tnew,256,seed,cy))==NULL) { free(tnew); srand48(0); /*clear the internal seed*/ return(NULL); } free(tnew); /*3rd scramble: 1-2 cycles*/ tnew=new; seed=(skeyb1+dkeyb1)^lrand48(); cy=(ksize&1)+1; if ((new=N_lib_scramble(tnew,256,seed,cy))==NULL) { free(tnew); srand48(0); /*clear the internal seed*/ return(NULL); } free(tnew); /*4th scramble: 1-2 cycles*/ tnew=new; seed=(skeyf2*dkeyf2+1)^lrand48(); cy=(key[0]&1)+1; if ((new=N_lib_scramble(tnew,256,seed,cy))==NULL) { free(tnew); srand48(0); /*clear the internal seed*/ return(NULL); } free(tnew); /*allocate new byte string and initialize*/ if ((tnew=malloc(dsize+4))==NULL) { /* +4 for dkeys*/ free(new); srand48(0); /*clear the internal seed*/ return(NULL); } /*copy data into tnew */ bcopy(data,tnew,dsize); /*generate 3rd hash value*/ for (x=0,g=h=0;key[x]!='\0';x++) { g=(g*251 + key[x])%2147483647; h=((h<<4)^key[x])^(h>>27); } seed=g^h; /*encode the dkeys*/ tnew[dsize]=dkeyf1^((seed^skeyf1)&255); tnew[dsize+1]=dkeyf2^((seed^skeyf2)&255); tnew[dsize+2]=dkeyb1^((seed^skeyb1)&255); tnew[dsize+3]=dkeyb2^((seed^skeyb2)&255); /*map data characters to new scrambled array*/ cycles++; /*do at least 2 initial cycles*/ for (y=0;y>3; for (x=dsize-1;x>=0;x--) { of=(tnew[x]&248)>>3; tnew[x]=(tnew[x]<<5)|carry; carry=of; } /*re-map by position*/ for (x=0;x>3; for (x=dsize+3;x>=0;x--) { of=(tnew[x]&248)>>3; tnew[x]=(tnew[x]<<5)|carry; carry=of; } /*re-position pkey randomly*/ for (h=0,x=0;x<(dsize+4);x++) h=h+tnew[x]; /*sum string*/ h*=x; /*x = data length here*/ seed=seed+(h*ksize); /*use seed value from 3rd hash above*/ if ((new=N_lib_scramble(tnew,x,seed,1))==NULL) { free(tnew); srand48(0); /*clear the internal seed*/ return(NULL); } free(tnew); if (esize!=NULL) *esize=x; srand48(0); /*clear the internal seed*/ return((char*)new); } /*end lib_encode() */ char *lib_decode(char *key, char *estring, int esize, int *dsize, short cycles) /*decode an encoded string using a symetric key*/ { unsigned char *enc, ascii[256],tascii[256],*new, *tnew; unsigned char val, vx, vy, *tenc; int skeyf1,skeyb1,skeyf2,skeyb2; unsigned char dkeyf1,dkeyf2,dkeyb1,dkeyb2; int x=0,y,i, *rarray, ksize; unsigned int h=0,g, seed, a, esum; unsigned char carry, of, cy; /*sanity checks*/ if (key==NULL || estring==NULL) return(NULL); if ((ksize=strlen(key))==0 || esize<5 || esize>260) return(NULL); if (cycles<1) cycles=2; else cycles++; /*create copy of estring to work with*/ if ((tenc=(unsigned char*)malloc(esize))==NULL) return(NULL); bcopy(estring,tenc,esize); /*key forward hash #1 and #2 */ for (seed=1,x=0;key[x]!='\0';x++) { h=(h<<4)+key[x]; if ((g=h&0xf0000000)!=0) h=(h^(g>>24))^g; seed=(seed*((key[x]*3)+x))+1; } y=x-1; /*y holds the position of the last key character*/ skeyf1=h; skeyf2=seed; /*key backward hash #1 and #2 */ for (seed=0,h=0,x=y,a=31415;x>=0;x--,a=(a*27183)%2147483646) { h=(h<<4)+key[x]; if ((g=h&0xf0000000)!=0) h=(h^(g>>24))^g; seed=((a*seed)+key[x])%2147483647; } skeyb1=h; skeyb2=seed; /*calculate sum for dkey seed*/ for (esum=0,y=0;y>27); } seed=g^h; /*Now we need to unscramble the string */ if ((rarray=(int*)malloc(esize*sizeof(int)))==NULL) { free(tenc); return(NULL); } srand48(seed+(esum*ksize)); for (x=0;x=0;x--) { val=tenc[x]; tenc[x]=tenc[rarray[x]]; tenc[rarray[x]]=val; } free(rarray); /*do initial bit shift*/ of=(tenc[esize-1]&31)<<3; for (x=0;x>5)|of; of=carry; } /*retrieve the dkeys*/ dkeyf1=tenc[esize-4]^((seed^skeyf1)&255); dkeyf2=tenc[esize-3]^((seed^skeyf2)&255); dkeyb1=tenc[esize-2]^((seed^skeyb1)&255); dkeyb2=tenc[esize-1]^((seed^skeyb2)&255); esize=esize-4; /*dkeys retrieved, set to correct size*/ /*generate ascii array*/ for (x=1;x<255;x++) ascii[x]=x; ascii[0]=255; ascii[255]=0; /*scramble ascii array with various hash values*/ /*1st scramble: 1-3 cycles*/ seed=skeyf1+(dkeyf1*ksize); if ((cy=dkeyf1&3)==0) cy=1; if ((new=N_lib_scramble(ascii,256,seed,cy))==NULL) { free(tenc); srand48(0); /*clear the internal seed*/ return(NULL); } /*2nd scramble: 1-3 cycles*/ tnew=new; seed=(skeyb2*dkeyb2+1)^lrand48(); if ((cy=(dkeyb1^cycles)&3)==0) cy=1; if ((new=N_lib_scramble(tnew,256,seed,cy))==NULL) { free(tenc); free(tnew); srand48(0); /*clear the internal seed*/ return(NULL); } free(tnew); /*3rd scramble: 1-2 cycles*/ tnew=new; seed=(skeyb1+dkeyb1)^lrand48(); cy=(ksize&1)+1; if ((new=N_lib_scramble(tnew,256,seed,cy))==NULL) { free(tenc); free(tnew); srand48(0); /*clear the internal seed*/ return(NULL); } free(tnew); /*4th scramble: 1-2 cylces*/ tnew=new; seed=(skeyf2*dkeyf2+1)^lrand48(); cy=(key[0]&1)+1; if ((new=N_lib_scramble(tnew,256,seed,cy))==NULL) { free(tenc); free(tnew); srand48(0); /*clear the internal seed*/ return(NULL); } free(tnew); /*generate reverse translation array*/ for (x=0;x<256;x++) tascii[new[x]]=x; free(new); enc=tenc; /*translate string into pin values*/ cycles++; /*do at list 2 initial cycles*/ for (i=0;i>5)|of; of=carry; } } /*close shop*/ if (dsize!=NULL) *dsize=esize; srand48(0); /*clear the internal seed*/ return((char*)enc); } /*end lib_decode() */ char *lib_pscramble(unsigned char *original, unsigned char *new, int size) /*scramble a string of bytes*/ { struct tms buffer; unsigned char *buff=NULL; long seed; /*sanity checks*/ if (original==NULL || new==NULL || size<1) return(NULL); if (size==1) { new[0]=original[0]; return((char*)new); } srand48(abs(times(&buffer)-time(0)+lrand48())); seed=lrand48(); if ((buff=N_lib_scramble(original,size,seed,2))==NULL) return(NULL); bcopy(buff,new,size); free(buff); srand48(0); /*clear the internal seed*/ return((char*)new); } /*end lib_pscramble() */ char *lib_scramble(unsigned char *orig, char *new, int size, long seed) /*scramble an array with a supplied key*/ { unsigned char *buff=NULL; /*sanity checks*/ if (orig==NULL || new==NULL || size<1) return(NULL); if (size==1) { new[0]=orig[0]; return(new); } if ((buff=N_lib_scramble(orig,size,seed,1))==NULL) return(NULL); bcopy(buff,new,size); free(buff); srand48(0); /*clear the internal seed*/ return(new); } /*end lib_scramble() */ char *lib_unscramble(unsigned char *str, char *orig, int size, long seed) /*unscramble an array with a supplied key*/ { int x, *array; unsigned char tmp; /*sanity checks*/ if (str==NULL || orig==NULL || size < 1) return(NULL); if (size==1) { orig[0]=str[0]; return(orig); } /*generate array of swap sequences*/ if ((array=(int*)malloc(size*sizeof(int)))==NULL) return(NULL); srand48(seed); for (x=0;x=0;x--) { tmp=orig[x]; orig[x]=orig[array[x]]; orig[array[x]]=tmp; } srand48(0); /*clear the internal seed*/ return(orig); } /*end lib_unscramble() */ unsigned int lib_checksum(char *data, int size, char function) /*calculate a checksum/hash value on a string*/ { unsigned int a,b,x,M=2147483647,h=0,g; if (data==NULL || size<1) return(0); if (function<1) function=1; else if (function>HFUNC) function=HFUNC; if (function==1) { /*CH*/ for (x=0;x>24))^g; } return(h); } if (function==2) { /*M3*/ for (x=0,h=0;x>27); return(h); } if (function==3) { /*B2*/ for (h=0,x=0,a=31415,b=27183;x>7; /*carry bit for end byte*/ for (x=len-1;x>=0;x--) { /*cycle through each byte*/ t2=(str[x]&128) >> 7; /*carry bit for current byte*/ str[x]=str[x]<<1; /*shift left*/ str[x]=str[x]|t; /*add carry bit*/ t=t2; } } else { /*rotate right*/ t=(str[len-1]&1)<<7; /*carry bit for end byte*/ for (x=0;x>1; /*shift right*/ str[x]=str[x]|t; /*add carry bit*/ t=t2; } } return(1); } /*end lib_bitrotate()*/ char *lib_hextobin(unsigned char *str, char *bin, int *dsize) /*convert hex ASCII into binary decimal*/ { int y=0,x=0; unsigned char high, low; /*sanity checks*/ if (str==NULL || bin==NULL) return(NULL); if (strlen((char*)str)<2) return(NULL); /*down to business-process each hex digit pair*/ while (str[y]!='\0' && str[y+1]!='\0') { /*ignore odd man out*/ if ((str[y]>='0') && (str[y]<='9')) high=str[y]-48; else if ((str[y]>='A') && (str[y]<='F')) high=str[y]-55; else if ((str[y]>='a') && (str[y]<='f')) high=str[y]-87; else return(NULL); if ((str[y+1]>='0') && (str[y+1]<='9')) low=str[y+1]-48; else if ((str[y+1]>='A') && (str[y+1]<='F')) low=str[y+1]-55; else if ((str[y+1]>='a') && (str[y+1]<='f')) low=str[y+1]-87; else return(NULL); high=high<<4; bin[x]=high | low; y+=2; x++; } if (dsize!=NULL) *dsize=x; return(bin); } /*end lib_hextobin()*/ char *lib_bintohex(unsigned char *str, int dsize, char *hex, int *hsize) /*convert binary decimal to hex ASCII*/ { int y=0,x; /*sanity checks*/ if (str==NULL || hex==NULL || dsize<1) return(NULL); /*down to business*/ for (x=0;x>4; hex[y+1]=str[x]&15; if (hex[y]<=9) hex[y]+=48; else hex[y]+=55; /*change 55 to 87 for lowercase*/ if (hex[y+1]<=9) hex[y+1]+=48; else hex[y+1]+=55; /*change 55 to 87 for lowercase*/ y+=2; } hex[y]=0; /*nul terminated for convience*/ if (hsize!=NULL) *hsize=y; return(hex); } /*end lib_bintohex()*/ char *lib_invert(unsigned char *text, int size, char pattern, char strict) /*invert bits (defined by _pattern_) of each byte in a string of bytes, except 0's or 255 (if _strict_ is not set) which might break character strings*/ { int x; if (size==0) return((char*)text); for (x=0;x32) count=32; /*32 bit int*/ if (interval<=0) interval=1; /* >= 1 msec*/ fds[0].fd=-1; for (x=0;x>24))^g; } h1=h; for (x=0,h=0;x>27); h2=h; for (h=0,x=0,a=31415,b=27183;x>24; workstr[1]=h2>>24; workstr[2]=h3>>24; workstr[3]=(h1>>16)&255; workstr[4]=(h2>>16)&255; workstr[5]=(h3>>16)&255; workstr[6]=(h1>>8)&255; workstr[7]=(h2>>8)&255; workstr[8]=(h3>>8)&255; workstr[9]=h1&255; workstr[10]=h2&255; workstr[11]=h3&255; workstr[12]=h4>>24; workstr[13]=(h4>>16)&255; workstr[14]=0; /*do a scramble*/ for (h=0,x=0;x>4; if (v<=9) hashstring[size]=v+48; else hashstring[size]=v+87; size++; v=tstr[x]&15; if (v<=9) hashstring[size]=v+48; else hashstring[size]=v+87; size++; } hashstring[size]='\0'; /*done, nul terminate*/ free(tstr); return(hashstring); } /*end lib_makehash()*/ char *lib_pwd_encrypt(char *password, char *new, int *days) /*encrypts a password via DES*/ { char pkey[65]="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890./"; char key[3]; int length; /*generate random salt keys*/ length=strlen(password); srand48(abs(time(0)-lrand48()+password[0])); key[0]=pkey[(int)(64*drand48())]; srand48(abs(rand()+length)); key[1]=pkey[(int)(64*drand48())]; key[2]=0; /*encrypt the password string*/ strcpy(new,(char*)crypt(password,key)); if (days!=NULL) *days=(int)(time(NULL)/86400); return(new); } /*end lib_pwd_encrypt() */ /*******************************************/ /* BEGIN DYNAMIC STRINGS FUNCTIONS SECTION */ /*******************************************/ struct dstring *lib_createStr(char *string) /*allocate memory for a dynamic string and initialize*/ { struct dstring *Str; int x,len; /*sanity checks*/ if (string==NULL) return(NULL); len=strlen(string); Str=(struct dstring*)malloc(sizeof(struct dstring)); if (Str==NULL) return(NULL); Str->buff=(char*)malloc(len+16); if (Str->buff==NULL) { free(Str); return(NULL); } Str->pattern=43690; /*1010 1010 1010 1010 for later checking*/ Str->bufsize=len+16; x=0; while (string[x]!='\0') { Str->buff[x]=string[x]; x++; } Str->buff[x]='\0'; Str->len=len; return(Str); } /*end lib_createStr()*/ int lib_destroyStr(struct dstring *Str) /*destroy a dstring struct*/ { /*sanity checks*/ if (Str==NULL) return(-1); if (Str->pattern!=43690) return(-1); if (Str->buff != NULL) free(Str->buff); free(Str); return(0); } /*end lib_destroyStr()*/ int lib_setStr(struct dstring *Str, char *string) /*set to a new string, returns length*/ { int len; char *nstr; /*sanity checks*/ if (Str==NULL) return(-1); if (Str->pattern!=43690) return(-1); if (string==NULL) return(-1); len=strlen(string); if (lenbufsize) { strcpy(Str->buff,string); Str->len=len; return(Str->len); } nstr=(char*)malloc(len+4); if (nstr==NULL) return(-1); strcpy(nstr,string); free(Str->buff); /*free old string*/ /*install the new string as king*/ Str->buff=nstr; Str->len=len; Str->bufsize=len+4; return(len); } /*end of lib_setStr()*/ int lib_resetStr(struct dstring *Str) /*recalculate the length of a string*/ { int len; /*sanity checks*/ if (Str==NULL) return(-1); if (Str->pattern!=43690) return(-1); len=strlen(Str->buff); if (len>=Str->bufsize) return(-1); /*possibly corrupted*/ Str->len=len; /*set to the new adjusted length*/ return(len); } /*end of lib_resetStr() */ char *lib_getStr(struct dstring *Str) /*return pointer to the string within dstring*/ { if (Str==NULL) return(NULL); if (Str->pattern!=43690 || Str->buff==NULL) return(NULL); return(Str->buff); } /*end lib_getStr()*/ int lib_Strlen(struct dstring *Str) /*return the length of a dynamic string*/ { /*sanity checks*/ if (Str==NULL) return(-1); if (Str->pattern!=43690 || Str->len<0) return(-1); return(Str->len); } /*end lib_Strlen()*/ int lib_Strtrunc(struct dstring *Str, int where) /*truncate the string within dstring*/ { /*sanity checks*/ if (Str==NULL || where<0) return(-1); if (Str->pattern!=43690 || Str->buff==NULL) return(-1); if (where>Str->len) return(Str->len); Str->buff[where]='\0'; /*just truncate, don't reallocate*/ Str->len=where; return(Str->len); } /*end lib_Strtrunc()*/ char *lib_Strcpy(struct dstring *Str, char *string) /*copy a string into a dstring*/ { int len,x, nbuf; char *nptr; /*sanity checks*/ if (Str==NULL || string==NULL) return(NULL); if (Str->pattern!=43690 || Str->buff==NULL) return(NULL); len=strlen(string); if (len==0) return(Str->buff); /*yay, nothing to do*/ if (lenbufsize) { /*is len < than our current buffer?*/ strcpy(Str->buff,string); Str->len=len; return(Str->buff); } else { /*buffer is not large enough*/ nbuf=len+16; /*reallocate more space*/ nptr=(char*)realloc(Str->buff,nbuf); if (nptr==NULL) return(NULL); /*make no changes on error*/ Str->bufsize=nbuf; /*safe to change now*/ Str->buff=nptr; for(x=0;xbufsize-1;x++) { Str->buff[x]=string[x]; if (string[x]=='\0') break; } Str->len=x; Str->buff[x]='\0'; /*safety first, in all our work or play*/ } return(Str->buff); } /*end lib_Strcpy()*/ char *lib_Strncpy(struct dstring *Str, char *string, int limit) /*do a limited copy of s string into a dynamic string*/ { int len, x, nbuf; char *nptr; /*sanity checks*/ if (Str==NULL || string==NULL) return(NULL); if (Str->pattern!=43690 || Str->buff==NULL) return(NULL); if (limit<0) return(NULL); if (limit==0) { /*pointless...*/ Str->buff[0]='\0'; Str->len=0; return(Str->buff); } len=strlen(string); if (len==0) return(Str->buff); /*yay, nothing to do*/ if (limit>len) limit=len; /*ah simplicity*/ if (limit < Str->bufsize) { strncpy(Str->buff,string,limit); Str->len=limit; /*nullify, whether strncpy() does or not. dumb behavior by*/ /*strncpy, but I'm sure there must have been a reason for it*/ Str->buff[limit]='\0'; return(Str->buff); } else { /*buffer is not large enough*/ nbuf=limit+16; /*reallocate more space*/ nptr=(char*)realloc(Str->buff,nbuf); if (nptr==NULL) return(NULL); /*make no changes on error*/ Str->bufsize=nbuf; /*safe to change now*/ Str->buff=nptr; for(x=0;xbufsize-1;x++) { Str->buff[x]=string[x]; if (string[x]=='\0') break; } Str->len=x; Str->buff[x]='\0'; /*safety first, in all our work or play*/ } return(Str->buff); } /*end lib_Strncpy()*/ char *lib_Strcat(struct dstring *Str, char *string) /*catenate a string to a dstring*/ { int len, nlen; char *tmp; if (Str==NULL || string==NULL) return(NULL); if (Str->pattern!=43690 || Str->buff==NULL) return(NULL); len=strlen(string); if (len==0) return(Str->buff); if (Str->len+len >= Str->bufsize) { /*grow buffer*/ nlen=Str->len+len+16; tmp=Str->buff; tmp=realloc(Str->buff,nlen); if (tmp==NULL) return(NULL); Str->bufsize=nlen; Str->buff=tmp; } strncat(Str->buff,string,Str->bufsize); Str->buff[Str->bufsize-1]='\0'; Str->len=Str->len+len; return(Str->buff); } /*end lib_Strcat()*/ char *lib_Strncat(struct dstring *Str, char *string, int clen) /*do a limited concatenate of a string to a dstring*/ { int len, nlen; char *tmp; if (Str==NULL || string==NULL || clen<0) return(NULL); if (Str->pattern!=43690 || Str->buff==NULL) return(NULL); len=strlen(string); if (len==0) return(Str->buff); if (clen>len) clen=len; if (Str->len+clen >= Str->bufsize) { /*grow buffer*/ nlen=Str->len+clen; nlen=nlen+16; /*extra bytes*/ tmp=Str->buff; tmp=realloc(Str->buff,nlen); if (tmp==NULL) return(NULL); Str->bufsize=nlen; Str->buff=tmp; } strncat(Str->buff,string,clen); Str->len=Str->len+clen; Str->buff[Str->len]='\0'; return(Str->buff); } /*end lib_Strncat()*/ int lib_Sprintf(struct dstring *Str, char *fmt, ...) /*do an sprintf with a dynamic string*/ { va_list ap; char *p; long lval; void *pval; int ival, count=0,size,scount; double dval; char buff[32], type, format[8]; if (Str==NULL || fmt==NULL) return(-1); if (Str->pattern!=43690 || Str->buff==NULL) return(-1); va_start(ap, fmt); for (p=fmt;*p; p++) { if (*p!='%') { count++; continue; } p++; if (*p=='%') { count++; continue; } type=N_getformat(&p,format,&size); switch (type) { case 's' : count=(scount=strlen(va_arg(ap, char*)))+count; if (scountbufsizebuff!=NULL) free(Str->buff); Str->buff=p; Str->bufsize=count+32; } va_start(ap, fmt); vsprintf(Str->buff,fmt,ap); va_end(ap); Str->len=strlen(Str->buff); /*_SHOULD_ equal count*/ return(Str->len); } /*end lib_Sprintf()*/ int lib_Strcasecmp(struct dstring *s1, struct dstring *s2) /*a version of strcasecmp() for dstrings*/ { int rv; /*sanity checks*/ if (s1==NULL || s2==NULL) return(-2); if (s1->pattern!=43690 || s1->buff==NULL) return(-2); if (s2->pattern!=43690 || s2->buff==NULL) return(-2); rv=strcasecmp(s1->buff,s2->buff); if (rv<0) rv=-1; else if (rv>0) rv=1; return(rv); } /*end of lib_Strcasecmp()*/ int lib_Strncasecmp(struct dstring *s1, struct dstring *s2, int n) /*a version of strncasecmp() for dstrings*/ { int rv; /*sanity checks*/ if (s1==NULL || s2==NULL || n<1) return(-2); if (s1->pattern!=43690 || s1->buff==NULL) return(-2); if (s2->pattern!=43690 || s2->buff==NULL) return(-2); rv=strncasecmp(s1->buff,s2->buff,n); if (rv<0) rv=-1; else if (rv>0) rv=1; return(rv); } /*end of lib_Strncasecmp()*/ int lib_Strcmp(struct dstring *s1, struct dstring *s2) /*a version of strcmp() for dstrings*/ { int rv; /*sanity checks*/ if (s1==NULL || s2==NULL) return(-2); if (s1->pattern!=43690 || s1->buff==NULL) return(-2); if (s2->pattern!=43690 || s2->buff==NULL) return(-2); rv=strcmp(s1->buff,s2->buff); if (rv<0) rv=-1; else if (rv>0) rv=1; return(rv); } /*end of lib_Strcmp()*/ int lib_Strncmp(struct dstring *s1, struct dstring *s2, int n) /*a version of strncmp() for dstrings*/ { int rv; /*sanity checks*/ if (s1==NULL || s2==NULL || n<1) return(-2); if (s1->pattern!=43690 || s1->buff==NULL) return(-2); if (s2->pattern!=43690 || s2->buff==NULL) return(-2); rv=strncmp(s1->buff,s2->buff,n); if (rv<0) rv=-1; else if (rv>0) rv=1; return(rv); } /*end of lib_Strncmp()*/ int lib_insertStr(struct dstring *s1, char *s2, short where) /*midstring substitution, returns new length, or -1 on error*/ { char *newstr; int nlen, len; /*sanity checks*/ if (s1==NULL || s2==NULL) return(-1); if (s1->pattern!=43690 || s1->buff==NULL) return(-2); if (where> s1->len || where <0) return(-1); len=strlen(s2); if (len==0) return(s1->len); /*now down to bidness*/ nlen=len+s1->len; newstr=(char*)malloc(nlen+4); if (newstr==NULL) return(-1); strncpy(newstr,s1->buff,where); newstr[where]='\0'; strcat(newstr,s2); strcat(newstr,&s1->buff[where]); free(s1->buff); s1->bufsize=nlen+4; s1->len=nlen; s1->buff=newstr; return(s1->len); } /*end of lib_insertStr()*/ int lib_replaceStr(struct dstring *s1, char *old, char *new) /*replace matching pattern,returns -1=error, or # of items replaced*/ { int olen, nlen, tlen, ocount=0, crange; char *strpos, *npos, *nstr, *cpos; /*sanity checks*/ if (s1==NULL || old==NULL || new==NULL) return(-1); if (s1->pattern!=43690 || s1->buff==NULL) return(-1); if ((olen=strlen(old))==0) return(-1); /*see if we need more space*/ nlen=strlen(new); strpos=s1->buff; while ((npos=strstr(strpos,old))!=NULL) { ocount++; strpos=npos+olen; } if (ocount==0) return(0); /*old not found*/ tlen=s1->len-(olen*ocount)+(nlen*ocount); nstr=(char*)malloc(tlen+4); if (nstr==NULL) return(-1); nstr[0]='\0'; strpos=s1->buff; npos=strstr(strpos,old); cpos=nstr; while (npos!=NULL) { if (npos>strpos) { /*copy static block*/ crange=npos-strpos; strncat(cpos,strpos,crange); cpos=cpos+crange; } strcat(cpos,new); /*copy new*/ strpos=npos+olen; cpos=cpos+nlen; npos=strstr(strpos,old); } crange=&s1->buff[s1->len]-npos; strcat(cpos,strpos); /*final copy*/ /*set up new string*/ s1->bufsize=tlen+4; s1->len=tlen; free(s1->buff); s1->buff=nstr; return(ocount); } /*end of lib_replaceStr()*/ int lib_sreplaceStr(struct dstring *s1, char *old, char *new, short which) /*replace a matching pattern,returns: 1=found, 0=not found, -1=error*/ { int x, y, olen, nlen, tlen, ocount=0, done=0, crange; char *bstr, *ostr, *rstr=NULL, *rold=NULL, *nstr, *rnew, *npos; /*sanity checks*/ if (s1==NULL || old==NULL || new==NULL) return(-1); if (s1->pattern!=43690 || s1->buff==NULL) return(-2); if ((olen=strlen(old))==0) return(-1); if (which==0) which=1; tlen=s1->len; nlen=strlen(new); if (which<0) { /*select from the end*/ rstr=(char*)malloc(s1->len + 1); if (rstr==NULL) return(-1); rold=(char*)malloc(olen+1); if (rold==NULL) { free(rstr); return(-1); } /*first, reverse base string*/ for (x=0,y=s1->len-1;xlen;x++,y--) { rstr[x]=s1->buff[y]; } rstr[s1->len]='\0'; for (x=0,y=olen-1;xbuff); if (bstr==NULL) return(-1); ostr=strdup(old); if (ostr==NULL) { free(bstr); return(-1); } rnew=strdup(new); if (rnew==NULL) { free(bstr); free(ostr); return(-1); } } /*first find what we're looking for*/ npos=bstr; while ((npos=strstr(npos,ostr))!=NULL) { ocount++; if (ocount==abs(which)) { done=1; break; } npos=npos+olen; } if (done==0) { /*hmmm, we don't have that many or didn't find it*/ free(bstr); free(ostr); return(0); /*not found*/ } /*at this point, _npos_ points to the start of our replacement*/ /*do the substitution*/ tlen=s1->len-olen+nlen; nstr=malloc(tlen+4); if (nstr==NULL) { free(bstr); free(ostr); free(rnew); return(-1); } crange=npos-bstr; strncpy(nstr,bstr,crange); nstr[crange]='\0'; strcat(nstr,rnew); npos=npos+olen; strcat(nstr,npos); if (which<0) { /*we must re-reverse nstr*/ char c; for (x=0,y=tlen-1;xlen=tlen; s1->bufsize=tlen+4; free(s1->buff); s1->buff=nstr; return(1); /*should be only 1 replaced*/ } /*end of lib_sreplaceStr()*/ struct dstring *lib_Strdup(struct dstring *str) /*duplicate existing dynamic string*/ { struct dstring *nstr; /*sanity checks*/ if (str==NULL) return(NULL); if (str->pattern!=43690) return(NULL); nstr=(struct dstring*)malloc(sizeof(struct dstring)); if (nstr==NULL) return(NULL); nstr->buff=(char*)malloc(str->len+16); if (nstr->buff==NULL) { free(nstr); return(NULL); } strcpy(nstr->buff,str->buff); nstr->len=str->len; nstr->pattern=43690; nstr->bufsize=str->len+16; return(nstr); } /*end of lib_Strdup()*/ int lib_freeall_Str(struct dstring **ptr, ...) /*multiple destroy calls in one for dstring data types*/ { struct dstring **rptr, *aptr; va_list ap; if (ptr==NULL) return(0); rptr=ptr; aptr=*rptr; if (aptr!=NULL) { if (aptr->buff!=NULL && aptr->bufsize>0) free(aptr->buff); free(aptr); *rptr=NULL; } va_start(ap,ptr); for (;;) { rptr=va_arg(ap,struct dstring**); if (rptr==NULL) break; aptr=*rptr; if (aptr!=NULL) { if (aptr->buff!=NULL && aptr->bufsize>0) free(aptr->buff); free(aptr); /*free the dstring struct*/ *rptr=NULL; } } va_end(ap); return(0); } /*end of lib_freeall_Str()*/ /*****************************************/ /* BEGIN DYNAMIC ARRAY FUNCTIONS SECTION */ /*****************************************/ struct darray_type *lib_darray_create(int initsize) /*allocate initial structs and populate values*/ { void *aptr; struct darray_type *d; int x; /*sanity checks*/ if (initsize<0) return(NULL); if (initsize==0) initsize=16; d=(struct darray_type*)malloc(sizeof(struct darray_type)); if (d==NULL) return(NULL); aptr=(void*)malloc(sizeof(void*)*initsize); if (aptr==NULL) { free(d); return(NULL); } d->size=0; d->maxlistsize=initsize; d->items=aptr; for (x=0;xmaxlistsize;x++) d->items[x]=NULL; return(d); } /*end lib_darray_create()*/ int lib_darray_discard(struct darray_type *d) /*free all structs - ignore pointers in array*/ { /*sanity check*/ if (d==NULL) return(-1); if (d->items!=NULL) free(d->items); free(d); d=NULL; return(0); } /*end lib_darray_discard()*/ int lib_darray_clear(struct darray_type *d) /*clear array, ignore values in array - externally managed*/ { int x; /*sanity checks*/ if (d==NULL) return(-1); if (d->items==NULL) return(-1); for (x=0;xsize;x++) d->items[x]=NULL; d->size=0; return(0); } /*end lib_darray_clear()*/ int lib_darray_free(struct darray_type *d) /*free's all times in the array - careful doing this*/ { int x; if (d==NULL) return(-1); if (d->size==0) return(0); if (d->size<0 || d->maxlistsize<0 || d->size>d->maxlistsize) return(-1); for (x=0;xsize;x++) { if (d->items[x]!=NULL) free(d->items[x]); d->items[x]=NULL; } return(1); } /*end lib_darray_free()*/ int lib_darray_add(struct darray_type *d, void *data) /*adds a new pointer to the end of the array*/ { void *nptr; int x; /*sanity checks*/ if (d==NULL) return(-1); if (d->items==NULL) return(-1); if (d->size >= d->maxlistsize-1) { nptr=(void*)realloc(d->items,(d->maxlistsize+16)*sizeof(void*)); if (nptr==NULL) return(-1); d->items=nptr; d->maxlistsize+=16; for (x=d->size;xmaxlistsize;x++) d->items[x]=NULL; } d->items[d->size]=data; d->size++; return(d->size); } /*end lib_darray_add()*/ int lib_darray_insert(struct darray_type *d, void *data, int which) /*inserts an item at a certain location making room for it*/ /*function returns number of items in array*/ { void *nptr; int x; /*sanity checks*/ if (d==NULL) return(-1); if (d->items==NULL) return(-1); if (which>=d->size || which<0) return(-1); /*out of range*/ if (d->size >= d->maxlistsize-1) { nptr=(void*)realloc(d->items,(d->maxlistsize+16)*sizeof(void*)); if (nptr==NULL) return(-1); d->items=nptr; d->maxlistsize+=16; for (x=d->size;xmaxlistsize;x++) d->items[x]=NULL; } if (which==d->size) { /*if at the end*/ d->items[d->size]=data; d->size++; return(d->size); } /*in the middle or beginning, move after block forward*/ for (x=d->size;x>which;x--) d->items[x]=d->items[x-1]; d->items[which]=data; d->size++; return(d->size); } /*end lib_darray_insert()*/ void *lib_darray_delete(struct darray_type *d, int which) /*remove an item filling in the space*/ { int x; void *dptr; /*sanity checks*/ if (d==NULL) return(NULL); if (d->items==NULL) return(NULL); if (which>=d->size || which<0) return(NULL); dptr=d->items[which]; d->size--; for (x=which;xsize;x++) d->items[x]=d->items[x+1]; return(dptr); } /*end lib_darray_delete()*/ void *lib_darray_fastdel(struct darray_type *d, int which) /*remove item and put last item in its place - ignore order*/ { void *nptr; /*sanity checks*/ if (d==NULL) return(NULL); if (d->items==NULL) return(NULL); if (which>=d->size || which<0) return(NULL); if (d->size==0) return(NULL); nptr=d->items[which]; d->size--; if (d->size==0) d->items[0]=NULL; /*empty now, set to NULL*/ else d->items[which]=d->items[d->size]; return(nptr); /*return removed items*/ } /*end lib_darray_fastdel()*/ void *lib_darray_get(struct darray_type *d, int which) /*return item at specified position*/ { /*sanity checks*/ if (d==NULL) return(NULL); if (d->items==NULL) return(NULL); if (which>=d->size || which<0) return(NULL); return(d->items[which]); } /*end lib_darray_get()*/ void *lib_darray_replace(struct darray_type *d, void *data, int which) /*replace a specific item*/ { void *nptr; /*sanity checks*/ if (d==NULL) return(NULL); if (d->items==NULL) return(NULL); if (which>=d->size || which<0) return(NULL); nptr=d->items[which]; d->items[which]=data; return(nptr); } /*end lib_darray_replace()*/ int lib_darray_swap(struct darray_type *d, int first, int second) /*swap two items, return 0 on success*/ { void *nptr; /*sanity checks*/ if (d==NULL) return(-1); if (d->items==NULL) return(-1); if (first>=d->size || first<0) return(-1); if (second>=d->size || second<0) return(-1); if (first==second) return(d->size); /*please...*/ nptr=d->items[first]; d->items[first]=d->items[second]; d->items[second]=nptr; return(d->size); } /*end lib_darray_swap()*/ int lib_darray_getsize(struct darray_type *d) /*return number of items*/ { /*sanity checks*/ if (d==NULL) return(-1); if (d->items==NULL) return(-1); return(d->size); } /*end lib_darray_getsize()*/ int lib_darray_blkdel(struct darray_type *d, int first, int size, int nfree) /*delete a block from the darray*/ { int x, pos, cs; /*sanity checks*/ if (d==NULL) return(-1); if (d->items==NULL) return(-1); if (first>=d->size || first<0) return(-1); if (size<0) return(-1); /*check true size of block delete*/ if ((d->size-first) < size) size=d->size-first; if (first+size==d->size) { /*ooh easy*/ for (x=0;x0 && d->items[first+x]!=NULL) free(d->items[first+x]); d->items[first+x]=NULL; } d->size=first; return(d->size); } /*reposition and fill gap*/ pos=first+size; /*first position after the deleted block*/ cs=d->size-pos; /*copy size*/ for (x=0;x0 && d->items[first+x]!=NULL) free(d->items[first+x]); d->items[first+x]=d->items[pos+x]; d->items[pos+x]=NULL; } d->size=d->size-size; return(d->size); } /*end lib_darray_blkdel()*/ struct darray_type *lib_darray_blkpull(struct darray_type *d, int f, int size) /*pull a block from the old darray and put in a new one*/ { struct darray_type *da; int x, pos, cs; /*sanity checks*/ if (d==NULL || f<0) return(NULL); if (d->size<=0 || f>d->size) return(NULL); if (d->items==NULL) return(NULL); if (size<0 || f<0) return(NULL); /*allocate memory for new darray*/ if (size+f > d->size) size=d->size-f; /*get real size*/ da=(struct darray_type*)malloc(sizeof(struct darray_type)); if (da==NULL) return(NULL); da->items=(void**)malloc((size+4)*sizeof(void*)); if (da->items==NULL) { free(da); return(NULL); } /*initialize new darray*/ da->maxlistsize=size+4; da->size=size; for (x=0;xmaxlistsize;x++) da->items[x]=NULL; /*move items from old da to the new one*/ for (x=0;xitems[x]=d->items[f+x]; d->items[f+x]=NULL; } /*reposition remaining items*/ pos=f+size; cs=d->size-pos; /*copy size*/ for (x=0;xitems[f+x]=d->items[pos+x]; d->items[pos+x]=NULL; } d->size=d->size-size; return(da); } /*end lib_darray_blkpull()*/ int lib_darray_blkinsert(struct darray_type *d, struct darray_type *add, int where) /*insert a block from another*/ { void *nptr; int x, pos, size, asize; /*sanity checks*/ if (d==NULL || add==NULL) return(-1); if (where<0 ||d->size<=0 || add->size<=0) return(-1); if (where>d->size || d->items==NULL || add->items==NULL) return(-1); size=d->size+add->size; /*total # of items*/ asize=size+4; /*put in a little breathing room*/ if (d->maxlistsize <= size) { /*must make room*/ nptr=(void*)realloc(d->items,asize*sizeof(void*)); if (nptr==NULL) return(-1); d->maxlistsize=asize; } if (where!=d->size) { /*must move items up to make room*/ pos=d->size+add->size-1; for (x=d->size;x>=where;x--) d->items[x+add->size]=d->items[x]; } /*now insert items*/ for (x=0;xsize;x++) d->items[where+x]=add->items[x]; d->size+=add->size; return(d->size); } /*end lib_darray_blkinsert()*/ struct darray_type *lib_darray_blkget(struct darray_type *d, int f, int size) /*return a copy of a block from the darray*/ { struct darray_type *da; int x; /*sanity checks*/ if (d==NULL || f<0) return(NULL); if (d->size<=0 || f>d->size || size>d->size) return(NULL); if (d->items==NULL) return(NULL); /*allocate memory for new darray*/ da=(struct darray_type*)malloc(sizeof(struct darray_type)); if (da==NULL) return(NULL); if (f+size > d->size) size=d->size-f; da->items=(void**)malloc((size+4)*sizeof(void*)); if (da->items==NULL) { free(da); return(NULL); } /*initialize new darray*/ da->maxlistsize=size+4; da->size=size; for (x=0;xmaxlistsize;x++) da->items[x]=NULL; /*move items from old da to the new one*/ for (x=0;xitems[x]=d->items[f+x]; return(da); } /*end lib_darray_blkget()*/ int lib_darray_dlisttrans(struct darray_type *d, struct dlist_type *dl) /*transfer the contents of a dlist into a darray*/ { int asize, pos; void *nptr; /*sanity checking*/ if (d==NULL || dl==NULL) return(-1); if (d->size<0 || dl->size<0) return(-1); if (d->items==NULL || dl->item==NULL) return(-1); /*check availbable space in _d_ */ if ((d->size+dl->size) >= d->maxlistsize) { /*more space needed*/ asize=d->size+dl->size+4; nptr=(void*)realloc(d->items,asize*sizeof(void*)); if (nptr==NULL) return(-1); d->maxlistsize=asize; d->items=nptr; } /*copy elements over*/ for (pos=0;possize;pos++) { d->items[d->size]=dl->item[pos]; d->size++; } return(d->size); } /*end lib_darray_dlisttrans()*/ int lib_freeall_darray(struct darray_type **ptr,...) /*multiple destroy calls in one for darray_type data types*/ { struct darray_type **rptr, *aptr; va_list ap; if (ptr==NULL) return(0); rptr=ptr; aptr=*rptr; if (aptr!=NULL) { if (aptr->items!=NULL && aptr->maxlistsize>0) free(aptr->items); free(aptr); *rptr=NULL; } va_start(ap,ptr); for (;;) { rptr=va_arg(ap,struct darray_type**); if (rptr==NULL) break; aptr=*rptr; if (aptr!=NULL) { if (aptr->items!=NULL && aptr->maxlistsize>0) free(aptr->items); free(aptr); *rptr=NULL; } } va_end(ap); return(0); } /*end of lib_freeall_darray()*/ /*******************************************/ /* BEGIN ASYCHRONOUS I/O FUNCTIONS SECTION */ /*******************************************/ struct aio_type *lib_aio_create(int rdfd, int wrfd, int rdsize, int wrsize) /*create a new aio struct and initialize it, no IO action*/ { struct aio_type *aio; int rflags=0, wflags=0; /*sanity checks*/ if (rdfd<0 && wrfd<0) return(NULL); /*no valid FDs*/ if (rdfd>=0 && wrsize<1) return(NULL); /*no valid read buffers*/ if (wrfd>=0 && wrsize<1) return(NULL); /*no valid write buffers*/ if (wrfd>=0) wflags=fcntl(wrfd, F_GETFL,0); if (rdfd>=0) rflags=fcntl(rdfd, F_GETFL,0); if (wflags<0 || rflags<0) return(NULL); /*memory allocations*/ aio=(struct aio_type*)malloc(sizeof(struct aio_type)); if (aio==NULL) return(NULL); if (rdsize>0 && rdfd>=0) { aio->readbuf=malloc(rdsize); if (aio->readbuf==NULL) { free(aio); return(NULL); } aio->rdbufsz=rdsize; } else aio->readbuf=NULL; if (wrsize>0 && wrfd>=0) { aio->writebuf=malloc(wrsize); if (aio->writebuf==NULL) { if (aio->readbuf!=NULL) free(aio->readbuf); free(aio); return(NULL); } aio->wrbufsz=wrsize; } else aio->writebuf=NULL; aio->readfd=rdfd; aio->writefd=wrfd; aio->rderrno=0; aio->wrerrno=0; aio->readqsz=0; aio->writeqsz=0; aio->rdreqsz=0; aio->rflags=rflags; aio->wflags=wflags; if (wrfd>=0) { /*turn on non-blocking*/ if (fcntl(aio->writefd, F_SETFL,aio->wflags|O_NONBLOCK)<0) { if (aio->readbuf!=NULL) free(aio->readbuf); free(aio->writebuf); free(aio); return(NULL); } } if (rdfd>=0 && rdfd!=wrfd) { /*turn on non-blocking*/ if (fcntl(aio->readfd, F_SETFL,aio->rflags|O_NONBLOCK)<0) { if (aio->writebuf!=NULL) free(aio->writebuf); free(aio->readbuf); free(aio); return(NULL); } } return(aio); } /*end lib_aio_create() */ int lib_aio_discard(struct aio_type *aio, int reset) /*discard and free memory for aio struct, no IO action*/ { /*sanity checks*/ if (aio==NULL) return(-1); if (aio->writebuf!=NULL) free(aio->writebuf); if (aio->readbuf!=NULL) free(aio->readbuf); /*restore (possible) non-blocking state of file descriptors*/ if (aio->writefd>=0 && reset==1) fcntl(aio->writefd, F_SETFL,aio->wflags); /*restore*/ if (aio->readfd!=aio->writefd && aio->readfd>=0 && reset==1) fcntl(aio->readfd, F_SETFL, aio->rflags); free(aio); return(1); } /*end lib_aio_discard()*/ int lib_aio_resize(struct aio_type *aio, int *newrdsz, int *newwrsz, int flag) /*resize|grow read and/or write buffers, no IO action*/ { char *tptr; /*sanity checks*/ if (aio==NULL || flag<0) return(-1); if (newrdsz==NULL && newwrsz==NULL) return(-1); if (flag>0) { /*set values as specified*/ if (newrdsz!=NULL) { /*check to set*/ if (*newrdsz < aio->rdbufsz) return(-1); if (*newrdsz > aio->rdbufsz) { tptr=realloc(aio->readbuf,*newrdsz); if (tptr!=NULL) { aio->readbuf=(unsigned char*)tptr; aio->rdbufsz=*newrdsz; } else return(-1); /*failed*/ } /*else do nothing if same size*/ } if (newwrsz!=NULL) { /*check to set*/ if (*newwrsz < aio->wrbufsz) return(-1); if (*newwrsz > aio->wrbufsz) { tptr=realloc(aio->writebuf,*newwrsz); if (tptr!=NULL) { aio->writebuf=(unsigned char*)tptr; aio->wrbufsz=*newwrsz; } else return(-1); /*failed*/ } /*else do nothing if same size*/ } } else { /*flag==0, return current values only */ if (newrdsz!=NULL) *newrdsz=aio->rdbufsz; if (newwrsz!=NULL) *newwrsz=aio->wrbufsz; } return(1); } /*end lib_aio_resize()*/ int lib_aio_read(struct aio_type *aio, char *buffer, int bufsize, int *bread) /*try to read bytes from fd and queue if not enough*/ { int x, cr; /*sanity checks*/ if (aio==NULL || buffer==NULL) return(-1); if (aio->readbuf==NULL || aio->rdbufsz==0) return(-1); if (bufsize<0 || aio->readfd<0) return(-1); if (bufsize>aio->rdbufsz) return(-2); /*queue isn't that large*/ if (bufsize==0) { if (aio->readqsz<=0) { aio->rdreqsz=0; return(0); } else return(aio->readqsz); /*data queued, can't reset to 0*/ } /*quick checks*/ if (aio->readqsz>=bufsize) { /*if already data in buffer, return it*/ bcopy(aio->readbuf,buffer,bufsize); for (x=0;xreadbuf[x]=aio->readbuf[x+bufsize]; aio->readqsz=aio->readqsz-bufsize; aio->rdreqsz=bufsize; /*set it anyway, even if fulfilled*/ aio->rderrno=0; if (bread!=NULL) *bread=bufsize; return(0); } aio->rdreqsz=bufsize; /*set how many bytes we're looking for*/ aio->rderrno=0; cr=read(aio->readfd,&aio->readbuf[aio->readqsz],aio->rdreqsz-aio->readqsz); if (cr<0) { /*error status, check it*/ if (errno==EAGAIN) { aio->rderrno=EINPROGRESS; return(aio->rdreqsz-aio->readqsz); } aio->rderrno=errno; return(-3); /*unknown error*/ } if (cr==0) { /*hmmm, other end closed, return what we got*/ if (bread!=NULL) *bread=aio->readqsz; bcopy(aio->readbuf,buffer,aio->readqsz); if (bread!=NULL) *bread=aio->readqsz; aio->readqsz=0; /*empty*/ aio->rdreqsz=0; /*done, clear it*/ aio->rderrno=0; return(0); /*done, though special conditions exist*/ } /*if still here, read something, add to queue and check size*/ aio->readqsz=aio->readqsz+cr; if (aio->readqsz>=bufsize) { /*shouldn't be larger, but copy*/ bcopy(aio->readbuf,buffer,bufsize); aio->readqsz=0; /*should be no more*/ aio->rdreqsz=bufsize; /*done, but set it for future*/ if (bread!=NULL) *bread=bufsize; aio->rderrno=0; return(0); } /*still here, then we don't have all the requested amount yet*/ return(aio->rdreqsz-aio->readqsz); } /*lib_aio_read()*/ int lib_aio_write(struct aio_type *aio, char *buffer, int bufsize) /*try to write bytes from fd and queue if blocks*/ { int x, st, saved; /*sanity checks*/ if (aio==NULL || buffer==NULL) return(-1); if (aio->writebuf==NULL) return(-1); if (bufsize<1 || bufsize>aio->wrbufsz) return(-1); if (bufsize==0 && aio->writeqsz==0) return(0); /*check if any lingering write data*/ if (aio->writeqsz>0) { /*there IS some buffered data*/ /*first check if we can add to buffer*/ if (bufsize+aio->writeqsz <= aio->wrbufsz) { /*it will fit, copy data into buffer*/ for (x=0;xwritebuf[aio->writeqsz]=buffer[x]; aio->writeqsz++; } /*now attempt to write entire buffer*/ aio->wrerrno=0; st=write(aio->writefd,aio->writebuf,aio->writeqsz); if (st<0) { /*got an error*/ if (errno==EAGAIN) { aio->wrerrno=EINPROGRESS; return(aio->writeqsz); /*queued*/ } aio->wrerrno=errno; return(-3); /*unknown error*/ } if (st==aio->writeqsz) { /*got it all written*/ aio->wrerrno=0; aio->writeqsz=0; return(0); } else { /*some written, queue the rest*/ int saved; saved=aio->writeqsz-st; for (x=0;xwritebuf[x]=aio->writebuf[st+x]; aio->writeqsz=saved; return(aio->writeqsz); } } else { /*can't add to buffer, must flush first*/ aio->wrerrno=0; st=write(aio->writefd,aio->writebuf,aio->writeqsz); if (st<=0) { aio->wrerrno=errno; if (errno==EAGAIN) return(-2); /*can't queue*/ else return(-3); /*unknown error*/ } if (st==aio->writeqsz) { /*great!, got it all*/ aio->writeqsz=0; flushonly: if (bufsize>aio->wrbufsz) return(-2); /*try to write incoming buffer now*/ st=write(aio->writefd,buffer,bufsize); if (st==bufsize) return(0); /*all done*/ if (st<0) { if (errno==EAGAIN) { /*full, just Q */ for (x=0;xwritebuf[x]=buffer[x]; aio->writeqsz++; } aio->wrerrno=EINPROGRESS; return(aio->writeqsz); } /*else return error type*/ aio->wrerrno=errno; return(-3); /*error*/ } /*wrote something out, queue the rest*/ saved=bufsize-st; bcopy(&buffer[st],aio->writebuf,saved); aio->writeqsz=saved; return(aio->writeqsz); } } /*end too big, flush only*/ } /*end if buffered data*/ else goto flushonly; /*try to write, else queue*/ return(aio->writeqsz); /*should never get here...in theory*/ } /*end lib_aio_write()*/ int lib_aio_rewrite(struct aio_type *aio, int force) /*attempt write flush of queued data*/ { int x, st, err; /*sanity checks*/ if (aio==NULL) return(-1); if (aio->writefd<0) return(-1); if (aio->writeqsz==0) return(0); if (force) { st=fcntl(aio->writefd, F_SETFL, aio->wflags&~O_NONBLOCK); if (st<0) return(-3); } st=write(aio->writefd, aio->writebuf, aio->writeqsz); err=errno; if (force) { /*set back to non-blocking*/ fcntl(aio->writefd, F_SETFL,aio->wflags|O_NONBLOCK); } if (st>0) { /*got something out*/ if (st==aio->writeqsz) { /*all done!*/ aio->writeqsz=0; aio->wrerrno=0; return(0); } /*else re-arrange buffer to fill in free space*/ for (x=0;xwritebuf[x]=aio->writebuf[st+x]; aio->writeqsz=aio->writeqsz-st; return(aio->writeqsz); } if (st<0) { if (err!=EAGAIN) { aio->wrerrno=err; return(-3); /*unknown error*/ } else aio->wrerrno=EINPROGRESS; } return(aio->writeqsz); } /*end lib_aio_rewrite()*/ int lib_aio_reread(struct aio_type *aio, int force) /*re-try read to fill buffer and return if successful*/ { int cr, st; /*sanity checks*/ if (aio==NULL) return(-1); if (aio->rdbufsz<=0) return(-1); if (aio->readfd<0) return(-1); if (aio->rdreqsz==0) return(0); /*nothing to do*/ /*quick checks*/ if (aio->readqsz==aio->rdreqsz) { return(0); /*return remainder to read, 0 means done*/ } if (force) { st=fcntl(aio->readfd, F_SETFL, aio->rflags&~O_NONBLOCK); if (st<0) { /*unknown error*/ aio->rderrno=errno; return(-3); } } aio->rderrno=0; cr=read(aio->readfd,&aio->readbuf[aio->readqsz],aio->rdreqsz-aio->readqsz); if (cr<0) aio->rderrno=errno; /*set in case fcntl (below) changes*/ if (force) { /*set back to non-blocking*/ fcntl(aio->readfd, F_SETFL,aio->rflags|O_NONBLOCK); } if (cr<0) { if (aio->rderrno==EAGAIN) { aio->rderrno=EINPROGRESS; return(aio->rdreqsz-aio->readqsz); } return(-3); /*unknown I/O error*/ } if (cr==0) { /*hmmm, 0 read, closed at other end, return done*/ return(0); /*tell them done, even if less than requested*/ } aio->readqsz=aio->readqsz+cr; return(aio->rdreqsz-aio->readqsz); /*if still here, more to be queued*/ } /*end lib_aio_reread() */ int lib_aio_readret(struct aio_type *aio, char *buffer, int bufsize) /*return the bytes read so far, up to _bufsize_*/ /*does NOT reset rdreqsz*/ { int csize, x; /*sanity checks*/ if (aio==NULL || buffer==NULL) return(-1); if (aio->readbuf==NULL || aio->rdbufsz==0) return(-1); if (bufsize<0 || aio->readfd<0) return(-1); if (aio->rdreqsz==0 || aio->readqsz==0) return(0); /*nothing to do*/ /*copy up to bufsize or readqsz, whichever is smaller*/ if (bufsize>aio->readqsz) csize=aio->readqsz; else csize=bufsize; bcopy(aio->readbuf, buffer, csize); aio->readqsz=aio->readqsz-csize; /*shift remainder of buffer into free space*/ for (x=0;xreadqsz;x++) aio->readbuf[x]=aio->readbuf[x+csize]; aio->rderrno=0; return(csize); } /*lib_aio_readret()*/ int lib_aio_readcancel(struct aio_type *aio) /*discard queued read data, no IO action*/ { /*sanity checks*/ if (aio==NULL) return(-1); if (aio->readfd<0) return(-1); aio->rderrno=0; aio->readqsz=0; aio->rdreqsz=0; return(0); } /*end lib_aio_readcancel()*/ int lib_aio_writecancel(struct aio_type *aio) /*discard queued write data, no IO action*/ { /*sanity checks*/ if (aio==NULL) return(-1); if (aio->writefd<0) return(-1); aio->wrerrno=0; aio->writeqsz=0; return(0); } /*end lib_aio_writeflush()*/ int lib_aio_getrdstat(struct aio_type *aio, int *rdreqqsz, int *rderr) /*retreive amount of queued read data and last read errno*/ { /*sanity checks*/ if (aio==NULL) return(-1); if (aio->readqsz>0) { /*pending request info*/ if (rdreqqsz!=NULL) *rdreqqsz=aio->rdreqsz; } if (rderr!=NULL) *rderr=aio->rderrno; /*last errno on IO*/ return(aio->readqsz); /*return # of queued bytes read*/ } /*end lib_aio_getrdstat()*/ int lib_aio_getwrstat(struct aio_type *aio, int *wrerr) /*retrieve amount of queued write data and last write errno*/ { /*sanity checks*/ if (aio==NULL) return(-1); if (wrerr!=NULL) *wrerr=aio->wrerrno; return(aio->writeqsz); } /*end lib_aio_getwrstat()*/ int lib_aio_getbufstat(struct aio_type *aio, int *rd, int *wr) /*return how many bytes can read/written inclusively*/ { /*sanity checks*/ if (aio==NULL) return(-1); if (rd!=NULL) { if (aio->readfd<0 || aio->rdbufsz<=0 || aio->readbuf==NULL) *rd=-1; else *rd=aio->rdbufsz-aio->readqsz; /*amount of Q space left*/ } if (wr!=NULL) { if (aio->writefd<0 || aio->wrbufsz<=0 || aio->writebuf==NULL) *wr=-1; else *wr=aio->wrbufsz-aio->writeqsz; /*amount of Q space left*/ } return(0); } /*end of lib_aio_getbufstat()*/ int lib_freeall_aio(struct aio_type **ptr, ...) /*ultiple destroy calls in one for aio data structures*/ { struct aio_type **rptr, *aptr; va_list ap; if (ptr==NULL) return(0); rptr=ptr; aptr=*rptr; if (aptr!=NULL) { if (aptr->readbuf!=NULL) free(aptr->readbuf); if (aptr->writebuf!=NULL) free(aptr->writebuf); free(aptr); *rptr=NULL; } va_start(ap,ptr); for (;;) { rptr=va_arg(ap,struct aio_type**); if (rptr==NULL) break; aptr=*rptr; if (aptr!=NULL) { if (aptr->readbuf!=NULL) free(aptr->readbuf); if (aptr->writebuf!=NULL) free(aptr->writebuf); free(aptr); *rptr=NULL; } } va_end(ap); return(0); } /*end of lib_freeall_aio()*/ /*********************************/ /* BEGIN TIMER FUNCTIONS SECTION */ /*********************************/ struct timer* lib_timer_create(void* pptr, int ptype, void* sptr, int stype) /*create timer object and initialize*/ { int x; struct timer *tp; tp=(struct timer*)malloc(sizeof(struct timer)); if (tp==NULL) return(NULL); tp->pptr=pptr; tp->sptr=sptr; tp->ptype=ptype; tp->stype=stype; tp->operation=tp->state=tp->stage=0; for (x=0;x<4;x++) { tp->etime[x].tv_sec=tp->etime[x].tv_usec=0; tp->mode[x]=0; /*off*/ tp->interval[x].tv_sec=tp->interval[x].tv_usec=0; /*unset*/ tp->counter[x]=0; } return(tp); } /*end lib_timer_create()*/ int lib_timer_destroy(struct timer *tp) /*cancel and free timer memory*/ { if (tp==NULL) return(-1); free(tp); return(0); } /*end lib_timer_destroy()*/ int lib_timer_counter(struct timer *tp, int incval, int which) /*increment or decrement counter*/ { if (tp==NULL) return(-1); if (which>4 || which <1) return(-1); tp->counter[which]=tp->counter[which]+incval; return(tp->counter[which]); } /*end lib_timer_counter()*/ int lib_timer_fillset(struct timer *tp, int ops, int state, int stage) /*set user defined values, >= -1 is allowed as a value*/ { if (tp==NULL) return(-1); if (ops>=-1) tp->operation=ops; if (state>=-1) tp->state=state; if (stage>=-1) tp->stage=stage; return(1); } /*end lib_timer_fillset()*/ int lib_timer_getset(struct timer *tp, int *ops, int *st, int *stg) /*get user defined values*/ { if (tp==NULL) return(-1); if (ops!=NULL) *ops=tp->operation; if (st!=NULL) *st=tp->state; if (stg!=NULL) *stg=tp->stage; return(1); } /*end lib_timer_getset()*/ int lib_timer_setptrs(struct timer *tp, void* ptr, int type, int op) /*set user data pointers*/ { if (tp==NULL) return(-1); if (op==0) { tp->pptr=ptr; tp->ptype=type; return(1); } else if (op==1) { tp->sptr=ptr; tp->stype=type; return(1); } return(0); } /*end lib_timer_setptrs()*/ int lib_timer_getptrs(struct timer *tp, void** pptr, int *ptype, void** sptr, int *stype) /*get user data pointers*/ { if (tp==NULL) return(-1); if (pptr!=NULL) *pptr=tp->pptr; if (sptr!=NULL) *sptr=tp->sptr; if (ptype!=NULL) *ptype=tp->ptype; if (stype!=NULL) *stype=tp->stype; return(1); } /*end lib_timer_getptrs()*/ int lib_timer_set(struct timer *tp, int which, unsigned int secs, unsigned int usecs) /*reset and/or change timer timeout value, autocancels*/ { unsigned int of=0; /*sanity checks*/ if (tp==NULL) return(-1); if (which>4 || which <1) return(-1); which--; if (secs>0 || usecs>0) tp->mode[which]=1; /*to be set*/ else tp->mode[which]=0; /*cleared*/ tp->etime[which].tv_sec=0; /*clear*/ tp->etime[which].tv_usec=0; /*clear*/ if (usecs>=1000000) { /*tricky caller, normalize*/ of=usecs/1000000; /*of now contains overflow*/ usecs=usecs%1000000; /*usec should be under a million now*/ } tp->interval[which].tv_sec=secs+of; tp->interval[which].tv_usec=usecs; if (tp->interval[which].tv_secinterval[which].tv_sec>2147483647) return(-1); /*yeah right*/ return(which+1); } /*end lib_timer_set()*/ int lib_timer_getstate(struct timer *tp, int whichflag, int modetype) /*return the active states of the timers, clear, set, or ticking*/ { int cnt=0, bit=0, x; /*sanity checks*/ if (tp==NULL) return(-1); if (whichflag>15 || whichflag <1) return(-1); if (modetype>2 || modetype<0) return(-1); for (x=0,bit=1;x<4;x++,bit=bit<<1) { if (tp->mode[x]==modetype) cnt=cnt|bit; } return(cnt); } /*end lib_timer_getstate()*/ int lib_timer_start(struct timer *tp, unsigned short whichflag) /*start and/or change expire timer*/ { struct timeval now; int x, bit=1, cnt=0; if (tp==NULL) return(-1); if (whichflag<1 || whichflag>15) return(-1); gettimeofday(&now,NULL); for (x=0;x<4;x++,bit=bit<<1) { if (tp->mode[x]!=1) continue; /*already started, or not set*/ if ((whichflag&bit) > 0) { /*start timer x up*/ tp->etime[x].tv_sec=now.tv_sec+tp->interval[x].tv_sec; tp->etime[x].tv_usec=now.tv_usec+tp->interval[x].tv_usec; if (tp->etime[x].tv_usec>=1000000) { tp->etime[x].tv_usec=tp->etime[x].tv_usec-1000000; tp->etime[x].tv_sec++; } tp->mode[x]=2; /*now ticking*/ cnt=cnt|bit; } } return(cnt); /*return which bits with active timers*/ } /*end lib_timer_start()*/ int lib_timer_stop(struct timer *tp, int whichflag) /*stop internal timer(s)*/ { int x, bit=1, cnt=0; if (tp==NULL) return(-1); for (x=0;x<4;x++,bit=bit<<1) { if ((whichflag&bit) > 0) { /*stop specified timer*/ if (tp->mode[x]!=2) continue; /*not ticking*/ tp->etime[x].tv_sec=0; tp->etime[x].tv_usec=0; tp->mode[x]=1; /*set, but no longer ticking*/ cnt=cnt|bit; } } return(cnt); /*return which timers have been stopped*/ } /*end lib_timer_stop()*/ int lib_timer_check(struct timer *tp) /*get expired timer alarm states*/ { int x, bit, tsets=0, active=0; struct timeval now; if (tp==NULL) return(-1); gettimeofday(&now,NULL); for (x=0,bit=1;x<4;x++,bit=bit<<1) { if (tp->mode[x]!=2) continue; /*not ticking*/ active++; if (tp->etime[x].tv_secetime[x].tv_sec>now.tv_sec) /*not expired*/ continue; if (tp->etime[x].tv_sec==now.tv_sec) { /*check usecs*/ if (tp->etime[x].tv_usec<=now.tv_usec) tsets=tsets|bit; /*expired*/ } } if (active==0) return(-2); return(tsets); /*return bits, set per timer*/ } /*end lib_timer_check()*/ int lib_freeall_timer(struct timer **ptr, ...) /*multiple destroy calls in one for timer data types*/ { struct timer **rptr, *aptr; va_list ap; if (ptr==NULL) return(0); rptr=ptr; aptr=*rptr; if (aptr!=NULL) { free(aptr); *rptr=NULL; } va_start(ap,ptr); for (;;) { rptr=va_arg(ap,struct timer**); if (rptr==NULL) break; aptr=*rptr; if (aptr!=NULL) { free(aptr); *rptr=NULL; } } va_end(ap); return(0); } /*end of lib_freeall_timer()*/ /************************************/ /* BEGIN INTERNAL FUNCTIONS SECTION */ /************************************/ char N_getformat(char **string, char *format, int *size) /*used by lib_log() and lib_dsprintf()*/ { char *pos,*types="dsfcxXeEgGup",*chars="0123456789.-+#*l",type; int x=1; pos=*string; format[0]='%'; while (1) { /*process until return or break;*/ if (strchr(chars,*pos)!=NULL) format[x++]=*pos; else if (strchr(types,*pos)!=NULL) { format[x++]=*pos; format[x]=0; type=*pos; break; } else return(0); if (x>4) return(0); pos++; } if (strcmp(format,"%ld")==0 && type=='d') type='D'; if (type=='s' && strcmp(format,"%s")!=0) { *size=0; x=1; while (format[x]!=0) { if (format[x]>='0' && format[x]<='9') *size=(*size*10)+format[x]-48; x++; } } else *size=0; *string=pos; return(type); } /*end N_getformat() */ int N_lockf(int fd, char locktype, char wait) /*internal, a simple lockf like function*/ /*wait: false=nowait,true=wait; locktype: 0=unlock, 1=read, 2=write*/ { int st; struct flock fl; if (wait<0 || wait>1) return(-1); if (locktype==0) fl.l_type=F_UNLCK; else if (locktype==1) fl.l_type=F_RDLCK; else if (locktype==2) fl.l_type=F_WRLCK; else return(-1); fl.l_whence=0; fl.l_len=0; fl.l_start=0; fl.l_pid=getpid(); if (!wait) { st=fcntl(fd, F_SETLK, &fl); return(st); } /*F_SETLKW hung sometimes on NFS locking, so we'll use a spinlock*/ while ((st=fcntl(fd, F_SETLK, &fl))==-1) { if (errno==EAGAIN) usleep(250000); /*retry every 1/4 second*/ else return(st); } return(st); } /*end N_lockf() */ unsigned int N_hashfunction(char *key, unsigned int hsize,char func) /*used by hash table functions, NOT crypt functions (at this time)*/ { if (func<1 || func>HFUNC) func=1; if (func==1) { unsigned int h=0,g; unsigned const char *k=(unsigned const char*)key; while (*k!=0) { h=(h << 4) + *k++; if ((g=h&0xf0000000)!=0) h=(h^(g>>24))^g; } return(h%hsize); } if (func==2) { unsigned int h=0,a; int x; for (x=0;key[x]!='\0';x++) { a=h>>27; h=((h<<4)^key[x])^a; } return(h%hsize); } if (func==3) { unsigned int h=0,a=31415,b=27183,M=2147483647; int x; for (x=0;key[x]!='\0';x++,a=(a*b)%(M-1)) h=((a*h) + key[x])%M; return(h%hsize); } if (func==4) { unsigned int seed=1; int x; for (x=0;key[x]!='\0';x++) seed=seed*(key[x]*3+x)+1; return(seed%hsize); } if (func==5) { unsigned int h=0,a=251,M=2147483647; int x; for (x=0;key[x]!='\0';x++) h=(a*h+key[x])%M; return(h%hsize); } if (func==6) { unsigned int x,seed=0; for (x=0;key[x]!='\0';x++) seed+=(key[x]*(x+key[x])); return(seed%hsize); } if (func==7) { /*HFUNC should equal this*/ unsigned int x,seed=0; for (x=0;key[x]!='\0';x++) seed=(seed*37)+key[x]; return(seed%hsize); } return(0); /*dummy return*/ } /*end N_hashfunction() */ unsigned char *N_lib_scramble(unsigned char *original, int size, long seed, short cycles) /*scramble the contents of a string in a random way*/ { int x,y, swpos; unsigned char tmp, *new; /*if empty or only one character, just return*/ if ((new=(unsigned char*)malloc(size+1))==NULL) return(NULL); if (size<1) return(NULL); if (size==1 || cycles==0) { bcopy(original,new,size); return(new); } /*now scramble*/ bcopy(original,new,size); cycles=abs(cycles); srand48(seed); for (y=0;ygfactor; if (dlist->gfactor<65536) /*double gfactor*/ dlist->gfactor=dlist->gfactor<<1; } ptr=realloc(dlist->item,(dlist->maxlistsize+growsize)*sizeof(void*)); if (ptr==NULL) return(-1); /*no more memory*/ dlist->item=ptr; dlist->maxlistsize+=growsize; for (x=dlist->size;xmaxlistsize;x++) dlist->item[x]=NULL; return(1); } /*end N_grow_dlist() */ int N_strcmp(char *s1, char *s2, int icase) /*generic string comparer*/ { if (icase) return(strcasecmp(s1,s2)); return(strcmp(s1,s2)); } /*end N_strcmp() */ int N_strcharcmp(char base, char test, char eflag) /*strcmp based on flags to grep*/ { if (base==test) return(1); if (test=='?' || test=='*') return(1); /*match any character*/ if (eflag&1) if (toupper(base)==toupper(test)) return(1); if (eflag&2) { /*test extended checks*/ if (test=='@') return(isalpha((int)base)); if (test=='#' || test=='%') return(isdigit((int)base)); if (test=='&') return(isalnum((int)base)); if (test=='$') return(isspace((int)base)); } return(0); } /*end N_strcharcmp() */ int N_strmatch(char *basestr, char *teststr, char icase, int *mpos, char eflag) /*compare strings, 0=no match, 1=exact match, 2=contains match, -1=error*/ { int tlen, blen, dlen, x, y, st; char match=1, *tdstr, *bdstr; if (teststr==NULL || basestr==NULL) return(-1); if ((tlen=strlen(teststr))==0) return(1); /* "" always matches*/ if ((blen=strlen(basestr))==0) return(0); /*empty base doesn't match*/ /*check for simpler cases*/ if (mpos!=NULL) *mpos=-1; dlen=blen-tlen; if (dlen<0) return(0); /*impossible to match*/ if (eflag) eflag=2; if (icase) icase=1; if (dlen==0) { /*must be exact*/ for (x=0;x0 && len<192) { where++; /*next byte after len*/ strncpy((char*)&tmp[place],(char*)&rec[where],len); where+=len; place+=len; tmp[place]='\0'; len=rec[where]; if (len>0 && len<192) { /*another section, append a '.'*/ tmp[place]='.'; place++; tmp[place]='\0'; } } if (len>=192) { /*ran into a pointer, gotta follow it*/ newpos=(rec[where]&31<<8)|rec[where+1]; N_parse_dn(rec,dnr,newpos); sprintf((char*)dn,"%s.%s",tmp,dnr); return(0); } else strcpy((char*)dn,(char*)tmp); return(0); } /*end N_parse_dn() */ int N_parse_drec(unsigned char *rec, short p, short ipflag, unsigned char *host) /*help parse a dns query record*/ { short ret,len; unsigned char h[128],dn[128]; dn[0]=host[0]=h[0]='\0'; if (ipflag) { /*got an IP address*/ sprintf((char*)host,"%d.%d.%d.%d",rec[p],rec[p+1],rec[p+2],rec[p+3]); return(4); } /*must be string*/ len=rec[p]; /*1st byte is length*/ p++; /*goto 1st byte of data*/ strncpy((char*)h,(char*)&rec[p],len); h[len]='\0'; p+=len; ret=N_parse_dn(rec, dn, p); if (ret<0) return(len); len=sprintf((char*)host,"%s.%s",h,dn); return(len); } /*end N_parse_drec() */