Skip to content
Snippets Groups Projects
  • Rob Swindell's avatar
    19e7f21e
    Add/use realloc_or_free() instead of realloc() in some places · 19e7f21e
    Rob Swindell authored
    Where ever we assign the realloc() result to the same pointer we pass, use this new function instead to eliminate the cppcheck error reported by Nelgin:
    Common realloc mistake: 'p' nulled but not freed upon failure  [memleakOnRealloc]
    
    This isn't going to actually solve any memory leaks, it's just good practice for critical error (e.g. no memory error) handling.
    19e7f21e
    History
    Add/use realloc_or_free() instead of realloc() in some places
    Rob Swindell authored
    Where ever we assign the realloc() result to the same pointer we pass, use this new function instead to eliminate the cppcheck error reported by Nelgin:
    Common realloc mistake: 'p' nulled but not freed upon failure  [memleakOnRealloc]
    
    This isn't going to actually solve any memory leaks, it's just good practice for critical error (e.g. no memory error) handling.
execmisc.cpp 40.81 KiB
/* Synchronet miscellaneous command shell/module routines */

/****************************************************************************
 * @format.tab-size 4		(Plain Text/Source Code File Header)			*
 * @format.use-tabs true	(see http://www.synchro.net/ptsc_hdr.html)		*
 *																			*
 * Copyright Rob Swindell - http://www.synchro.net/copyright.html			*
 *																			*
 * This program is free software; you can redistribute it and/or			*
 * modify it under the terms of the GNU General Public License				*
 * as published by the Free Software Foundation; either version 2			*
 * of the License, or (at your option) any later version.					*
 * See the GNU General Public License for more details: gpl.txt or			*
 * http://www.fsf.org/copyleft/gpl.html										*
 *																			*
 * For Synchronet coding style and modification guidelines, see				*
 * http://www.synchro.net/source.html										*
 *																			*
 * Note: If this box doesn't appear square, then you need to fix your tabs.	*
 ****************************************************************************/

#include "sbbs.h"
#include "cmdshell.h"
#include "xpprintf.h"

static char* format_string(sbbs_t* sbbs, csi_t* csi)
{
	char*		fmt;
	void*		vp;
	int32_t*	lp;
	unsigned	i;
	unsigned	args;

	fmt=xp_asprintf_start((char*)csi->ip);
	while(*(csi->ip++));	/* Find '\0' terminator */
	args=*(csi->ip++); 		/* total args */
	for(i=0;i<args;i++) {
		if((vp=sbbs->getstrvar(csi,*(int32_t *)csi->ip))==NULL) {
			if((lp=sbbs->getintvar(csi,*(int32_t *)csi->ip))==NULL)
				fmt=xp_asprintf_next(fmt,XP_PRINTF_CONVERT|XP_PRINTF_TYPE_INT,0);
			else
				fmt=xp_asprintf_next(fmt,XP_PRINTF_CONVERT|XP_PRINTF_TYPE_INT,*lp);
		}
		else
			fmt=xp_asprintf_next(fmt,XP_PRINTF_CONVERT|XP_PRINTF_TYPE_CHARP,*(char **)vp);
		csi->ip+=4;
	}
	return xp_asprintf_end(fmt, NULL);
}

