socketmud/
socketmud/doc/
socketmud/help/
socketmud/players/
socketmud/scripts/
socketmud/scripts/brain_data/
socketmud/scripts/brain_data/base_brains/
socketmud/scripts/cmd_data/
socketmud/scripts/cmd_data/commands/
socketmud/scripts/home/
socketmud/scripts/home/LordLua/
#include <stdlib.h>
#include <dirent.h>
#include <string.h>
#include <sys/stat.h>
#include <malloc.h>
#ifndef CYGWIN32
#include <unistd.h>
#endif
#include "scripting.h"
#include "mud.h"

extern int errno;
DIRFILE_ENTRY * dirfile_root;

DIRFILE_ENTRY * new_dir_entry()
{
	DIRFILE_ENTRY * new;
	new = malloc(sizeof(*new));
	new->name = strdup("");
	new->creator = strdup("");
	new->vSecurity = 5;
	new->eSecurity = 5;
	new->cSecurity = 5;
	new->parent = NULL;
	new->contents = NULL;
	return new;
}

void free_dir_entry(DIRFILE_ENTRY *target)
{
	free(target->name);
	free(target->creator);
	/*free the list stuff, dont' need it yet, can't delete dir's.*/
	free(target);
}

bool read_dirfile(LIST * target,const char * path, DIRFILE_ENTRY * parent)
{
	FILE * fp;
	char filename[MAX_BUFFER];
	char buf[MAX_BUFFER];
	char * word;
	ITERATOR pIter;
	bool done = FALSE;
	bool found;
	DIRFILE_ENTRY *current;
	
	sprintf(filename, "%s/dir", path);
	if ((fp = fopen(filename, "r")) == NULL)
	    return FALSE;
	
	  word = fread_word(fp);
	  while (!done)
	  {
		    found = FALSE;
		    switch (word[0])
		    {
		    case 'B':
		    	current = new_dir_entry();
		    	current->contents = NULL;
		    	if (parent == NULL)
		    	{
		    		/*If a directory is somehow orphaned, link it to root.*/
		    		current->parent = dirfile_root;
		    	}
		    	else
		    	{
		    		current->parent = parent;
		    	}	
		    	current->locked = FALSE;
		        free(current->name);
		        free(current->creator);
		    	found = TRUE;
		    	break;
		    case 'n':
		    	SREAD("name", current->name);
		    	break;
		    case 'c':
		    	SREAD("creator", current->creator);
		    	IREAD("csec", current->cSecurity);
		    	break;
		    case 'e':
		    	IREAD("esec", current->eSecurity);
		    	break;
		    case 't':
		    	IREAD("type", current->type);
		    	break;
		    case 'v':
		    	IREAD("vsec", current->vSecurity);
		    	break;
		    case 'E':
		    	if (!strcasecmp(word, "EOF")) {done = TRUE; found = TRUE; break;}
		    	if (!strcasecmp(word, "END"))
		    		{
		    			AttachToList(current, target);
		    			sprintf(buf, "%s/%s", path, current->name);
		    			current->realpath = strdup(buf);
		    			found = TRUE;
		    		}
	    	break;

		    }
		    if (!found)
		        {
		          bug("read_dirfile: unexpected '%s' in %s's dirfile.", word, path);
		        }
		    /* read one more */
		    if (!done)
		    {
		    	word = fread_word(fp);
		    }
	  }
	  fclose(fp);
	  AttachIterator(&pIter, target);
	  
	  while ((current = (DIRFILE_ENTRY *) NextInList(&pIter)) != NULL)
	  {
		  if (current->type == DIRFILE_TYPE_DIR && strcasecmp(current->name, "."))
				  {
			  		sprintf(buf, "%s/%s", path, current->name);
			  		if (current->contents == NULL)
			  			current->contents = AllocList();
			  		read_dirfile(current->contents, buf, current);
				  }
	  }
	  DetachIterator(&pIter);
  
	return TRUE;
}

