/*
 *
 * utils.c 
 * BIG BROTHER C utilities functions
 * Sean MacGuire
 * Version 1.9b
 * Apr 08th, 2002
 *
 * (c) Copyright Quest Software, Inc.  1997-2002  All rights reserved.
 *
 */


#include "bb.h"		/* THE BIG BROTHER INCLUDE FILE */
#ifdef TIMEH
#include <time.h>       /* FOR TIMING STUFF SMM */
#else
#include <sys/time.h>   /* FOR TIMING STUFF SMM */
#endif
#include <utime.h>
#include <sys/stat.h>
#include <dirent.h>
#include <ctype.h>
#include <errno.h>

#if REGEXEC
#include <regex.h>
#else
#if REGEX
#if SCO
#include <libgen.h>
#endif
#else
#if RE_EXEC
#include <re_comp.h>
#else

#endif
#endif
#endif

int replacestr(dst,dstmaxlen,from,to) 
char *dst;
int dstmaxlen;
char *from;
char *to;
{
char *realdst;
char *frompos;
char *dsttmp = NULL;

#if DEBUG
	debug("INTO REPLACESTR\n");
#endif
	realdst = dst;

	/* Dont work on null strings */
	if (!dst || !from || !to || (dstmaxlen == 0)) {
#if DEBUG
		debug("dst: [%s] from: [%s] to: [%s] dstmaxlen: [%d]\n",dst,from,to,dstmaxlen);
#endif
		return(1);
	}

	while( (frompos=(char *)strstr(dst,from)) ) {
#if DEBUG
		debug("match on [%s]\n",from);
#endif
		if( !dsttmp ) {
			dsttmp = (char *) malloc(dstmaxlen);
			/* Couldn't malloc */
			if( !dsttmp )
				return(2);
			memset(dsttmp,0,dstmaxlen);
		}
		/* Some strncpy barf on len = 0 */
		if( frompos-dst ) {
			*frompos = '\0';
			if( (int) (strlen(dsttmp) + strlen(dst)) > (dstmaxlen-1) ) {
#if DEBUG
				debug("[%s] generates a string too large, stopped !\n",from);
#endif
				strcpy(realdst,dsttmp);
				free(dsttmp);
				return(3);
			}
			strcat(dsttmp,dst);
		}
		if( (int) (strlen(dsttmp) + strlen(to)) > (dstmaxlen-1) ) {
#if DEBUG
			debug("[%s] generates a string too large, stopped !\n",from);
#endif
			strcpy(realdst,dsttmp);
			free(dsttmp);
			return(3);
		}
		strcat(dsttmp,to);
		dst = frompos + strlen(from);
#if DEBUG
		debug("dsttmp at this point: [%s], dst: [%s]\n",dsttmp,dst);
#endif
	}
	if( dsttmp ) {
		if( (int) (strlen(dsttmp) + strlen(dst)) > (dstmaxlen-1) ) {
#if DEBUG
			debug("[%s] generates a string too large, stopped !\n",from);
#endif
			strcpy(realdst,dsttmp);
			free(dsttmp);
			return(3);
		}
		strcat(dsttmp,dst);
		strcpy(realdst,dsttmp);
		free(dsttmp);
	}

#if DEBUG
	debug("String returned: [%s]\n",dst);
#endif

	return(0);
}

/*
 * Strip leading blanks
 */

void stripleadspaces(str)
char *str;
{
char *strptr;

	if( !str ) {
		return;
	}
	if( strlen(str) == 0 ) {
		return;
	}
	strptr = str;
	while(isspace(*strptr))
		strptr++;

	if( str != strptr )
		strcpy(str,strptr);

	return;
}

/*
 * Strip both lead and trailing spaces
 */

void striptrailspaces(str)
char *str;
{
char *strptr;

	if( !str ) {
		return;
	}
	if( strlen(str) == 0 ) {
		return;
	}

	strptr = str + strlen(str) - 1;

	while( (strptr >= str) && isspace(*strptr) ) {
		*strptr = '\0';
		strptr--;
	}
	return;
}