int sbbs_t::exec_misc(csi_t* csi, const char *path)
{
	char	str[512],tmp[512],buf[1025],ch,op,*p,**pp,**pp1,**pp2;
	ushort	w;
	int 	i=0,j;
	long	l;
	int32_t	*lp=NULL,*lp1=NULL,*lp2=NULL;
	void	*vp;
	struct	dirent *de;
    struct  tm tm;
	FILE*	fp;
	DIR*	dp;

	switch(*(csi->ip++)) {
		case CS_VAR_INSTRUCTION:
			switch(*(csi->ip++)) {	/* sub-op-code stored as next byte */
				case PRINT_VAR:
					pp=getstrvar(csi,*(int32_t *)csi->ip);
					if(!pp || !*pp) {
						lp=getintvar(csi,*(int32_t *)csi->ip);
						if(lp)
							bprintf("%d",*lp);
					}
					else
						putmsg(cmdstr(*pp,path,csi->str,buf)
							,P_SAVEATR|P_NOABORT|P_NOATCODES);
					csi->ip+=4;
					return(0);
				case VAR_PRINTF:
				case VAR_PRINTF_LOCAL:
					op=*(csi->ip-1);
					p=format_string(this, csi);
					if(op==VAR_PRINTF)
						putmsg(cmdstr(p,path,csi->str,buf),P_SAVEATR|P_NOABORT|P_NOATCODES);
					else {
						lputs(LOG_INFO,cmdstr(p,path,csi->str,buf));
					}
					free(p);
					return(0);
				case SHOW_VARS:
					bprintf("shell     str=(%p) %s\r\n"
						,csi->str,csi->str);
					for(i=0;i<csi->str_vars;i++)
						bprintf("local  str[%d]=(%08X) (%p) %s\r\n"
							,i,csi->str_var_name[i]
							,csi->str_var[i]
							,csi->str_var[i]);
					for(i=0;i<csi->int_vars;i++)
						bprintf("local  int[%d]=(%08X) (%08X) %d\r\n"
							,i,csi->int_var_name[i]
							,csi->int_var[i]
							,csi->int_var[i]);
					for(i=0;i<global_str_vars;i++)
						bprintf("global str[%d]=(%08X) (%p) %s\r\n"
							,i,global_str_var_name[i]
							,global_str_var[i]
							,global_str_var[i]);
					for(i=0;i<global_int_vars;i++)
						bprintf("global int[%d]=(%08X) (%08X) %d\r\n"
							,i,global_int_var_name[i]
							,global_int_var[i]
							,global_int_var[i]);
					return(0);
				case DEFINE_STR_VAR:
					if(getstrvar(csi,*(int32_t *)csi->ip)) {
						csi->ip+=4;
						return(0);
					}
					csi->str_vars++;
					csi->str_var=(char **)realloc_or_free(csi->str_var
						,sizeof(char *)*csi->str_vars);
					csi->str_var_name=(uint32_t *)realloc_or_free(csi->str_var_name
						,sizeof(int32_t)*csi->str_vars);
					if(csi->str_var==NULL
						|| csi->str_var_name==NULL) { /* REALLOC failed */
						errormsg(WHERE,ERR_ALLOC,"local str var"
							,sizeof(char *)*csi->str_vars);
						if(csi->str_var_name) {
							free(csi->str_var_name);
							csi->str_var_name=0;
						}
						if(csi->str_var) {
							free(csi->str_var);
							csi->str_var=0;
						}
						csi->str_vars=0;
					}
					else {
						csi->str_var_name[csi->str_vars-1]=*(int32_t *)csi->ip;
						csi->str_var[csi->str_vars-1]=0;
					}
					csi->ip+=4; /* Skip variable name */
					return(0);
				case DEFINE_INT_VAR:
					if(getintvar(csi,*(int32_t *)csi->ip)) {
						csi->ip+=4;
						return(0);
					}
					csi->int_vars++;
					csi->int_var=(int32_t *)realloc_or_free(csi->int_var
						,sizeof(char *)*csi->int_vars);
					csi->int_var_name=(uint32_t *)realloc_or_free(csi->int_var_name
						,sizeof(int32_t)*csi->int_vars);
					if(csi->int_var==NULL
						|| csi->int_var_name==NULL) { /* REALLOC failed */
						errormsg(WHERE,ERR_ALLOC,"local int var"
							,sizeof(char *)*csi->int_vars);
						if(csi->int_var_name) {
							free(csi->int_var_name);
							csi->int_var_name=0;
						}
						if(csi->int_var) {
							free(csi->int_var);
							csi->int_var=0;
						}
						csi->int_vars=0;
					}
					else {
						csi->int_var_name[csi->int_vars-1]=*(int32_t *)csi->ip;
						csi->int_var[csi->int_vars-1]=0;
					}
					csi->ip+=4; /* Skip variable name */
					return(0);
				case DEFINE_GLOBAL_STR_VAR:
					if(getstrvar(csi,*(int32_t *)csi->ip)) {
						csi->ip+=4;
						return(0);
					}
					global_str_vars++;
					global_str_var=(char **)realloc_or_free(global_str_var
						,sizeof(char *)*global_str_vars);
					global_str_var_name=(uint32_t *)realloc_or_free(global_str_var_name
						,sizeof(int32_t)*global_str_vars);
					if(global_str_var==NULL
						|| global_str_var_name==NULL) { /* REALLOC failed */
						errormsg(WHERE,ERR_ALLOC,"global str var"
							,sizeof(char *)*global_str_vars);
						if(global_str_var_name) {
							free(global_str_var_name);
							global_str_var_name=0;
						}
						if(global_str_var) {
							free(global_str_var);
							global_str_var=0;
						}
						global_str_vars=0;
					}
					else {
						global_str_var_name[global_str_vars-1]=
							*(int32_t *)csi->ip;
						global_str_var[global_str_vars-1]=0;
					}
					csi->ip+=4; /* Skip variable name */
					return(0);
				case DEFINE_GLOBAL_INT_VAR:
					if(getintvar(csi,*(int32_t *)csi->ip)) {
						csi->ip+=4;
						return(0);
					}
					global_int_vars++;
					global_int_var=(int32_t *)realloc_or_free(global_int_var
						,sizeof(char *)*global_int_vars);
					global_int_var_name=(uint32_t *)realloc_or_free(global_int_var_name
						,sizeof(int32_t)*global_int_vars);
					if(global_int_var==NULL
						|| global_int_var_name==NULL) { /* REALLOC failed */
						errormsg(WHERE,ERR_ALLOC,"local int var"
							,sizeof(char *)*global_int_vars);
						if(global_int_var_name) {
							free(global_int_var_name);
							global_int_var_name=0;
						}
						if(global_int_var) {
							free(global_int_var);
							global_int_var=0;
						}
						global_int_vars=0;
					}
					else {
						global_int_var_name[global_int_vars-1]
							=*(int32_t *)csi->ip;
						global_int_var[global_int_vars-1]=0;
					}
					csi->ip+=4; /* Skip variable name */
					return(0);

				case SET_STR_VAR:
					pp=getstrvar(csi,*(int32_t *)csi->ip);
					csi->ip+=4; /* Skip variable name */
					if(pp)
						*pp=copystrvar(csi,*pp
							,cmdstr((char *)csi->ip,path,csi->str,buf));
					while(*(csi->ip++));	 /* Find NULL */
					return(0);
				case SET_INT_VAR:
					lp=getintvar(csi,*(int32_t *)csi->ip);
					csi->ip+=4; /* Skip variable name */
					if(lp)
						*lp=*(int32_t *)csi->ip;
					csi->ip+=4; /* Skip value */
					return(0);
				case COMPARE_STR_VAR:
					pp=getstrvar(csi,*(int32_t *)csi->ip);
					csi->ip+=4; /* Skip variable name */
					if(pp && *pp)
						csi->logic=stricmp(*pp
							,cmdstr((char *)csi->ip,path,csi->str,buf));
					else {	/* Uninitialized str var */
						if(*(csi->ip)==0)	 /* Blank static str */
							csi->logic=LOGIC_TRUE;
						else
							csi->logic=LOGIC_FALSE;
					}
					while(*(csi->ip++));	 /* Find NULL */
					return(0);
				case STRSTR_VAR:
					pp=getstrvar(csi,*(int32_t *)csi->ip);
					csi->ip+=4; /* Skip variable name */
					if(pp && *pp && strstr(*pp
						,cmdstr((char *)csi->ip,path,csi->str,buf)))
						csi->logic=LOGIC_TRUE;
					else
						csi->logic=LOGIC_FALSE;
					while(*(csi->ip++));	 /* Find NULL */
					return(0);
				case STRNCMP_VAR:
					i=*csi->ip++;
					pp=getstrvar(csi,*(int32_t *)csi->ip);
					csi->ip+=4; /* Skip variable name */
					if(pp && *pp)
						csi->logic=strnicmp(*pp
							,cmdstr((char *)csi->ip,path,csi->str,buf),i);
					else
						csi->logic=LOGIC_FALSE;
					while(*(csi->ip++));	 /* Find NULL */
					return(0);
				case STRNCMP_VARS:
					i=*csi->ip++;
					pp1=getstrvar(csi,*(int32_t *)csi->ip);
					csi->ip+=4; /* Skip variable name */
					pp2=getstrvar(csi,*(int32_t *)csi->ip);
					csi->ip+=4;
					if(pp1 && *pp1 && pp2 && *pp2)
						csi->logic=strnicmp(*pp1,*pp2,i);
					else
						csi->logic=LOGIC_FALSE;
					return(0);
				case STRSTR_VARS:
					pp1=getstrvar(csi,*(int32_t *)csi->ip);
					csi->ip+=4; /* Skip variable name */
					pp2=getstrvar(csi,*(int32_t *)csi->ip);
					csi->ip+=4;
					if(pp1 && *pp1 && pp2 && *pp2 && strstr(*pp1,*pp2))
						csi->logic=LOGIC_TRUE;
					else
						csi->logic=LOGIC_FALSE;
					return(0);
				case COMPARE_INT_VAR:
					lp=getintvar(csi,*(int32_t *)csi->ip);
					csi->ip+=4; /* Skip variable name */
					l=*(int32_t *)csi->ip;
					csi->ip+=4; /* Skip static value */
					if(!lp) {	/* Unknown variable */
						csi->logic=LOGIC_FALSE;
						return(0);
					}
					if(*lp>l)
						csi->logic=LOGIC_GREATER;
					else if(*lp<l)
						csi->logic=LOGIC_LESS;
					else
						csi->logic=LOGIC_EQUAL;
					return(0);
				case COMPARE_VARS:
					lp1=lp2=0;
					pp1=getstrvar(csi,*(int32_t *)csi->ip);
					if(!pp1)
						lp1=getintvar(csi,*(int32_t *)csi->ip);
					csi->ip+=4; /* Skip variable name */
					pp2=getstrvar(csi,*(int32_t *)csi->ip);
					if(!pp2)
						lp2=getintvar(csi,*(int32_t *)csi->ip);
					csi->ip+=4; /* Skip variable name */

					if(((!pp1 || !*pp1) && !lp1)
						|| ((!pp2 || !*pp2) && !lp2)) {
						if(pp1 && pp2)		/* Both unitialized or blank */
							csi->logic=LOGIC_TRUE;
						else
							csi->logic=LOGIC_FALSE;
						return(0);
					}

					if(pp1) { /* ASCII */
						if(!pp2) {
							ultoa(*lp2,tmp,10);
							csi->logic=stricmp(*pp1,tmp);
						}
						else
							csi->logic=stricmp(*pp1,*pp2);
						return(0);
					}

					/* Binary */
					if(!lp2) {
						l=strtol(*pp2,0,0);
						if(*lp1>l)
							csi->logic=LOGIC_GREATER;
						else if(*lp1<l)
							csi->logic=LOGIC_LESS;
						else
							csi->logic=LOGIC_EQUAL;
						return(0);
					}
					if(*lp1>*lp2)
						csi->logic=LOGIC_GREATER;
					else if(*lp1<*lp2)
						csi->logic=LOGIC_LESS;
					else
						csi->logic=LOGIC_EQUAL;
					return(0);
				case COPY_VAR:
					lp1=lp2=0;
					pp1=getstrvar(csi,*(int32_t *)csi->ip);
					if(!pp1)
						lp1=getintvar(csi,*(int32_t *)csi->ip);
					csi->ip+=4; /* Skip variable name */
					pp2=getstrvar(csi,*(int32_t *)csi->ip);
					if(!pp2)
						lp2=getintvar(csi,*(int32_t *)csi->ip);
					csi->ip+=4; /* Skip variable name */

					if((!pp1 && !lp1)
						|| ((!pp2 || !*pp2) && !lp2)) {
						csi->logic=LOGIC_FALSE;
						return(0);
					}
					csi->logic=LOGIC_TRUE;

					if(pp1) {	/* ASCII */
						if(!pp2)
							ultoa(*lp2,tmp,10);
						else
							strcpy(tmp,*pp2);
						*pp1=copystrvar(csi,*pp1,tmp);
						return(0);
					}
					if(!lp2)
						*lp1=strtol(*pp2,0,0);
					else
						*lp1=*lp2;
					return(0);
				case SWAP_VARS:
					lp1=lp2=0;
					pp1=getstrvar(csi,*(int32_t *)csi->ip);
					if(!pp1)
						lp1=getintvar(csi,*(int32_t *)csi->ip);
					csi->ip+=4; /* Skip variable name */
					pp2=getstrvar(csi,*(int32_t *)csi->ip);
					if(!pp2)
						lp2=getintvar(csi,*(int32_t *)csi->ip);
					csi->ip+=4; /* Skip variable name */

					if(((!pp1 || !*pp1) && !lp1)
						|| ((!pp2 || !*pp2) && !lp2)) {
						csi->logic=LOGIC_FALSE;
						return(0);
					}

					csi->logic=LOGIC_TRUE;

					if(pp1) {	/* ASCII */
						if(!pp2) {
							if(!strnicmp(*pp1,"0x",2)) {
								l=strtol((*pp1)+2,0,16);
								ultoa(*lp2,tmp,16);
							}
							else {
								l=atol(*pp1);
								ultoa(*lp2,tmp,10);
							}
							*pp1=copystrvar(csi,*pp1,tmp);
							*lp2=l;
						}
						else {
							p=*pp1;
							*pp1=*pp2;
							*pp2=p;
						}
						return(0);
					}

					/* Binary */
					if(!lp2) {
						if(!strnicmp(*pp2,"0x",2)) {
							l=strtol((*pp2)+2,0,16);
							ultoa(*lp1,tmp,16);
						}
						else {
							l=atol(*pp2);
							ultoa(*lp1,tmp,10);
						}
						*pp2=copystrvar(csi,*pp2,tmp);
						*lp1=l;
					}
					else {
						l=*lp1;
						*lp1=*lp2;
						*lp2=l;
					}
					return(0);
				case CAT_STR_VAR:
					pp=getstrvar(csi,*(int32_t *)csi->ip);
					csi->ip+=4; /* Skip variable name */
					strcpy(tmp,(char *)csi->ip);
					while(*(csi->ip++));
					if(pp && *pp)
						for(i=0;i<MAX_SYSVARS;i++)
							if(*pp==sysvar_p[i])
								break;
					if(pp && *pp!=csi->str && i==MAX_SYSVARS) {
						if(*pp)
							*pp=(char *)realloc_or_free(*pp,strlen(*pp)+strlen(tmp)+1);
						else
							*pp=(char *)realloc_or_free(*pp,strlen(tmp)+1);
					}
					if(pp && *pp)
						strcat(*pp,tmp);
					return(0);
				case CAT_STR_VARS:
					pp1=getstrvar(csi,*(int32_t *)csi->ip);
					csi->ip+=4; /* Skip dest variable name */
					pp2=getstrvar(csi,*(int32_t *)csi->ip);
					csi->ip+=4; /* Skip source variable name */

					/* Concatenate an int var to a str var (as char) */
					if(pp2==NULL) {
						lp=getintvar(csi,*(int32_t *)(csi->ip-4));
						if(lp==NULL) {
							csi->logic=LOGIC_FALSE;
							return(0);
						}
						pp=pp1;
						tmp[0]=(uchar)*lp;
						tmp[1]=0;
						if(pp && *pp)
							for(i=0;i<MAX_SYSVARS;i++)
								if(*pp==sysvar_p[i])
									break;
						if(pp && *pp!=csi->str && i==MAX_SYSVARS) {
							if(*pp)
								*pp=(char *)realloc_or_free(*pp,strlen(*pp)+strlen(tmp)+1);
							else
								*pp=(char *)realloc_or_free(*pp,strlen(tmp)+1);
						}
						if(pp && *pp)
							strcat(*pp,tmp);
						return(0);
					}

					if(!pp1 || !pp2 || !*pp2) {
						csi->logic=LOGIC_FALSE;
						return(0);
					}
					csi->logic=LOGIC_TRUE;
					if(*pp1)
						for(i=0;i<MAX_SYSVARS;i++)
							if(*pp1==sysvar_p[i])
								break;
					if(*pp1!=csi->str && (!*pp1 || i==MAX_SYSVARS)) {
						if(*pp1)
							*pp1=(char *)realloc_or_free(*pp1,strlen(*pp1)+strlen(*pp2)+1);
						else
							*pp1=(char *)realloc_or_free(*pp1,strlen(*pp2)+1);
					}
					if(*pp1 != NULL)
						strcat(*pp1,*pp2);
					return(0);
				case FORMAT_STR_VAR:
					pp=getstrvar(csi,*(int32_t *)csi->ip);
					csi->ip+=4; /* Skip variable name */
					p=format_string(this, csi);
					cmdstr(p,path,csi->str,str);
					if(pp)
						*pp=copystrvar(csi,*pp,str);
					free(p);
					return(0);
				case FORMAT_TIME_STR:
					pp=getstrvar(csi,*(int32_t *)csi->ip);
					csi->ip+=4; /* Skip variable name */
					strcpy(str,(char *)csi->ip);
					while(*(csi->ip++));	/* Find NULL */
					lp=getintvar(csi,*(int32_t *)csi->ip);
					csi->ip+=4;
					if(pp && lp) {
						time_t	tt;
						tt=*lp;
						if(localtime_r(&tt,&tm)!=NULL) {
							strftime(buf,128,str,&tm);
							*pp=copystrvar(csi,*pp,buf);
						}
					}
					return(0);
				case TIME_STR:
					pp=getstrvar(csi,*(int32_t *)csi->ip);
					csi->ip+=4; /* Skip str variable name */
					lp=getintvar(csi,*(int32_t *)csi->ip);
					csi->ip+=4; /* Skip int variable name */
					if(pp && lp) {
						strcpy(str,timestr(*lp));
						*pp=copystrvar(csi,*pp,str);
					}
					return(0);
				case DATE_STR:
					pp=getstrvar(csi,*(int32_t *)csi->ip);
					csi->ip+=4; /* Skip str variable name */
					lp=getintvar(csi,*(int32_t *)csi->ip);
					csi->ip+=4; /* Skip int variable name */
					if(pp && lp) {
						unixtodstr(&cfg,*lp,str);
						*pp=copystrvar(csi,*pp,str);
					}
					return(0);
				case SECOND_STR:
					pp=getstrvar(csi,*(int32_t *)csi->ip);
					csi->ip+=4; /* Skip str variable name */
					lp=getintvar(csi,*(int32_t *)csi->ip);
					csi->ip+=4; /* Skip int variable name */
					if(pp && lp) {
						sectostr(*lp,str);
						*pp=copystrvar(csi,*pp,str);
					}
					return(0);
				case STRUPR_VAR:
					pp=getstrvar(csi,*(int32_t *)csi->ip);
					csi->ip+=4;
					if(pp && *pp)
						strupr(*pp);
					return(0);
				case STRLWR_VAR:
					pp=getstrvar(csi,*(int32_t *)csi->ip);
					csi->ip+=4;
					if(pp && *pp)
						strlwr(*pp);
					return(0);
				case TRUNCSP_STR_VAR:
					pp=getstrvar(csi,*(int32_t *)csi->ip);
					csi->ip+=4;
					if(pp && *pp)
						truncsp(*pp);
					return(0);
				case STRIP_CTRL_STR_VAR:
					pp=getstrvar(csi,*(int32_t *)csi->ip);
					csi->ip+=4;
					if(pp && *pp)
						strip_ctrl(*pp, *pp);
					return(0);

				case ADD_INT_VAR:
				case SUB_INT_VAR:
				case MUL_INT_VAR:
				case DIV_INT_VAR:
				case MOD_INT_VAR:
				case AND_INT_VAR:
				case OR_INT_VAR:
				case NOT_INT_VAR:
				case XOR_INT_VAR:
					i=*(csi->ip-1);
					lp=getintvar(csi,*(int32_t *)csi->ip);
					csi->ip+=4;
					l=*(int32_t *)csi->ip;
					csi->ip+=4;
					if(!lp)
						return(0);
					switch(i) {
						case ADD_INT_VAR:
							*lp+=l;
							break;
						case SUB_INT_VAR:
							*lp-=l;
							break;
						case MUL_INT_VAR:
							*lp*=l;
							break;
						case DIV_INT_VAR:
							*lp/=l;
							break;
						case MOD_INT_VAR:
							*lp%=l;
							break;
						case AND_INT_VAR:
							*lp&=l;
							break;
						case OR_INT_VAR:
							*lp|=l;
							break;
						case NOT_INT_VAR:
							*lp&=~l;
							break;
						case XOR_INT_VAR:
							*lp^=l;
							break;
					}
					return(0);
				case COMPARE_ANY_BITS:
				case COMPARE_ALL_BITS:
					i=*(csi->ip-1);
					lp=getintvar(csi,*(int32_t *)csi->ip);
					csi->ip+=4;
					l=*(int32_t *)csi->ip;
					csi->ip+=4;
					csi->logic=LOGIC_FALSE;
					if(!lp)
						return(0);

					if(i==COMPARE_ANY_BITS) {
						if(((*lp)&l)!=0)
							csi->logic=LOGIC_TRUE;
					} else {
						if(((*lp)&l)==l)
							csi->logic=LOGIC_TRUE;
					}
					return(0);
				case ADD_INT_VARS:
				case SUB_INT_VARS:
				case MUL_INT_VARS:
				case DIV_INT_VARS:
				case MOD_INT_VARS:
				case AND_INT_VARS:
				case OR_INT_VARS:
				case NOT_INT_VARS:
				case XOR_INT_VARS:
					i=*(csi->ip-1);
					lp1=getintvar(csi,*(int32_t *)csi->ip);
					csi->ip+=4;
					lp2=getintvar(csi,*(int32_t *)csi->ip);
					if(!lp2) {
						pp=getstrvar(csi,*(int32_t *)csi->ip);
						if(!pp || !*pp)
							return(0);
						l=strtol(*pp,0,0);
					}
					else
						l=*lp2;
					csi->ip+=4;
					if(!lp1)
						return(0);
					switch(i) {
						case ADD_INT_VARS:
							*lp1+=l;
							break;
						case SUB_INT_VARS:
							*lp1-=l;
							break;
						case MUL_INT_VARS:
							*lp1*=l;
							break;
						case DIV_INT_VARS:
							*lp1/=l;
							break;
						case MOD_INT_VARS:
							*lp1%=l;
							break;
						case AND_INT_VARS:
							*lp1&=l;
							break;
						case OR_INT_VARS:
							*lp1|=l;
							break;
						case NOT_INT_VARS:
							*lp1&=~l;
							break;
						case XOR_INT_VARS:
							*lp1^=l;
							break;
					}
					return(0);
				case RANDOM_INT_VAR:
					lp=getintvar(csi,*(int32_t *)csi->ip);
					csi->ip+=4;
					l=*(int32_t *)csi->ip;
					csi->ip+=4;
					if(lp)
						*lp=sbbs_random(l);
					return(0);
				case TIME_INT_VAR:
					lp=getintvar(csi,*(int32_t *)csi->ip);
					csi->ip+=4;
					if(lp)
						*lp=time32(NULL);
					return(0);
				case DATE_STR_TO_INT:
					lp=getintvar(csi,*(int32_t *)csi->ip);
					csi->ip+=4;
					pp=getstrvar(csi,*(int32_t *)csi->ip);
					csi->ip+=4;
					if(lp && pp && *pp)
						*lp=(int32_t)dstrtounix(&cfg,*pp);
					return(0);
				case STRLEN_INT_VAR:
					lp=getintvar(csi,*(int32_t *)csi->ip);
					csi->ip+=4;
					pp=getstrvar(csi,*(int32_t *)csi->ip);
					csi->ip+=4;
					if(lp) {
						if(pp && *pp)
							*lp=strlen(*pp);
						else
							*lp=0;
					}
					return(0);
				case CRC16_TO_INT:
					lp=getintvar(csi,*(int32_t *)csi->ip);
					csi->ip+=4;
					pp=getstrvar(csi,*(int32_t *)csi->ip);
					csi->ip+=4;
					if(lp) {
						if(pp && *pp)
							*lp=crc16(*pp,0);
						else
							*lp=0;
					}
					return(0);
				case CRC32_TO_INT:
					lp=getintvar(csi,*(int32_t *)csi->ip);
					csi->ip+=4;
					pp=getstrvar(csi,*(int32_t *)csi->ip);
					csi->ip+=4;
					if(lp) {
						if(pp && *pp)
							*lp=crc32(*pp,0);
						else
							*lp=0;
					}
					return(0);
				case CHKSUM_TO_INT:
					lp=getintvar(csi,*(int32_t *)csi->ip);
					csi->ip+=4;
					pp=getstrvar(csi,*(int32_t *)csi->ip);
					csi->ip+=4;
					if(lp) {
						*lp=0;
						if(pp && *pp) {
							i=0;
							while(*((*pp)+i))
								*lp+=(uchar)*((*pp)+(i++)); }
					}
					return(0);
				case FLENGTH_TO_INT:
					lp=getintvar(csi,*(int32_t *)csi->ip);
					csi->ip+=4;
					pp=getstrvar(csi,*(int32_t *)csi->ip);
					csi->ip+=4;
					if(lp) {
						if(pp && *pp)
							*lp=(uint32_t)flength(*pp);
						else
							*lp=0;
					}
					return(0);
				case FTIME_TO_INT:
					lp=getintvar(csi,*(int32_t *)csi->ip);
					csi->ip+=4;
					pp=getstrvar(csi,*(int32_t *)csi->ip);
					csi->ip+=4;
					if(lp) {
						if(pp && *pp)
							*lp=(int32_t)fdate(*pp);
						else
							*lp=0;
					}
					return(0);
				case CHARVAL_TO_INT:
				case COPY_FIRST_CHAR:	// duplicate functionality - doh!
					lp=getintvar(csi,*(int32_t *)csi->ip);
					csi->ip+=4;
					pp=getstrvar(csi,*(int32_t *)csi->ip);
					csi->ip+=4;
					if(lp) {
						if(pp && *pp)
							*lp=**pp;
						else
							*lp=0;
					}
					return(0);
				case GETSTR_VAR:
				case GETLINE_VAR:
				case GETNAME_VAR:
				case GETSTRUPR_VAR:
				case GETSTR_MODE:
					pp=getstrvar(csi,*(int32_t *)csi->ip);
					csi->ip+=4;
					i=*(csi->ip++);
					csi->logic=LOGIC_FALSE;
					switch(*(csi->ip-6)) {
						case GETNAME_VAR:
							getstr(buf,i,K_UPRLWR);
							break;
						case GETSTRUPR_VAR:
							getstr(buf,i,K_UPPER);
							break;
						case GETLINE_VAR:
							getstr(buf,i,K_LINE);
							break;
						case GETSTR_MODE:
							l=*(int32_t *)csi->ip;
							csi->ip+=4;
							if(l&K_EDIT) {
								if(pp && *pp)
									strcpy(buf,*pp);
								else
									buf[0]=0;
							}
							getstr(buf,i,l);
							break;
						default:
							getstr(buf,i,0);
					}
					if(sys_status&SS_ABORT)
						return(0);
					if(pp) {
						*pp=copystrvar(csi,*pp,buf);
						csi->logic=LOGIC_TRUE;
					}
					return(0);
				case GETNUM_VAR:
					pp=getstrvar(csi,*(int32_t *)csi->ip);
					if(!pp)
						lp=getintvar(csi,*(int32_t *)csi->ip);
					csi->ip+=4;
					i=*(short *)csi->ip;
					csi->ip+=2;
					csi->logic=LOGIC_FALSE;
					l=getnum(i);
					if(!pp && !lp)
						return(0);
					if(pp) {
						if(l<=0)
							str[0]=0;
						else
							ultoa(l,str,10);
						*pp=copystrvar(csi,*pp,str);
						csi->logic=LOGIC_TRUE;
						return(0);
					}
					if(lp) {
						*lp=l;
						csi->logic=LOGIC_TRUE;
					}
					return(0);

				case SHIFT_STR_VAR:
					pp=getstrvar(csi,*(int32_t *)csi->ip);
					csi->ip+=4;
					i=*(csi->ip++);
					if(!pp || !*pp)
						return(0);
					if((int)strlen(*pp)>=i)
						memmove(*pp,*pp+i,strlen(*pp)+1);
					return(0);

				case SHIFT_TO_FIRST_CHAR:
				case SHIFT_TO_LAST_CHAR:
					i=*(csi->ip-1);
					pp=getstrvar(csi,*(int32_t *)csi->ip);
					csi->ip+=4;
					ch=*(csi->ip++);
					csi->logic=LOGIC_FALSE;
					if(!pp || !*pp)
						return(0);
					if(i==SHIFT_TO_FIRST_CHAR)
						p=strchr(*pp,ch);
					else	/* _TO_LAST_CHAR */
						p=strrchr(*pp,ch);
					if(p==NULL)
						return(0);
					csi->logic=LOGIC_TRUE;
					i=p-*pp;
					if(i>0)
						memmove(*pp,*pp+i,strlen(p)+1);
					return(0);

				case CHKFILE_VAR:
					pp=getstrvar(csi,*(int32_t *)csi->ip);
					csi->ip+=4;
					if(pp && *pp && fexistcase(cmdstr(*pp,path,csi->str,buf)))
						csi->logic=LOGIC_TRUE;
					else
						csi->logic=LOGIC_FALSE;
					return(0);
				case PRINTFILE_VAR_MODE:
					pp=getstrvar(csi,*(int32_t *)csi->ip);
					csi->ip+=4;
					i=*(short *)(csi->ip);
					csi->ip+=2;
					if(pp && *pp)
						printfile(*pp,i);
					return(0);
				case PRINTTAIL_VAR_MODE:
					pp=getstrvar(csi,*(int32_t *)csi->ip);
					csi->ip+=4;
					i=*(short *)(csi->ip);
					csi->ip+=2;
					j=*csi->ip;
					csi->ip++;
					if(pp && *pp)
						printtail(*pp,j,i);
					return(0);
				case TELNET_GATE_VAR:
					l=*(uint32_t *)(csi->ip);	// Mode
					csi->ip+=4;
					pp=getstrvar(csi,*(int32_t *)csi->ip);
					csi->ip+=4;
					if(pp && *pp)
						telnet_gate(*pp,l);
					return(0);
				case TELNET_GATE_STR:
					l=*(uint32_t *)(csi->ip);	// Mode
					csi->ip+=4;
					strcpy(str,(char *)csi->ip);
					while(*(csi->ip++));	/* Find NULL */
					telnet_gate(str,l);
					return(0);
				case COPY_CHAR:
					pp=getstrvar(csi,*(int32_t *)csi->ip);
					if(pp==NULL)
						lp=getintvar(csi,*(int32_t *)csi->ip);
					csi->ip+=4;

					if(pp==NULL && lp!=NULL)
						*lp=csi->cmd;
					else if(pp!=NULL) {
						sprintf(tmp,"%c",csi->cmd);
						*pp=copystrvar(csi,*pp,tmp);
					}
					return(0);
				case COMPARE_FIRST_CHAR:
					pp=getstrvar(csi,*(int32_t *)csi->ip);
					csi->ip+=4;
					ch=*(csi->ip++);	/* char const */
					if(pp==NULL || *pp==NULL)
						csi->logic=LOGIC_FALSE;
					else {
						if(**pp==ch)
							csi->logic=LOGIC_EQUAL;
						else if(**pp>ch)
							csi->logic=LOGIC_GREATER;
						else
							csi->logic=LOGIC_LESS;
					}
					return(0);

				case SEND_FILE_VIA:
				case RECEIVE_FILE_VIA:
					j=*(csi->ip-1);
					ch=*(csi->ip++);	/* Protocol */
					cmdstr((char *)csi->ip,csi->str,csi->str,str);
					while(*(csi->ip++));	/* Find NULL */
					for(i=0;i<cfg.total_prots;i++)
						if(cfg.prot[i]->mnemonic==ch && chk_ar(cfg.prot[i]->ar,&useron,&client))
							break;
					csi->logic=LOGIC_FALSE;
					if(i<cfg.total_prots)
						if(protocol(cfg.prot[i],j==SEND_FILE_VIA ? XFER_DOWNLOAD : XFER_UPLOAD
							,str,str,true)==0)
							csi->logic=LOGIC_TRUE;
					return(0);
				case SEND_FILE_VIA_VAR:
				case RECEIVE_FILE_VIA_VAR:
					j=*(csi->ip-1);
					ch=*(csi->ip++);	/* Protocol */
					pp=getstrvar(csi,*(int32_t *)csi->ip);
					csi->ip+=4;
					for(i=0;i<cfg.total_prots;i++)
						if(cfg.prot[i]->mnemonic==ch && chk_ar(cfg.prot[i]->ar,&useron,&client))
							break;
					csi->logic=LOGIC_FALSE;
					if(!pp || !(*pp))
						return(0);
					if(i<cfg.total_prots)
						if(protocol(cfg.prot[i]
							,j==SEND_FILE_VIA_VAR ? XFER_DOWNLOAD : XFER_UPLOAD
							,*pp,*pp,true)==0)
							csi->logic=LOGIC_TRUE;
					return(0);

				case MATCHUSER:
					lp=getintvar(csi,*(int32_t *)csi->ip);
					csi->ip+=4;
					pp=getstrvar(csi,*(int32_t *)csi->ip);
					csi->ip+=4;
					if(lp) {
						if(pp && *pp)
							*lp=matchuser(&cfg, *pp, TRUE /*sysop_alias*/);
						else
							*lp=0;
					}
					return(0);

				default:
					errormsg(WHERE,ERR_CHK,"var sub-instruction",*(csi->ip-1));
					return(0);
		}

		case CS_FIO_FUNCTION:
			switch(*(csi->ip++)) {	/* sub-op-code stored as next byte */
				case FIO_OPEN:
				case FIO_OPEN_VAR:
					lp=getintvar(csi,*(int32_t *)csi->ip);
					csi->ip+=4;
					w=*(ushort *)csi->ip;
					csi->ip+=2;
					csi->logic=LOGIC_FALSE;
					if(*(csi->ip-7)==FIO_OPEN) {
						cmdstr((char *)csi->ip,path,csi->str,str);
						while(*(csi->ip++)); 	 /* skip filename */
					}
					else {
						pp=getstrvar(csi,*(int32_t *)csi->ip);
						csi->ip+=4;
						if(!pp || !*pp)
							return(0);
						strcpy(str,*pp);
					}
					if(csi->files>=MAX_FOPENS)
						return(0);
					if(lp) {
						/* Access flags are not cross-platform, so convert */
						i=0;
						if(w&0x001) i|=O_RDONLY;
						if(w&0x002) i|=O_WRONLY;
						if(w&0x004) i|=O_RDWR;
						if(w&0x040) i|=O_DENYNONE;
						if(w&0x100) i|=O_CREAT;
						if(w&0x200) i|=O_TRUNC;
						if(w&0x400) i|=O_EXCL;
						if(w&0x800) i|=O_APPEND;
						fp=fnopen((int *)&j,str,i);
						if(fp!=NULL) {
							for(i=0;i<csi->files;i++)
								if(csi->file[i]==NULL)
									break;
							csi->file[i]=fp;
							if(i==csi->files)
								csi->files++;
							*lp = i;	/* store the csi->file index, not the FILE* */
							csi->logic=LOGIC_TRUE;
						}
					}
					return(0);
				case FIO_CLOSE:
					lp=getintvar(csi,*(int32_t *)csi->ip);
					csi->ip+=4;
					if(lp && *lp<csi->files) {
						csi->logic=fclose(csi->file[*lp]);
						csi->file[*lp]=NULL;
						if(*lp==(csi->files-1))
							csi->files--;
					}
					else
						csi->logic=LOGIC_FALSE;
					return(0);
				case FIO_FLUSH:
					lp=getintvar(csi,*(int32_t *)csi->ip);
					csi->ip+=4;
					if(lp && *lp<csi->files)
						csi->logic=fflush(csi->file[*lp]);
					else
						csi->logic=LOGIC_FALSE;
					return(0);
				case FIO_READ:
				case FIO_READ_VAR:
					lp1=getintvar(csi,*(int32_t *)csi->ip);		/* Handle */
					csi->ip+=4;
					pp=getstrvar(csi,*(int32_t *)csi->ip);
					if(!pp)
						lp2=getintvar(csi,*(int32_t *)csi->ip);
					csi->ip+=4;
					csi->logic=LOGIC_FALSE;
					if(*(csi->ip-9)==FIO_READ) {
						i=*(short *)csi->ip;
						csi->ip+=2; /* Length */ }
					else {			/* FIO_READ_VAR */
						vp=getintvar(csi,*(int32_t *)csi->ip);
						csi->ip+=4;
						if(!vp)
							return(0);
						i=*(short *)vp;
					}
					if(i>(int)sizeof(buf)-1)
						i=sizeof(buf)-1;
					if(!lp1 || *lp1>=csi->files || (!pp && !lp2))
						return(0);
					if(pp) {
						if(i<1) {
							if(*pp && **pp)
								i=strlen(*pp);
							else
								i=128;
						}
						if((j=fread(buf,1,i,csi->file[*lp1]))==i)
							csi->logic=LOGIC_TRUE;
						buf[j]=0;
						if(csi->etx) {
							p=strchr(buf,csi->etx);
							if(p) *p=0;
						}
						*pp=copystrvar(csi,*pp,buf);
					}
					else {
						*lp2=0;
						if(i>4 || i<1) i=4;
						if(fread(lp2,1,i,csi->file[*lp1])==(size_t)i)
							csi->logic=LOGIC_TRUE;
					}
					return(0);
				case FIO_READ_LINE:
					lp1=getintvar(csi,*(int32_t *)csi->ip);		/* Handle */
					csi->ip+=4;
					pp=getstrvar(csi,*(int32_t *)csi->ip);
					if(!pp)
						lp2=getintvar(csi,*(int32_t *)csi->ip);
					csi->ip+=4;
					csi->logic=LOGIC_FALSE;
					if(!lp1 || *lp1>=csi->files || feof(csi->file[*lp1]) || (!pp && !lp2))
						return(0);
					csi->logic=LOGIC_TRUE;
					for(i=0;i<(int)sizeof(buf)-1;i++) {
						if(!fread(buf+i,1,1,csi->file[*lp1]))
							break;
						if(*(buf+i)==LF) {
							i++;
							break;
						}
					}
					buf[i]=0;
					if(csi->etx) {
						p=strchr(buf,csi->etx);
						if(p) *p=0;
					}
					if(pp)
						*pp=copystrvar(csi,*pp,buf);
					else
						*lp2=strtol(buf,0,0);
					return(0);
				case FIO_WRITE:
				case FIO_WRITE_VAR:
					lp1=getintvar(csi,*(int32_t *)csi->ip);
					csi->ip+=4;
					pp=getstrvar(csi,*(int32_t *)csi->ip);
					if(!pp)
						lp2=getintvar(csi,*(int32_t *)csi->ip);
					csi->ip+=4;
					csi->logic=LOGIC_FALSE;
					if(*(csi->ip-9)==FIO_WRITE) {
						i=*(short *)csi->ip;
						csi->ip+=2; /* Length */ }
					else {			/* FIO_WRITE_VAR */
						vp=getintvar(csi,*(int32_t *)csi->ip);
						csi->ip+=4;
						if(!vp)
							return(0);
						i=*(short *)vp;
					}
					if(i>(int)sizeof(buf)-1)
						i=sizeof(buf)-1;
					if(!lp1 || *lp1>=csi->files || (!pp && !lp2) || (pp && !*pp))
						return(0);
					if(pp) {
						j=strlen(*pp);
						if(i<1) i=j;
						if(j>i) j=i;
						if(fwrite(*pp,1,j,csi->file[*lp1])!=(size_t)j)
							csi->logic=LOGIC_FALSE;
						else {
							if(j<i) {
								memset(buf,csi->etx,i-j);
								fwrite(buf,1,i-j,csi->file[*lp1]);
							}
							csi->logic=LOGIC_TRUE;
						}
					} else {
						if(i<1 || i>4) i=4;
						if(fwrite(lp2,1,i,csi->file[*lp1])==(size_t)i)
							csi->logic=LOGIC_TRUE;
					}
					return(0);
				case FIO_GET_LENGTH:
					lp1=getintvar(csi,*(int32_t *)csi->ip);
					csi->ip+=4;
					lp2=getintvar(csi,*(int32_t *)csi->ip);
					csi->ip+=4;
					if(lp1 && *lp1<csi->files && lp2)
						*lp2=(uint32_t)filelength(fileno(csi->file[*lp1]));
					return(0);
				case FIO_GET_TIME:
					lp1=getintvar(csi,*(int32_t *)csi->ip);
					csi->ip+=4;
					lp2=getintvar(csi,*(int32_t *)csi->ip);
					csi->ip+=4;
					if(lp1 && *lp1<csi->files && lp2)
						*lp2=(int32_t)filetime(fileno(csi->file[*lp1]));
					return(0);
				case FIO_SET_TIME:
					lp1=getintvar(csi,*(int32_t *)csi->ip);
					csi->ip+=4;
					lp2=getintvar(csi,*(int32_t *)csi->ip);
					csi->ip+=4;
	#if 0 /* ftime */
					if(lp1 && (uint)*lp1<csi->files && lp2) {
						ft=unixtoftime(*lp2);
						setftime(fileno(csi->file[*lp1),&ft);
					}
	#endif
					return(0);
				case FIO_EOF:
					lp=getintvar(csi,*(int32_t *)csi->ip);
					csi->ip+=4;
					csi->logic=LOGIC_FALSE;
					if(lp && *lp<csi->files)
						if(ftell(csi->file[*lp])>=filelength(fileno(csi->file[*lp])))
							csi->logic=LOGIC_TRUE;
					return(0);
				case FIO_GET_POS:
					lp1=getintvar(csi,*(int32_t *)csi->ip);
					csi->ip+=4;
					lp2=getintvar(csi,*(int32_t *)csi->ip);
					csi->ip+=4;
					if(lp1 && *lp1<csi->files && lp2)
						*lp2=(uint32_t)ftell(csi->file[*lp1]);
					return(0);
				case FIO_SEEK:
				case FIO_SEEK_VAR:
					lp1=getintvar(csi,*(int32_t *)csi->ip);
					csi->ip+=4;
					csi->logic=LOGIC_FALSE;
					if(*(csi->ip-5)==FIO_SEEK) {
						l=*(int32_t *)csi->ip;
						csi->ip+=4;
					}
					else {
						lp2=getintvar(csi,*(int32_t *)csi->ip);
						csi->ip+=4;
						if(!lp2) {
							csi->ip+=2;
							return(0);
						}
						l=*lp2;
					}
					i=*(short *)csi->ip;
					csi->ip+=2;
					if(lp1 && *lp1<csi->files)
						if(fseek(csi->file[*lp1],l,i)!=-1)
							csi->logic=LOGIC_TRUE;
					return(0);
				case FIO_LOCK:
				case FIO_LOCK_VAR:
					lp1=getintvar(csi,*(int32_t *)csi->ip);
					csi->ip+=4;
					csi->logic=LOGIC_FALSE;
					if(*(csi->ip-5)==FIO_LOCK) {
						l=*(int32_t *)csi->ip;
						csi->ip+=4;
					} else {
						lp2=getintvar(csi,*(int32_t *)csi->ip);
						csi->ip+=4;
						if(!lp2)
							return(0);
						l=*lp2;
					}
					if(lp1 && *lp1<csi->files) {
						fflush(csi->file[*lp1]);
						csi->logic=!lock(fileno(csi->file[*lp1]),ftell(csi->file[*lp1]),l);
					}
					return(0);
				case FIO_UNLOCK:
				case FIO_UNLOCK_VAR:
					lp1=getintvar(csi,*(int32_t *)csi->ip);
					csi->ip+=4;
					csi->logic=LOGIC_FALSE;
					if(*(csi->ip-5)==FIO_UNLOCK) {
						l=*(int32_t *)csi->ip;
						csi->ip+=4;
					} else {
						lp2=getintvar(csi,*(int32_t *)csi->ip);
						csi->ip+=4;
						if(!lp2)
							return(0);
						l=*lp2;
					}
					if(lp1 && *lp1<csi->files) {
						fflush(csi->file[*lp1]);
						csi->logic=!unlock(fileno(csi->file[*lp1]),ftell(csi->file[*lp1]),l);
					}
					return(0);
				case FIO_SET_LENGTH:
				case FIO_SET_LENGTH_VAR:
					lp1=getintvar(csi,*(int32_t *)csi->ip);
					csi->ip+=4;
					csi->logic=LOGIC_FALSE;
					if(*(csi->ip-5)==FIO_SET_LENGTH) {
						l=*(int32_t *)csi->ip;
						csi->ip+=4;
					} else {
						lp2=getintvar(csi,*(int32_t *)csi->ip);
						csi->ip+=4;
						if(!lp2)
							return(0);
						l=*lp2;
					}
					if(lp1 && *lp1<csi->files)
						csi->logic=chsize(fileno(csi->file[*lp1]),l);
					return(0);
				case FIO_PRINTF:
					lp1=getintvar(csi,*(int32_t *)csi->ip);
					csi->ip+=4;
					p=format_string(this, csi);
					if(lp1 && *lp1<csi->files) {
						cmdstr(p,path,csi->str,str);
						fwrite(str,1,strlen(str),csi->file[*lp1]);
					}
					free(p);
					return(0);
				case FIO_SET_ETX:
					csi->etx=*(csi->ip++);
					return(0);
				case REMOVE_FILE:
					pp=getstrvar(csi,*(int32_t *)csi->ip);
					csi->ip+=4;
					if(pp && *pp && removecase(*pp)==0)
						csi->logic=LOGIC_TRUE;
					else
						csi->logic=LOGIC_FALSE;
					return(0);
				case RENAME_FILE:
				case COPY_FILE:
				case MOVE_FILE:
					pp1=getstrvar(csi,*(int32_t *)csi->ip);
					csi->ip+=4; /* Skip variable name */
					pp2=getstrvar(csi,*(int32_t *)csi->ip);
					csi->ip+=4;
					if(pp1 && *pp1 && pp2 && *pp2)
						switch(*(csi->ip-9)) {
							case RENAME_FILE:
								csi->logic=rename(*pp1,*pp2);
								break;
							case COPY_FILE:
								csi->logic=mv(*pp1,*pp2,1);
								break;
							case MOVE_FILE:
								csi->logic=mv(*pp1,*pp2,0);
								break;
					}
					else
						csi->logic=LOGIC_FALSE;
					return(0);
				case GET_FILE_ATTRIB:
				case SET_FILE_ATTRIB:
					lp=getintvar(csi,*(int32_t *)csi->ip);
					csi->ip+=4;
					pp=getstrvar(csi,*(int32_t *)csi->ip);
					csi->ip+=4;
					if(pp && *pp && lp) {
						if(*(csi->ip-9)==GET_FILE_ATTRIB)
							*lp=getfattr(*pp);
						else
							*lp=CHMOD(*pp,(int)*lp);
					}
					return(0);
				case MAKE_DIR:
				case REMOVE_DIR:
				case CHANGE_DIR:
					pp=getstrvar(csi,*(int32_t *)csi->ip);
					csi->ip+=4;
					if(pp && *pp)
						switch(*(csi->ip-5)) {
							case MAKE_DIR:
								csi->logic=MKDIR(*pp);
								break;
							case REMOVE_DIR:
								csi->logic=rmdir(*pp);
								break;
							case CHANGE_DIR:
								csi->logic=chdir(*pp);
								break;
					}
					else
						csi->logic=LOGIC_FALSE;
					return(0);

				case OPEN_DIR:
					lp=getintvar(csi,*(int32_t *)csi->ip);
					csi->ip+=4;
					pp=getstrvar(csi,*(int32_t *)csi->ip);
					csi->ip+=4;
					csi->logic=LOGIC_FALSE;
					if(csi->dirs>=MAX_OPENDIRS)
						return(0);
					if(pp && *pp && lp) {
						dp=opendir((char *)*pp);
						if(dp!=NULL) {
							for(i=0;i<csi->dirs;i++)
								if(csi->dir[i]==NULL)
									break;
							csi->dir[i]=dp;
							if(i==csi->dirs)
								csi->dirs++;
							*lp = i;	/* store the csi->file index, not the DIR* */
							csi->logic=LOGIC_TRUE;
						}
					}
					return(0);
				case READ_DIR:
					lp=getintvar(csi,*(int32_t *)csi->ip);
					csi->ip+=4;
					pp=getstrvar(csi,*(int32_t *)csi->ip);
					csi->ip+=4;
					csi->logic=LOGIC_FALSE;
					if(pp && lp && *lp<csi->dirs) {
						de=readdir(csi->dir[*lp]);
						if(de!=NULL) {
							csi->logic=LOGIC_TRUE;
							*pp=copystrvar(csi,*pp,de->d_name);
						}
					}
					return(0);
				case REWIND_DIR:
					lp=getintvar(csi,*(int32_t *)csi->ip);
					csi->ip+=4;
					if(lp && *lp<csi->dirs) {
						rewinddir(csi->dir[*lp]);
						csi->logic=LOGIC_TRUE;
					} else
						csi->logic=LOGIC_FALSE;
					return(0);
				case CLOSE_DIR:
					lp=getintvar(csi,*(int32_t *)csi->ip);
					csi->ip+=4;
					if(lp && *lp<csi->dirs && closedir(csi->dir[*lp])==0) {
						csi->logic=LOGIC_TRUE;
						csi->dir[*lp]=NULL;
						if(*lp==(csi->dirs-1))
							csi->dirs--;
					} else
						csi->logic=LOGIC_FALSE;
					return(0);

				default:
					errormsg(WHERE,ERR_CHK,"fio sub-instruction",*(csi->ip-1));
					return(0);
			}

		case CS_NET_FUNCTION:
			return(exec_net(csi));

		case CS_SWITCH:
			lp=getintvar(csi,*(int32_t *)csi->ip);
			csi->ip+=4;
			if(!lp) {
				skipto(csi,CS_END_SWITCH);
				csi->ip++;
			}
			else {
				csi->misc|=CS_IN_SWITCH;
				csi->switch_val=*lp;
			}
			return(0);
		case CS_CASE:
			l=*(int32_t *)csi->ip;
			csi->ip+=4;
			if(csi->misc&CS_IN_SWITCH && csi->switch_val!=l)
				skipto(csi,CS_NEXTCASE);
			else
				csi->misc&=~CS_IN_SWITCH;
			return(0);
		case CS_COMPARE_ARS:
			i=*(csi->ip++);  /* Length of ARS stored as byte before ARS */
			csi->logic=!chk_ar(csi->ip,&useron,&client);
			csi->ip+=i;
			return(0);
		case CS_TOGGLE_USER_MISC:
			useron.misc^=*(uint32_t *)csi->ip;
			putusermisc(useron.number, useron.misc);
			csi->ip+=4;
			return(0);
		case CS_COMPARE_USER_MISC:
			if((useron.misc&*(uint32_t *)csi->ip)==*(uint32_t *)csi->ip)
				csi->logic=LOGIC_TRUE;
			else
				csi->logic=LOGIC_FALSE;
			csi->ip+=4;
			return(0);
		case CS_TOGGLE_USER_CHAT:
			useron.chat^=*(uint32_t *)csi->ip;
			putuserchat(useron.number, useron.chat);
			csi->ip+=4;
			return(0);
		case CS_COMPARE_USER_CHAT:
			if((useron.chat&*(uint32_t *)csi->ip)==*(uint32_t *)csi->ip)
				csi->logic=LOGIC_TRUE;
			else
				csi->logic=LOGIC_FALSE;
			csi->ip+=4;
			return(0);
		case CS_TOGGLE_USER_QWK:
			useron.qwk^=*(uint32_t *)csi->ip;
			putuserqwk(useron.number, useron.qwk);
			csi->ip+=4;
			return(0);
		case CS_COMPARE_USER_QWK:
			if((useron.qwk&*(uint32_t *)csi->ip)==*(uint32_t *)csi->ip)
				csi->logic=LOGIC_TRUE;
			else
				csi->logic=LOGIC_FALSE;
			csi->ip+=4;
			return(0);
		case CS_REPLACE_TEXT:
			i=*(ushort *)csi->ip;
			csi->ip+=2;
			i--;
			if(i>=TOTAL_TEXT) {
				errormsg(WHERE,ERR_CHK,"replace text #",i);
				while(*(csi->ip++));	 /* Find NULL */
				return(0);
			}
			if(text[i]!=text_sav[i] && text[i]!=nulstr)
				free(text[i]);
			j=strlen(cmdstr((char *)csi->ip,path,csi->str,buf));
			if(!j)
				text[i]=(char*)nulstr;
			else
				text[i]=(char *)malloc(j+1);
			if(!text[i]) {
				errormsg(WHERE,ERR_ALLOC,"replacement text",j);
				while(*(csi->ip++));	 /* Find NULL */
				text[i]=text_sav[i];
				return(0);
			}
			if(j)
				strcpy(text[i],buf);
			while(*(csi->ip++));	 /* Find NULL */
			return(0);
		case CS_USE_INT_VAR:	// Self-modifying code!
			pp=getstrvar(csi,*(int32_t *)csi->ip);
			if(pp && *pp)
				l=strtol(*pp,0,0);
			else {
				lp=getintvar(csi,*(int32_t *)csi->ip);
				if(lp)
					l=*lp;
				else
					l=0;
			}
			csi->ip+=4; 			// Variable
			i=*(csi->ip++); 		// Offset
			if(i<1 || csi->ip+1+i>=csi->cs+csi->length) {
				errormsg(WHERE,ERR_CHK,"offset",i);
				csi->ip++;
				return(0);
			}
			switch(*(csi->ip++)) {	// Length
				case sizeof(char):
					*(csi->ip+i)=(char)l;
					break;
				case sizeof(short):
					*((short *)(csi->ip+i))=(short)l;
					break;
				case sizeof(int32_t):
					*((int32_t *)(csi->ip+i))=l;
					break;
				default:
					errormsg(WHERE,ERR_CHK,"length",*(csi->ip-1));
					break;
			}
			return(0);
		default:
			errormsg(WHERE,ERR_CHK,"shell instruction",*(csi->ip-1));
			return(0);
	}
}