void init_dir_structure()
{
	dirfile_root = new_dir_entry();
        free(dirfile_root->name);
	dirfile_root->name = strdup("/");
	dirfile_root->contents = AllocList();
	dirfile_root->realpath = SCRIPT_DIR;
	if (!read_dirfile(dirfile_root->contents, SCRIPT_DIR, NULL))
		log_string("read_dirfile failed!");

}


DIRFILE_ENTRY * get_entry_by_name(const char * name, LIST * target)
{
	ITERATOR pIter;
	DIRFILE_ENTRY *current;
	if (target == NULL)
		return NULL;
	AttachIterator(&pIter, target);
	  while ((current = (DIRFILE_ENTRY *) NextInList(&pIter)) != NULL)
	  {
		  if (!strcasecmp(current->name, name))
		  {
			  DetachIterator(&pIter);
			  return current;
		  }
	  }
	  DetachIterator(&pIter);
	  return NULL;
}


DIRFILE_ENTRY * get_dirfile_from_path(const char * path, DIRFILE_ENTRY *start, D_MOBILE *dMob)
{
	char *lPath;
	char *token;
	DIRFILE_ENTRY *current;
	char buf[MAX_BUFFER];
	lPath = strdup(path);
	token = strtok(lPath, "/");
	
	if (lPath[0] != '/')
	{
		current = start;
	}
	else
	{
		current = dirfile_root;
		if (token == NULL)
	        {
		
		        free(lPath);
		        return current;	   
		}
	   
	}

	if (!strcasecmp(token, "~"))
	{
		 sprintf(buf, "/home/%s",dMob->name );
		 current = get_dirfile_from_path(buf, NULL, NULL);
         token = strtok(NULL, "/");

	}
	
	while (token != NULL)
	{
		if (strcasecmp(token, ".."))
			current = get_entry_by_name(token, current->contents);
		else
			current = current->parent;
		if (current == NULL)
		{
			return NULL;
		}
		token = strtok(NULL, "/");
	}
   free(lPath);
	return current;
}

DIRFILE_ENTRY * get_dirfile_from_real_path(const char* path, D_MOBILE *dMob)
{
	char * nPath;
	nPath = strpbrk(path, "/");
	
	nPath++;
	nPath = strdup(nPath);
	nPath = strpbrk(nPath, "/");
	return get_dirfile_from_path(nPath, NULL, dMob);
	
}


void write_dirfile(LIST * target)
{
	DIRFILE_ENTRY * current;
	ITERATOR pIter;
	char filename[MAX_BUFFER];
	FILE *fp;
	
	current = get_entry_by_name(".", target);
	if (current == NULL)
	{
		bug("Null current in write_dirfile");
		return;
	}
	if (current->type == DIRFILE_TYPE_FILE)
	{
		bug("Wrong type in write_dirfile");
		return;
	}
	sprintf(filename, "%s/dir", current->realpath);
	
    if ((fp = fopen(filename, "w")) == NULL)
	{
	    bug("Unable to write to %s's dirfile", current->realpath);
	    return;
	}
    AttachIterator(&pIter, target);
    	
	while ((current = (DIRFILE_ENTRY *) NextInList(&pIter)) != NULL)
	{
		fprintf(fp, "BEGIN \n");
		fprintf(fp, "name     %s~\n", current->name);
		fprintf(fp, "creator  %s~\n", current->creator);
		fprintf(fp, "vsec     %d\n", current->vSecurity);
		fprintf(fp, "esec     %d\n", current->eSecurity);
		fprintf(fp, "csec     %d\n", current->cSecurity);
		fprintf(fp, "type     %d\n", current->type);
		fprintf(fp, "END \n");
	}
	fprintf(fp, "EOF ");
	fclose(fp);
}

