init: Support loading awesome with shebang (#!) executables.
This commits re-use the modeline code from the previous commit to support Lua scripts starting with #!. Previously, it was non-trivial to add support since most *nix OS wont parse the command line arguments correctly. Since we now have a state machine good enough for 95%+ of the use case, it is easy to support them.
This commit is contained in:
parent
f1aedb237a
commit
d2f8999595
|
@ -589,8 +589,11 @@ main(int argc, char **argv)
|
||||||
/* Text won't be printed correctly otherwise */
|
/* Text won't be printed correctly otherwise */
|
||||||
setlocale(LC_CTYPE, "");
|
setlocale(LC_CTYPE, "");
|
||||||
|
|
||||||
/* check args */
|
char *confpath = options_detect_shebang(argc, argv);
|
||||||
char *confpath = options_check_args(argc, argv, &default_init_flags, &searchpath);
|
|
||||||
|
/* if no shebang is detected, check the args. Shebang (#!) args are parsed later */
|
||||||
|
if (!confpath)
|
||||||
|
confpath = options_check_args(argc, argv, &default_init_flags, &searchpath);
|
||||||
|
|
||||||
/* Get XDG basedir data */
|
/* Get XDG basedir data */
|
||||||
if(!xdgInitHandle(&xdg))
|
if(!xdgInitHandle(&xdg))
|
||||||
|
|
51
options.c
51
options.c
|
@ -24,6 +24,7 @@
|
||||||
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
#include <getopt.h>
|
#include <getopt.h>
|
||||||
|
|
||||||
#define KEY_VALUE_BUF_MAX 64
|
#define KEY_VALUE_BUF_MAX 64
|
||||||
|
@ -267,6 +268,56 @@ options_init_config(char *execpath, char *configpath, int *init_flags, string_ar
|
||||||
return state == MODELINE_STATE_COMPLETE;
|
return state == MODELINE_STATE_COMPLETE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
char *
|
||||||
|
options_detect_shebang(int argc, char **argv)
|
||||||
|
{
|
||||||
|
/* There is no cross-platform ways to check if it is *really* called by a
|
||||||
|
* shebang. There is a couple Linux specific hacks which work with the
|
||||||
|
* most common C libraries, but they wont work on *BSD.
|
||||||
|
*
|
||||||
|
* On some platforms, the argv is going to be parsed by the OS, in other
|
||||||
|
* they will be concatenated in one big string. There is some ambiguities
|
||||||
|
* caused by that. For example, `awesome -s foo` and and `#!/bin/awesome -s`
|
||||||
|
* are both technically valid if `foo` is a directory in the first and
|
||||||
|
* lua file (without extension) in the second. While `-s` with a file
|
||||||
|
* wont work, it is hard to know by looking at the string.
|
||||||
|
*
|
||||||
|
* The trick to avoid any ambiguity is to just read the file and see if
|
||||||
|
* the args match. `options_init_config` will be called later and the args
|
||||||
|
* will be parsed properly.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* On WSL and some other *nix this isn't true, but it is true often enough */
|
||||||
|
if (argc > 3 || argc == 1)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
/* Check if it is executable */
|
||||||
|
struct stat inf;
|
||||||
|
if (stat(argv[argc-1], &inf) || !(inf.st_mode & S_IXUSR))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
FILE *fp = fopen(argv[argc-1], "r");
|
||||||
|
|
||||||
|
if (!fp)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
char buf[3];
|
||||||
|
|
||||||
|
if (!fgets(buf, 2, fp)) {
|
||||||
|
fclose(fp);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(fp);
|
||||||
|
|
||||||
|
if (!strcmp(buf, "#!"))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
/* Ok, good enough, this is a shebang script, assume it called `awesome` */
|
||||||
|
return a_strdup(argv[argc-1]);
|
||||||
|
}
|
||||||
|
|
||||||
/** Print help and exit(2) with given exit_code.
|
/** Print help and exit(2) with given exit_code.
|
||||||
* \param exit_code The exit code.
|
* \param exit_code The exit code.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -34,5 +34,6 @@ typedef enum {
|
||||||
INIT_FLAG_FORCE_CMD_ARGS = 0x1 << 5,
|
INIT_FLAG_FORCE_CMD_ARGS = 0x1 << 5,
|
||||||
} awesome_init_config_t;
|
} awesome_init_config_t;
|
||||||
|
|
||||||
|
char *options_detect_shebang(int argc, char **argv);
|
||||||
bool options_init_config(char *execpath, char *configpath, int *init_flags, string_array_t *paths);
|
bool options_init_config(char *execpath, char *configpath, int *init_flags, string_array_t *paths);
|
||||||
char *options_check_args(int argc, char **argv, int *init_flags, string_array_t *paths);
|
char *options_check_args(int argc, char **argv, int *init_flags, string_array_t *paths);
|
||||||
|
|
Loading…
Reference in New Issue