summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDirk-Jan C. Binnema <djcb@djcbsoftware.nl>2025-08-16 20:28:00 +0300
committerDirk-Jan C. Binnema <djcb@djcbsoftware.nl>2025-08-17 12:02:29 +0300
commite56c8489522e1aebb1309a03d460314138cb35dc (patch)
tree816933ac027e7895ea3515136ce7359bad66f392
parent8c706a77db5a2aee6bcc6af53788e35e9805f945 (diff)
scm: support --listen flag for uds
Support the --listen flag to mu scm, to start listening on a Unix domain socket.
-rw-r--r--mu/mu-options.cc5
-rw-r--r--mu/mu-options.hh1
-rw-r--r--scm/meson.build7
-rw-r--r--scm/mu-scm-repl.scm (renamed from scm/mu-scm-shell.scm)12
-rw-r--r--scm/mu-scm-store.cc1
-rw-r--r--scm/mu-scm.cc41
6 files changed, 52 insertions, 15 deletions
diff --git a/mu/mu-options.cc b/mu/mu-options.cc
index 1a11bdb..b91138e 100644
--- a/mu/mu-options.cc
+++ b/mu/mu-options.cc
@@ -632,8 +632,11 @@ sub_server(CLI::App& sub, Options& opts)
static void
sub_scm(CLI::App& sub, Options& opts)
{
+ sub.add_flag("--listen", opts.scm.listen,
+ "Start listening on a domain socket");
sub.add_option("script-path", opts.scm.script_path, "Path to script")
- ->type_name("<path>");
+ ->type_name("<path>")
+ ->excludes("--listen");
sub.add_option("script-args", opts.scm.params, "Parameters for script")
->type_name("<parameters>");
}
diff --git a/mu/mu-options.hh b/mu/mu-options.hh
index ead9ab9..245678d 100644
--- a/mu/mu-options.hh
+++ b/mu/mu-options.hh
@@ -259,6 +259,7 @@ struct Options {
struct Scm {
OptString script_path; /**< Path to script (optional) */
StringVec params; /**< Parameters for script (after "--") */
+ bool listen; /**< Whether to start listening on a socket */
} scm;
diff --git a/scm/meson.build b/scm/meson.build
index f7ef0f7..d0ce391 100644
--- a/scm/meson.build
+++ b/scm/meson.build
@@ -17,8 +17,7 @@ mu_scm_dir=join_paths(datadir, 'mu', 'scm')
mu_scm_dir_arg='-DMU_SCM_DIR="' + mu_scm_dir + '"'
lib_mu_scm=static_library(
- 'mu-scm',
- [
+ 'mu-scm', [
'mu-scm.cc',
'mu-scm-message.cc',
'mu-scm-mime.cc',
@@ -33,7 +32,9 @@ lib_mu_scm=static_library(
install: false,
cpp_args: [mu_scm_dir_arg])
-install_data(['mu-scm.scm', 'mu-scm-shell.scm'], install_dir : mu_scm_dir)
+install_data(['mu-scm.scm',
+ 'mu-scm-repl.scm'],
+ install_dir : mu_scm_dir)
# note: top-level meson.build defines a dummy replacement for this.
mu_scm_dep = declare_dependency(
diff --git a/scm/mu-scm-shell.scm b/scm/mu-scm-repl.scm
index 0efe7f8..9664071 100644
--- a/scm/mu-scm-shell.scm
+++ b/scm/mu-scm-repl.scm
@@ -13,6 +13,16 @@
;; 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+(use-modules (system repl server)
+ (ice-9 threads))
+(use-modules (mu))
+
+;; when a socket path is defined, listen on it (blocking)
+;; after printing UNIX-CONNECT:<socket-file>\n on stdout
+(let ((socket-path (getenv "MU_SCM_SOCKET_PATH")))
+ (when socket-path
+ (format #t "UNIX-CONNECT:~a\n" socket-path)
+ (run-server
+ (make-unix-domain-server-socket #:path socket-path))))
(display "Welcome to the mu shell!\n\n")
-(use-modules (mu))
diff --git a/scm/mu-scm-store.cc b/scm/mu-scm-store.cc
index 44cbcf1..4bf22e2 100644
--- a/scm/mu-scm-store.cc
+++ b/scm/mu-scm-store.cc
@@ -216,7 +216,6 @@ init_subrs()
#pragma GCC diagnostic pop
}
-
void
Mu::Scm::init_store(const Store& store)
{
diff --git a/scm/mu-scm.cc b/scm/mu-scm.cc
index 0a0f4e6..9d460de 100644
--- a/scm/mu-scm.cc
+++ b/scm/mu-scm.cc
@@ -85,7 +85,9 @@ make_mu_scm_path(const std::string& fname) {
namespace {
static std::string mu_scm_path;
-static std::string mu_scm_shell_path;
+static std::string mu_scm_repl_path;
+static std::string mu_scm_socket_path;
+constexpr auto SOCKET_PATH_ENV = "MU_SCM_SOCKET_PATH";
}
static Result<void>
@@ -104,12 +106,11 @@ prepare_run(const Mu::Scm::Config& conf)
else
return Err(path.error());
- if (const auto path = make_mu_scm_path("mu-scm-shell.scm"); path)
- mu_scm_shell_path = *path;
+ if (const auto path = make_mu_scm_path("mu-scm-repl.scm"); path)
+ mu_scm_repl_path = *path;
else
return Err(path.error());
-
if (config->options.scm.script_path) {
const auto path{config->options.scm.script_path->c_str()};
if (const auto res = ::access(path, R_OK); res != 0) {
@@ -121,9 +122,28 @@ prepare_run(const Mu::Scm::Config& conf)
return Ok();
}
-Result<void>
-Mu::Scm::run(const Mu::Scm::Config& conf) {
+// make a unique unix-socket path
+static std::string
+maybe_set_uds_path(bool set)
+{
+ if (set) {
+ GRand* grand{g_rand_new()};
+ auto path = join_paths(g_get_user_runtime_dir(),
+ mu_format("mu-scm-socket-{:08x}",
+ g_rand_int(grand)));
+ g_rand_free(grand);
+ g_setenv(SOCKET_PATH_ENV, path.c_str(), 1);
+ return path;
+ } else {
+ g_unsetenv(SOCKET_PATH_ENV);
+ return {};
+ }
+}
+
+Result<void>
+Mu::Scm::run(const Mu::Scm::Config& conf)
+{
if (const auto res = prepare_run(conf); !res)
return Err(res.error());
@@ -151,10 +171,13 @@ Mu::Scm::run(const Mu::Scm::Config& conf) {
"-c", cmd.c_str()})
args.emplace_back(arg);
} else {
- // otherwise, drop us into an interactive shell/repl (and
- // shell spec)
+ // otherwise, drop us into an interactive shell/repl
+ // or start listening on a domain socket.
+ mu_scm_socket_path =
+ maybe_set_uds_path(config->options.scm.listen);
+ args.emplace_back("--no-auto-compile");
args.emplace_back("-l");
- args.emplace_back(mu_scm_shell_path.c_str());
+ args.emplace_back(mu_scm_repl_path.c_str());
}
/* ahem...*/
scm_shell(std::size(args), const_cast<char**>(args.data()));