From b31a4f91a245348690fc9d05c2d0c95cf95143fb Mon Sep 17 00:00:00 2001 From: Leon Henrik Plickat Date: Mon, 8 Jan 2024 13:04:12 +0100 Subject: [PATCH] load argv[1] as script and remove default paths --- doc/riverguile.1 | 34 ++++++++++++------- src/riverguile.c | 88 +++++++++++++++++++++--------------------------- 2 files changed, 61 insertions(+), 61 deletions(-) diff --git a/doc/riverguile.1 b/doc/riverguile.1 index 3a3cc5c..5fcac8b 100644 --- a/doc/riverguile.1 +++ b/doc/riverguile.1 @@ -7,6 +7,7 @@ riverguile \- scheme powered scripting layer for river . .SH SYNOPSIS .SY riverguile +path-to-script .YS . . @@ -17,20 +18,29 @@ Scripting layer for the Wayland server. Allows the user to send commands to the Wayland server (probably river) and install handlers for events from a scheme script. +The sheme implementation is provided by +.BR guile (1). .P -By default, riverguile will exit after the script has been loaded and evaluated. -If certain handlers are installed it will run continously. +The canonical way to use riverguile is as an interpreter for the river init +script. +To do so place the following expression at the very top of your init script: .P -Uppon launch, riverguile tries to load the script from the following paths -in the given order: -.IP \(bu 2 -\fBlayout.scm\fR -.IP \(bu 2 -\fB$XDG_CONFIG_HOME/river/layout.scm\fR -.IP \(bu 2 -\fB$HOME/.config/river/layout.scm\fR -.IP \(bu 2 -\fB/etc/riverguile/layout.scm\fR +.RS +.EX +#!/bin/env riverguile +!# +.EE +.RE +.P +Do not leave out the second line, as the octothorpe plus exlamation-mark +combination indicates a multi-line comment in scheme. +Do not forget to mark your init script as executable. +Your custom scheme code to configure the river session may follow after these +two lines. +.P +By default, riverguile will exit after the script has been loaded. +However if certain handlers are installed it will run continously to provide +that functionality. . . .SH COMMANDS diff --git a/src/riverguile.c b/src/riverguile.c index 53805ee..dd2a4c2 100644 --- a/src/riverguile.c +++ b/src/riverguile.c @@ -255,79 +255,69 @@ static char *formatted_buffer (const char *fmt, ...) return buffer; } -static char *get_script_path (void) +static char *get_script_path (char *relative_path) { - struct { - const char *fmt; - bool needs_env; - const char *env; - } paths[] = { - { .fmt = "layout.scm", .needs_env = false, .env = NULL }, - { .fmt = "%s/riverguile/layout.scm", .needs_env = true, .env = getenv("XDG_CONFIG_HOME") }, - { .fmt = "%s/river/layout.scm", .needs_env = true, .env = getenv("XDG_CONFIG_HOME") }, - { .fmt = "%s/.config/riverguile/layout.scm", .needs_env = true, .env = getenv("HOME") }, - { .fmt = "%s/.config/river/layout.scm", .needs_env = true, .env = getenv("HOME") }, - { .fmt = "/etc/riverguile/layout.scm", .needs_env = false, .env = NULL } - }; + assert(relative_path != NULL); char *path = NULL; - for (size_t i = 0; i < (sizeof(paths) / sizeof(paths[0])); i++) + if ( relative_path[0] == '/' ) + path = formatted_buffer("%s", relative_path); + else { - if ( path != NULL ) + /* When scm_primitive_load_path() receives a relative path, it + * tries to look it up in the guile module path. So we must + * always provide it an absolute path. + */ + char buffer[4 * 1024]; + char *cwd = getcwd(buffer, 4 * 1024); + if ( cwd == NULL ) { - free(path); - path = NULL; - } - - /* Path needs env var, but it is not set. */ - if ( paths[i].needs_env && paths[i].env == NULL ) - continue; - - path = formatted_buffer(paths[i].fmt, paths[i].env); - if ( path == NULL ) - return NULL; - - /* Does the path exist? */ - if ( access(path, F_OK) != 0 ) - continue; - - /* Is it readable? */ - if ( access(path, R_OK) != 0 ) - { - fprintf(stderr, "ERROR: Script '%s' exists, but is not readable.\n", path); - free(path); + fprintf(stderr, "ERROR: getcwd: %s\n", strerror(errno)); return NULL; } - return path; + path = formatted_buffer("%s/%s", cwd, relative_path); + } + if ( path == NULL ) + return NULL; + + if ( access(path, R_OK) != 0 ) + { + fprintf(stderr, "ERROR: Script '%s' is not readable.\n", path); + free(path); + return NULL; } - if ( path != NULL ) - free(path); - - fputs("ERROR: No script found.\n", stderr); - return NULL; + return path; } -int main(int argc, char *argv[]) +int main (int argc, char *argv[]) { + if ( argc != 2 + || strcmp(argv[1], "--help") == 0 + || strcmp(argv[1], "-h") == 0 + || strcmp(argv[1], "-?") == 0 ) + { + fprintf(stderr, "USAGE: %s path-to-script\n", argv[0]); + return EXIT_FAILURE; + } + fputs("INFO: Welcome to riverguile!\n", stderr); signal(SIGSEGV, handle_error); signal(SIGFPE, handle_error); signal(SIGINT, handle_interrupt); - wl_list_init(&context.outputs); - wl_list_init(&context.seats); - - // TODO use argv[1] if present - context.path = get_script_path(); + context.path = get_script_path(argv[1]); if ( context.path == NULL ) { context.ret = EXIT_FAILURE; goto early_exit; } - fprintf(stderr, "INFO: Found script: %s\n", context.path); + fprintf(stderr, "INFO: Using script: %s\n", context.path); + + wl_list_init(&context.outputs); + wl_list_init(&context.seats); /* We query the display name here instead of letting wl_display_connect() * figure it out itself, because libwayland (for legacy reasons) falls