void handle_file_editing(D_MOBILE *dMob, char *arg)
{
	FILE *fp;
	int	line;
	char filename[MAX_BUFFER];
	char cmd[MAX_BUFFER];
	char * orig;
	char arg2[MAX_BUFFER];
	orig = strdup(arg);
	arg = one_arg(arg, cmd);
	if (!strcasecmp(cmd, "*"))
	{
		text_to_mobile(dMob, "Leaving editor, file unsaved.\n\r");
	    dMob->editing->locked = FALSE;
	    buffer_free(dMob->editing->data);
	    dMob->editing = NULL;
	    free(orig);
		return;
	}
	
	if (!strcasecmp(cmd, "@"))
	{
		sprintf(filename, "%s",dMob->editing->realpath);
		text_to_mobile(dMob, "Leaving editor, file saved.\n\r");
	    if ((fp = fopen(filename, "w")) == NULL)
		{
		    bug("Unable to write to file %s", dMob->editing->realpath);
		    return;
		}
	    fprintf(fp, "%s", dMob->editing->data->data);
	    fclose(fp);
	    dMob->editing->locked = FALSE;
	    buffer_free(dMob->editing->data);
	    dMob->editing = NULL;
	    free(orig);
		return;
	}
	if (!strcasecmp(cmd, ".s"))
	{
	   free(orig);
		numbered_buffer_to_mobile(dMob->editing->data, dMob);		
		return;
	}
	if (!strcasecmp(cmd, ".bl"))
	{
		free(orig);
		buffer_strcat(dMob->editing->data, "\n");
		return;
	}
	if (!strcasecmp(cmd, ".ld"))
	{
	   free(orig);
		line = atoi(arg);
		log_string("%d is the line.", line);
		if (line == 0)
		{
			text_to_mobile(dMob, "syntax: .ld <line number>\n\r");
		}
		else
		{
			buffer_remline(dMob->editing->data, line);		
			text_to_mobile(dMob, "Ok.\n\r");
		}
		return;
	}
	if (!strcasecmp(cmd, ".li"))
	{
	   free(orig);
		arg = one_arg(arg, arg2);
		line = atoi(arg2);

		if (line == 0 || arg[0] == '\0')
		{
			text_to_mobile(dMob, "syntax: .li <line number> <text>\n\r");
		}
		else
		{
			buffer_insertline(dMob->editing->data, line, arg);
			text_to_mobile(dMob, "Ok.\n\r");
		}		
		return;
	}
	if (!strcasecmp(cmd, ".lr"))
	{
	   free(orig);
		arg = one_arg(arg, arg2);
		line = atoi(arg2);

		if (line == 0 || arg[0] == '\0')
		{
			text_to_mobile(dMob, "syntax: .lr <line number> <text>\n\r");
		}
		else
		{
			buffer_replaceline(dMob->editing->data, line, arg);
			text_to_mobile(dMob, "Ok.\n\r");
		}
		return;
	}

	buffer_strcat(dMob->editing->data, orig);
	/*buffer_strcat(dMob->editing->data, "\n");*/
	free(orig);
}

bool file_exists(const char * filename)
{
	struct stat fStats;
	
	if (stat(filename, &fStats) == -1)
	{
		if (errno == ENOENT)
			return FALSE;
	}
	
	if (S_ISREG(fStats.st_mode))
		return TRUE;
	return FALSE;
}
void load_code(LIST * target)
{
	ITERATOR pIter;
	DIRFILE_ENTRY *current;
	if (target == NULL)
		return;
	AttachIterator(&pIter, target);
	  while ((current = (DIRFILE_ENTRY *) NextInList(&pIter)) != NULL)
		  {		  	  
			  if (current->type == DIRFILE_TYPE_FILE && is_postfix(current->name, ".lua"))
			  {
					log_string("loading file: %s ", current->realpath);
					if (luaL_loadfile(lua, current->realpath) == 0)
					{
						if (lua_pcall(lua, 0, 0, 0) != 0)
						{
							log_string("error running file. error: %s", lua_tostring(lua, -1));
						}				
					}
					else
					{
						log_string("Error loading file. Error: %s", lua_tostring(lua, -1));
					}

			  }
		  }
	DetachIterator(&pIter);
	/*Split into two loops so code is loaded one directory at a time, top down.*/
	AttachIterator(&pIter, target);
    while ((current = (DIRFILE_ENTRY *) NextInList(&pIter)) != NULL)
	  {
    	if (!strcmp(current->name, "home"))
    	{
    		log_string("Skipping home dir.");
    		continue;
    	}
	  
    	if (current->type == DIRFILE_TYPE_DIR)
    	{
		  load_code(current->contents);
    	}
	  }
    DetachIterator(&pIter);
}

