Skip to content

Commit

Permalink
Polish: install script, run stdin, global state option
Browse files Browse the repository at this point in the history
  • Loading branch information
rootmos committed Oct 2, 2023
1 parent 3839f06 commit 01db6c8
Show file tree
Hide file tree
Showing 5 changed files with 185 additions and 70 deletions.
12 changes: 8 additions & 4 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
export DESTDIR ?= $(HOME)/.local

.PHONY: build
build:
$(MAKE) -C src build

.PHONY: install
install: build
install src/cli.exe $(HOME)/.local/bin/displayswitcheroo2
install -D data/displayswitcheroo/list.lua $(HOME)/.local/share/displayswitcheroo/list.lua
install -D data/displayswitcheroo/displayswitcheroo.lua $(HOME)/.local/share/displayswitcheroo/displayswitcheroo.lua
install:
./install.sh

.PHONY: clean
clean:
$(MAKE) -C src clean
42 changes: 42 additions & 0 deletions install.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
#!/bin/bash

set -o nounset -o pipefail -o errexit

SCRIPT_DIR=$(readlink -f "$0" | xargs dirname)

usage() {
cat <<EOF 1>&2
Usage: $(basename "$0") [options]
Options:
-h show this message
-d DESTDIR set DESTDIR
-u user installation: DESTDIR=~/.local
-s systemwide installation: DESTDIR=/usr
-a APP application name
EOF
exit "${1-0}"
}

DESTDIR=${DESTDIR-$HOME/.local}
APP=${APP-displayswitcheroo}
while getopts "dusah-" OPT; do
case $OPT in
d) DESTDIR=$OPTARG ;;
u) DESTDIR=$HOME/.local ;;
s) DESTDIR=/usr ;;
a) APP=$OPTARG ;;
h) usage ;;
-) break ;;
?) usage 2 ;;
esac
done
shift $((OPTIND-1))

make -C "$SCRIPT_DIR" clean build EXTRA_CFLAGS="-DXDG_APP='\"$APP\"'"

mkdir -pm 0700 "$DESTDIR/bin"
install -v "$SCRIPT_DIR/src/cli.exe" "$DESTDIR/bin/$APP"

mkdir -pm 0700 "$DESTDIR/share/$APP"
install -v -D "$SCRIPT_DIR/data/displayswitcheroo/list.lua" "$DESTDIR/share/$APP/list.lua"
install -v -D "$SCRIPT_DIR/data/displayswitcheroo/displayswitcheroo.lua" "$DESTDIR/share/$APP/$APP.lua"
2 changes: 1 addition & 1 deletion src/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ build: cli.exe x11.so
SRC = x11.c edid.c r.c

cli.exe: cli.c version.c wait.c $(SRC)
$(CC) $(CFLAGS) $(READLINE_CFLAGS) -o$@ $^ $(LDFLAGS) $(READLINE_LDFLAGS)
$(CC) $(CFLAGS) $(EXTRA_CFLAGS) $(READLINE_CFLAGS) -o$@ $^ $(LDFLAGS) $(READLINE_LDFLAGS) $(EXTRA_LDFLAGS)

x11.so: $(SRC)
$(CC) -rdynamic -fPIC -shared $(CFLAGS) -o$@ $^ $(LDFLAGS)
Expand Down
194 changes: 130 additions & 64 deletions src/cli.c
Original file line number Diff line number Diff line change
Expand Up @@ -166,11 +166,93 @@ static int add_xdg_to_search_paths(lua_State* L)
luaR_return(L, 0);
}

static lua_State* new_lua_state(void)
{
lua_State* L = luaL_newstate();
CHECK_NOT(L, NULL, "unable to create Lua state");

openlibs(L);
add_xdg_to_search_paths(L);

return L;
}

static const char* resolve_script(const char* script)
{
if(script == NULL) return NULL;

debug("trying to resolve as path: %s", script);
struct stat st;
if(stat(script, &st) == 0) {
return script;
}

// config
debug("trying to resolve relative to XDG config dirs: %s", script);
const char* p = xdg_resolves(xdg, XDG_CONFIG, script, NULL);
if(p) return p;

static char buf[NAME_MAX];
int r = snprintf(LIT(buf), "%s.lua", script);
if(r >= sizeof(buf)) failwith("buffer overflow");
debug("trying to resolve relative to XDG config dirs: %s", buf);
p = xdg_resolves(xdg, XDG_CONFIG, buf, NULL);
if(p) return p;


// data
debug("trying to resolve relative to XDG data dirs: %s", script);
p = xdg_resolves(xdg, XDG_DATA, script, NULL);
if(p) return p;

r = snprintf(LIT(buf), "%s.lua", script);
if(r >= sizeof(buf)) failwith("buffer overflow");

debug("trying to resolve relative to XDG data dirs: %s", buf);
p = xdg_resolves(xdg, XDG_DATA, buf, NULL);
if(p) return p;

// path
debug("trying to resolve as path: %s", buf);
if(stat(buf, &st) == 0) {
return buf;
}

dprintf(2, "unable to resolve script: %s\n", script);
exit(1);
}

static char* collect_fd(int fd, size_t* len)
{
size_t l = 0, L = 4096;
char* buf = malloc(L);
CHECK_MALLOC(buf);

for(;;) {
int r = read(fd, &buf[l], L-l);
CHECK(r, "read(%d)", 0);
l += r;
if(r == 0) {
if(len) {
*len = l;
}
return buf;
}

if(l >= L) {
L <<= 1;
buf = realloc(buf, L);
CHECK_MALLOC(buf);
}
}
}

