]> rt3x.de gitolite Repositories - bbs.git/commitdiff
✨ Multiple new features for mfingerd to get ready for the SmolWeb main
authorMalte Bublitz <malte@rolltreppe3.de>
Thu, 22 Jan 2026 13:20:42 +0000 (14:20 +0100)
committerMalte Bublitz <malte@rolltreppe3.de>
Thu, 22 Jan 2026 13:25:21 +0000 (14:25 +0100)
bbs/mfingerd.py
bin/finger-inetd
bin/qotd.py [new file with mode: 0755]
finger-smallweb/README.txt [new file with mode: 0644]
finger-smallweb/rfcs/rfc1149.txt [new file with mode: 0644]

index 9d39ec08880407030941dcc7b369abe2ae01c6c5..f542752684fa30ab8aad814d448abaddc49b5858 100644 (file)
@@ -64,7 +64,7 @@ def fingerinfo(username, client=None):
        # Replace placeholders like %%IP%% or %%BOFH%%.
        info = replace_placeholders(info, client)
 
-       print(info)
+       return info
 
 
 class FingerHandler(socketserver.StreamRequestHandler):
index c37c603dd7422046c0b2c11aa0c532be49cfdf7e..ec9d44e9558bc719269157929685e0624c169071 100755 (executable)
@@ -9,13 +9,26 @@
 
 import os
 import sys
+import glob
 
+
+# 
+# Add the Git project root to Python's sys.path,
+# and make it the current working directory.
+# 
+# When invoked by inetd, this is required for all
+# code find below these lines.
+# 
 BBS = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
 sys.path.insert(0, BBS)
 os.chdir(BBS)
 
+
+# Now we can import mfingerd
 import bbs.mfingerd
 
+
+# 
 try:
        username = sys.stdin.readline().strip()
 except UnicodeDecodeError:
@@ -23,6 +36,10 @@ except UnicodeDecodeError:
        print("???")
        sys.exit(0)
 
+# 
+# inetd passes the client IP to us using an environment
+# variable
+# 
 remote_ip = os.getenv("TCPREMOTEIP", None)
 
 
@@ -35,5 +52,98 @@ for env in sorted(list(os.environ.keys())):
 # }}}"""
 
 
-bbs.mfingerd.fingerinfo(username, remote_ip)
+# 
+# rfc/ - Serve some selected RFCs in plain text format
+# 
+RFC_PATH = "/opt/bbs/finger-smallweb/rfcs"
+HOSTNAME = "giesskanne.flachbaum.de"
+
+def get_rfc_filenames_sorted(rfc_path: str, glob_expression = "rfc*.txt"):
+       rfc_files = glob.glob(os.path.join(rfc_path, glob_expression))
+       rfc_files = sorted(
+               rfc_files,
+               key = lambda x: int(
+                       x.split("/")[-1].replace("rfc","").replace(".txt","")
+               )
+       )
+       return rfc_files
+
+
+if username.split("/")[0] == "rfc":
+       rfc_id = username.rstrip("/").split("/")
+       if len(rfc_id) > 1:
+               rfc_id = rfc_id[1]
+       else:
+               rfc_id = "-1"
+
+       try:
+               if str(int(rfc_id)) != rfc_id:
+                       print("rfc :: Invalid RFC ID!")
+                       sys.exit(0)
+       except:
+               print("EXCEPTION")
+               sys.exit(0)
+
+       if int(rfc_id) >= 1:
+               rfc_file = os.path.join(
+                       RFC_PATH,
+                       "rfc" + str(int(rfc_id)) + ".txt"
+               )
+
+               if not os.path.exists(rfc_file):
+                       print("RFC " + rfc_id + " now available yet on this service.")
+                       sys.exit(0)
+
+               with open(rfc_file) as rfc:
+                       contents = ""
+                       for l in rfc.readlines():
+                               l = l.rstrip("\n").replace("\x0c", "\n\n\n\n\n")
+                               contents += l + "\n"
+
+       else:
+               contents = ""
+               contents += "List of RFCs viewable on this server:\n"
+               contents += "\n"
+
+               for rfc_file in get_rfc_filenames_sorted(RFC_PATH):
+                       rfc_id = rfc_file.split("/")[-1].replace("rfc","").replace(".txt","")
+                       contents += "finger://"
+                       contents += HOSTNAME
+                       contents += "/rfc/" + str(rfc_id)
+                       contents += "\n"
+
+               contents += "\n\n"
+               contents += "More documents might be available in the future.\n"
+
+       print(contents)
+
+       sys.exit(0)
+
+
+# 
+# qotd.py - Serve my QOTD client over finger://
+# 
+if username == "qotd.py":
+       script_filename = "bin/qotd.py"
+       try:
+               with open(script_filename, "r") as f:
+                       content = f.read()
+
+       except FileNotFoundError:
+               print("Server Error: File not found.")
+               sys.exit()
+
+       except PermissionError:
+               print("Server Error: Premission denied.")
+               sys.exit()
+
+       print(content)
+       sys.exit()
+
+
+# 
+# Display fingerinfo from database
+# 
+print(bbs.mfingerd.fingerinfo(username, remote_ip))
+
 