void stripleadtrailspaces(str)
char *str;
{
	stripleadspaces(str);
	striptrailspaces(str);
}

int valid_ipaddr(ipaddr)
char *ipaddr;
{
int ip1,ip2,ip3,ip4;

	/* Too big ? */
	if( strlen(ipaddr) > 15 ) {
		return(0);
	}

	ip1 = -1;
	ip2 = -1;
	ip3 = -1;
	ip4 = -1;
	sscanf(ipaddr,"%d.%d.%d.%d",&ip1,&ip2,&ip3,&ip4);
	if( (ip1 < 0) && (ip1 > 255) ) {
		return(0);
	}
	if( (ip2 < 0) && (ip2 > 255) ) {
		return(0);
	}
	if( (ip3 < 0) && (ip3 > 255) ) {
		return(0);
	}
	if( (ip4 < 0) && (ip4 > 255) ) {
		return(0);
	}

	return(1);
}

int getlinebbhosts(fp,entry,maxlen,flags)
FILE **fp;
char *entry;
int  maxlen;
int  flags;
{
char *bbhosts;
int  rc = 0;
char entries[16];		/* for at least the IP address */
char ipaddr[16],name[16];

	/* OK, 1st time thru, open bb-hosts */
	if( *fp == NULL ) {
		/* First time */
        	bbhosts = (char *) getenv("BBHOSTS");
        	if( bbhosts != NULL && strlen(bbhosts) > 0 ) {
			*fp = fopen(bbhosts,"r");
		}
	}

	/* bb-hosts is already opened or just has been */
	if( *fp != NULL ) {
		memset(entry,0,maxlen);
		while( fgets(entry,maxlen-1,*fp) != NULL ) {
			stripleadtrailspaces(entry);
			if( strlen(entry) == 0 ) {
				continue;
			}
			/* Empty line, only newline ? */
			if( entry[0] == '\n' ) {
				continue;
			}
			/* Bypass Comments */
			if( entry[0] == '#' ) {
				continue;
			}

			if( flags & LINEBBHOSTS_ALL ) {
				rc = 1;
				break;
			}
			else if( flags & LINEBBHOSTS_IPADDR ) {
				if( isdigit(entry[0]) ) {
					memset(entries,0,sizeof(entries));
					memset(ipaddr,0,sizeof(ipaddr));
					memset(name,0,sizeof(name));
					strncpy(entries,entry,sizeof(entries)-1);
					/* name will not be complete */
					/* we just want to make sure we got IP addr */
					sscanf(entries,"%s %s",ipaddr,name);
					if( valid_ipaddr(ipaddr) == 1 ) {
						rc = 1;
						break;
					}
				}
			}
			memset(entry,0,maxlen);
		}
	}

	if( (*fp != NULL) && (rc == 0) ) {
		fclose(*fp);
		*fp = NULL;
	}

	return(rc);
}

/* 
 * retrieve IP address of host from bb-hosts
 * 
 * If IP address cannot be found then return hostname
 * If IP address is 0.0.0.0 then return hostname unless
 *   force flag is on
 */

