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 */
|
||||
setlocale(LC_CTYPE, "");
|
||||
|
||||
/* check args */
|
||||
char *confpath = options_check_args(argc, argv, &default_init_flags, &searchpath);
|
||||
char *confpath = options_detect_shebang(argc, argv);
|
||||
|
||||
/* 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 */
|
||||
if(!xdgInitHandle(&xdg))
|
||||
|
|
51
options.c
51
options.c
|
@ -24,6 +24,7 @@
|
|||
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/stat.h>
|
||||
#include <getopt.h>
|
||||
|
||||
#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;
|
||||
}
|
||||
|
||||
|
||||
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.
|
||||
* \param exit_code The exit code.
|
||||
*/
|
||||
|
|
|
@ -34,5 +34,6 @@ typedef enum {
|
|||
INIT_FLAG_FORCE_CMD_ARGS = 0x1 << 5,
|
||||
} 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);
|
||||
char *options_check_args(int argc, char **argv, int *init_flags, string_array_t *paths);
|
||||
|
|
Loading…
Reference in New Issue