diff --git a/bin/qotd.py b/bin/qotd.py
new file mode 100755 (executable)
index 0000000..9a05651
--- /dev/null
@@ -0,0 +1,78 @@
+#!/usr/bin/env python3
+
+__doc__ = """A basic QOTD client.
+
+Use socket.socket to get a qoute of the day
+from a remote server.
+
+Uses my own QOTD server by default, but you
+can set your own hostname and port using
+environment variables:
+
+- $QOTD_HOST
+  - Defaults to "giesskanne.flachbaum.de"
+- $QOTD_PORT
+  - Defaults to 17
+"""
+
+import os
+import sys
+import socket
+
+
+QOTD_HOST = "giesskanne.flachbaum.de"
+QOTD_PORT = 17
+
+
+def get_qotd(
+               remote_addr: tuple[str, int] = (QOTD_HOST, QOTD_PORT),
+               buffer_size: int             = 64,
+               read_limit:  int | None      = 2048
+               ) -> str:
+       """Retrieve a qoute from a QOTD server.
+
+       Args:
+               remote_addr (tuple[str, int]): Remote host and port number.
+
+       Returns:
+               str: The quote recieved from `remote_addr`
+
+       """
+       s = socket.socket(
+               socket.AF_INET,
+               socket.SOCK_STREAM
+       )
+       s.connect(remote_addr)
+
+       qotd = ""
+       while True:
+               data = s.recv(buffer_size)
+               if not data or data is None:
+                       break
+               qotd += data.decode("UTF-8")
+       s.close()
+
+       return qotd
+
+
+def main():
+       # Default host and port from environment variables, falls back to
+       # `QOTD_HOST` and `QOTD_PORT` defined above.
+       qotd_remote_server = (
+               os.getenv("QOTD_HOST", QOTD_HOST),
+               int(os.getenv("QOTD_PORT", QOTD_PORT))
+       )
+       try:
+               print(get_qotd(qotd_remote_server))
+
+       except ConnectionRefusedError:
+               _remote = qotd_remote_server[0] + ":" + str(qotd_remote_server[1])
+               print(f"{os.path.basename(__file__)}: Error: Connection refused "
+                       f"to {_remote}", file=sys.stderr)
+               return 1
+
+       return 0
+
+
+if __name__ == "__main__":
+       sys.exit(main())
diff --git a/finger-smallweb/README.txt b/finger-smallweb/README.txt
new file mode 100644 (file)
index 0000000..e50ac5f
--- /dev/null
@@ -0,0 +1,3 @@
+# Host a finger:// smallweb page using bbs.mfingerd
+
+
diff --git a/finger-smallweb/rfcs/rfc1149.txt b/finger-smallweb/rfcs/rfc1149.txt
new file mode 100644 (file)
index 0000000..a981394
--- /dev/null
@@ -0,0 +1,115 @@
+
+
+
+
+
+
+Network Working Group                                        D. Waitzman
+Request for Comments: 1149                                       BBN STC
+                                                            1 April 1990
+
+
+   A Standard for the Transmission of IP Datagrams on Avian Carriers
+
+Status of this Memo
+
+   This memo describes an experimental method for the encapsulation of
+   IP datagrams in avian carriers.  This specification is primarily
+   useful in Metropolitan Area Networks.  This is an experimental, not
+   recommended standard.  Distribution of this memo is unlimited.
+
+Overview and Rational
+
+   Avian carriers can provide high delay, low throughput, and low
+   altitude service.  The connection topology is limited to a single
+   point-to-point path for each carrier, used with standard carriers,
+   but many carriers can be used without significant interference with
+   each other, outside of early spring.  This is because of the 3D ether
+   space available to the carriers, in contrast to the 1D ether used by
+   IEEE802.3.  The carriers have an intrinsic collision avoidance
+   system, which increases availability.  Unlike some network
+   technologies, such as packet radio, communication is not limited to
+   line-of-sight distance.  Connection oriented service is available in
+   some cities, usually based upon a central hub topology.
+
+Frame Format
+
+   The IP datagram is printed, on a small scroll of paper, in
+   hexadecimal, with each octet separated by whitestuff and blackstuff.
+   The scroll of paper is wrapped around one leg of the avian carrier.
+   A band of duct tape is used to secure the datagram's edges.  The
+   bandwidth is limited to the leg length.  The MTU is variable, and
+   paradoxically, generally increases with increased carrier age.  A
+   typical MTU is 256 milligrams.  Some datagram padding may be needed.
+
+   Upon receipt, the duct tape is removed and the paper copy of the
+   datagram is optically scanned into a electronically transmittable
+   form.
+
+Discussion
+
+   Multiple types of service can be provided with a prioritized pecking
+   order.  An additional property is built-in worm detection and
+   eradication.  Because IP only guarantees best effort delivery, loss
+   of a carrier can be tolerated.  With time, the carriers are self-
+
+
+
+Waitzman                                                        [Page 1]
+\f
+RFC 1149             IP Datagrams on Avian Carriers         1 April 1990
+
+
+   regenerating.  While broadcasting is not specified, storms can cause
+   data loss.  There is persistent delivery retry, until the carrier
+   drops.  Audit trails are automatically generated, and can often be
+   found on logs and cable trays.
+
+Security Considerations
+
+   Security is not generally a problem in normal operation, but special
+   measures must be taken (such as data encryption) when avian carriers
+   are used in a tactical environment.
+
+Author's Address
+
+   David Waitzman
+   BBN Systems and Technologies Corporation
+   BBN Labs Division
+   10 Moulton Street
+   Cambridge, MA 02238
+
+   Phone: (617) 873-4323
+
+   EMail: dwaitzman@BBN.COM
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Waitzman                                                        [Page 2]
+\f
\ No newline at end of file