int getipaddr(bbhost,storestr, maxstorestrsize, forceip)
char *bbhost;
char *storestr;
int maxstorestrsize;
int forceip;
{
char *bbhosts = NULL, *fqdn = NULL;
FILE *bbhosts_fp;
char *hostptr, hostname[MAXLINE], *nextchar;
char ip_host[MAXLINE], *bbip;
int beginline, fullname, namelen;

	/* Check for stupid errors, return host name passwd as argument */

	if( bbhost == NULL ) {
		return(1);
	}
	if( strlen(bbhost) == 0 ) {
		return(1);
	}
	if( strlen(bbhost) >= (maxstorestrsize-1) ) {
		return(1);
	}

	strcpy(storestr,bbhost);

        bbhosts = (char *) getenv("BBHOSTS");
        if( bbhosts != NULL ) {
		if( (bbhosts_fp=fopen(bbhosts,"r")) != NULL ) {
			beginline = 1;
			while( fgets(ip_host,sizeof(ip_host)-1,bbhosts_fp) != NULL ) {
				if( beginline ) {
					/* Have we read a full line ? */
					if( strlen(ip_host) == (sizeof(ip_host)-1) ) {
						beginline = 0;
					}
					stripleadspaces(ip_host);
					/* Is first column a digit ? */
					/* Expecting 255.255.255.255 hostname ... in bb-hosts */
					if( isdigit(ip_host[0]) ) {
						bbip = hostptr = ip_host;
						while( isdigit(*hostptr) || (*hostptr == '.') ) {
							hostptr++;
						}
						if( !isspace(*hostptr) ) {
							continue;
						}
						/* Put in EOS such that bbip only contains IP addr */
						*hostptr = '\0';
						hostptr++;
						strcpy(hostname,hostptr);
						stripleadspaces(hostname);
						fullname = 0;
        					fqdn = (char *) getenv("FQDN");
					        if( fqdn != NULL ) {
							if( ! strcmp(fqdn,"TRUE") ) {
								fullname = 1;
							}
						}
						namelen = strlen(bbhost);
						if( !strncmp(hostname,bbhost,namelen) ) {
							nextchar = hostname + namelen;
							if( fullname ) {
								if( ! (isspace(*nextchar) || (*nextchar == '\0')) ) {
									continue;
								}
							}
							else {
								if( ! (isspace(*nextchar) || (*nextchar == '\0') || (*nextchar == '.')) ) {
									continue;
								}
							}

							/* Return IP address if non-zero or forceip flag is on */
							if( strcmp(bbip,"0.0.0.0") || forceip ) {
								strcpy(storestr,bbip);
							}

							return(0);
						}
					}
				}
				else {
					/* Reset if we've read the last part of a line */
					if( strlen(ip_host) != (sizeof(ip_host)-1) ) {
						beginline = 1;
					}
				}
			}
			fclose(bbhosts_fp);
		}
	}

	/* made it here, not found, return original string */
	return(1);
}

int getcolornum(color)
char *color;
{
	if(!strcmp(color,"red"))
		return(6);
	if(!strcmp(color,"purple"))
		return(5);
	if(!strcmp(color,"yellow"))
		return(4);
	if(!strcmp(color,"green"))
		return(3);
	if(!strcmp(color,"blue"))
		return(2);
	if(!strcmp(color,"clear"))
		return(1);
	return(0);
}

void clean_string(str,rm_chars,newchar)
char *str;
char *rm_chars;
char newchar;
{
char *tmpstr;
  
	while( *rm_chars ) {
		while( (tmpstr=(char *)strchr(str,*rm_chars)) != NULL ) {
			*tmpstr = newchar;
		}
		rm_chars++;
	}

#ifdef WHATDOESTHISBREAK
	tmpstr = str;
	while(*tmpstr) {
		if( !isprint(*tmpstr) ) {
			*tmpstr = newchar;
		}
		tmpstr++;
	}
#endif
} 

char *gettimestr()
{ 
time_t  timenow;
char *timestr;
static char worktimestr[MAXLINE];
char *timestrp;
  
        time(&timenow); 
        timestr = ctime(&timenow);
        strcpy(worktimestr,timestr);
        if( (timestrp = (char *)strchr(worktimestr,'\n')) != NULL ) {
                *timestrp = '\0';
        }

        return(worktimestr);
}


/*
 * Make a string space seperated (squeezed out extra spaces)
 */
int space_sep(workstr)
char *workstr;
{

	/* Replace all tabs by spaces */
	while( *workstr ) {
		if( isspace(*workstr) ) {
			*workstr = ' ';
		}
		workstr++;
	}

	/* Make sure only a single space seperaters words */
	replacestr(workstr,strlen(workstr),"  "," ");

	return(0);
}

