mirror of
https://github.com/retro100/dosbox-wii.git
synced 2025-01-12 18:29:07 +01:00
sync
This commit is contained in:
parent
5ef584b880
commit
336d2c0758
@ -1,265 +1,265 @@
|
||||
/*
|
||||
* Copyright (C) 2002-2009 The DOSBox Team
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/* $Id: cross.cpp,v 1.7 2009/05/26 17:43:39 qbix79 Exp $ */
|
||||
|
||||
#include "dosbox.h"
|
||||
#include "cross.h"
|
||||
#include "support.h"
|
||||
#include <string>
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef HW_RVL
|
||||
#include "wiihardware.h"
|
||||
#endif
|
||||
|
||||
#ifdef WIN32
|
||||
#ifndef _WIN32_IE
|
||||
#define _WIN32_IE 0x0400
|
||||
#endif
|
||||
#include <shlobj.h>
|
||||
#endif
|
||||
|
||||
#if defined HAVE_SYS_TYPES_H && defined HAVE_PWD_H
|
||||
#include <sys/types.h>
|
||||
#include <pwd.h>
|
||||
#endif
|
||||
|
||||
#ifdef WIN32
|
||||
static void W32_ConfDir(std::string& in,bool create) {
|
||||
int c = create?1:0;
|
||||
char result[MAX_PATH] = { 0 };
|
||||
BOOL r = SHGetSpecialFolderPath(NULL,result,CSIDL_LOCAL_APPDATA,c);
|
||||
if(!r || result[0] == 0) r = SHGetSpecialFolderPath(NULL,result,CSIDL_APPDATA,c);
|
||||
if(!r || result[0] == 0) {
|
||||
char const * windir = getenv("windir");
|
||||
if(!windir) windir = "c:\\windows";
|
||||
safe_strncpy(result,windir,MAX_PATH);
|
||||
char const* appdata = "\\Application Data";
|
||||
size_t len = strlen(result);
|
||||
if(len + strlen(appdata) < MAX_PATH) strcat(result,appdata);
|
||||
if(create) mkdir(result);
|
||||
}
|
||||
in = result;
|
||||
}
|
||||
#endif
|
||||
|
||||
void Cross::GetPlatformConfigDir(std::string& in) {
|
||||
#ifdef WIN32
|
||||
W32_ConfDir(in,false);
|
||||
in += "\\DOSBox";
|
||||
#elif defined(MACOSX)
|
||||
in = "~/Library/Preferences";
|
||||
ResolveHomedir(in);
|
||||
#elif defined(HW_RVL)
|
||||
in = "sd:/DOSBox";
|
||||
#else
|
||||
in = "~/.dosbox";
|
||||
ResolveHomedir(in);
|
||||
#endif
|
||||
in += CROSS_FILESPLIT;
|
||||
}
|
||||
|
||||
void Cross::GetPlatformConfigName(std::string& in) {
|
||||
#ifdef WIN32
|
||||
#define DEFAULT_CONFIG_FILE "dosbox-" VERSION ".conf"
|
||||
#elif defined(MACOSX)
|
||||
#define DEFAULT_CONFIG_FILE "DOSBox " VERSION " Preferences"
|
||||
#elif defined(HW_RVL)
|
||||
#define DEFAULT_CONFIG_FILE "dosbox.conf"
|
||||
#else /*linux freebsd*/
|
||||
#define DEFAULT_CONFIG_FILE "dosbox-" VERSION ".conf"
|
||||
#endif
|
||||
in = DEFAULT_CONFIG_FILE;
|
||||
}
|
||||
|
||||
void Cross::CreatePlatformConfigDir(std::string& in) {
|
||||
#ifdef WIN32
|
||||
W32_ConfDir(in,true);
|
||||
in += "\\DOSBox";
|
||||
mkdir(in.c_str());
|
||||
#elif defined(MACOSX)
|
||||
in = "~/Library/Preferences/";
|
||||
ResolveHomedir(in);
|
||||
//Don't create it. Assume it exists
|
||||
#elif defined(HW_RVL)
|
||||
in = "sd:/DOSBox";
|
||||
CreateDir(in);
|
||||
#else
|
||||
in = "~/.dosbox";
|
||||
ResolveHomedir(in);
|
||||
mkdir(in.c_str(),0700);
|
||||
#endif
|
||||
in += CROSS_FILESPLIT;
|
||||
}
|
||||
|
||||
void Cross::ResolveHomedir(std::string & temp_line) {
|
||||
if(!temp_line.size() || temp_line[0] != '~') return; //No ~
|
||||
|
||||
if(temp_line.size() == 1 || temp_line[1] == CROSS_FILESPLIT) { //The ~ and ~/ variant
|
||||
char * home = getenv("HOME");
|
||||
if(home) temp_line.replace(0,1,std::string(home));
|
||||
#if defined HAVE_SYS_TYPES_H && defined HAVE_PWD_H
|
||||
} else { // The ~username variant
|
||||
std::string::size_type namelen = temp_line.find(CROSS_FILESPLIT);
|
||||
if(namelen == std::string::npos) namelen = temp_line.size();
|
||||
std::string username = temp_line.substr(1,namelen - 1);
|
||||
struct passwd* pass = getpwnam(username.c_str());
|
||||
if(pass) temp_line.replace(0,namelen,pass->pw_dir); //namelen -1 +1(for the ~)
|
||||
#endif // USERNAME lookup code
|
||||
}
|
||||
}
|
||||
|
||||
void Cross::CreateDir(std::string const& in) {
|
||||
#ifdef WIN32
|
||||
mkdir(in.c_str());
|
||||
#else
|
||||
mkdir(in.c_str(),0700);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined (WIN32)
|
||||
|
||||
dir_information* open_directory(const char* dirname) {
|
||||
if (dirname == NULL) return NULL;
|
||||
|
||||
size_t len = strlen(dirname);
|
||||
if (len == 0) return NULL;
|
||||
|
||||
static dir_information dir;
|
||||
|
||||
safe_strncpy(dir.base_path,dirname,MAX_PATH);
|
||||
|
||||
if (dirname[len-1] == '\\') strcat(dir.base_path,"*.*");
|
||||
else strcat(dir.base_path,"\\*.*");
|
||||
|
||||
dir.handle = INVALID_HANDLE_VALUE;
|
||||
|
||||
return (access(dirname,0) ? NULL : &dir);
|
||||
}
|
||||
|
||||
bool read_directory_first(dir_information* dirp, char* entry_name, bool& is_directory) {
|
||||
dirp->handle = FindFirstFile(dirp->base_path, &dirp->search_data);
|
||||
if (INVALID_HANDLE_VALUE == dirp->handle) {
|
||||
return false;
|
||||
}
|
||||
|
||||
safe_strncpy(entry_name,dirp->search_data.cFileName,(MAX_PATH<CROSS_LEN)?MAX_PATH:CROSS_LEN);
|
||||
|
||||
if (dirp->search_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) is_directory = true;
|
||||
else is_directory = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool read_directory_next(dir_information* dirp, char* entry_name, bool& is_directory) {
|
||||
int result = FindNextFile(dirp->handle, &dirp->search_data);
|
||||
if (result==0) return false;
|
||||
|
||||
safe_strncpy(entry_name,dirp->search_data.cFileName,(MAX_PATH<CROSS_LEN)?MAX_PATH:CROSS_LEN);
|
||||
|
||||
if (dirp->search_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) is_directory = true;
|
||||
else is_directory = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void close_directory(dir_information* dirp) {
|
||||
if (dirp->handle != INVALID_HANDLE_VALUE) {
|
||||
FindClose(dirp->handle);
|
||||
dirp->handle = INVALID_HANDLE_VALUE;
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
dir_information* open_directory(const char* dirname) {
|
||||
static dir_information dir;
|
||||
dir.dir=opendir(dirname);
|
||||
safe_strncpy(dir.base_path,dirname,CROSS_LEN);
|
||||
return dir.dir?&dir:NULL;
|
||||
}
|
||||
|
||||
bool read_directory_first(dir_information* dirp, char* entry_name, bool& is_directory) {
|
||||
struct dirent* dentry = readdir(dirp->dir);
|
||||
if (dentry==NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// safe_strncpy(entry_name,dentry->d_name,(FILENAME_MAX<MAX_PATH)?FILENAME_MAX:MAX_PATH); // [include stdio.h], maybe pathconf()
|
||||
safe_strncpy(entry_name,dentry->d_name,CROSS_LEN);
|
||||
|
||||
#ifdef DIRENT_HAS_D_TYPE
|
||||
if(dentry->d_type == DT_DIR) {
|
||||
is_directory = true;
|
||||
return true;
|
||||
} else if(dentry->d_type == DT_REG) {
|
||||
is_directory = false;
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
// probably use d_type here instead of a full stat()
|
||||
static char buffer[2*CROSS_LEN] = { 0 };
|
||||
buffer[0] = 0;
|
||||
strcpy(buffer,dirp->base_path);
|
||||
strcat(buffer,entry_name);
|
||||
struct stat status;
|
||||
if (stat(buffer,&status)==0) is_directory = (S_ISDIR(status.st_mode)>0);
|
||||
else is_directory = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool read_directory_next(dir_information* dirp, char* entry_name, bool& is_directory) {
|
||||
struct dirent* dentry = readdir(dirp->dir);
|
||||
if (dentry==NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// safe_strncpy(entry_name,dentry->d_name,(FILENAME_MAX<MAX_PATH)?FILENAME_MAX:MAX_PATH); // [include stdio.h], maybe pathconf()
|
||||
safe_strncpy(entry_name,dentry->d_name,CROSS_LEN);
|
||||
|
||||
#ifdef DIRENT_HAS_D_TYPE
|
||||
if(dentry->d_type == DT_DIR) {
|
||||
is_directory = true;
|
||||
return true;
|
||||
} else if(dentry->d_type == DT_REG) {
|
||||
is_directory = false;
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
// probably use d_type here instead of a full stat()
|
||||
static char buffer[2*CROSS_LEN] = { 0 };
|
||||
buffer[0] = 0;
|
||||
strcpy(buffer,dirp->base_path);
|
||||
strcat(buffer,entry_name);
|
||||
struct stat status;
|
||||
|
||||
if (stat(buffer,&status)==0) is_directory = (S_ISDIR(status.st_mode)>0);
|
||||
else is_directory = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void close_directory(dir_information* dirp) {
|
||||
closedir(dirp->dir);
|
||||
}
|
||||
|
||||
#endif
|
||||
/*
|
||||
* Copyright (C) 2002-2009 The DOSBox Team
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/* $Id: cross.cpp,v 1.7 2009-05-26 17:43:39 qbix79 Exp $ */
|
||||
|
||||
#include "dosbox.h"
|
||||
#include "cross.h"
|
||||
#include "support.h"
|
||||
#include <string>
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef HW_RVL
|
||||
#include "wiihardware.h"
|
||||
#endif
|
||||
|
||||
#ifdef WIN32
|
||||
#ifndef _WIN32_IE
|
||||
#define _WIN32_IE 0x0400
|
||||
#endif
|
||||
#include <shlobj.h>
|
||||
#endif
|
||||
|
||||
#if defined HAVE_SYS_TYPES_H && defined HAVE_PWD_H
|
||||
#include <sys/types.h>
|
||||
#include <pwd.h>
|
||||
#endif
|
||||
|
||||
#ifdef WIN32
|
||||
static void W32_ConfDir(std::string& in,bool create) {
|
||||
int c = create?1:0;
|
||||
char result[MAX_PATH] = { 0 };
|
||||
BOOL r = SHGetSpecialFolderPath(NULL,result,CSIDL_LOCAL_APPDATA,c);
|
||||
if(!r || result[0] == 0) r = SHGetSpecialFolderPath(NULL,result,CSIDL_APPDATA,c);
|
||||
if(!r || result[0] == 0) {
|
||||
char const * windir = getenv("windir");
|
||||
if(!windir) windir = "c:\\windows";
|
||||
safe_strncpy(result,windir,MAX_PATH);
|
||||
char const* appdata = "\\Application Data";
|
||||
size_t len = strlen(result);
|
||||
if(len + strlen(appdata) < MAX_PATH) strcat(result,appdata);
|
||||
if(create) mkdir(result);
|
||||
}
|
||||
in = result;
|
||||
}
|
||||
#endif
|
||||
|
||||
void Cross::GetPlatformConfigDir(std::string& in) {
|
||||
#ifdef WIN32
|
||||
W32_ConfDir(in,false);
|
||||
in += "\\DOSBox";
|
||||
#elif defined(MACOSX)
|
||||
in = "~/Library/Preferences";
|
||||
ResolveHomedir(in);
|
||||
#elif defined(HW_RVL)
|
||||
in = "sd:/DOSBox";
|
||||
#else
|
||||
in = "~/.dosbox";
|
||||
ResolveHomedir(in);
|
||||
#endif
|
||||
in += CROSS_FILESPLIT;
|
||||
}
|
||||
|
||||
void Cross::GetPlatformConfigName(std::string& in) {
|
||||
#ifdef WIN32
|
||||
#define DEFAULT_CONFIG_FILE "dosbox-" VERSION ".conf"
|
||||
#elif defined(MACOSX)
|
||||
#define DEFAULT_CONFIG_FILE "DOSBox " VERSION " Preferences"
|
||||
#elif defined(HW_RVL)
|
||||
#define DEFAULT_CONFIG_FILE "dosbox.conf"
|
||||
#else /*linux freebsd*/
|
||||
#define DEFAULT_CONFIG_FILE "dosbox-" VERSION ".conf"
|
||||
#endif
|
||||
in = DEFAULT_CONFIG_FILE;
|
||||
}
|
||||
|
||||
void Cross::CreatePlatformConfigDir(std::string& in) {
|
||||
#ifdef WIN32
|
||||
W32_ConfDir(in,true);
|
||||
in += "\\DOSBox";
|
||||
mkdir(in.c_str());
|
||||
#elif defined(MACOSX)
|
||||
in = "~/Library/Preferences/";
|
||||
ResolveHomedir(in);
|
||||
//Don't create it. Assume it exists
|
||||
#elif defined(HW_RVL)
|
||||
in = "sd:/DOSBox";
|
||||
CreateDir(in);
|
||||
#else
|
||||
in = "~/.dosbox";
|
||||
ResolveHomedir(in);
|
||||
mkdir(in.c_str(),0700);
|
||||
#endif
|
||||
in += CROSS_FILESPLIT;
|
||||
}
|
||||
|
||||
void Cross::ResolveHomedir(std::string & temp_line) {
|
||||
if(!temp_line.size() || temp_line[0] != '~') return; //No ~
|
||||
|
||||
if(temp_line.size() == 1 || temp_line[1] == CROSS_FILESPLIT) { //The ~ and ~/ variant
|
||||
char * home = getenv("HOME");
|
||||
if(home) temp_line.replace(0,1,std::string(home));
|
||||
#if defined HAVE_SYS_TYPES_H && defined HAVE_PWD_H
|
||||
} else { // The ~username variant
|
||||
std::string::size_type namelen = temp_line.find(CROSS_FILESPLIT);
|
||||
if(namelen == std::string::npos) namelen = temp_line.size();
|
||||
std::string username = temp_line.substr(1,namelen - 1);
|
||||
struct passwd* pass = getpwnam(username.c_str());
|
||||
if(pass) temp_line.replace(0,namelen,pass->pw_dir); //namelen -1 +1(for the ~)
|
||||
#endif // USERNAME lookup code
|
||||
}
|
||||
}
|
||||
|
||||
void Cross::CreateDir(std::string const& in) {
|
||||
#ifdef WIN32
|
||||
mkdir(in.c_str());
|
||||
#else
|
||||
mkdir(in.c_str(),0700);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined (WIN32)
|
||||
|
||||
dir_information* open_directory(const char* dirname) {
|
||||
if (dirname == NULL) return NULL;
|
||||
|
||||
size_t len = strlen(dirname);
|
||||
if (len == 0) return NULL;
|
||||
|
||||
static dir_information dir;
|
||||
|
||||
safe_strncpy(dir.base_path,dirname,MAX_PATH);
|
||||
|
||||
if (dirname[len-1] == '\\') strcat(dir.base_path,"*.*");
|
||||
else strcat(dir.base_path,"\\*.*");
|
||||
|
||||
dir.handle = INVALID_HANDLE_VALUE;
|
||||
|
||||
return (access(dirname,0) ? NULL : &dir);
|
||||
}
|
||||
|
||||
bool read_directory_first(dir_information* dirp, char* entry_name, bool& is_directory) {
|
||||
dirp->handle = FindFirstFile(dirp->base_path, &dirp->search_data);
|
||||
if (INVALID_HANDLE_VALUE == dirp->handle) {
|
||||
return false;
|
||||
}
|
||||
|
||||
safe_strncpy(entry_name,dirp->search_data.cFileName,(MAX_PATH<CROSS_LEN)?MAX_PATH:CROSS_LEN);
|
||||
|
||||
if (dirp->search_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) is_directory = true;
|
||||
else is_directory = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool read_directory_next(dir_information* dirp, char* entry_name, bool& is_directory) {
|
||||
int result = FindNextFile(dirp->handle, &dirp->search_data);
|
||||
if (result==0) return false;
|
||||
|
||||
safe_strncpy(entry_name,dirp->search_data.cFileName,(MAX_PATH<CROSS_LEN)?MAX_PATH:CROSS_LEN);
|
||||
|
||||
if (dirp->search_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) is_directory = true;
|
||||
else is_directory = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void close_directory(dir_information* dirp) {
|
||||
if (dirp->handle != INVALID_HANDLE_VALUE) {
|
||||
FindClose(dirp->handle);
|
||||
dirp->handle = INVALID_HANDLE_VALUE;
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
dir_information* open_directory(const char* dirname) {
|
||||
static dir_information dir;
|
||||
dir.dir=opendir(dirname);
|
||||
safe_strncpy(dir.base_path,dirname,CROSS_LEN);
|
||||
return dir.dir?&dir:NULL;
|
||||
}
|
||||
|
||||
bool read_directory_first(dir_information* dirp, char* entry_name, bool& is_directory) {
|
||||
struct dirent* dentry = readdir(dirp->dir);
|
||||
if (dentry==NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// safe_strncpy(entry_name,dentry->d_name,(FILENAME_MAX<MAX_PATH)?FILENAME_MAX:MAX_PATH); // [include stdio.h], maybe pathconf()
|
||||
safe_strncpy(entry_name,dentry->d_name,CROSS_LEN);
|
||||
|
||||
#ifdef DIRENT_HAS_D_TYPE
|
||||
if(dentry->d_type == DT_DIR) {
|
||||
is_directory = true;
|
||||
return true;
|
||||
} else if(dentry->d_type == DT_REG) {
|
||||
is_directory = false;
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
// probably use d_type here instead of a full stat()
|
||||
static char buffer[2*CROSS_LEN] = { 0 };
|
||||
buffer[0] = 0;
|
||||
strcpy(buffer,dirp->base_path);
|
||||
strcat(buffer,entry_name);
|
||||
struct stat status;
|
||||
if (stat(buffer,&status)==0) is_directory = (S_ISDIR(status.st_mode)>0);
|
||||
else is_directory = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool read_directory_next(dir_information* dirp, char* entry_name, bool& is_directory) {
|
||||
struct dirent* dentry = readdir(dirp->dir);
|
||||
if (dentry==NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// safe_strncpy(entry_name,dentry->d_name,(FILENAME_MAX<MAX_PATH)?FILENAME_MAX:MAX_PATH); // [include stdio.h], maybe pathconf()
|
||||
safe_strncpy(entry_name,dentry->d_name,CROSS_LEN);
|
||||
|
||||
#ifdef DIRENT_HAS_D_TYPE
|
||||
if(dentry->d_type == DT_DIR) {
|
||||
is_directory = true;
|
||||
return true;
|
||||
} else if(dentry->d_type == DT_REG) {
|
||||
is_directory = false;
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
// probably use d_type here instead of a full stat()
|
||||
static char buffer[2*CROSS_LEN] = { 0 };
|
||||
buffer[0] = 0;
|
||||
strcpy(buffer,dirp->base_path);
|
||||
strcat(buffer,entry_name);
|
||||
struct stat status;
|
||||
|
||||
if (stat(buffer,&status)==0) is_directory = (S_ISDIR(status.st_mode)>0);
|
||||
else is_directory = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void close_directory(dir_information* dirp) {
|
||||
closedir(dirp->dir);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -1,144 +1,144 @@
|
||||
/*
|
||||
* Copyright (C) 2002-2009 The DOSBox Team
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/* $Id: messages.cpp,v 1.23 2009/06/17 08:52:35 qbix79 Exp $ */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "dosbox.h"
|
||||
#include "cross.h"
|
||||
#include "support.h"
|
||||
#include "setup.h"
|
||||
#include "control.h"
|
||||
#include <list>
|
||||
#include <string>
|
||||
using namespace std;
|
||||
|
||||
|
||||
|
||||
#define LINE_IN_MAXLEN 2048
|
||||
|
||||
struct MessageBlock {
|
||||
string name;
|
||||
string val;
|
||||
MessageBlock(const char* _name, const char* _val):
|
||||
name(_name),val(_val){}
|
||||
};
|
||||
|
||||
static list<MessageBlock> Lang;
|
||||
typedef list<MessageBlock>::iterator itmb;
|
||||
|
||||
void MSG_Add(const char * _name, const char* _val) {
|
||||
/* Find the message */
|
||||
for(itmb tel=Lang.begin();tel!=Lang.end();tel++) {
|
||||
if((*tel).name==_name) {
|
||||
// LOG_MSG("double entry for %s",_name); //Message file might be loaded before default text messages
|
||||
return;
|
||||
}
|
||||
}
|
||||
/* if the message doesn't exist add it */
|
||||
Lang.push_back(MessageBlock(_name,_val));
|
||||
}
|
||||
|
||||
void MSG_Replace(const char * _name, const char* _val) {
|
||||
/* Find the message */
|
||||
for(itmb tel=Lang.begin();tel!=Lang.end();tel++) {
|
||||
if((*tel).name==_name) {
|
||||
Lang.erase(tel);
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* Even if the message doesn't exist add it */
|
||||
Lang.push_back(MessageBlock(_name,_val));
|
||||
}
|
||||
|
||||
static void LoadMessageFile(const char * fname) {
|
||||
if (!fname) return;
|
||||
if(*fname=='\0') return;//empty string=no languagefile
|
||||
FILE * mfile=fopen(fname,"rt");
|
||||
/* This should never happen and since other modules depend on this use a normal printf */
|
||||
if (!mfile) {
|
||||
E_Exit("MSG:Can't load messages: %s",fname);
|
||||
}
|
||||
char linein[LINE_IN_MAXLEN];
|
||||
char name[LINE_IN_MAXLEN];
|
||||
char string[LINE_IN_MAXLEN*10];
|
||||
/* Start out with empty strings */
|
||||
name[0]=0;string[0]=0;
|
||||
while(fgets(linein, LINE_IN_MAXLEN, mfile)!=0) {
|
||||
/* Parse the read line */
|
||||
/* First remove characters 10 and 13 from the line */
|
||||
char * parser=linein;
|
||||
char * writer=linein;
|
||||
while (*parser) {
|
||||
if (*parser!=10 && *parser!=13) {
|
||||
*writer++=*parser;
|
||||
}
|
||||
*parser++;
|
||||
}
|
||||
*writer=0;
|
||||
/* New string name */
|
||||
if (linein[0]==':') {
|
||||
string[0]=0;
|
||||
strcpy(name,linein+1);
|
||||
/* End of string marker */
|
||||
} else if (linein[0]=='.') {
|
||||
/* Replace/Add the string to the internal langaugefile */
|
||||
/* Remove last newline (marker is \n.\n) */
|
||||
size_t ll = strlen(string);
|
||||
if(ll && string[ll - 1] == '\n') string[ll - 1] = 0; //Second if should not be needed, but better be safe.
|
||||
MSG_Replace(name,string);
|
||||
} else {
|
||||
/* Normal string to be added */
|
||||
strcat(string,linein);
|
||||
strcat(string,"\n");
|
||||
}
|
||||
}
|
||||
fclose(mfile);
|
||||
}
|
||||
|
||||
const char * MSG_Get(char const * msg) {
|
||||
for(itmb tel=Lang.begin();tel!=Lang.end();tel++){
|
||||
if((*tel).name==msg)
|
||||
{
|
||||
return (*tel).val.c_str();
|
||||
}
|
||||
}
|
||||
return "Message not Found!\n";
|
||||
}
|
||||
|
||||
|
||||
void MSG_Write(const char * location) {
|
||||
FILE* out=fopen(location,"w+t");
|
||||
if(out==NULL) return;//maybe an error?
|
||||
for(itmb tel=Lang.begin();tel!=Lang.end();tel++){
|
||||
fprintf(out,":%s\n%s\n.\n",(*tel).name.c_str(),(*tel).val.c_str());
|
||||
}
|
||||
fclose(out);
|
||||
}
|
||||
|
||||
void MSG_Init(Section_prop * section) {
|
||||
std::string file_name;
|
||||
if (control->cmdline->FindString("-lang",file_name,true)) {
|
||||
LoadMessageFile(file_name.c_str());
|
||||
} else {
|
||||
Prop_path* pathprop = section->Get_path("language");
|
||||
if(pathprop) LoadMessageFile(pathprop->realpath.c_str());
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Copyright (C) 2002-2009 The DOSBox Team
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/* $Id: messages.cpp,v 1.23 2009-06-17 08:52:35 qbix79 Exp $ */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "dosbox.h"
|
||||
#include "cross.h"
|
||||
#include "support.h"
|
||||
#include "setup.h"
|
||||
#include "control.h"
|
||||
#include <list>
|
||||
#include <string>
|
||||
using namespace std;
|
||||
|
||||
|
||||
|
||||
#define LINE_IN_MAXLEN 2048
|
||||
|
||||
struct MessageBlock {
|
||||
string name;
|
||||
string val;
|
||||
MessageBlock(const char* _name, const char* _val):
|
||||
name(_name),val(_val){}
|
||||
};
|
||||
|
||||
static list<MessageBlock> Lang;
|
||||
typedef list<MessageBlock>::iterator itmb;
|
||||
|
||||
void MSG_Add(const char * _name, const char* _val) {
|
||||
/* Find the message */
|
||||
for(itmb tel=Lang.begin();tel!=Lang.end();tel++) {
|
||||
if((*tel).name==_name) {
|
||||
// LOG_MSG("double entry for %s",_name); //Message file might be loaded before default text messages
|
||||
return;
|
||||
}
|
||||
}
|
||||
/* if the message doesn't exist add it */
|
||||
Lang.push_back(MessageBlock(_name,_val));
|
||||
}
|
||||
|
||||
void MSG_Replace(const char * _name, const char* _val) {
|
||||
/* Find the message */
|
||||
for(itmb tel=Lang.begin();tel!=Lang.end();tel++) {
|
||||
if((*tel).name==_name) {
|
||||
Lang.erase(tel);
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* Even if the message doesn't exist add it */
|
||||
Lang.push_back(MessageBlock(_name,_val));
|
||||
}
|
||||
|
||||
static void LoadMessageFile(const char * fname) {
|
||||
if (!fname) return;
|
||||
if(*fname=='\0') return;//empty string=no languagefile
|
||||
FILE * mfile=fopen(fname,"rt");
|
||||
/* This should never happen and since other modules depend on this use a normal printf */
|
||||
if (!mfile) {
|
||||
E_Exit("MSG:Can't load messages: %s",fname);
|
||||
}
|
||||
char linein[LINE_IN_MAXLEN];
|
||||
char name[LINE_IN_MAXLEN];
|
||||
char string[LINE_IN_MAXLEN*10];
|
||||
/* Start out with empty strings */
|
||||
name[0]=0;string[0]=0;
|
||||
while(fgets(linein, LINE_IN_MAXLEN, mfile)!=0) {
|
||||
/* Parse the read line */
|
||||
/* First remove characters 10 and 13 from the line */
|
||||
char * parser=linein;
|
||||
char * writer=linein;
|
||||
while (*parser) {
|
||||
if (*parser!=10 && *parser!=13) {
|
||||
*writer++=*parser;
|
||||
}
|
||||
*parser++;
|
||||
}
|
||||
*writer=0;
|
||||
/* New string name */
|
||||
if (linein[0]==':') {
|
||||
string[0]=0;
|
||||
strcpy(name,linein+1);
|
||||
/* End of string marker */
|
||||
} else if (linein[0]=='.') {
|
||||
/* Replace/Add the string to the internal langaugefile */
|
||||
/* Remove last newline (marker is \n.\n) */
|
||||
size_t ll = strlen(string);
|
||||
if(ll && string[ll - 1] == '\n') string[ll - 1] = 0; //Second if should not be needed, but better be safe.
|
||||
MSG_Replace(name,string);
|
||||
} else {
|
||||
/* Normal string to be added */
|
||||
strcat(string,linein);
|
||||
strcat(string,"\n");
|
||||
}
|
||||
}
|
||||
fclose(mfile);
|
||||
}
|
||||
|
||||
const char * MSG_Get(char const * msg) {
|
||||
for(itmb tel=Lang.begin();tel!=Lang.end();tel++){
|
||||
if((*tel).name==msg)
|
||||
{
|
||||
return (*tel).val.c_str();
|
||||
}
|
||||
}
|
||||
return "Message not Found!\n";
|
||||
}
|
||||
|
||||
|
||||
void MSG_Write(const char * location) {
|
||||
FILE* out=fopen(location,"w+t");
|
||||
if(out==NULL) return;//maybe an error?
|
||||
for(itmb tel=Lang.begin();tel!=Lang.end();tel++){
|
||||
fprintf(out,":%s\n%s\n.\n",(*tel).name.c_str(),(*tel).val.c_str());
|
||||
}
|
||||
fclose(out);
|
||||
}
|
||||
|
||||
void MSG_Init(Section_prop * section) {
|
||||
std::string file_name;
|
||||
if (control->cmdline->FindString("-lang",file_name,true)) {
|
||||
LoadMessageFile(file_name.c_str());
|
||||
} else {
|
||||
Prop_path* pathprop = section->Get_path("language");
|
||||
if(pathprop) LoadMessageFile(pathprop->realpath.c_str());
|
||||
}
|
||||
}
|
||||
|
@ -1,392 +1,392 @@
|
||||
/*
|
||||
* Copyright (C) 2002-2009 The DOSBox Team
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/* $Id: programs.cpp,v 1.37 2009/05/27 09:15:42 qbix79 Exp $ */
|
||||
|
||||
#include <vector>
|
||||
#include <ctype.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "programs.h"
|
||||
#include "callback.h"
|
||||
#include "regs.h"
|
||||
#include "support.h"
|
||||
#include "cross.h"
|
||||
#include "control.h"
|
||||
#include "shell.h"
|
||||
|
||||
Bitu call_program;
|
||||
|
||||
/* This registers a file on the virtual drive and creates the correct structure for it*/
|
||||
|
||||
static Bit8u exe_block[]={
|
||||
0xbc,0x00,0x04, //MOV SP,0x400 decrease stack size
|
||||
0xbb,0x40,0x00, //MOV BX,0x040 for memory resize
|
||||
0xb4,0x4a, //MOV AH,0x4A Resize memory block
|
||||
0xcd,0x21, //INT 0x21
|
||||
//pos 12 is callback number
|
||||
0xFE,0x38,0x00,0x00, //CALLBack number
|
||||
0xb8,0x00,0x4c, //Mov ax,4c00
|
||||
0xcd,0x21, //INT 0x21
|
||||
};
|
||||
|
||||
#define CB_POS 12
|
||||
|
||||
static std::vector<PROGRAMS_Main*> internal_progs;
|
||||
|
||||
void PROGRAMS_MakeFile(char const * const name,PROGRAMS_Main * main) {
|
||||
Bit8u * comdata=(Bit8u *)malloc(32); //MEM LEAK
|
||||
memcpy(comdata,&exe_block,sizeof(exe_block));
|
||||
comdata[CB_POS]=(Bit8u)(call_program&0xff);
|
||||
comdata[CB_POS+1]=(Bit8u)((call_program>>8)&0xff);
|
||||
|
||||
/* Copy save the pointer in the vector and save it's index */
|
||||
if (internal_progs.size()>255) E_Exit("PROGRAMS_MakeFile program size too large (%d)",static_cast<int>(internal_progs.size()));
|
||||
Bit8u index = (Bit8u)internal_progs.size();
|
||||
internal_progs.push_back(main);
|
||||
|
||||
memcpy(&comdata[sizeof(exe_block)],&index,sizeof(index));
|
||||
Bit32u size=sizeof(exe_block)+sizeof(index);
|
||||
VFILE_Register(name,comdata,size);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static Bitu PROGRAMS_Handler(void) {
|
||||
/* This sets up everything for a program start up call */
|
||||
Bitu size=sizeof(Bit8u);
|
||||
Bit8u index;
|
||||
/* Read the index from program code in memory */
|
||||
PhysPt reader=PhysMake(dos.psp(),256+sizeof(exe_block));
|
||||
HostPt writer=(HostPt)&index;
|
||||
for (;size>0;size--) *writer++=mem_readb(reader++);
|
||||
Program * new_program;
|
||||
if(index > internal_progs.size()) E_Exit("something is messing with the memory");
|
||||
PROGRAMS_Main * handler = internal_progs[index];
|
||||
(*handler)(&new_program);
|
||||
new_program->Run();
|
||||
delete new_program;
|
||||
return CBRET_NONE;
|
||||
}
|
||||
|
||||
|
||||
/* Main functions used in all program */
|
||||
|
||||
|
||||
Program::Program() {
|
||||
/* Find the command line and setup the PSP */
|
||||
psp = new DOS_PSP(dos.psp());
|
||||
/* Scan environment for filename */
|
||||
PhysPt envscan=PhysMake(psp->GetEnvironment(),0);
|
||||
while (mem_readb(envscan)) envscan+=mem_strlen(envscan)+1;
|
||||
envscan+=3;
|
||||
CommandTail tail;
|
||||
MEM_BlockRead(PhysMake(dos.psp(),128),&tail,128);
|
||||
if (tail.count<127) tail.buffer[tail.count]=0;
|
||||
else tail.buffer[126]=0;
|
||||
char filename[256+1];
|
||||
MEM_StrCopy(envscan,filename,256);
|
||||
cmd = new CommandLine(filename,tail.buffer);
|
||||
}
|
||||
|
||||
extern std::string full_arguments;
|
||||
|
||||
void Program::ChangeToLongCmd() {
|
||||
/*
|
||||
* Get arguments directly from the shell instead of the psp.
|
||||
* this is done in securemode: (as then the arguments to mount and friends
|
||||
* can only be given on the shell ( so no int 21 4b)
|
||||
* Securemode part is disabled as each of the internal command has already
|
||||
* protection for it. (and it breaks games like cdman)
|
||||
* it is also done for long arguments to as it is convient (as the total commandline can be longer then 127 characters.
|
||||
* imgmount with lot's of parameters
|
||||
* Length of arguments can be ~120. but switch when above 100 to be sure
|
||||
*/
|
||||
|
||||
if(/*control->SecureMode() ||*/ cmd->Get_arglength() > 100) {
|
||||
CommandLine* temp = new CommandLine(cmd->GetFileName(),full_arguments.c_str());
|
||||
delete cmd;
|
||||
cmd = temp;
|
||||
}
|
||||
full_arguments.assign(""); //Clear so it gets even more save
|
||||
}
|
||||
|
||||
void Program::WriteOut(const char * format,...) {
|
||||
char buf[2048];
|
||||
va_list msg;
|
||||
|
||||
va_start(msg,format);
|
||||
vsnprintf(buf,2047,format,msg);
|
||||
va_end(msg);
|
||||
|
||||
Bit16u size = (Bit16u)strlen(buf);
|
||||
DOS_WriteFile(STDOUT,(Bit8u *)buf,&size);
|
||||
}
|
||||
|
||||
void Program::WriteOut_NoParsing(const char * format) {
|
||||
Bit16u size = (Bit16u)strlen(format);
|
||||
DOS_WriteFile(STDOUT,(Bit8u *)format,&size);
|
||||
}
|
||||
|
||||
|
||||
bool Program::GetEnvStr(const char * entry,std::string & result) {
|
||||
/* Walk through the internal environment and see for a match */
|
||||
PhysPt env_read=PhysMake(psp->GetEnvironment(),0);
|
||||
char env_string[1024+1];
|
||||
result.erase();
|
||||
if (!entry[0]) return false;
|
||||
do {
|
||||
MEM_StrCopy(env_read,env_string,1024);
|
||||
if (!env_string[0]) return false;
|
||||
env_read += (PhysPt)(strlen(env_string)+1);
|
||||
char* equal = strchr(env_string,'=');
|
||||
if (!equal) continue;
|
||||
/* replace the = with \0 to get the length */
|
||||
*equal = 0;
|
||||
if (strlen(env_string) != strlen(entry)) continue;
|
||||
if (strcasecmp(entry,env_string)!=0) continue;
|
||||
/* restore the = to get the original result */
|
||||
*equal = '=';
|
||||
result = env_string;
|
||||
return true;
|
||||
} while (1);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Program::GetEnvNum(Bitu num,std::string & result) {
|
||||
char env_string[1024+1];
|
||||
PhysPt env_read=PhysMake(psp->GetEnvironment(),0);
|
||||
do {
|
||||
MEM_StrCopy(env_read,env_string,1024);
|
||||
if (!env_string[0]) break;
|
||||
if (!num) { result=env_string;return true;}
|
||||
env_read += (PhysPt)(strlen(env_string)+1);
|
||||
num--;
|
||||
} while (1);
|
||||
return false;
|
||||
}
|
||||
|
||||
Bitu Program::GetEnvCount(void) {
|
||||
PhysPt env_read=PhysMake(psp->GetEnvironment(),0);
|
||||
Bitu num=0;
|
||||
while (mem_readb(env_read)!=0) {
|
||||
for (;mem_readb(env_read);env_read++) {};
|
||||
env_read++;
|
||||
num++;
|
||||
}
|
||||
return num;
|
||||
}
|
||||
|
||||
bool Program::SetEnv(const char * entry,const char * new_string) {
|
||||
PhysPt env_read=PhysMake(psp->GetEnvironment(),0);
|
||||
PhysPt env_write=env_read;
|
||||
char env_string[1024+1];
|
||||
do {
|
||||
MEM_StrCopy(env_read,env_string,1024);
|
||||
if (!env_string[0]) break;
|
||||
env_read += (PhysPt)(strlen(env_string)+1);
|
||||
if (!strchr(env_string,'=')) continue; /* Remove corrupt entry? */
|
||||
if ((strncasecmp(entry,env_string,strlen(entry))==0) &&
|
||||
env_string[strlen(entry)]=='=') continue;
|
||||
MEM_BlockWrite(env_write,env_string,(Bitu)(strlen(env_string)+1));
|
||||
env_write += (PhysPt)(strlen(env_string)+1);
|
||||
} while (1);
|
||||
/* TODO Maybe save the program name sometime. not really needed though */
|
||||
/* Save the new entry */
|
||||
if (new_string[0]) {
|
||||
std::string bigentry(entry);
|
||||
for (std::string::iterator it = bigentry.begin(); it != bigentry.end(); ++it) *it = toupper(*it);
|
||||
sprintf(env_string,"%s=%s",bigentry.c_str(),new_string);
|
||||
// sprintf(env_string,"%s=%s",entry,new_string); //oldcode
|
||||
MEM_BlockWrite(env_write,env_string,(Bitu)(strlen(env_string)+1));
|
||||
env_write += (PhysPt)(strlen(env_string)+1);
|
||||
}
|
||||
/* Clear out the final piece of the environment */
|
||||
mem_writed(env_write,0);
|
||||
return true;
|
||||
}
|
||||
|
||||
class CONFIG : public Program {
|
||||
public:
|
||||
void Run(void);
|
||||
};
|
||||
|
||||
void MSG_Write(const char *);
|
||||
|
||||
void CONFIG::Run(void) {
|
||||
FILE * f;
|
||||
if (cmd->FindString("-writeconf",temp_line,true)
|
||||
|| cmd->FindString("-wc",temp_line,true)) {
|
||||
/* In secure mode don't allow a new configfile to be created */
|
||||
if(control->SecureMode()) {
|
||||
WriteOut(MSG_Get("PROGRAM_CONFIG_SECURE_DISALLOW"));
|
||||
return;
|
||||
}
|
||||
f=fopen(temp_line.c_str(),"wb+");
|
||||
if (!f) {
|
||||
WriteOut(MSG_Get("PROGRAM_CONFIG_FILE_ERROR"),temp_line.c_str());
|
||||
return;
|
||||
}
|
||||
fclose(f);
|
||||
control->PrintConfig(temp_line.c_str());
|
||||
return;
|
||||
}
|
||||
if (cmd->FindString("-writelang",temp_line,true)
|
||||
||cmd->FindString("-wl",temp_line,true)) {
|
||||
/* In secure mode don't allow a new languagefile to be created
|
||||
* Who knows which kind of file we would overwriting. */
|
||||
if(control->SecureMode()) {
|
||||
WriteOut(MSG_Get("PROGRAM_CONFIG_SECURE_DISALLOW"));
|
||||
return;
|
||||
}
|
||||
f=fopen(temp_line.c_str(),"wb+");
|
||||
if (!f) {
|
||||
WriteOut(MSG_Get("PROGRAM_CONFIG_FILE_ERROR"),temp_line.c_str());
|
||||
return;
|
||||
}
|
||||
fclose(f);
|
||||
MSG_Write(temp_line.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
/* Code for switching to secure mode */
|
||||
if(cmd->FindExist("-securemode",true)) {
|
||||
control->SwitchToSecureMode();
|
||||
WriteOut(MSG_Get("PROGRAM_CONFIG_SECURE_ON"));
|
||||
return;
|
||||
}
|
||||
|
||||
/* Code for getting the current configuration. *
|
||||
* Official format: config -get "section property" *
|
||||
* As a bonus it will set %CONFIG% to this value as well */
|
||||
if(cmd->FindString("-get",temp_line,true)) {
|
||||
std::string temp2 = "";
|
||||
cmd->GetStringRemain(temp2);//So -get n1 n2= can be used without quotes
|
||||
if(temp2 != "") temp_line = temp_line + " " + temp2;
|
||||
|
||||
std::string::size_type space = temp_line.find(" ");
|
||||
if(space == std::string::npos) {
|
||||
WriteOut(MSG_Get("PROGRAM_CONFIG_GET_SYNTAX"));
|
||||
return;
|
||||
}
|
||||
//Copy the found property to a new string and erase from templine (mind the space)
|
||||
std::string prop = temp_line.substr(space+1); temp_line.erase(space);
|
||||
|
||||
Section* sec = control->GetSection(temp_line.c_str());
|
||||
if(!sec) {
|
||||
WriteOut(MSG_Get("PROGRAM_CONFIG_SECTION_ERROR"),temp_line.c_str());
|
||||
return;
|
||||
}
|
||||
std::string val = sec->GetPropValue(prop.c_str());
|
||||
if(val == NO_SUCH_PROPERTY) {
|
||||
WriteOut(MSG_Get("PROGRAM_CONFIG_NO_PROPERTY"),prop.c_str(),temp_line.c_str());
|
||||
return;
|
||||
}
|
||||
WriteOut("%s",val.c_str());
|
||||
first_shell->SetEnv("CONFIG",val.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Code for the configuration changes *
|
||||
* Official format: config -set "section property=value" *
|
||||
* Accepted: without quotes and/or without -set and/or without section *
|
||||
* and/or the "=" replaced by a " " */
|
||||
|
||||
if (cmd->FindString("-set",temp_line,true)) { //get all arguments
|
||||
std::string temp2 = "";
|
||||
cmd->GetStringRemain(temp2);//So -set n1 n2=n3 can be used without quotes
|
||||
if(temp2!="") temp_line = temp_line + " " + temp2;
|
||||
} else if(!cmd->GetStringRemain(temp_line)) {//no set
|
||||
WriteOut(MSG_Get("PROGRAM_CONFIG_USAGE")); //and no arguments specified
|
||||
return;
|
||||
};
|
||||
//Wanted input: n1 n2=n3
|
||||
char copy[1024];
|
||||
strcpy(copy,temp_line.c_str());
|
||||
//seperate section from property
|
||||
const char* temp = strchr(copy,' ');
|
||||
if((temp && *temp) || (temp=strchr(copy,'=')) ) copy[temp++ - copy]= 0;
|
||||
else {
|
||||
WriteOut(MSG_Get("PROGRAM_CONFIG_USAGE"));
|
||||
return;
|
||||
}
|
||||
//if n1 n2 n3 then replace last space with =
|
||||
const char* sign = strchr(temp,'=');
|
||||
if(!sign) {
|
||||
sign = strchr(temp,' ');
|
||||
if(sign) {
|
||||
copy[sign - copy] = '=';
|
||||
} else {
|
||||
//2 items specified (no space nor = between n2 and n3
|
||||
//assume that they posted: property value
|
||||
//Try to determine the section.
|
||||
Section* sec=control->GetSectionFromProperty(copy);
|
||||
if(!sec){
|
||||
if(control->GetSectionFromProperty(temp)) return; //Weird situation:ignore
|
||||
WriteOut(MSG_Get("PROGRAM_CONFIG_PROPERTY_ERROR"),copy);
|
||||
return;
|
||||
} //Hack to allow config ems true
|
||||
char buffer[1024];strcpy(buffer,copy);strcat(buffer,"=");strcat(buffer,temp);
|
||||
sign = strchr(buffer,' ');
|
||||
if(sign) buffer[sign - buffer] = '=';
|
||||
strcpy(copy,sec->GetName());
|
||||
temp = buffer;
|
||||
}
|
||||
}
|
||||
|
||||
/* Input processed. Now the real job starts
|
||||
* copy contains the likely "sectionname"
|
||||
* temp contains "property=value"
|
||||
* the section is destroyed and a new input line is given to
|
||||
* the configuration parser. Then the section is restarted.
|
||||
*/
|
||||
char* inputline = const_cast<char*>(temp);
|
||||
Section* sec = 0;
|
||||
sec = control->GetSection(copy);
|
||||
if(!sec) { WriteOut(MSG_Get("PROGRAM_CONFIG_SECTION_ERROR"),copy);return;}
|
||||
sec->ExecuteDestroy(false);
|
||||
sec->HandleInputline(inputline);
|
||||
sec->ExecuteInit(false);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
static void CONFIG_ProgramStart(Program * * make) {
|
||||
*make=new CONFIG;
|
||||
}
|
||||
|
||||
|
||||
void PROGRAMS_Init(Section* /*sec*/) {
|
||||
/* Setup a special callback to start virtual programs */
|
||||
call_program=CALLBACK_Allocate();
|
||||
CALLBACK_Setup(call_program,&PROGRAMS_Handler,CB_RETF,"internal program");
|
||||
PROGRAMS_MakeFile("CONFIG.COM",CONFIG_ProgramStart);
|
||||
|
||||
MSG_Add("PROGRAM_CONFIG_FILE_ERROR","Can't open file %s\n");
|
||||
MSG_Add("PROGRAM_CONFIG_USAGE","Config tool:\nUse -writeconf filename to write the current config.\nUse -writelang filename to write the current language strings.\n");
|
||||
MSG_Add("PROGRAM_CONFIG_SECURE_ON","Switched to secure mode.\n");
|
||||
MSG_Add("PROGRAM_CONFIG_SECURE_DISALLOW","This operation is not permitted in secure mode.\n");
|
||||
MSG_Add("PROGRAM_CONFIG_SECTION_ERROR","Section %s doesn't exist.\n");
|
||||
MSG_Add("PROGRAM_CONFIG_PROPERTY_ERROR","No such section or property.\n");
|
||||
MSG_Add("PROGRAM_CONFIG_NO_PROPERTY","There is no property %s in section %s.\n");
|
||||
MSG_Add("PROGRAM_CONFIG_GET_SYNTAX","Correct syntax: config -get \"section property\".\n");
|
||||
}
|
||||
/*
|
||||
* Copyright (C) 2002-2009 The DOSBox Team
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/* $Id: programs.cpp,v 1.37 2009-05-27 09:15:42 qbix79 Exp $ */
|
||||
|
||||
#include <vector>
|
||||
#include <ctype.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "programs.h"
|
||||
#include "callback.h"
|
||||
#include "regs.h"
|
||||
#include "support.h"
|
||||
#include "cross.h"
|
||||
#include "control.h"
|
||||
#include "shell.h"
|
||||
|
||||
Bitu call_program;
|
||||
|
||||
/* This registers a file on the virtual drive and creates the correct structure for it*/
|
||||
|
||||
static Bit8u exe_block[]={
|
||||
0xbc,0x00,0x04, //MOV SP,0x400 decrease stack size
|
||||
0xbb,0x40,0x00, //MOV BX,0x040 for memory resize
|
||||
0xb4,0x4a, //MOV AH,0x4A Resize memory block
|
||||
0xcd,0x21, //INT 0x21
|
||||
//pos 12 is callback number
|
||||
0xFE,0x38,0x00,0x00, //CALLBack number
|
||||
0xb8,0x00,0x4c, //Mov ax,4c00
|
||||
0xcd,0x21, //INT 0x21
|
||||
};
|
||||
|
||||
#define CB_POS 12
|
||||
|
||||
static std::vector<PROGRAMS_Main*> internal_progs;
|
||||
|
||||
void PROGRAMS_MakeFile(char const * const name,PROGRAMS_Main * main) {
|
||||
Bit8u * comdata=(Bit8u *)malloc(32); //MEM LEAK
|
||||
memcpy(comdata,&exe_block,sizeof(exe_block));
|
||||
comdata[CB_POS]=(Bit8u)(call_program&0xff);
|
||||
comdata[CB_POS+1]=(Bit8u)((call_program>>8)&0xff);
|
||||
|
||||
/* Copy save the pointer in the vector and save it's index */
|
||||
if (internal_progs.size()>255) E_Exit("PROGRAMS_MakeFile program size too large (%d)",static_cast<int>(internal_progs.size()));
|
||||
Bit8u index = (Bit8u)internal_progs.size();
|
||||
internal_progs.push_back(main);
|
||||
|
||||
memcpy(&comdata[sizeof(exe_block)],&index,sizeof(index));
|
||||
Bit32u size=sizeof(exe_block)+sizeof(index);
|
||||
VFILE_Register(name,comdata,size);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static Bitu PROGRAMS_Handler(void) {
|
||||
/* This sets up everything for a program start up call */
|
||||
Bitu size=sizeof(Bit8u);
|
||||
Bit8u index;
|
||||
/* Read the index from program code in memory */
|
||||
PhysPt reader=PhysMake(dos.psp(),256+sizeof(exe_block));
|
||||
HostPt writer=(HostPt)&index;
|
||||
for (;size>0;size--) *writer++=mem_readb(reader++);
|
||||
Program * new_program;
|
||||
if(index > internal_progs.size()) E_Exit("something is messing with the memory");
|
||||
PROGRAMS_Main * handler = internal_progs[index];
|
||||
(*handler)(&new_program);
|
||||
new_program->Run();
|
||||
delete new_program;
|
||||
return CBRET_NONE;
|
||||
}
|
||||
|
||||
|
||||
/* Main functions used in all program */
|
||||
|
||||
|
||||
Program::Program() {
|
||||
/* Find the command line and setup the PSP */
|
||||
psp = new DOS_PSP(dos.psp());
|
||||
/* Scan environment for filename */
|
||||
PhysPt envscan=PhysMake(psp->GetEnvironment(),0);
|
||||
while (mem_readb(envscan)) envscan+=mem_strlen(envscan)+1;
|
||||
envscan+=3;
|
||||
CommandTail tail;
|
||||
MEM_BlockRead(PhysMake(dos.psp(),128),&tail,128);
|
||||
if (tail.count<127) tail.buffer[tail.count]=0;
|
||||
else tail.buffer[126]=0;
|
||||
char filename[256+1];
|
||||
MEM_StrCopy(envscan,filename,256);
|
||||
cmd = new CommandLine(filename,tail.buffer);
|
||||
}
|
||||
|
||||
extern std::string full_arguments;
|
||||
|
||||
void Program::ChangeToLongCmd() {
|
||||
/*
|
||||
* Get arguments directly from the shell instead of the psp.
|
||||
* this is done in securemode: (as then the arguments to mount and friends
|
||||
* can only be given on the shell ( so no int 21 4b)
|
||||
* Securemode part is disabled as each of the internal command has already
|
||||
* protection for it. (and it breaks games like cdman)
|
||||
* it is also done for long arguments to as it is convient (as the total commandline can be longer then 127 characters.
|
||||
* imgmount with lot's of parameters
|
||||
* Length of arguments can be ~120. but switch when above 100 to be sure
|
||||
*/
|
||||
|
||||
if(/*control->SecureMode() ||*/ cmd->Get_arglength() > 100) {
|
||||
CommandLine* temp = new CommandLine(cmd->GetFileName(),full_arguments.c_str());
|
||||
delete cmd;
|
||||
cmd = temp;
|
||||
}
|
||||
full_arguments.assign(""); //Clear so it gets even more save
|
||||
}
|
||||
|
||||
void Program::WriteOut(const char * format,...) {
|
||||
char buf[2048];
|
||||
va_list msg;
|
||||
|
||||
va_start(msg,format);
|
||||
vsnprintf(buf,2047,format,msg);
|
||||
va_end(msg);
|
||||
|
||||
Bit16u size = (Bit16u)strlen(buf);
|
||||
DOS_WriteFile(STDOUT,(Bit8u *)buf,&size);
|
||||
}
|
||||
|
||||
void Program::WriteOut_NoParsing(const char * format) {
|
||||
Bit16u size = (Bit16u)strlen(format);
|
||||
DOS_WriteFile(STDOUT,(Bit8u *)format,&size);
|
||||
}
|
||||
|
||||
|
||||
bool Program::GetEnvStr(const char * entry,std::string & result) {
|
||||
/* Walk through the internal environment and see for a match */
|
||||
PhysPt env_read=PhysMake(psp->GetEnvironment(),0);
|
||||
char env_string[1024+1];
|
||||
result.erase();
|
||||
if (!entry[0]) return false;
|
||||
do {
|
||||
MEM_StrCopy(env_read,env_string,1024);
|
||||
if (!env_string[0]) return false;
|
||||
env_read += (PhysPt)(strlen(env_string)+1);
|
||||
char* equal = strchr(env_string,'=');
|
||||
if (!equal) continue;
|
||||
/* replace the = with \0 to get the length */
|
||||
*equal = 0;
|
||||
if (strlen(env_string) != strlen(entry)) continue;
|
||||
if (strcasecmp(entry,env_string)!=0) continue;
|
||||
/* restore the = to get the original result */
|
||||
*equal = '=';
|
||||
result = env_string;
|
||||
return true;
|
||||
} while (1);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Program::GetEnvNum(Bitu num,std::string & result) {
|
||||
char env_string[1024+1];
|
||||
PhysPt env_read=PhysMake(psp->GetEnvironment(),0);
|
||||
do {
|
||||
MEM_StrCopy(env_read,env_string,1024);
|
||||
if (!env_string[0]) break;
|
||||
if (!num) { result=env_string;return true;}
|
||||
env_read += (PhysPt)(strlen(env_string)+1);
|
||||
num--;
|
||||
} while (1);
|
||||
return false;
|
||||
}
|
||||
|
||||
Bitu Program::GetEnvCount(void) {
|
||||
PhysPt env_read=PhysMake(psp->GetEnvironment(),0);
|
||||
Bitu num=0;
|
||||
while (mem_readb(env_read)!=0) {
|
||||
for (;mem_readb(env_read);env_read++) {};
|
||||
env_read++;
|
||||
num++;
|
||||
}
|
||||
return num;
|
||||
}
|
||||
|
||||
bool Program::SetEnv(const char * entry,const char * new_string) {
|
||||
PhysPt env_read=PhysMake(psp->GetEnvironment(),0);
|
||||
PhysPt env_write=env_read;
|
||||
char env_string[1024+1];
|
||||
do {
|
||||
MEM_StrCopy(env_read,env_string,1024);
|
||||
if (!env_string[0]) break;
|
||||
env_read += (PhysPt)(strlen(env_string)+1);
|
||||
if (!strchr(env_string,'=')) continue; /* Remove corrupt entry? */
|
||||
if ((strncasecmp(entry,env_string,strlen(entry))==0) &&
|
||||
env_string[strlen(entry)]=='=') continue;
|
||||
MEM_BlockWrite(env_write,env_string,(Bitu)(strlen(env_string)+1));
|
||||
env_write += (PhysPt)(strlen(env_string)+1);
|
||||
} while (1);
|
||||
/* TODO Maybe save the program name sometime. not really needed though */
|
||||
/* Save the new entry */
|
||||
if (new_string[0]) {
|
||||
std::string bigentry(entry);
|
||||
for (std::string::iterator it = bigentry.begin(); it != bigentry.end(); ++it) *it = toupper(*it);
|
||||
sprintf(env_string,"%s=%s",bigentry.c_str(),new_string);
|
||||
// sprintf(env_string,"%s=%s",entry,new_string); //oldcode
|
||||
MEM_BlockWrite(env_write,env_string,(Bitu)(strlen(env_string)+1));
|
||||
env_write += (PhysPt)(strlen(env_string)+1);
|
||||
}
|
||||
/* Clear out the final piece of the environment */
|
||||
mem_writed(env_write,0);
|
||||
return true;
|
||||
}
|
||||
|
||||
class CONFIG : public Program {
|
||||
public:
|
||||
void Run(void);
|
||||
};
|
||||
|
||||
void MSG_Write(const char *);
|
||||
|
||||
void CONFIG::Run(void) {
|
||||
FILE * f;
|
||||
if (cmd->FindString("-writeconf",temp_line,true)
|
||||
|| cmd->FindString("-wc",temp_line,true)) {
|
||||
/* In secure mode don't allow a new configfile to be created */
|
||||
if(control->SecureMode()) {
|
||||
WriteOut(MSG_Get("PROGRAM_CONFIG_SECURE_DISALLOW"));
|
||||
return;
|
||||
}
|
||||
f=fopen(temp_line.c_str(),"wb+");
|
||||
if (!f) {
|
||||
WriteOut(MSG_Get("PROGRAM_CONFIG_FILE_ERROR"),temp_line.c_str());
|
||||
return;
|
||||
}
|
||||
fclose(f);
|
||||
control->PrintConfig(temp_line.c_str());
|
||||
return;
|
||||
}
|
||||
if (cmd->FindString("-writelang",temp_line,true)
|
||||
||cmd->FindString("-wl",temp_line,true)) {
|
||||
/* In secure mode don't allow a new languagefile to be created
|
||||
* Who knows which kind of file we would overwriting. */
|
||||
if(control->SecureMode()) {
|
||||
WriteOut(MSG_Get("PROGRAM_CONFIG_SECURE_DISALLOW"));
|
||||
return;
|
||||
}
|
||||
f=fopen(temp_line.c_str(),"wb+");
|
||||
if (!f) {
|
||||
WriteOut(MSG_Get("PROGRAM_CONFIG_FILE_ERROR"),temp_line.c_str());
|
||||
return;
|
||||
}
|
||||
fclose(f);
|
||||
MSG_Write(temp_line.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
/* Code for switching to secure mode */
|
||||
if(cmd->FindExist("-securemode",true)) {
|
||||
control->SwitchToSecureMode();
|
||||
WriteOut(MSG_Get("PROGRAM_CONFIG_SECURE_ON"));
|
||||
return;
|
||||
}
|
||||
|
||||
/* Code for getting the current configuration. *
|
||||
* Official format: config -get "section property" *
|
||||
* As a bonus it will set %CONFIG% to this value as well */
|
||||
if(cmd->FindString("-get",temp_line,true)) {
|
||||
std::string temp2 = "";
|
||||
cmd->GetStringRemain(temp2);//So -get n1 n2= can be used without quotes
|
||||
if(temp2 != "") temp_line = temp_line + " " + temp2;
|
||||
|
||||
std::string::size_type space = temp_line.find(" ");
|
||||
if(space == std::string::npos) {
|
||||
WriteOut(MSG_Get("PROGRAM_CONFIG_GET_SYNTAX"));
|
||||
return;
|
||||
}
|
||||
//Copy the found property to a new string and erase from templine (mind the space)
|
||||
std::string prop = temp_line.substr(space+1); temp_line.erase(space);
|
||||
|
||||
Section* sec = control->GetSection(temp_line.c_str());
|
||||
if(!sec) {
|
||||
WriteOut(MSG_Get("PROGRAM_CONFIG_SECTION_ERROR"),temp_line.c_str());
|
||||
return;
|
||||
}
|
||||
std::string val = sec->GetPropValue(prop.c_str());
|
||||
if(val == NO_SUCH_PROPERTY) {
|
||||
WriteOut(MSG_Get("PROGRAM_CONFIG_NO_PROPERTY"),prop.c_str(),temp_line.c_str());
|
||||
return;
|
||||
}
|
||||
WriteOut("%s",val.c_str());
|
||||
first_shell->SetEnv("CONFIG",val.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Code for the configuration changes *
|
||||
* Official format: config -set "section property=value" *
|
||||
* Accepted: without quotes and/or without -set and/or without section *
|
||||
* and/or the "=" replaced by a " " */
|
||||
|
||||
if (cmd->FindString("-set",temp_line,true)) { //get all arguments
|
||||
std::string temp2 = "";
|
||||
cmd->GetStringRemain(temp2);//So -set n1 n2=n3 can be used without quotes
|
||||
if(temp2!="") temp_line = temp_line + " " + temp2;
|
||||
} else if(!cmd->GetStringRemain(temp_line)) {//no set
|
||||
WriteOut(MSG_Get("PROGRAM_CONFIG_USAGE")); //and no arguments specified
|
||||
return;
|
||||
};
|
||||
//Wanted input: n1 n2=n3
|
||||
char copy[1024];
|
||||
strcpy(copy,temp_line.c_str());
|
||||
//seperate section from property
|
||||
const char* temp = strchr(copy,' ');
|
||||
if((temp && *temp) || (temp=strchr(copy,'=')) ) copy[temp++ - copy]= 0;
|
||||
else {
|
||||
WriteOut(MSG_Get("PROGRAM_CONFIG_USAGE"));
|
||||
return;
|
||||
}
|
||||
//if n1 n2 n3 then replace last space with =
|
||||
const char* sign = strchr(temp,'=');
|
||||
if(!sign) {
|
||||
sign = strchr(temp,' ');
|
||||
if(sign) {
|
||||
copy[sign - copy] = '=';
|
||||
} else {
|
||||
//2 items specified (no space nor = between n2 and n3
|
||||
//assume that they posted: property value
|
||||
//Try to determine the section.
|
||||
Section* sec=control->GetSectionFromProperty(copy);
|
||||
if(!sec){
|
||||
if(control->GetSectionFromProperty(temp)) return; //Weird situation:ignore
|
||||
WriteOut(MSG_Get("PROGRAM_CONFIG_PROPERTY_ERROR"),copy);
|
||||
return;
|
||||
} //Hack to allow config ems true
|
||||
char buffer[1024];strcpy(buffer,copy);strcat(buffer,"=");strcat(buffer,temp);
|
||||
sign = strchr(buffer,' ');
|
||||
if(sign) buffer[sign - buffer] = '=';
|
||||
strcpy(copy,sec->GetName());
|
||||
temp = buffer;
|
||||
}
|
||||
}
|
||||
|
||||
/* Input processed. Now the real job starts
|
||||
* copy contains the likely "sectionname"
|
||||
* temp contains "property=value"
|
||||
* the section is destroyed and a new input line is given to
|
||||
* the configuration parser. Then the section is restarted.
|
||||
*/
|
||||
char* inputline = const_cast<char*>(temp);
|
||||
Section* sec = 0;
|
||||
sec = control->GetSection(copy);
|
||||
if(!sec) { WriteOut(MSG_Get("PROGRAM_CONFIG_SECTION_ERROR"),copy);return;}
|
||||
sec->ExecuteDestroy(false);
|
||||
sec->HandleInputline(inputline);
|
||||
sec->ExecuteInit(false);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
static void CONFIG_ProgramStart(Program * * make) {
|
||||
*make=new CONFIG;
|
||||
}
|
||||
|
||||
|
||||
void PROGRAMS_Init(Section* /*sec*/) {
|
||||
/* Setup a special callback to start virtual programs */
|
||||
call_program=CALLBACK_Allocate();
|
||||
CALLBACK_Setup(call_program,&PROGRAMS_Handler,CB_RETF,"internal program");
|
||||
PROGRAMS_MakeFile("CONFIG.COM",CONFIG_ProgramStart);
|
||||
|
||||
MSG_Add("PROGRAM_CONFIG_FILE_ERROR","Can't open file %s\n");
|
||||
MSG_Add("PROGRAM_CONFIG_USAGE","Config tool:\nUse -writeconf filename to write the current config.\nUse -writelang filename to write the current language strings.\n");
|
||||
MSG_Add("PROGRAM_CONFIG_SECURE_ON","Switched to secure mode.\n");
|
||||
MSG_Add("PROGRAM_CONFIG_SECURE_DISALLOW","This operation is not permitted in secure mode.\n");
|
||||
MSG_Add("PROGRAM_CONFIG_SECTION_ERROR","Section %s doesn't exist.\n");
|
||||
MSG_Add("PROGRAM_CONFIG_PROPERTY_ERROR","No such section or property.\n");
|
||||
MSG_Add("PROGRAM_CONFIG_NO_PROPERTY","There is no property %s in section %s.\n");
|
||||
MSG_Add("PROGRAM_CONFIG_GET_SYNTAX","Correct syntax: config -get \"section property\".\n");
|
||||
}
|
||||
|
2006
src/misc/setup.cpp
2006
src/misc/setup.cpp
File diff suppressed because it is too large
Load Diff
@ -1,185 +1,185 @@
|
||||
/*
|
||||
* Copyright (C) 2002-2009 The DOSBox Team
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/* $Id: support.cpp,v 1.37 2009/05/27 09:15:42 qbix79 Exp $ */
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <ctype.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <algorithm>
|
||||
#include <cctype>
|
||||
#include <string>
|
||||
|
||||
#include "dosbox.h"
|
||||
#include "debug.h"
|
||||
#include "support.h"
|
||||
#include "video.h"
|
||||
|
||||
|
||||
void upcase(std::string &str) {
|
||||
int (*tf)(int) = std::toupper;
|
||||
std::transform(str.begin(), str.end(), str.begin(), tf);
|
||||
}
|
||||
|
||||
void lowcase(std::string &str) {
|
||||
int (*tf)(int) = std::tolower;
|
||||
std::transform(str.begin(), str.end(), str.begin(), tf);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Ripped some source from freedos for this one.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* replaces all instances of character o with character c
|
||||
*/
|
||||
|
||||
|
||||
void strreplace(char * str,char o,char n) {
|
||||
while (*str) {
|
||||
if (*str==o) *str=n;
|
||||
str++;
|
||||
}
|
||||
}
|
||||
char *ltrim(char *str) {
|
||||
while (*str && isspace(*reinterpret_cast<unsigned char*>(str))) str++;
|
||||
return str;
|
||||
}
|
||||
|
||||
char *rtrim(char *str) {
|
||||
char *p;
|
||||
p = strchr(str, '\0');
|
||||
while (--p >= str && isspace(*reinterpret_cast<unsigned char*>(p))) {};
|
||||
p[1] = '\0';
|
||||
return str;
|
||||
}
|
||||
|
||||
char *trim(char *str) {
|
||||
return ltrim(rtrim(str));
|
||||
}
|
||||
|
||||
char * upcase(char * str) {
|
||||
for (char* idx = str; *idx ; idx++) *idx = toupper(*reinterpret_cast<unsigned char*>(idx));
|
||||
return str;
|
||||
}
|
||||
|
||||
char * lowcase(char * str) {
|
||||
for(char* idx = str; *idx ; idx++) *idx = tolower(*reinterpret_cast<unsigned char*>(idx));
|
||||
return str;
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool ScanCMDBool(char * cmd,char const * const check) {
|
||||
char * scan=cmd;size_t c_len=strlen(check);
|
||||
while ((scan=strchr(scan,'/'))) {
|
||||
/* found a / now see behind it */
|
||||
scan++;
|
||||
if (strncasecmp(scan,check,c_len)==0 && (scan[c_len]==' ' || scan[c_len]=='\t' || scan[c_len]=='/' || scan[c_len]==0)) {
|
||||
/* Found a math now remove it from the string */
|
||||
memmove(scan-1,scan+c_len,strlen(scan+c_len)+1);
|
||||
trim(scan-1);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/* This scans the command line for a remaining switch and reports it else returns 0*/
|
||||
char * ScanCMDRemain(char * cmd) {
|
||||
char * scan,*found;;
|
||||
if ((scan=found=strchr(cmd,'/'))) {
|
||||
while ( *scan && !isspace(*reinterpret_cast<unsigned char*>(scan)) ) scan++;
|
||||
*scan=0;
|
||||
return found;
|
||||
} else return 0;
|
||||
}
|
||||
|
||||
char * StripWord(char *&line) {
|
||||
char * scan=line;
|
||||
scan=ltrim(scan);
|
||||
if (*scan=='"') {
|
||||
char * end_quote=strchr(scan+1,'"');
|
||||
if (end_quote) {
|
||||
*end_quote=0;
|
||||
line=ltrim(++end_quote);
|
||||
return (scan+1);
|
||||
}
|
||||
}
|
||||
char * begin=scan;
|
||||
for (char c = *scan ;(c = *scan);scan++) {
|
||||
if (isspace(*reinterpret_cast<unsigned char*>(&c))) {
|
||||
*scan++=0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
line=scan;
|
||||
return begin;
|
||||
}
|
||||
|
||||
Bits ConvDecWord(char * word) {
|
||||
bool negative=false;Bitu ret=0;
|
||||
if (*word=='-') {
|
||||
negative=true;
|
||||
word++;
|
||||
}
|
||||
while (char c=*word) {
|
||||
ret*=10;
|
||||
ret+=c-'0';
|
||||
word++;
|
||||
}
|
||||
if (negative) return 0-ret;
|
||||
else return ret;
|
||||
}
|
||||
|
||||
Bits ConvHexWord(char * word) {
|
||||
Bitu ret=0;
|
||||
while (char c=toupper(*reinterpret_cast<unsigned char*>(word))) {
|
||||
ret*=16;
|
||||
if (c>='0' && c<='9') ret+=c-'0';
|
||||
else if (c>='A' && c<='F') ret+=10+(c-'A');
|
||||
word++;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
double ConvDblWord(char * word) {
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
|
||||
static char buf[1024]; //greater scope as else it doesn't always gets thrown right (linux/gcc2.95)
|
||||
void E_Exit(const char * format,...) {
|
||||
#if C_DEBUG && C_HEAVY_DEBUG
|
||||
DEBUG_HeavyWriteLogInstruction();
|
||||
#endif
|
||||
va_list msg;
|
||||
va_start(msg,format);
|
||||
vsprintf(buf,format,msg);
|
||||
va_end(msg);
|
||||
strcat(buf,"\n");
|
||||
|
||||
throw(buf);
|
||||
}
|
||||
/*
|
||||
* Copyright (C) 2002-2009 The DOSBox Team
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/* $Id: support.cpp,v 1.37 2009-05-27 09:15:42 qbix79 Exp $ */
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <ctype.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <algorithm>
|
||||
#include <cctype>
|
||||
#include <string>
|
||||
|
||||
#include "dosbox.h"
|
||||
#include "debug.h"
|
||||
#include "support.h"
|
||||
#include "video.h"
|
||||
|
||||
|
||||
void upcase(std::string &str) {
|
||||
int (*tf)(int) = std::toupper;
|
||||
std::transform(str.begin(), str.end(), str.begin(), tf);
|
||||
}
|
||||
|
||||
void lowcase(std::string &str) {
|
||||
int (*tf)(int) = std::tolower;
|
||||
std::transform(str.begin(), str.end(), str.begin(), tf);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Ripped some source from freedos for this one.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* replaces all instances of character o with character c
|
||||
*/
|
||||
|
||||
|
||||
void strreplace(char * str,char o,char n) {
|
||||
while (*str) {
|
||||
if (*str==o) *str=n;
|
||||
str++;
|
||||
}
|
||||
}
|
||||
char *ltrim(char *str) {
|
||||
while (*str && isspace(*reinterpret_cast<unsigned char*>(str))) str++;
|
||||
return str;
|
||||
}
|
||||
|
||||
char *rtrim(char *str) {
|
||||
char *p;
|
||||
p = strchr(str, '\0');
|
||||
while (--p >= str && isspace(*reinterpret_cast<unsigned char*>(p))) {};
|
||||
p[1] = '\0';
|
||||
return str;
|
||||
}
|
||||
|
||||
char *trim(char *str) {
|
||||
return ltrim(rtrim(str));
|
||||
}
|
||||
|
||||
char * upcase(char * str) {
|
||||
for (char* idx = str; *idx ; idx++) *idx = toupper(*reinterpret_cast<unsigned char*>(idx));
|
||||
return str;
|
||||
}
|
||||
|
||||
char * lowcase(char * str) {
|
||||
for(char* idx = str; *idx ; idx++) *idx = tolower(*reinterpret_cast<unsigned char*>(idx));
|
||||
return str;
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool ScanCMDBool(char * cmd,char const * const check) {
|
||||
char * scan=cmd;size_t c_len=strlen(check);
|
||||
while ((scan=strchr(scan,'/'))) {
|
||||
/* found a / now see behind it */
|
||||
scan++;
|
||||
if (strncasecmp(scan,check,c_len)==0 && (scan[c_len]==' ' || scan[c_len]=='\t' || scan[c_len]=='/' || scan[c_len]==0)) {
|
||||
/* Found a math now remove it from the string */
|
||||
memmove(scan-1,scan+c_len,strlen(scan+c_len)+1);
|
||||
trim(scan-1);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/* This scans the command line for a remaining switch and reports it else returns 0*/
|
||||
char * ScanCMDRemain(char * cmd) {
|
||||
char * scan,*found;;
|
||||
if ((scan=found=strchr(cmd,'/'))) {
|
||||
while ( *scan && !isspace(*reinterpret_cast<unsigned char*>(scan)) ) scan++;
|
||||
*scan=0;
|
||||
return found;
|
||||
} else return 0;
|
||||
}
|
||||
|
||||
char * StripWord(char *&line) {
|
||||
char * scan=line;
|
||||
scan=ltrim(scan);
|
||||
if (*scan=='"') {
|
||||
char * end_quote=strchr(scan+1,'"');
|
||||
if (end_quote) {
|
||||
*end_quote=0;
|
||||
line=ltrim(++end_quote);
|
||||
return (scan+1);
|
||||
}
|
||||
}
|
||||
char * begin=scan;
|
||||
for (char c = *scan ;(c = *scan);scan++) {
|
||||
if (isspace(*reinterpret_cast<unsigned char*>(&c))) {
|
||||
*scan++=0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
line=scan;
|
||||
return begin;
|
||||
}
|
||||
|
||||
Bits ConvDecWord(char * word) {
|
||||
bool negative=false;Bitu ret=0;
|
||||
if (*word=='-') {
|
||||
negative=true;
|
||||
word++;
|
||||
}
|
||||
while (char c=*word) {
|
||||
ret*=10;
|
||||
ret+=c-'0';
|
||||
word++;
|
||||
}
|
||||
if (negative) return 0-ret;
|
||||
else return ret;
|
||||
}
|
||||
|
||||
Bits ConvHexWord(char * word) {
|
||||
Bitu ret=0;
|
||||
while (char c=toupper(*reinterpret_cast<unsigned char*>(word))) {
|
||||
ret*=16;
|
||||
if (c>='0' && c<='9') ret+=c-'0';
|
||||
else if (c>='A' && c<='F') ret+=10+(c-'A');
|
||||
word++;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
double ConvDblWord(char * word) {
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
|
||||
static char buf[1024]; //greater scope as else it doesn't always gets thrown right (linux/gcc2.95)
|
||||
void E_Exit(const char * format,...) {
|
||||
#if C_DEBUG && C_HEAVY_DEBUG
|
||||
DEBUG_HeavyWriteLogInstruction();
|
||||
#endif
|
||||
va_list msg;
|
||||
va_start(msg,format);
|
||||
vsprintf(buf,format,msg);
|
||||
va_end(msg);
|
||||
strcat(buf,"\n");
|
||||
|
||||
throw(buf);
|
||||
}
|
||||
|
1346
src/shell/shell.cpp
1346
src/shell/shell.cpp
File diff suppressed because it is too large
Load Diff
@ -1,202 +1,202 @@
|
||||
/*
|
||||
* Copyright (C) 2002-2009 The DOSBox Team
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/* $Id: shell_batch.cpp,v 1.36 2009/07/03 19:36:56 qbix79 Exp $ */
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "shell.h"
|
||||
#include "support.h"
|
||||
|
||||
BatchFile::BatchFile(DOS_Shell * host,char const * const name, char const * const cmd_line) {
|
||||
location = 0;
|
||||
prev=host->bf;
|
||||
echo=host->echo;
|
||||
shell=host;
|
||||
char totalname[DOS_PATHLENGTH+4];
|
||||
DOS_Canonicalize(name,totalname); // Get fullname including drive specificiation
|
||||
cmd = new CommandLine(totalname,cmd_line);
|
||||
filename = totalname;
|
||||
|
||||
//Test if file is openable
|
||||
if (!DOS_OpenFile(totalname,128,&file_handle)) {
|
||||
//TODO Come up with something better
|
||||
E_Exit("SHELL:Can't open BatchFile %s",totalname);
|
||||
}
|
||||
DOS_CloseFile(file_handle);
|
||||
}
|
||||
|
||||
BatchFile::~BatchFile() {
|
||||
delete cmd;
|
||||
shell->bf=prev;
|
||||
shell->echo=echo;
|
||||
}
|
||||
|
||||
bool BatchFile::ReadLine(char * line) {
|
||||
//Open the batchfile and seek to stored postion
|
||||
if (!DOS_OpenFile(filename.c_str(),128,&file_handle)) {
|
||||
LOG(LOG_MISC,LOG_ERROR)("ReadLine Can't open BatchFile %s",filename.c_str());
|
||||
delete this;
|
||||
return false;
|
||||
}
|
||||
DOS_SeekFile(file_handle,&(this->location),DOS_SEEK_SET);
|
||||
|
||||
Bit8u c=0;Bit16u n=1;
|
||||
char temp[CMD_MAXLINE];
|
||||
emptyline:
|
||||
char * cmd_write=temp;
|
||||
do {
|
||||
n=1;
|
||||
DOS_ReadFile(file_handle,&c,&n);
|
||||
if (n>0) {
|
||||
/* Why are we filtering this ?
|
||||
* Exclusion list: tab for batch files
|
||||
* escape for ansi
|
||||
* backspace for alien odyssey */
|
||||
if (c>31 || c==0x1b || c=='\t' || c==8)
|
||||
*cmd_write++=c;
|
||||
}
|
||||
} while (c!='\n' && n);
|
||||
*cmd_write=0;
|
||||
if (!n && cmd_write==temp) {
|
||||
//Close file and delete bat file
|
||||
DOS_CloseFile(file_handle);
|
||||
delete this;
|
||||
return false;
|
||||
}
|
||||
if (!strlen(temp)) goto emptyline;
|
||||
if (temp[0]==':') goto emptyline;
|
||||
|
||||
/* Now parse the line read from the bat file for % stuff */
|
||||
cmd_write=line;
|
||||
char * cmd_read=temp;
|
||||
char env_name[256];char * env_write;
|
||||
while (*cmd_read) {
|
||||
env_write=env_name;
|
||||
if (*cmd_read=='%') {
|
||||
cmd_read++;
|
||||
if (cmd_read[0] == '%') {
|
||||
cmd_read++;
|
||||
*cmd_write++='%';
|
||||
continue;
|
||||
}
|
||||
if (cmd_read[0] == '0') { /* Handle %0 */
|
||||
const char *file_name = cmd->GetFileName();
|
||||
cmd_read++;
|
||||
strcpy(cmd_write,file_name);
|
||||
cmd_write+=strlen(file_name);
|
||||
continue;
|
||||
}
|
||||
char next = cmd_read[0];
|
||||
if(next > '0' && next <= '9') {
|
||||
/* Handle %1 %2 .. %9 */
|
||||
cmd_read++; //Progress reader
|
||||
next -= '0';
|
||||
if (cmd->GetCount()<(unsigned int)next) continue;
|
||||
std::string word;
|
||||
if (!cmd->FindCommand(next,word)) continue;
|
||||
strcpy(cmd_write,word.c_str());
|
||||
cmd_write+=strlen(word.c_str());
|
||||
continue;
|
||||
} else {
|
||||
/* Not a command line number has to be an environment */
|
||||
char * first=strchr(cmd_read,'%');
|
||||
/* No env afterall.Somewhat of a hack though as %% and % aren't handled consistent in dosbox. Maybe echo needs to parse % and %% as well. */
|
||||
if (!first) {*cmd_write++ = '%';continue;}
|
||||
*first++ = 0;
|
||||
std::string env;
|
||||
if (shell->GetEnvStr(cmd_read,env)) {
|
||||
const char * equals=strchr(env.c_str(),'=');
|
||||
if (!equals) continue;
|
||||
equals++;
|
||||
strcpy(cmd_write,equals);
|
||||
cmd_write+=strlen(equals);
|
||||
}
|
||||
cmd_read=first;
|
||||
}
|
||||
} else {
|
||||
*cmd_write++=*cmd_read++;
|
||||
}
|
||||
}
|
||||
*cmd_write=0;
|
||||
//Store current location and close bat file
|
||||
this->location = 0;
|
||||
DOS_SeekFile(file_handle,&(this->location),DOS_SEEK_CUR);
|
||||
DOS_CloseFile(file_handle);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BatchFile::Goto(char * where) {
|
||||
//Open bat file and search for the where string
|
||||
if (!DOS_OpenFile(filename.c_str(),128,&file_handle)) {
|
||||
LOG(LOG_MISC,LOG_ERROR)("SHELL:Goto Can't open BatchFile %s",filename.c_str());
|
||||
delete this;
|
||||
return false;
|
||||
}
|
||||
|
||||
char cmd_buffer[CMD_MAXLINE];
|
||||
char * cmd_write;
|
||||
|
||||
/* Scan till we have a match or return false */
|
||||
Bit8u c;Bit16u n;
|
||||
again:
|
||||
cmd_write=cmd_buffer;
|
||||
do {
|
||||
n=1;
|
||||
DOS_ReadFile(file_handle,&c,&n);
|
||||
if (n>0) {
|
||||
if (c>31)
|
||||
*cmd_write++=c;
|
||||
}
|
||||
} while (c!='\n' && n);
|
||||
*cmd_write++ = 0;
|
||||
char *nospace = trim(cmd_buffer);
|
||||
if (nospace[0] == ':') {
|
||||
nospace++; //Skip :
|
||||
//Strip spaces and = from it.
|
||||
while(*nospace && (isspace(*reinterpret_cast<unsigned char*>(nospace)) || (*nospace == '=')))
|
||||
nospace++;
|
||||
|
||||
//label is until space/=/eol
|
||||
char* const beginlabel = nospace;
|
||||
while(*nospace && !isspace(*reinterpret_cast<unsigned char*>(nospace)) && (*nospace != '='))
|
||||
nospace++;
|
||||
|
||||
*nospace = 0;
|
||||
if (strcasecmp(beginlabel,where)==0) {
|
||||
//Found it! Store location and continue
|
||||
this->location = 0;
|
||||
DOS_SeekFile(file_handle,&(this->location),DOS_SEEK_CUR);
|
||||
DOS_CloseFile(file_handle);
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
if (!n) {
|
||||
DOS_CloseFile(file_handle);
|
||||
delete this;
|
||||
return false;
|
||||
}
|
||||
goto again;
|
||||
return false;
|
||||
}
|
||||
|
||||
void BatchFile::Shift(void) {
|
||||
cmd->Shift(1);
|
||||
}
|
||||
/*
|
||||
* Copyright (C) 2002-2009 The DOSBox Team
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/* $Id: shell_batch.cpp,v 1.36 2009-07-03 19:36:56 qbix79 Exp $ */
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "shell.h"
|
||||
#include "support.h"
|
||||
|
||||
BatchFile::BatchFile(DOS_Shell * host,char const * const name, char const * const cmd_line) {
|
||||
location = 0;
|
||||
prev=host->bf;
|
||||
echo=host->echo;
|
||||
shell=host;
|
||||
char totalname[DOS_PATHLENGTH+4];
|
||||
DOS_Canonicalize(name,totalname); // Get fullname including drive specificiation
|
||||
cmd = new CommandLine(totalname,cmd_line);
|
||||
filename = totalname;
|
||||
|
||||
//Test if file is openable
|
||||
if (!DOS_OpenFile(totalname,128,&file_handle)) {
|
||||
//TODO Come up with something better
|
||||
E_Exit("SHELL:Can't open BatchFile %s",totalname);
|
||||
}
|
||||
DOS_CloseFile(file_handle);
|
||||
}
|
||||
|
||||
BatchFile::~BatchFile() {
|
||||
delete cmd;
|
||||
shell->bf=prev;
|
||||
shell->echo=echo;
|
||||
}
|
||||
|
||||
bool BatchFile::ReadLine(char * line) {
|
||||
//Open the batchfile and seek to stored postion
|
||||
if (!DOS_OpenFile(filename.c_str(),128,&file_handle)) {
|
||||
LOG(LOG_MISC,LOG_ERROR)("ReadLine Can't open BatchFile %s",filename.c_str());
|
||||
delete this;
|
||||
return false;
|
||||
}
|
||||
DOS_SeekFile(file_handle,&(this->location),DOS_SEEK_SET);
|
||||
|
||||
Bit8u c=0;Bit16u n=1;
|
||||
char temp[CMD_MAXLINE];
|
||||
emptyline:
|
||||
char * cmd_write=temp;
|
||||
do {
|
||||
n=1;
|
||||
DOS_ReadFile(file_handle,&c,&n);
|
||||
if (n>0) {
|
||||
/* Why are we filtering this ?
|
||||
* Exclusion list: tab for batch files
|
||||
* escape for ansi
|
||||
* backspace for alien odyssey */
|
||||
if (c>31 || c==0x1b || c=='\t' || c==8)
|
||||
*cmd_write++=c;
|
||||
}
|
||||
} while (c!='\n' && n);
|
||||
*cmd_write=0;
|
||||
if (!n && cmd_write==temp) {
|
||||
//Close file and delete bat file
|
||||
DOS_CloseFile(file_handle);
|
||||
delete this;
|
||||
return false;
|
||||
}
|
||||
if (!strlen(temp)) goto emptyline;
|
||||
if (temp[0]==':') goto emptyline;
|
||||
|
||||
/* Now parse the line read from the bat file for % stuff */
|
||||
cmd_write=line;
|
||||
char * cmd_read=temp;
|
||||
char env_name[256];char * env_write;
|
||||
while (*cmd_read) {
|
||||
env_write=env_name;
|
||||
if (*cmd_read=='%') {
|
||||
cmd_read++;
|
||||
if (cmd_read[0] == '%') {
|
||||
cmd_read++;
|
||||
*cmd_write++='%';
|
||||
continue;
|
||||
}
|
||||
if (cmd_read[0] == '0') { /* Handle %0 */
|
||||
const char *file_name = cmd->GetFileName();
|
||||
cmd_read++;
|
||||
strcpy(cmd_write,file_name);
|
||||
cmd_write+=strlen(file_name);
|
||||
continue;
|
||||
}
|
||||
char next = cmd_read[0];
|
||||
if(next > '0' && next <= '9') {
|
||||
/* Handle %1 %2 .. %9 */
|
||||
cmd_read++; //Progress reader
|
||||
next -= '0';
|
||||
if (cmd->GetCount()<(unsigned int)next) continue;
|
||||
std::string word;
|
||||
if (!cmd->FindCommand(next,word)) continue;
|
||||
strcpy(cmd_write,word.c_str());
|
||||
cmd_write+=strlen(word.c_str());
|
||||
continue;
|
||||
} else {
|
||||
/* Not a command line number has to be an environment */
|
||||
char * first=strchr(cmd_read,'%');
|
||||
/* No env afterall.Somewhat of a hack though as %% and % aren't handled consistent in dosbox. Maybe echo needs to parse % and %% as well. */
|
||||
if (!first) {*cmd_write++ = '%';continue;}
|
||||
*first++ = 0;
|
||||
std::string env;
|
||||
if (shell->GetEnvStr(cmd_read,env)) {
|
||||
const char * equals=strchr(env.c_str(),'=');
|
||||
if (!equals) continue;
|
||||
equals++;
|
||||
strcpy(cmd_write,equals);
|
||||
cmd_write+=strlen(equals);
|
||||
}
|
||||
cmd_read=first;
|
||||
}
|
||||
} else {
|
||||
*cmd_write++=*cmd_read++;
|
||||
}
|
||||
}
|
||||
*cmd_write=0;
|
||||
//Store current location and close bat file
|
||||
this->location = 0;
|
||||
DOS_SeekFile(file_handle,&(this->location),DOS_SEEK_CUR);
|
||||
DOS_CloseFile(file_handle);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BatchFile::Goto(char * where) {
|
||||
//Open bat file and search for the where string
|
||||
if (!DOS_OpenFile(filename.c_str(),128,&file_handle)) {
|
||||
LOG(LOG_MISC,LOG_ERROR)("SHELL:Goto Can't open BatchFile %s",filename.c_str());
|
||||
delete this;
|
||||
return false;
|
||||
}
|
||||
|
||||
char cmd_buffer[CMD_MAXLINE];
|
||||
char * cmd_write;
|
||||
|
||||
/* Scan till we have a match or return false */
|
||||
Bit8u c;Bit16u n;
|
||||
again:
|
||||
cmd_write=cmd_buffer;
|
||||
do {
|
||||
n=1;
|
||||
DOS_ReadFile(file_handle,&c,&n);
|
||||
if (n>0) {
|
||||
if (c>31)
|
||||
*cmd_write++=c;
|
||||
}
|
||||
} while (c!='\n' && n);
|
||||
*cmd_write++ = 0;
|
||||
char *nospace = trim(cmd_buffer);
|
||||
if (nospace[0] == ':') {
|
||||
nospace++; //Skip :
|
||||
//Strip spaces and = from it.
|
||||
while(*nospace && (isspace(*reinterpret_cast<unsigned char*>(nospace)) || (*nospace == '=')))
|
||||
nospace++;
|
||||
|
||||
//label is until space/=/eol
|
||||
char* const beginlabel = nospace;
|
||||
while(*nospace && !isspace(*reinterpret_cast<unsigned char*>(nospace)) && (*nospace != '='))
|
||||
nospace++;
|
||||
|
||||
*nospace = 0;
|
||||
if (strcasecmp(beginlabel,where)==0) {
|
||||
//Found it! Store location and continue
|
||||
this->location = 0;
|
||||
DOS_SeekFile(file_handle,&(this->location),DOS_SEEK_CUR);
|
||||
DOS_CloseFile(file_handle);
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
if (!n) {
|
||||
DOS_CloseFile(file_handle);
|
||||
delete this;
|
||||
return false;
|
||||
}
|
||||
goto again;
|
||||
return false;
|
||||
}
|
||||
|
||||
void BatchFile::Shift(void) {
|
||||
cmd->Shift(1);
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user