load argv[1] as script and remove default paths

This commit is contained in:
Leon Henrik Plickat
2024-01-08 13:04:12 +01:00
parent 4ae3654e35
commit b31a4f91a2
2 changed files with 61 additions and 61 deletions

View File

@@ -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

View File

@@ -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