/* Match() mimicks and egrep */
/* egrep -i : ignore case : REG_IGN_CASE */
/* egrep -x : match whole line : REG_FULL */
/* egrep "^..." : beginning of line : REG_BOL */
/* egrep "...$" : end of line : REG_EOL */
/* REG_PATHEXP make the match behave like pathname expansion */

int match(str,pattern,flags)
char *str;
char *pattern;
int flags;
{
char *workpattern;
int workpatternlen,rc;

#if REGEXEC
regex_t preg;
int reflags;
#else
#if REGEX|RE_EXEC
char *comp_form,*curr_expr,*next_expr;
char *workpattern1;
int workpattern1len,i;
#else
#endif
#endif

	workpatternlen = strlen(pattern) + MAXLINE;

	if( (workpattern=(char *)calloc(1,workpatternlen)) == NULL ) {
		return(0);
	}

#if REGEXEC

	if( flags & REG_FULL ) {
		sprintf(workpattern,"^(%s)$",pattern);
	}
	else if( flags & REG_BOL ) {
		sprintf(workpattern,"^%s",pattern);
	}
	else if( flags & REG_EOL ) {
		sprintf(workpattern,"%s$",pattern);
	}
	else {
		strcpy(workpattern,pattern);
	}

	reflags = REG_EXTENDED|REG_NOSUB;
	if( flags & REG_IGN_CASE ) {
		reflags |= REG_ICASE;
	}
	/* All * are to be replaced by .* but before doing it */
	/* normalize all .* to * first then transform */
	/* but keep ]* construct intact */
	if( flags & REG_PATHEXP ) {
		/* mimick filename path expansion */
		replacestr(workpattern,workpatternlen,".","[.,]");
		replacestr(workpattern,workpatternlen,"*",".*");
	}
	else {
		replacestr(workpattern,workpatternlen,"]*","([_])");
		replacestr(workpattern,workpatternlen,".*","*");
		replacestr(workpattern,workpatternlen,"*",".*");
		replacestr(workpattern,workpatternlen,"([_])","]*");
	}

#if DEBUG
	fprintf(stderr,"Matching <%s> against <%s>\n",str,workpattern);
	fflush(stderr);
#endif

	if( regcomp(&preg,workpattern,reflags) != 0 ) {
		free(workpattern);
		return(0);
	}

	free(workpattern);

	rc = regexec(&preg,str,0,NULL,0);

	regfree(&preg);

	if( rc == 0 ) {
		return(1);
	}
	else {
		return(0);
	}
	
#else
#if REGEX|RE_EXEC

	workpattern1len = strlen(pattern) + MAXLINE;
	if( (workpattern1=(char*)calloc(1,workpattern1len)) == NULL ) {
		free(workpattern);
		return(0);
	}

	/*
	 * REGEX doesn't do multiple patterns at once
	 * So got to do it ourselves
	 */

	curr_expr = next_expr = pattern;
	while( curr_expr ) {
		/*
		 * Get the first expression
		 */
		next_expr = (char *)strchr(curr_expr,'|');
		if( next_expr != NULL ) {
			strncpy(workpattern,curr_expr,next_expr-curr_expr);
			workpattern[next_expr-curr_expr] = '\0';
			next_expr++;
			while( *next_expr == '|' ) {
				next_expr++;
			}
			if( *next_expr == '\0' ) {
				next_expr = NULL;
			}
			else {
				curr_expr = next_expr;
			}
		}
		else {
			strcpy(workpattern,curr_expr);
			curr_expr = NULL;
		}

		if( flags & REG_FULL ) {
			/*
			 * Make sure there's only one '^' at the BOL
			 */
			while( workpattern[0] == '^' ) {
				strcpy(workpattern,workpattern+1);
			}
			i = strlen(workpattern) - 1;
			while( (i >= 0) && (workpattern[i] == '$') ) {
				workpattern[i] = '\0';
				i--;
			}
			if( strlen(workpattern) > 0 ) {
				sprintf(workpattern1,"^%s$",workpattern);
			}
			else {
				continue;
			}
		}
		else if( flags & REG_BOL ) {
			/*
			 * Make sure there's only one '^' at the BOL
			 */
			while( workpattern[0] == '^' ) {
				strcpy(workpattern1,workpattern+1);
			}
			if( strlen(workpattern) > 0 ) {
				sprintf(workpattern1,"^%s",workpattern);
			}
			else {
				continue;
			}
		}
		else if( flags & REG_EOL ) {
			/*
			 * Make sure there's only one '$' at the EOL
			 */
			i = strlen(workpattern) - 1;
			while( (i >= 0) && (workpattern[i] == '$') ) {
				workpattern[i] = '\0';
				i--;
			}
			if( strlen(workpattern) > 0 ) {
				sprintf(workpattern1,"%s$",workpattern);
			}
			else {
				continue;
			}
		}
		else {
			strcpy(workpattern1,workpattern);
		}

		/* All * are to be replaced by .* but before doing it */
		/* normalize all .* to * first then transform */
		/* but keep ]* construct intact */
		if( flags & REG_PATHEXP ) {
			/* mimick filename path expansion */
			replacestr(workpattern,workpatternlen,".","[.,]");
			replacestr(workpattern,workpatternlen,"*",".*");
		}
		else {
			replacestr(workpattern1,workpattern1len,"]*","([_])");
			replacestr(workpattern1,workpattern1len,".*","*");
			replacestr(workpattern1,workpattern1len,"*",".*");
			replacestr(workpattern1,workpattern1len,"([_])","]*");
		}

#if DEBUG
		fprintf(stderr,"Matching <%s> against <%s>\n",str,workpattern1);
		fflush(stderr);
#endif

#if REGEX
		comp_form = (char *)regcmp(workpattern1,NULL);
		if( comp_form == NULL ) {
			continue;
		}
		if( regex(comp_form,str) ) {
			free(workpattern);
			free(workpattern1);
			free(comp_form);
			return(1);
		}
		free(comp_form);
#else
#if RE_EXEC
		comp_form = re_comp(workpattern1);
		if( comp_form != NULL ) {
			continue;
		}
		if( re_exec(str) ) {
			free(workpattern);
			free(workpattern1);
			return(1);
		}
#else
#endif
#endif

	}

	free(workpattern);
	free(workpattern1);

	return(0);
			
#else
#endif
#endif

}