bool can_access(D_MOBILE *dMob, DIRFILE_ENTRY *target, int type)
{
	bool access = FALSE;
	if (!strcasecmp(dMob->name, target->creator))
		access = TRUE;
	switch (type)
	{
	case ESECURITY:
		if (dMob->level >= target->eSecurity)
			access=TRUE;
		break;
	case VSECURITY:
		if (dMob->level >= target->vSecurity)
			access=TRUE;
		break;
	case CSECURITY:
		if (dMob->level >= target->cSecurity)
			access=TRUE;
		break;

	}
	return access;
}

/* shell commands below here. */

void cmd_chmod(D_MOBILE *dMob, char * arg)
{
	char filename[MAX_BUFFER];
	char type[MAX_BUFFER];
	DIRFILE_ENTRY * file;
	int	rank;
	
	arg = one_arg(arg, filename);
	arg = one_arg(arg, type);
	rank = atoi(arg);
	
	file = get_entry_by_name(filename, dMob->curdir->contents);
	
	if (file == NULL)
	{
		text_to_mobile(dMob, "File not found.\n]r");
		return;
	}
	
	if (rank > dMob->level)
	{
		text_to_mobile(dMob, "You cannot set the rank higher than your own.\n\r");
		return;
	}
	
	if (!can_access(dMob, file, ESECURITY))
	{
		text_to_mobile(dMob, "Insufficent security");
		return;
	}

	switch(type[0])
	{
		case 'v':
		case 'V':
			file->vSecurity = rank;
			break;
		case 'E':
		case 'e':
			file->eSecurity = rank;
			break;
		case 'C':
		case 'c':
			file->cSecurity = rank;
			break;
		default:
			text_to_mobile(dMob, "Incorrect type, use v,c, or e.\n\r");
			return;
	}
	
	text_to_mobile(dMob, "Value set.\n\r");
	write_dirfile(dMob->curdir->contents);
}

void cmd_chown(D_MOBILE *dMob, char * arg)
{
	DIRFILE_ENTRY * current;
	char arg2[MAX_BUFFER];
	D_MOBILE *target;
	arg = one_arg(arg, arg2);
	if (arg[0] == '\0' || arg2[0] == '\0')
	{
		text_to_mobile(dMob,"Syntax: chown <target> <new owner>\n\r");
		return;
	}
	current = get_entry_by_name(arg2, dMob->curdir->contents);
	target = get_mobile_by_name(arg);
	if (target == NULL)
	{
		text_to_mobile(dMob, "Set owner to who?\n\r");
		return;
	}
	
	if (!can_access(dMob, current, ESECURITY))
	{
		text_to_mobile(dMob, "Insufficent security");
		return;
	}
	free(current->creator);
	current->creator = strdup(target->name);
	text_to_mobile(dMob, "Owner changed.\n\r");
	write_dirfile(dMob->curdir->contents);
}

void cmd_mkcore(D_MOBILE *dMob, char * arg)
{
	DIRFILE_ENTRY * current;
	if (arg[0] == '\0')
	{
		text_to_mobile(dMob,"Syntax: mkcore <target>\n\r");
		return;
	}
	current = get_entry_by_name(arg, dMob->curdir->contents);
	if (current == NULL)
	{
		text_to_mobile(dMob, "File not found.\n\r");
		return;
	}
	if (!can_access(dMob, current, ESECURITY))
	{
		text_to_mobile(dMob, "Insufficent security");
		return;
	}
	
	
	free(current->creator);
	current->creator = strdup("core");
	write_dirfile(dMob->curdir->contents);
	text_to_mobile(dMob, "File added to core.\n\r");
}

