load argv[1] as script and remove default paths
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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;
|
||||
fprintf(stderr, "ERROR: getcwd: %s\n", strerror(errno));
|
||||
return 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);
|
||||
path = formatted_buffer("%s/%s", cwd, relative_path);
|
||||
}
|
||||
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);
|
||||
fprintf(stderr, "ERROR: Script '%s' is not readable.\n", path);
|
||||
free(path);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
if ( path != NULL )
|
||||
free(path);
|
||||
|
||||
fputs("ERROR: No script found.\n", stderr);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
Reference in New Issue
Block a user