void strtolower(str)
char *str;
{
	while(str && *str) {
		*str = tolower(*str);
		str++;
	}
}

void strtoupper(str)
char *str;
{
	while(str && *str) {
		*str = toupper(*str);
		str++;
	}
}

int getdirnextentry(dirinfo,dirname,filemask,filename,flags,ftype)
DIR  *dirinfo;
char *dirname;
char *filemask;
char *filename;
int  flags;
int  *ftype;
{
struct dirent *direntp;
struct stat statinfo;
char fname[MAXLINE];

	*ftype = 0;

	while( (direntp=readdir(dirinfo)) != NULL ) {
		sprintf(fname,"%s/%s",dirname,direntp->d_name);
		if( stat(fname,&statinfo) != 0 ) {
			continue;	/* Can't stat() it ... hummm weird */
		}
		/* If requesting only files, ignore if not */
		if( statinfo.st_mode & S_IFREG ) {
			*ftype = GETDIR_FILE;
			if( !(flags & (GETDIR_FILE|GETDIR_ALL)) ) {
				continue;
			}
		}
		/* If requesting only directories, ignore if not */
		else if( statinfo.st_mode & S_IFDIR ) {
			*ftype = GETDIR_DIR;
			if( !(flags & (GETDIR_DIR|GETDIR_ALL)) ) {
				continue;
			}
		}
		else {
			*ftype = GETDIR_OTHER;
			if( !(flags & GETDIR_ALL) ) {
				continue;
			}
		}
#if DEBUG
		fprintf(stderr,"Matching <%s> <%s>\n",direntp->d_name,filemask);
		fflush(stderr);
#endif
		if( match(direntp->d_name,filemask,REG_FULL|REG_PATHEXP) ) {
#if DEBUG
			fprintf(stderr,"Matched ! <%s> <%s>\n",direntp->d_name,filemask);
			fflush(stderr);
#endif
			strcpy(filename,direntp->d_name);
			return(1);
		}
	}

	return(0);
}