void cmd_demote(D_MOBILE *dMob, char *arg)
{
	D_MOBILE * target;
	char buf[MAX_BUFFER];
	int rank;

	arg = one_arg(arg, buf);
	rank = atoi(arg);
	
	if (arg[0] == '\0')
	{
		text_to_mobile(dMob, "Syntax: demote <target> <rank>\n\r");
		return;
	}
	
	target = get_mobile_by_name(buf);
	
	if (target == NULL)
	{
		text_to_mobile(dMob, "They're not here.\n\r");
		return;
	}
	
	if (target->level >= dMob->level)
	{
		text_to_mobile(dMob, "You can't demote them.\n\r");
		log_string("%s tried to demote %s to rank %d", dMob->name,target->name, rank);
		return;
	}
	
	if (rank < 1)
		rank = 1;
	
	target->level = rank;
	text_to_mobile(dMob, "Ok.\n\r");
	text_to_mobile(target, "You have been demoted.\n\r");
}
void cmd_promote(D_MOBILE *dMob, char *arg)
{
	D_MOBILE * target;
	char buf[MAX_BUFFER];
	char path[MAX_BUFFER];
	struct stat stats;

	DIRFILE_ENTRY *home;
	DIRFILE_ENTRY *new;
	DIRFILE_ENTRY *first;
	int	rank;

	arg = one_arg(arg, buf);
	rank = atoi(arg);
	if (buf[0] =='\0' ||  rank == 0)
	{
		text_to_mobile(dMob, "Promote who to what rank?\n\r");
		return;
	}
/*	if (rank >= dMob->level)
	{
		text_to_mobile(dMob, "You can't promote people to that level.\n\r");
		return;
	}*/
	target = get_mobile_by_name(buf);
	if (target == NULL)
	{
		text_to_mobile(dMob, "No such player found.\n\r");
		return;
	}
	if (target == dMob)
	{
		text_to_mobile(dMob, "Nice try.\n\r");
		log_string("%s tried to promote themselves to level %d", dMob->name, rank);
		return;
	}
	if (target->level > rank)
	{
		text_to_mobile(dMob, "Use the demote command.\n\r");
		return;
	}
	
	sprintf(path, "%s/%s", IMP_HOME_DIR, target->name);
	home = get_dirfile_from_path (path, NULL, NULL);

	target->level = rank;

	if (home != NULL)
	{
		text_to_mobile(dMob, "That home directory is already in use, attaching player.\n\r");
		text_to_mobile(target, "You have been promoted to shell access.\n\r");
		log_string("%s has been promoted to level %d.", target->name, target->level);
	}
	home = get_dirfile_from_path(IMP_HOME_DIR, NULL, NULL);

	new = new_dir_entry();
	new->parent =home;
	AttachToList(new, home->contents);
	sprintf(buf, "%s/%s", home->realpath, target->name );
	new->name = strdup(target->name);
	new->creator = strdup(target->name);
	new->cSecurity = target->level;
	new->vSecurity = target->level;
	new->eSecurity = target->level;
	new->type = DIRFILE_TYPE_DIR;
	new->contents = AllocList();
	new->realpath = strdup(buf);
	log_string(buf);
	/* . entry in new dir.*/
	first = new_dir_entry();
	first->name = strdup(".");
	first->cSecurity = target->level;
	first->vSecurity = target->level;
	first->eSecurity = target->level;
	first->type = DIRFILE_TYPE_DIR;
	first->realpath = strdup(buf);
	AttachToList(first, new->contents);
	stats.st_mode = S_IRWXU;
	mkdir(buf, stats.st_mode);
	write_dirfile(home->contents);
	write_dirfile(new->contents);
	text_to_mobile(dMob, "They have been promoted.\n\r");
	text_to_mobile(target, "You have been promoted to shell access.\n\r");
	log_string("%s has been promoted to rank %d.", target->name, target->level);
	return;
	
}
void cmd_edit(D_MOBILE *dMob, char * arg)
{
	DIRFILE_ENTRY * current;
	FILE *fp;
	char * file;
	/*int c;
	char buf[MAX_BUFFER];*/
	
	if (dMob->curdir == NULL)
	{
		log_string("Null curdir in cmd_edit for mobile %d", dMob->name);
		return;
	}
	current = get_entry_by_name(arg, dMob->curdir->contents);
	
	if (current == NULL || current->type == DIRFILE_TYPE_DIR)
	{
		text_to_mobile(dMob, "File not found.\n\r");
		return;
	}
	
	if (!can_access(dMob, current,ESECURITY))
	{
		text_to_mobile(dMob, "Insufficent security.\n\r");
		return;
	}
	dMob->editing = current;
	dMob->editing->data = buffer_new(MAX_BUFFER);
	buffer_clear(dMob->editing->data);
	if (file_exists(dMob->editing->realpath))
	{
		if ((fp = fopen(dMob->editing->realpath, "r")) == NULL)
		{
			text_to_mobile(dMob, "Error viewing file.\n\r");
			return;
		}
		file= read_lua_file(fp);
		buffer_strcat(dMob->editing->data, file);
		fclose(fp);
	}
	numbered_buffer_to_mobile(dMob->editing->data, dMob);
	current->locked = TRUE;
}

