diff --git a/python/common/src/rascsi/sys_cmds.py b/python/common/src/rascsi/sys_cmds.py
index 46971d8a..2432dfbe 100644
--- a/python/common/src/rascsi/sys_cmds.py
+++ b/python/common/src/rascsi/sys_cmds.py
@@ -181,3 +181,15 @@ class SysCmds:
return process.returncode, process.stdout.decode("utf-8")
return process.returncode, process.stderr.decode("utf-8")
+
+ @staticmethod
+ def get_filecontents(file_path):
+ """
+ Takes (str) file_path, with the path to the file to fetch the contents of.
+ Returns either the file contents, or the exception error.
+ """
+ try:
+ with open(file_path) as file:
+ return 0, file.read()
+ except Exception as error:
+ return 1, error
diff --git a/python/web/src/templates/base.html b/python/web/src/templates/base.html
index e8a21057..eeb51247 100644
--- a/python/web/src/templates/base.html
+++ b/python/web/src/templates/base.html
@@ -89,7 +89,7 @@
{% block content %}{% endblock content %}
diff --git a/python/web/src/templates/index.html b/python/web/src/templates/index.html
index ed53f90d..01e2494b 100644
--- a/python/web/src/templates/index.html
+++ b/python/web/src/templates/index.html
@@ -171,7 +171,7 @@
- {{ _("Manage image files in the active RaSCSI image directory: %(directory)s with a scan depth of %(scan_depth)s.", directory=base_dir, scan_depth=scan_depth) }}
- - {{ _("Select a valid SCSI ID and LUN to attach to. Unless you know what you're doing, always use LUN 0.", url="https://en.wikipedia.org/wiki/Logical_unit_number") }}
+
- {{ _("Select a valid SCSI ID and LUN to attach to. Unless you know what you're doing, always use LUN 0.", url="https://en.wikipedia.org/wiki/Logical_unit_number") }}
- {{ _("If RaSCSI was unable to detect the media type associated with the image, you get to choose the type from the dropdown.") }}
-
@@ -348,17 +348,17 @@
- {{ _("Please configure the rascsi_bridge network bridge before attaching an emulated network adapter!") }}
{% endif %}
- {{ _("If you have a DHCP setup, choose only the interface you have configured the bridge with. You can ignore the inet field when attaching.") }}
- - {{ _("To browse the modern web, install a vintage web proxy such as Macproxy.", url="https://github.com/akuker/RASCSI/wiki/Vintage-Web-Proxy#macproxy") }}
+ - {{ _("To browse the modern web, install a vintage web proxy such as Macproxy.", url="https://github.com/akuker/RASCSI/wiki/Vintage-Web-Proxy#macproxy") }}
- {{ _("Read more about supported device types on the wiki.", url="https://github.com/akuker/RASCSI/wiki/Supported-Device-Types") }}
+ {{ _("Read more about supported device types on the wiki.", url="https://github.com/akuker/RASCSI/wiki/Supported-Device-Types") }}
{{ _("Device") }} |
- {{ _("Code") }} |
+ {{ _("Key") }} |
{{ _("Parameters and Actions") }} |
{% for type in REMOVABLE_DEVICE_TYPES + PERIPHERAL_DEVICE_TYPES %}
@@ -442,7 +442,7 @@
- {{ _("The largest file size accepted in this form is %(max_file_size)s MiB. Use other file transfer means for larger files.", max_file_size=max_file_size) }}
- {{ _("File uploads will progress only if you stay on this page. If you navigate away before the transfer is completed, you will end up with an incomplete file.") }}
- - {{ _("Install Netatalk to use the AFP File Server.", url="https://github.com/akuker/RASCSI/wiki/AFP-File-Sharing") }}
+ - {{ _("Install Netatalk to use the AFP File Server.", url="https://github.com/akuker/RASCSI/wiki/AFP-File-Sharing") }}
@@ -498,7 +498,7 @@
- {{ _("Choose the desination directory and download a file from the Web to your Raspberry Pi.") }}
- - {{ _("Install Netatalk to use the AFP File Server.", url="https://github.com/akuker/RASCSI/wiki/AFP-File-Sharing") }}
+ - {{ _("Install Netatalk to use the AFP File Server.", url="https://github.com/akuker/RASCSI/wiki/AFP-File-Sharing") }}
@@ -579,11 +579,7 @@
{{ _("Create Empty Disk Image File") }}
- - {{ _("The Generic Hard Disk image type is recommended for most computer platforms.") }}
- - {{ _("The Apple image type improves compatibility with Apple Macintosh computers.") }}
- - {{ _("The NEC image type improves compatibility with NEC PC-98 computers.") }}
- - {{ _("The SCSI-1 image type makes RaSCSI behave like a legacy SCSI-1 device, which may improve compatibility with very old SCSI controllers.") }}
- - {{ _("The Removable Disk image type can be used with SCSI floppy drives, SyQuest drives, Zip drives, etc.") }}
+ - {{ _("Please refer to wiki documentation to learn more about the supported image file types.", url="https://github.com/akuker/RASCSI/wiki/Supported-Device-Types#image-types") }}
diff --git a/python/web/src/templates/manpage.html b/python/web/src/templates/manpage.html
new file mode 100644
index 00000000..9b79ac96
--- /dev/null
+++ b/python/web/src/templates/manpage.html
@@ -0,0 +1,8 @@
+{% extends "base.html" %}
+
+{% block content %}
+{{ _("Manual for %(app)s:", app=app) }}
+{{ manpage }}
+{{ _("Go to Home") }}
+
+{% endblock content %}
diff --git a/python/web/src/web.py b/python/web/src/web.py
index 0d8785ac..386929ab 100644
--- a/python/web/src/web.py
+++ b/python/web/src/web.py
@@ -57,6 +57,7 @@ from web_utils import (
upload_with_dropzonejs,
)
from settings import (
+ WEB_DIR,
AFP_DIR,
MAX_FILE_SIZE,
DEFAULT_CONFIG,
@@ -487,6 +488,45 @@ def show_diskinfo():
)
+@APP.route("/sys/manpage", methods=["GET"])
+def show_manpage():
+ """
+ Displays manpage
+ """
+ app_allowlist = ["rascsi", "rasctl", "rasdump", "scsimon"]
+
+ app = request.args.get("app", type = str)
+
+ if app not in app_allowlist:
+ return response(
+ error=True,
+ message=_("%(app)s is not a recognized RaSCSI app", app=app)
+ )
+
+ server_info = ractl_cmd.get_server_info()
+ file_path = f"{WEB_DIR}/../../../doc/{app}_man_page.txt"
+
+ returncode, manpage = sys_cmd.get_filecontents(file_path)
+ if returncode == 0:
+ formatted_manpage = ""
+ for line in manpage.splitlines(True):
+ # Strip out irrelevant header
+ if not line.startswith("!!"):
+ formatted_manpage += line
+
+ return response(
+ template="manpage.html",
+ app=app,
+ manpage=formatted_manpage,
+ version=server_info["version"],
+ )
+
+ return response(
+ error=True,
+ message=_("An error occurred when accessing man page: %(error)s", error=manpage)
+ )
+
+
@APP.route("/logs/show", methods=["POST"])
def show_logs():
"""
diff --git a/python/web/tests/api/test_misc.py b/python/web/tests/api/test_misc.py
index b1084bcc..a88a7243 100644
--- a/python/web/tests/api/test_misc.py
+++ b/python/web/tests/api/test_misc.py
@@ -95,3 +95,11 @@ def test_create_image_with_properties_file(http_client, delete_file):
# Cleanup
delete_file(file_name)
+
+# route("/sys/manpage", methods=["POST"])
+def test_show_manpage(http_client):
+ response = http_client.get("/sys/manpage?app=rascsi")
+ response_data = response.json()
+
+ assert response.status_code == 200
+ assert "rascsi" in response_data["data"]["manpage"]