/*
 * Return the first filename that matches
 * the filemask in the given directory
 * Save the file name in filename
 * Returns: 0 - none found
 *          1 - match found
 */
int getdirfirst(dirinfo,dirname,filemask,filename,flags,ftype)
DIR  **dirinfo;
char *dirname;
char *filemask;
char *filename;
int  flags;
int  *ftype;
{
DIR *dirp;

	if( (dirp = opendir(dirname)) == NULL ) {
		return(0);
	}

	if( getdirnextentry(dirp,dirname,filemask,filename,flags,ftype) == 1 ) {
		*dirinfo = dirp;
		return(1);
	}

	closedir(dirp);
	*dirinfo = NULL;

	return(0);
}

/*
 * Return the next filename that matches
 * the filemask in the given directory
 * Save the file name in filename
 * Returns: 0 - none found
 *          1 - match found
 */
int getdirnext(dirinfo,dirname,filemask,filename,flags,ftype)
DIR  *dirinfo;            
char *dirname;
char *filemask;
char *filename;
int  flags;
int  *ftype;
{

	if( dirinfo == NULL ) {
		return(0);
	}

	if( getdirnextentry(dirinfo,dirname,filemask,filename,flags,ftype) == 1 ) {
		return(1);
	}
	else {
		return(0);
	}
}

/*
 * Release resources associated with getdirfirst(),getdirnext()
 */
void getdirdone(dirinfo)
DIR *dirinfo;
{
	if( dirinfo == NULL ) {
		return;
	}

	closedir(dirinfo);
	dirinfo = NULL;
}

/*
 * Change the access and modification time on a file
 */
int touchtime(touchfile,offset)
char *touchfile;
int  offset;
{
struct utimbuf tb;
time_t ticks;
FILE *fp;

        offset *= 60;		/* NOW IN SECONDS */
        ticks = time(&ticks) + offset;

	tb.actime=ticks;
	tb.modtime=ticks;
 
	/* 
	 * NOW CREATE THE TOUCHFILE
	 * OR JUST CHANGE THE MODIFICATION TIME IF IT ALREADY EXISTS
	 */
	if( (fp=fopen(touchfile, "a")) != NULL ) {
		fclose(fp);
	}
	else {
		fprintf(stderr, "Can't touch %s\n", touchfile);
		return(0);
	}

	utime(touchfile, &tb);

	return(1);
}

/*
 * Save the text to the associated file
 */
int writefile(filename,text,mode)
char *filename;
char *text;
char *mode;
{
FILE *fp;

	if( !filename || !text ) {
		return(0);
	}
	if( strlen(filename) == 0 ) {
		return(0);
	}

	if( (fp=fopen(filename,mode)) != NULL ) {
		fprintf(fp,"%s",text);
		fclose(fp);
		return(1);
	}
	else {
		return(0);
	}
}

/*
 * Save the text in the associated file
 */
int savefile(filename,text)
char *filename;
char *text;
{
	return(writefile(filename,text,"w"));
}

/*
 * Append the text to the associated file
 */
int appendfile(filename,text)
char *filename;
char *text;
{
	return(writefile(filename,text,"a"));
}

/*
 * Read the given file
 */
char *readfile(filename,maxsize)
char *filename;
int  maxsize;
{
FILE *fp;
struct stat statinfo;
char *buffer = NULL;
int size;

	if( !filename ) {
		return(NULL);
	}
	if( strlen(filename) == 0 ) {
		return(NULL);
	}
	if( maxsize < 1 ) {
		return(NULL);
	}

	if( stat(filename,&statinfo) == 0 ) {
		if( (int)statinfo.st_size >= maxsize ) {
			size = maxsize;
		}
		else {
			size = (int) statinfo.st_size;
		}
		if( (fp=fopen(filename,"r")) != NULL ) {
			if( (buffer=(char *)calloc(1,size+1)) != NULL) {
				if( fread(buffer,(int)size,1,fp) < 1 ) {
					free(buffer);
					buffer = NULL;
				}
			}
			fclose(fp);
		}
	}

	return(buffer);
}