void cmd_ls(D_MOBILE *dMob, char * arg)
{
	ITERATOR pIter;
	DIRFILE_ENTRY * current;
	char buf[MAX_BUFFER];
	if (arg[0] =='\0')
	{
		if (dMob->curdir == NULL) /*root dir.*/
		{
			log_string("Null curdir for mob %s", dMob->name);
		}
		else
			AttachIterator(&pIter, dMob->curdir->contents);
		  
		  text_to_mobile(dMob, "                     	E	V	C	Creator\n\r");
		  while ((current = (DIRFILE_ENTRY *) NextInList(&pIter)) != NULL)
		  {
			  if (current->type == DIRFILE_TYPE_DIR)
			  {
			  		sprintf(buf, "#B%-20s	%d	%d	%d	%s\n\r", current->name, current->eSecurity, current->vSecurity, current->cSecurity, current->creator);
			  }
			  else
			  {
				  sprintf(buf, "#r%-20s	%d	%d	%d	%s\n\r", current->name, current->eSecurity, current->vSecurity, current->cSecurity, current->creator);
			  }
			  text_to_mobile(dMob, buf);
		  }

	}
	else
	{
		current = get_dirfile_from_path(arg, dMob->curdir, NULL);
		if (current == NULL || current->type == DIRFILE_TYPE_FILE)
		{
			text_to_mobile(dMob,"Directory not found.");
			return;
		}
		AttachIterator(&pIter, current->contents);
		  while ((current = (DIRFILE_ENTRY *) NextInList(&pIter)) != NULL)
		  {
			  if (current->type == DIRFILE_TYPE_DIR)
			  {
			  		sprintf(buf, "#B%s\n\r", current->name);
			  }
			  else
			  {
				  sprintf(buf, "#r%s\n\r", current->name);
			  }
			  text_to_mobile(dMob, buf);
		  }

	}
}
void cmd_rmdir(D_MOBILE *dMob, char * arg)
{
	DIRFILE_ENTRY * target;
	DIR * dir;
	struct dirent * entry;
	int count;
	char buf[MAX_BUFFER];
	
	target = get_entry_by_name(arg, dMob->curdir->contents);
	
	if (target == NULL || target->type == DIRFILE_TYPE_FILE)
	{
		text_to_mobile(dMob, "That directory does not exist.\n\r");
		return;
	}
	if (!can_access(dMob, target, CSECURITY))
	{
		text_to_mobile(dMob, "You do not have enough security.\n\r");
		return;
	}
	if (target == dMob->curdir)
	{
		text_to_mobile(dMob, "Now how would that work??\n\r");
		return;
	}
	/*check emptyness except for Dir file.  
	 * If it's the only file there, remove it, so rmdir can work.
	 */
	count = 0;
	dir=opendir(target->realpath);
	while ((entry = readdir(dir))!= NULL)
	{
		if (!strcasecmp(".", entry->d_name) || !strcasecmp("..", entry->d_name) || !strcasecmp("dir", entry->d_name))
		{
			continue;
		}
		else count++;
		
	}
	closedir(dir);
	if (count >0)
	{
		text_to_mobile(dMob, "That directory is not empty.\n\r");
		return;
	}
	else
	{
		sprintf(buf, "%s/dir",target->realpath);
		if (unlink(buf) == -1)
		{
			bug("Error deleting file: %s", buf);
		}
		
	}
	
	if (rmdir(target->realpath) != 0 )
	{
		if (errno == EEXIST || errno == ENOTEMPTY)
		{
		text_to_mobile(dMob, "The directory is not empty.\n\r");
		return;
		}
		bug("Error deleting file: %s", target->realpath);
	}

		DetachFromList(target, dMob->curdir->contents);
		write_dirfile(dMob->curdir->contents);
		
	free_dir_entry(target);
	
}