struct options {
const char* script;
int interact;
int wait;
int once;
int global;
};

static void print_usage(int fd)
Expand All @@ -181,6 +263,7 @@ static void print_usage(int fd)
dprintf(fd, " -i enter interactive mode after executing SCRIPT\n");
dprintf(fd, " -w wait for output connect/disconnects\n");
dprintf(fd, " -1 run once before waiting\n");
dprintf(fd, " -g keep global state between runs\n");
dprintf(fd, " -h print this message\n");
dprintf(fd, " -v print version information\n");
}
Expand All @@ -192,7 +275,7 @@ static void parse_options(struct options* o, int argc, char* argv[])
memset(o, 0, sizeof(*o));

int res;
while((res = getopt(argc, argv, "iw1hv")) != -1) {
while((res = getopt(argc, argv, "iw1ghv")) != -1) {
switch(res) {
case 'i':
o->interact = 1;
Expand All @@ -203,6 +286,9 @@ static void parse_options(struct options* o, int argc, char* argv[])
case '1':
o->once = 1;
break;
case 'g':
o->global = 1;
break;
case 'v':
print_version(progname);
exit(0);
Expand All @@ -218,69 +304,36 @@ static void parse_options(struct options* o, int argc, char* argv[])
}
}

static const char* resolve_script(const struct options* o)
{
if(o->script == NULL) return NULL;

debug("trying to resolve as path: %s", o->script);
struct stat st;
if(stat(o->script, &st) == 0) {
return o->script;
}

// config
debug("trying to resolve relative to XDG config dirs: %s", o->script);
const char* p = xdg_resolves(xdg, XDG_CONFIG, o->script, NULL);
if(p) return p;

static char buf[NAME_MAX];
int r = snprintf(LIT(buf), "%s.lua", o->script);
if(r >= sizeof(buf)) failwith("buffer overflow");
debug("trying to resolve relative to XDG config dirs: %s", buf);
p = xdg_resolves(xdg, XDG_CONFIG, buf, NULL);
if(p) return p;


// data
debug("trying to resolve relative to XDG data dirs: %s", o->script);
p = xdg_resolves(xdg, XDG_DATA, o->script, NULL);
if(p) return p;

r = snprintf(LIT(buf), "%s.lua", o->script);
if(r >= sizeof(buf)) failwith("buffer overflow");
struct state {
struct options o;

debug("trying to resolve relative to XDG data dirs: %s", buf);
p = xdg_resolves(xdg, XDG_DATA, buf, NULL);
if(p) return p;
const char* script;

// path
debug("trying to resolve as path: %s", buf);
if(stat(buf, &st) == 0) {
return buf;
}
char* stdin_buf;
size_t stdin_len;

dprintf(2, "unable to resolve script: %s\n", o->script);
exit(1);
}
lua_State* L0;
};

void run(const struct options* o)
static void run(struct state* st)
{
const char* script = resolve_script(o);
if(script) {
debug("resolved script: %s", script);
}

lua_State* L = luaL_newstate();
CHECK_NOT(L, NULL, "unable to create Lua state");
lua_State* L = st->L0 ? st->L0 : new_lua_state();

openlibs(L);
add_xdg_to_search_paths(L);
if(st->script || st->stdin_buf) {
int r;
if(st->script) {
info("running script: %s", st->script);
r = luaL_dofile(L, st->script);
} else {
info("running script from stdin");
r = luaL_loadbuffer(L, st->stdin_buf, st->stdin_len, "stdin");
if(r == LUA_OK) {
r = lua_pcall(L, 0, LUA_MULTRET, 0);
}
}

if(script) {
info("running script: %s", script);
int r = luaL_dofile(L, script);
if(r == LUA_OK) {
if(o->interact) {
if(st->o.interact) {
run_repl(L);
}
} else {
Expand All @@ -292,23 +345,36 @@ void run(const struct options* o)
run_repl(L);
}

lua_close(L);
if(!st->L0) {
lua_close(L);
}
}

int main(int argc, char* argv[])
{
struct options o;
parse_options(&o, argc, argv);
struct state st;
memset(&st, 0, sizeof(st));
parse_options(&st.o, argc, argv);

st.L0 = st.o.global ? new_lua_state() : NULL;

xdg_init();

if(o.wait) {
if(o.once) {
run(&o);
if(st.o.script) {
if(strcmp(st.o.script, "-") == 0) {
st.stdin_buf = collect_fd(0, &st.stdin_len);
} else {
st.script = resolve_script(st.o.script);
}
}

if(st.o.wait) {
if(st.o.once) {
run(&st);
}
run_wait_loop((void(*)(void*))run, &o);
run_wait_loop((void(*)(void*))run, &st);
} else {
run(&o);
run(&st);
}

xdg_deinit();
Expand Down
5 changes: 4 additions & 1 deletion tools/common.makefile
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,12 @@ VERSION ?= $(TOOLS)/version
CC = gcc
PKG_CONFIG ?= pkg-config

CFLAGS ?= -Wall -Werror -O2
CFLAGS ?= -Wall -Werror -O1
LDFLAGS ?=

EXTRA_CFLAGS ?=
EXTRA_LDFLAGS ?=

LOG_LEVEL ?= INFO
CFLAGS += -DLOG_LEVEL=LOG_$(LOG_LEVEL)

Expand Down

0 comments on commit 01db6c8

Please sign in to comment.