int valid_logname(filename)
char *filename;
{
char *name;
int len;

	/*
	 *
	 */
	len = strlen(filename);
	if( strspn(filename,VALIDFILENAMECHARS) != len ) {
		/* invalid characters in there */
		fprintf(stderr,"%s bbd FILENAME CONSTAINS INVALID CHARACTERS - IGNORED: %s\n",gettimestr(),filename);
		fflush(stderr);
#if DEBUG
		debug("FILENAME CONSTAINS INVALID CHARACTERS - IGNORED\n");
#endif
		return(0);;
	}

	/* It shouldn't end with '.' ? */
	if (filename[strlen(filename)-1] == '.') {
		/* File has no extension */
#if DEBUG
		debug("FILENAME HAS NO EXTENSION - IGNORED\n");
#endif
		return(0);
	}

	/* It shouldn't end with ',' ? */
	if (filename[strlen(filename)-1] == ',') {
		/* File has no extension */
#if DEBUG
		debug("FILENAME HAS NO EXTENSION - IGNORED\n");
#endif
		return(0);
	}

	/* It should have a '.' ? */
	if ((char *)strchr(filename,'.') == NULL ) {
		/* File has no extension */
#if DEBUG
		debug("FILENAME HAS NO EXTENSION - IGNORED\n");
#endif
		return(0);
	}

	/* Thanks to Holger Marzen <Holger.Marzen@sik-gmbh.de> */
	/* It shouldn't start with a '.' ? */
	if (filename[0] == '.') {
		/* no hostname - must be garbage */
#if DEBUG
		debug("FILENAME HAS NO HOSTNAME - IGNORED\n");
#endif
		return(0);
	}

	/* It shouldn't start with a '-' ? */
	if (filename[0] == '-') {
		/* no hostname - must be garbage */
#if DEBUG
		debug("FILENAME HAS NO HOSTNAME - IGNORED\n");
#endif
		return(0);
	}

	/* It shouldn't start with ',' ? */
	if (filename[0] == ',') {
		/* File has no extension */
#if DEBUG
		debug("FILENAME STARTS WITH AN INVALID CHAR ',' - IGNORED\n");
#endif
		return(0);
	}

	/* It should be at least X.Y */
	/* This is probably redundant but let's keep it */
	if (len < 3) {
		/* too small - must be garbage */
		/* must be at least x.x        */
#if DEBUG
		debug("FILENAME TOO SMALL - IGNORED\n");
#endif
		return(0);
	}

	/* 
	 * THANKS TO Jac Kersing <J.Kersing@the-box.com>
	 * SMM: IGNORE ATTEMPTS TO WRITE TO PARENT DIRECTORIES
	 * AND CHECK FOR BUFFER OVERFLOWS
	 */
	name = (char *)strrchr(filename,'/');
	if (name != (char *)NULL) {		/* FOUND A FUNNY */
#if DEBUG
		debug("ILLEGAL FILE NAME - IGNORED\n");
#endif
		return(0);				/* GO AWAY */
	}


	return(1);

}

int bb_errmsg(type,msg)
char *type;
char *msg;
{
int rc = 0;
extern char bbprog[];

	if( msg && type && strlen(bbprog) > 0 && strlen(type) > 0 ) {
		fprintf(stderr,"%s %s %s %s\n",gettimestr(),bbprog,type,msg);
	}
	else if( msg && strlen(bbprog) > 0 ) {
		fprintf(stderr,"%s %s %s\n",gettimestr(),bbprog,msg);
	}
	else if( msg && type && strlen(type) > 0 ) {
		fprintf(stderr,"%s %s %s\n",gettimestr(),type,msg);
	}
	else {
		fprintf(stderr,"%s bbutils bb_errmsg() invalid arguments\n",gettimestr());
		rc = 1;
	}
	fflush(stderr);

	return(rc);
}