void cmd_mkdir(D_MOBILE *dMob, char * arg)
{
	DIRFILE_ENTRY * current;
	DIRFILE_ENTRY * new;
	DIRFILE_ENTRY * first;
	struct stat stats;
	char buf[MAX_BUFFER];

	current = dMob->curdir;
	new = get_entry_by_name(arg, current->contents);

	if (new != NULL)
	{
		text_to_mobile(dMob, "That name is taken.\n\r");
		return;
	}
	if (can_access(dMob, current, CSECURITY))
	{
		new = new_dir_entry();
		new->parent =current;
		AttachToList(new, current->contents);
		sprintf(buf, "%s/%s", current->realpath, arg );
		new->name = strdup(arg);
		new->creator = strdup(dMob->name);
		new->cSecurity = dMob->level;
		new->vSecurity = dMob->level;
		new->eSecurity = dMob->level;
		new->type = DIRFILE_TYPE_DIR;
		new->contents = AllocList();
		new->realpath = strdup(buf);
		log_string(buf);
		/* . entry in new dir.*/
		first = new_dir_entry();
		first->name = strdup(".");
		first->cSecurity = dMob->level;
		first->vSecurity = dMob->level;
		first->eSecurity = dMob->level;
		first->type = DIRFILE_TYPE_DIR;
		first->realpath = strdup(buf);
		AttachToList(first, new->contents);
		stats.st_mode = S_IRWXU;
		mkdir(buf, stats.st_mode);
		write_dirfile(current->contents);
		write_dirfile(new->contents);
		return;
	}
	log_string("insufficient security.");	
}

void cmd_touch(D_MOBILE *dMob,  char * arg)
{
	DIRFILE_ENTRY * current;
	DIRFILE_ENTRY * new;
	char buf[MAX_BUFFER];
	current = dMob->curdir;
	new = get_entry_by_name(arg, current->contents);
	if (new != NULL)
	{
		text_to_mobile(dMob, "That name is taken.\n\r");
		return;
	}
	if (can_access(dMob, current, CSECURITY))
	{
		new = new_dir_entry();
		new->parent =current;
		AttachToList(new, current->contents);
		sprintf(buf, "%s/%s", current->realpath, arg );
		new->name = strdup(arg);
		new->creator = strdup(dMob->name);
		new->cSecurity = dMob->level;
		new->vSecurity = dMob->level;
		new->eSecurity = dMob->level;
		new->type = DIRFILE_TYPE_FILE;
		new->realpath = strdup(buf);
		log_string(buf);
		write_dirfile(current->contents);
		return;
	}
	log_string("insufficient security.");
}

