Use ByteReader in BatchFile

Abstracts away file management in BatchFile.

Prevents a crash when attempting to read a file without
the necessary permissions.
This commit is contained in:
MeAreJeenius 2023-06-01 00:50:16 -06:00 committed by kcgen
parent 525002e769
commit 039532b95b
4 changed files with 30 additions and 50 deletions

View file

@ -54,7 +54,7 @@ public:
class BatchFile {
public:
BatchFile(DOS_Shell* host, const char* const resolved_name,
BatchFile(DOS_Shell* host, std::unique_ptr<ByteReader> input_reader,
const char* const entered_name, const char* const cmd_line);
BatchFile(const BatchFile&) = delete; // prevent copying
BatchFile& operator=(const BatchFile&) = delete; // prevent assignment
@ -62,17 +62,16 @@ public:
virtual bool ReadLine(char* line);
bool Goto(std::string_view label);
void Shift();
uint16_t file_handle = 0;
uint32_t location = 0;
bool echo = false;
DOS_Shell* shell = nullptr;
std::shared_ptr<BatchFile> prev = {}; // shared with Shell.bf
std::unique_ptr<CommandLine> cmd = {};
std::string filename{};
private:
[[nodiscard]] std::string ExpandedBatchLine(std::string_view line) const;
[[nodiscard]] std::string GetLine();
std::unique_ptr<ByteReader> reader;
};
class AutoexecEditor;

View file

@ -72,13 +72,6 @@ void MOUNT::Move_Z(char new_z)
tempenv += "COMMAND.COM";
first_shell->SetEnv("COMSPEC",tempenv.c_str());
/* Update batch file if running from Z: (very likely: autoexec) */
if (first_shell->bf) {
std::string &name = first_shell->bf->filename;
if (starts_with(name, "Z:")) {
name[0] = new_drive_z;
}
}
/* Change the active drive */
if (DOS_GetDefaultDrive() == 25)
DOS_SetDrive(new_idx);

View file

@ -24,31 +24,19 @@
#include "string_utils.h"
// Permitted ASCII control characters in batch files
constexpr uint8_t Esc = 27;
constexpr uint8_t UnitSeparator = 31;
constexpr char Esc = 27;
constexpr char UnitSeparator = 31;
[[nodiscard]] static bool found_label(std::string_view line, std::string_view label);
BatchFile::BatchFile(DOS_Shell* const host, const char* const resolved_name,
BatchFile::BatchFile(DOS_Shell* const host, std::unique_ptr<ByteReader> input_reader,
const char* const entered_name, const char* const cmd_line)
: echo(host->echo),
shell(host),
prev(host->bf),
cmd(new CommandLine(entered_name, cmd_line))
cmd(new CommandLine(entered_name, cmd_line)),
reader(std::move(input_reader))
{
char totalname[DOS_PATHLENGTH + 4];
// Get fullname including drive specification
if (!DOS_Canonicalize(resolved_name, totalname)) {
E_Exit("SHELL: Can't determine path to batch file %s", resolved_name);
}
filename = totalname;
// Test if file is openable
if (!DOS_OpenFile(totalname, (DOS_NOT_INHERIT | OPEN_READ), &file_handle)) {
shell->WriteOut("SHELL: Can't open BatchFile %s\n", totalname);
}
DOS_CloseFile(file_handle);
}
BatchFile::~BatchFile()
@ -87,25 +75,19 @@ bool BatchFile::ReadLine(char* lineout)
std::string BatchFile::GetLine()
{
if (!DOS_OpenFile(filename.c_str(), (DOS_NOT_INHERIT | OPEN_READ), &file_handle)) {
LOG(LOG_MISC, LOG_ERROR)
("ReadLine Can't open BatchFile %s", filename.c_str());
return "";
}
DOS_SeekFile(file_handle, &(this->location), DOS_SEEK_SET);
uint8_t data = 0;
uint16_t bytes_read = 1;
std::string line = {};
char data = 0;
std::string line = {};
while (data != '\n') {
DOS_ReadFile(file_handle, &data, &bytes_read);
const auto result = reader->Read();
// EOF
if (bytes_read == 0) {
if (!result) {
break;
}
data = *result;
/* Inclusion criteria:
* - backspace for alien odyssey
* - tab for batch files
@ -117,14 +99,10 @@ std::string BatchFile::GetLine()
data,
data);
} else {
line += static_cast<char>(data);
line += data;
}
}
this->location = 0;
DOS_SeekFile(file_handle, &(this->location), DOS_SEEK_CUR);
DOS_CloseFile(file_handle);
return line;
}
@ -175,7 +153,7 @@ std::string BatchFile::ExpandedBatchLine(std::string_view line) const
bool BatchFile::Goto(const std::string_view label)
{
std::string line = " ";
this->location = 0;
reader->Reset();
while (!line.empty()) {
line = GetLine();

View file

@ -21,9 +21,11 @@
#include <algorithm>
#include <cstring>
#include <memory>
#include "../ints/int10.h"
#include "callback.h"
#include "file_reader.h"
#include "keyboard.h"
#include "regs.h"
#include "string_utils.h"
@ -468,11 +470,19 @@ bool DOS_Shell::Execute(std::string_view name, std::string_view args)
if (bf && !call) {
bf.reset();
}
bf = std::make_shared<BatchFile>(this,
fullname.c_str(),
std::string(name).c_str(),
std::string(args).c_str());
auto reader = FileReader::GetFileReader(fullname);
if (reader) {
bf = std::make_shared<BatchFile>(this,
std::move(*reader),
std::string(name).c_str(),
std::string(args).c_str());
} else {
WriteOut("Could not open %s", fullname.c_str());
}
echo = temp_echo;
return true;
}