int bb_putenv(varname,val,staticvar,maxlen)
char *varname;
char *val;
char *staticvar;
int  maxlen;
{
int  rc;
char *valp;

	if( varname == NULL || val == NULL ) {
		return(-1);
	}
	if( strlen(varname) == 0 ) {
		return(-1);
	}

	if( maxlen < (strlen(varname)+2) ) {
		return(-1);
	}
	memset(staticvar,0,maxlen);
	strcpy(staticvar,varname);
	strcat(staticvar,"=");
	strncat(staticvar,val,maxlen-strlen(staticvar)-1);

	if( (rc=putenv(staticvar)) != 0 ) {
#if DEBUG
		fprintf(stderr,"bb_putenv() failed for <%s>\n",staticvar);
		fprintf(stderr,"            trying again by truncating value length in 1/2\n");
		fflush(stderr);
#endif
		if( strlen(staticvar) > (strlen(varname)+1) ) {
			valp = staticvar + strlen(varname) + 1 + ((strlen(staticvar)-strlen(varname)-1)/2);
			/* Reduce tha value part by half its length */
			*(valp+1) = '\0';
			if( (rc=putenv(staticvar)) != 0 ) {
#if DEBUG
			fprintf(stderr,"bb_putenv() failed on 2nd try for <%s>\n",staticvar);
			fflush(stderr);
#endif
				;
			}
		}
	}

	return(rc);
}

void convert_web_str(buf)
char *buf;
{
char *bufp;
char newchar,currchar1,currchar2;

	if( !buf ) {
		return;
	}
	if( strlen(buf) == 0 ) {
		return;
	}
	bufp = buf;
	while( bufp && *bufp && ((bufp=(char *)strchr(bufp,'%')) != NULL) ) {
		currchar1 = *(bufp+1);
		if( (currchar1 > '1') && (currchar1 < '8') ) {
			newchar = (char) ((currchar1 - '0') * 16);
			currchar2 = toupper(*(bufp+2));
			if( (currchar2 >= '0') && (currchar2 <= '9') ) {
				newchar += (char) (currchar2 - '0');
			}
			else if( (currchar2 >= 'A') && (currchar2 <= 'F') ) {
				newchar += (char) ((currchar2 - 'A') + 10);
			}
			else {
				bufp++;
				continue;
			}
			*bufp = newchar;
			bufp++;
			/* Or we at the end of the buffer ? */
			if( (*(bufp+2)) ) {
				strcpy(bufp,bufp+2);
			}
			else {
				*bufp = '\0';
				break;
			}
		}
		else {
			bufp++;
		}
	}

	return;
}

int bb_rename(oldfile,newfile)
char *oldfile;
char *newfile;
{
int rc;
char errmsg[MAXLINE*3];

#ifndef NORENAME
	if( (rc=rename(oldfile,newfile)) ) {
		sprintf(errmsg,"Could not rename %s to %s - errno: %d\n",oldfile,newfile,errno);
		bb_errmsg("bb_rename",errmsg);
	}
#else
	/* rename() does not exists on this platform */
	/* use link then remove the old file */

	/* make sure the newfile does not exists */
	if( (rc=unlink(newfile)) && (errno != ENOENT) ) {
		sprintf(errmsg,"Could not unlink %s - errno: %d\n",newfile,errno);
		bb_errmsg("bb_rename",errmsg);
	}
	else if( (rc=link(oldfile,newfile)) ) {
		sprintf(errmsg,"Could not link %s to %s - errno: %d\n",oldfile,newfile,errno);
		bb_errmsg("bb_rename",errmsg);
	}
	else if( (rc=unlink(oldfile)) ) {
		sprintf(errmsg,"Could not unlink %s - errno: %d\n",oldfile,errno);
		bb_errmsg("bb_rename",errmsg);
	}
#endif

	return(rc);
}