void cmd_cd(D_MOBILE *dMob, char * arg)
{
	DIRFILE_ENTRY * current;
	if (!strcasecmp(arg, ".."))
	{
		if (dMob->curdir->parent ==NULL)
		{
			text_to_mobile(dMob,"No such path.\n\r");
			return;
		}
		if (can_access(dMob, dMob->curdir->parent, VSECURITY))
		{
			dMob->curdir = dMob->curdir->parent;
			return;
		}
		else
		{
			text_to_mobile(dMob,"You're not allowed to view that directory.\n\r");
			return;
		}

	}
	current = get_dirfile_from_path(arg, dMob->curdir, dMob);
	if (current == NULL || current->type == DIRFILE_TYPE_FILE)
	{
		text_to_mobile(dMob, "path not found.");
		return;
	}
	if (can_access(dMob, current, VSECURITY))
	{
		dMob->curdir = current;
	}
	else
	{
		text_to_mobile(dMob,"You're not allowed to view that directory.\n\r");
		return;
	}
	
}
void cmd_rm(D_MOBILE *dMob, char * arg)
{
	DIRFILE_ENTRY * target;

	target = get_entry_by_name(arg, dMob->curdir->contents);
	
	if (target == NULL || target->type == DIRFILE_TYPE_DIR)
	{
		text_to_mobile(dMob, "That file does not exist.\n\r");
		return;
	}
	if (!can_access(dMob, target, CSECURITY))
	{
		text_to_mobile(dMob, "You do not have enough security.\n\r");
		return;
	}
	if (target->locked)
	{
		text_to_mobile(dMob, "That file is busy.\n\r");
		return;
	}
		DetachFromList(target, dMob->curdir->contents);
		write_dirfile(dMob->curdir->contents);
	if (file_exists(target->realpath) == TRUE && unlink(target->realpath) == -1)
	{
		bug("Error deleting file: %s", target->realpath);
	}
		
	free_dir_entry(target);
	
}
void cmd_view(D_MOBILE *dMob, char * arg)
{
	DIRFILE_ENTRY * target;
	FILE *fp;
	char * file;
	
	target = get_entry_by_name(arg, dMob->curdir->contents);
	
	if (target == NULL || target->type == DIRFILE_TYPE_DIR)
	{
		text_to_mobile(dMob, "That file does not exist.\n\r");
		return;
	}
	if (!can_access(dMob, target, VSECURITY))
	{
		text_to_mobile(dMob, "You do not have enough security.\n\r");
		return;
	}
	
	if ((fp = fopen(target->realpath, "r")) == NULL)
	{
	    text_to_mobile(dMob, "Error viewing file.\n\r");
	    return;
	}
	file = read_lua_file(fp);
	text_to_mobile(dMob, file);
	fclose(fp);
}

void cmd_reload(D_MOBILE *dMob, char *arg)
{
	/*TODO: Add refresh info to lua class superstructure*/
	DIRFILE_ENTRY * current;
		current = get_entry_by_name(arg, dMob->curdir->contents);
	
	if (current == NULL || current->type == DIRFILE_TYPE_DIR)
	{
		text_to_mobile(dMob, "File not found.\n\r");
		return;
	}
	
	if (!can_access(dMob, current, ESECURITY))
	{
		text_to_mobile(dMob, "Insufficent security.\n\r");
		return;
	}
	
	log_string("reloading file: %s ", current->realpath);
	if (luaL_loadfile(lua, current->realpath) == 0)
	{
		if (lua_pcall(lua, 0, 0, 0) != 0)
		{
			log_string("error while reloading file. error: %s", lua_tostring(lua, -1));
		}				
	}
	else
	{
		log_string("Error reloading file. Error: %s", lua_tostring(lua, -1));
	}

	
}

void cmd_return(D_MOBILE *dMob, char * arg)
{
	dMob->shell = FALSE;
}