mirror of
https://github.com/NikitaIvanovV/ctpv.git
synced 2025-06-20 18:08:02 +02:00
Add ueberzug support
This commit is contained in:
parent
6a5fb93850
commit
0ab9be934f
12
Makefile
12
Makefile
@ -5,7 +5,7 @@ SRC := $(wildcard *.c)
|
|||||||
OBJ := $(SRC:.c=.o)
|
OBJ := $(SRC:.c=.o)
|
||||||
DEP := $(OBJ:.o=.d)
|
DEP := $(OBJ:.o=.d)
|
||||||
PRE := $(wildcard prev/*.sh)
|
PRE := $(wildcard prev/*.sh)
|
||||||
GEN := gen/prev/scripts.h
|
GEN := gen/prev/scripts.h gen/server.h
|
||||||
|
|
||||||
CFLAGS += -Os -MD -Wall -Wextra -Wno-unused-parameter
|
CFLAGS += -Os -MD -Wall -Wextra -Wno-unused-parameter
|
||||||
LDFLAGS += -lmagic
|
LDFLAGS += -lmagic
|
||||||
@ -17,9 +17,9 @@ options:
|
|||||||
@echo "CFLAGS = $(CFLAGS)"
|
@echo "CFLAGS = $(CFLAGS)"
|
||||||
@echo "LDFLAGS = $(LDFLAGS)"
|
@echo "LDFLAGS = $(LDFLAGS)"
|
||||||
|
|
||||||
install: ctpv
|
install: ctpv ctpvclear
|
||||||
install -d $(BINPREFIX)
|
install -d $(BINPREFIX)
|
||||||
install $< $(BINPREFIX)
|
install $^ $(BINPREFIX)
|
||||||
|
|
||||||
uninstall:
|
uninstall:
|
||||||
$(RM) $(BINPREFIX)/ctpv
|
$(RM) $(BINPREFIX)/ctpv
|
||||||
@ -35,10 +35,14 @@ ctpv: $(OBJ)
|
|||||||
|
|
||||||
ctpv.c: $(GEN)
|
ctpv.c: $(GEN)
|
||||||
|
|
||||||
gen/prev/scripts.h: embed/embed $(PRE)
|
gen/prev/scripts.h: $(PRE) embed/embed helpers.sh
|
||||||
@mkdir -p $(@D)
|
@mkdir -p $(@D)
|
||||||
embed/embed -p prev_scr_ -h helpers.sh $(PRE) > $@
|
embed/embed -p prev_scr_ -h helpers.sh $(PRE) > $@
|
||||||
|
|
||||||
|
gen/server.h: clear.sh end.sh embed/embed helpers.sh
|
||||||
|
@mkdir -p $(@D)
|
||||||
|
embed/embed -p scr_ -h helpers.sh clear.sh end.sh > $@
|
||||||
|
|
||||||
embed/embed: make_embed
|
embed/embed: make_embed
|
||||||
@:
|
@:
|
||||||
|
|
||||||
|
7
clear.sh
Normal file
7
clear.sh
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
fifo="$(get_fifo "$id")"
|
||||||
|
|
||||||
|
[ -e "$fifo" ] || exit 1
|
||||||
|
|
||||||
|
fifo_open "$fifo" && {
|
||||||
|
printf '{"action": "remove", "identifier": "preview"}\n' > "$fifo"
|
||||||
|
}
|
49
ctpv.c
49
ctpv.c
@ -1,10 +1,13 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <magic.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdio.h>
|
#include <signal.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <magic.h>
|
|
||||||
|
|
||||||
#include "error.h"
|
#include "error.h"
|
||||||
|
#include "server.h"
|
||||||
|
#include "preview.h"
|
||||||
#include "previews.h"
|
#include "previews.h"
|
||||||
|
|
||||||
#define ANY_TYPE "*"
|
#define ANY_TYPE "*"
|
||||||
@ -17,10 +20,13 @@ static struct {
|
|||||||
enum {
|
enum {
|
||||||
MODE_PREVIEW,
|
MODE_PREVIEW,
|
||||||
MODE_SERVER,
|
MODE_SERVER,
|
||||||
|
MODE_CLEAR,
|
||||||
|
MODE_END,
|
||||||
MODE_LIST,
|
MODE_LIST,
|
||||||
MODE_MIME,
|
MODE_MIME,
|
||||||
} mode;
|
} mode;
|
||||||
} ctpv = { MODE_PREVIEW };
|
char *server_id_s;
|
||||||
|
} ctpv = { .mode = MODE_PREVIEW };
|
||||||
|
|
||||||
static void cleanup(void) {
|
static void cleanup(void) {
|
||||||
cleanup_previews();
|
cleanup_previews();
|
||||||
@ -108,15 +114,22 @@ static int preview(int argc, char *argv[])
|
|||||||
|
|
||||||
PreviewArgs args = { .f = f, .w = w, .h = h, .x = x, .y = y };
|
PreviewArgs args = { .f = f, .w = w, .h = h, .x = x, .y = y };
|
||||||
|
|
||||||
ERRCHK_RET_OK(run_preview(get_ext(f), mimetype, &args));
|
return run_preview(get_ext(f), mimetype, &args);
|
||||||
|
|
||||||
return OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int server(void)
|
static int server(char const *id_s)
|
||||||
{
|
{
|
||||||
/* TODO */
|
return server_listen(id_s);
|
||||||
return OK;
|
}
|
||||||
|
|
||||||
|
static int clear(void)
|
||||||
|
{
|
||||||
|
return server_clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
static int end(char const *id_s)
|
||||||
|
{
|
||||||
|
return server_end(id_s);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int list(void)
|
static int list(void)
|
||||||
@ -179,10 +192,18 @@ int main(int argc, char *argv[])
|
|||||||
program = argc > 0 ? argv[0] : "ctpv";
|
program = argc > 0 ? argv[0] : "ctpv";
|
||||||
|
|
||||||
int c;
|
int c;
|
||||||
while ((c = getopt(argc, argv, "slm")) != -1) {
|
while ((c = getopt(argc, argv, "s:ce:lm")) != -1) {
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case 's':
|
case 's':
|
||||||
ctpv.mode = MODE_SERVER;
|
ctpv.mode = MODE_SERVER;
|
||||||
|
ctpv.server_id_s = optarg;
|
||||||
|
break;
|
||||||
|
case 'c':
|
||||||
|
ctpv.mode = MODE_CLEAR;
|
||||||
|
break;
|
||||||
|
case 'e':
|
||||||
|
ctpv.mode = MODE_END;
|
||||||
|
ctpv.server_id_s = optarg;
|
||||||
break;
|
break;
|
||||||
case 'l':
|
case 'l':
|
||||||
ctpv.mode = MODE_LIST;
|
ctpv.mode = MODE_LIST;
|
||||||
@ -204,7 +225,13 @@ int main(int argc, char *argv[])
|
|||||||
ret = preview(argc, argv);
|
ret = preview(argc, argv);
|
||||||
break;
|
break;
|
||||||
case MODE_SERVER:
|
case MODE_SERVER:
|
||||||
ret = server();
|
ret = server(ctpv.server_id_s);
|
||||||
|
break;
|
||||||
|
case MODE_CLEAR:
|
||||||
|
ret = clear();
|
||||||
|
break;
|
||||||
|
case MODE_END:
|
||||||
|
ret = end(ctpv.server_id_s);
|
||||||
break;
|
break;
|
||||||
case MODE_LIST:
|
case MODE_LIST:
|
||||||
ret = list();
|
ret = list();
|
||||||
|
6
end.sh
Normal file
6
end.sh
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
fifo="$(get_fifo "$1")"
|
||||||
|
|
||||||
|
[ -e "$fifo" ] || exit 1
|
||||||
|
|
||||||
|
# sending zero byte tells listener to stop
|
||||||
|
fifo_open "$fifo" && printf '\0' > "$fifo"
|
12
error.h
12
error.h
@ -33,12 +33,24 @@
|
|||||||
} \
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
#define ERRCHK_GOTO(cond, ret, label, ...) \
|
||||||
|
do { \
|
||||||
|
if (cond) { \
|
||||||
|
__VA_OPT__(PRINTINTERR(__VA_ARGS__);) \
|
||||||
|
ret = ERR; \
|
||||||
|
goto label; \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Shortcut for ERRCHK_RET(expr != OK)
|
* Shortcut for ERRCHK_RET(expr != OK)
|
||||||
*/
|
*/
|
||||||
#define ERRCHK_RET_OK(expr, ...) \
|
#define ERRCHK_RET_OK(expr, ...) \
|
||||||
ERRCHK_RET((expr) != OK __VA_OPT__(, ) __VA_ARGS__)
|
ERRCHK_RET((expr) != OK __VA_OPT__(, ) __VA_ARGS__)
|
||||||
|
|
||||||
|
#define ERRCHK_GOTO_OK(expr, ...) \
|
||||||
|
ERRCHK_GOTO((expr) != OK __VA_OPT__(, ) __VA_ARGS__)
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
OK,
|
OK,
|
||||||
ERR,
|
ERR,
|
||||||
|
10
helpers.sh
10
helpers.sh
@ -1,3 +1,13 @@
|
|||||||
|
get_fifo() {
|
||||||
|
printf '/tmp/ctpvfifo.%s' "$1"
|
||||||
|
}
|
||||||
|
|
||||||
exists() {
|
exists() {
|
||||||
command -v "$1" > /dev/null
|
command -v "$1" > /dev/null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fifo_open() {
|
||||||
|
# https://unix.stackexchange.com/a/522940/183147
|
||||||
|
dd oflag=nonblock conv=notrunc,nocreat count=0 of="$1" \
|
||||||
|
>/dev/null 2>/dev/null
|
||||||
|
}
|
||||||
|
13
prev/image.sh
Normal file
13
prev/image.sh
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
fifo="$(get_fifo "$id")"
|
||||||
|
|
||||||
|
# tell ctpv to fallback to another preview
|
||||||
|
[ -e "$fifo" ] || exit 127
|
||||||
|
|
||||||
|
path="$(printf '%s' "$f" | sed 's/\\/\\\\/g; s/"/\\"/g')"
|
||||||
|
|
||||||
|
fifo_open "$fifo" && {
|
||||||
|
printf '{ "action": "add", "identifier": "preview", "x": %d, "y": %d, "width": %d, "height": %d, "scaler": "contain", "scaling_position_x": 1, "scaling_position_y": 1, "path": "%s"}\n' "$x" "$y" "$w" "$h" "$path" > "$fifo"
|
||||||
|
}
|
||||||
|
|
||||||
|
# tell lf to disable preview caching
|
||||||
|
exit 1
|
24
preview.c
24
preview.c
@ -3,14 +3,13 @@
|
|||||||
|
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include "error.h"
|
#include "error.h"
|
||||||
|
#include "shell.h"
|
||||||
#include "preview.h"
|
#include "preview.h"
|
||||||
|
|
||||||
#define FAILED_PREVIEW_EC 127
|
#define FAILED_PREVIEW_EC NOTEXIST_EC
|
||||||
|
|
||||||
#define PREVP_SIZE sizeof(Preview *)
|
#define PREVP_SIZE sizeof(Preview *)
|
||||||
|
|
||||||
static char shell[] = "sh";
|
|
||||||
|
|
||||||
static struct {
|
static struct {
|
||||||
size_t len;
|
size_t len;
|
||||||
Preview **list;
|
Preview **list;
|
||||||
@ -119,21 +118,20 @@ static void check_init_previews(void)
|
|||||||
|
|
||||||
static int run(Preview *p, int *exitcode)
|
static int run(Preview *p, int *exitcode)
|
||||||
{
|
{
|
||||||
int pipe_fd[2];
|
int pipe_fds[2];
|
||||||
ERRCHK_RET(pipe(pipe_fd) == -1, FUNCFAILED("pipe"), ERRNOS);
|
ERRCHK_RET(pipe(pipe_fds) == -1, FUNCFAILED("pipe"), ERRNOS);
|
||||||
|
|
||||||
int fd = STDERR_FILENO;
|
int sp_arg[] = { pipe_fds[0], pipe_fds[1], STDERR_FILENO };
|
||||||
int *sp_arg[] = { pipe_fd, &fd };
|
|
||||||
|
|
||||||
char *args[] = { shell, "-c", p->script, shell, NULL };
|
char *args[] = SHELL_ARGS(p->script);
|
||||||
int ret = spawn(args, NULL, exitcode, spawn_redirect, sp_arg);
|
int ret = spawn(args, NULL, exitcode, spawn_redirect, sp_arg);
|
||||||
|
|
||||||
close(pipe_fd[1]);
|
close(pipe_fds[1]);
|
||||||
|
|
||||||
if (*exitcode != FAILED_PREVIEW_EC) {
|
if (*exitcode != FAILED_PREVIEW_EC) {
|
||||||
char buf[CMD_ERR_BUF];
|
char buf[CMD_ERR_BUF];
|
||||||
int len;
|
int len;
|
||||||
while ((len = read(pipe_fd[0], buf, CMD_ERR_BUF)) > 0) {
|
while ((len = read(pipe_fds[0], buf, CMD_ERR_BUF)) > 0) {
|
||||||
write(STDOUT_FILENO, buf, len);
|
write(STDOUT_FILENO, buf, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -143,7 +141,7 @@ static int run(Preview *p, int *exitcode)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
close(pipe_fd[0]);
|
close(pipe_fds[0]);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -176,7 +174,7 @@ run:
|
|||||||
p = find_preview(mimetype, ext, &i);
|
p = find_preview(mimetype, ext, &i);
|
||||||
if (!p) {
|
if (!p) {
|
||||||
puts("ctpv: no previews found");
|
puts("ctpv: no previews found");
|
||||||
return OK;
|
return ERR;
|
||||||
}
|
}
|
||||||
|
|
||||||
ERRCHK_RET_OK(run(p, &exitcode));
|
ERRCHK_RET_OK(run(p, &exitcode));
|
||||||
@ -185,7 +183,7 @@ run:
|
|||||||
goto run;
|
goto run;
|
||||||
}
|
}
|
||||||
|
|
||||||
return OK;
|
return exitcode == 0 ? OK : ERR;
|
||||||
}
|
}
|
||||||
|
|
||||||
Preview **get_previews_list(size_t *len)
|
Preview **get_previews_list(size_t *len)
|
||||||
|
@ -17,4 +17,5 @@ Preview previews[] = {
|
|||||||
PR(NULL, NULL, NULL, any),
|
PR(NULL, NULL, NULL, any),
|
||||||
PR("md", NULL, NULL, markdown),
|
PR("md", NULL, NULL, markdown),
|
||||||
PR(NULL, "application", "json", json),
|
PR(NULL, "application", "json", json),
|
||||||
|
PR(NULL, "image", NULL, image),
|
||||||
};
|
};
|
||||||
|
137
server.c
Normal file
137
server.c
Normal file
@ -0,0 +1,137 @@
|
|||||||
|
#include <poll.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
#include "error.h"
|
||||||
|
#include "utils.h"
|
||||||
|
#include "shell.h"
|
||||||
|
#include "gen/server.h"
|
||||||
|
|
||||||
|
static pid_t ueberzug_pid;
|
||||||
|
|
||||||
|
static void kill_ueberzug(void)
|
||||||
|
{
|
||||||
|
if (kill(ueberzug_pid, SIGTERM) == -1) {
|
||||||
|
if (errno == ESRCH)
|
||||||
|
print_error("ueberzug is not running");
|
||||||
|
else
|
||||||
|
PRINTINTERR(FUNCFAILED("kill"), ERRNOS);
|
||||||
|
}
|
||||||
|
|
||||||
|
spawn_wait(ueberzug_pid, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sig_int_handler(int s)
|
||||||
|
{
|
||||||
|
/* Do nothing */
|
||||||
|
}
|
||||||
|
|
||||||
|
static int listen(int fifo_fd)
|
||||||
|
{
|
||||||
|
int ret = OK;
|
||||||
|
|
||||||
|
ERRCHK_GOTO(signal(SIGINT, sig_int_handler) == SIG_ERR, ret, exit,
|
||||||
|
FUNCFAILED("signal"), ERRNOS);
|
||||||
|
|
||||||
|
int pipe_fds[2];
|
||||||
|
ERRCHK_GOTO(pipe(pipe_fds) == -1, ret, signal, FUNCFAILED("pipe"), ERRNOS);
|
||||||
|
|
||||||
|
char *args[] = { "ueberzug", "layer", NULL };
|
||||||
|
int sp_arg[] = { pipe_fds[1], pipe_fds[0], STDIN_FILENO };
|
||||||
|
if (spawn(args, &ueberzug_pid, NULL, spawn_redirect, sp_arg) != OK)
|
||||||
|
ret = ERR;
|
||||||
|
|
||||||
|
close(pipe_fds[0]);
|
||||||
|
|
||||||
|
/* If spawn() failed */
|
||||||
|
if (ret != OK)
|
||||||
|
goto close;
|
||||||
|
|
||||||
|
struct pollfd pollfd = { .fd = fifo_fd, .events = POLLIN };
|
||||||
|
|
||||||
|
int poll_ret, len;
|
||||||
|
while ((poll_ret = poll(&pollfd, 1, -1) > 0)) {
|
||||||
|
static char buf[1024];
|
||||||
|
while ((len = read(fifo_fd, buf, LEN(buf))) > 0) {
|
||||||
|
/* First zero byte means that ctpv -e $id was run */
|
||||||
|
if (buf[0] == 0)
|
||||||
|
goto close;
|
||||||
|
write(pipe_fds[1], buf, len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ERRCHK_GOTO(poll_ret < 0, ret, close, FUNCFAILED("poll"), ERRNOS);
|
||||||
|
|
||||||
|
close:
|
||||||
|
close(pipe_fds[1]);
|
||||||
|
kill_ueberzug();
|
||||||
|
|
||||||
|
signal:
|
||||||
|
signal(SIGINT, SIG_DFL);
|
||||||
|
|
||||||
|
exit:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int check_ueberzug(int *exitcode)
|
||||||
|
{
|
||||||
|
char *args[] = SHELL_ARGS("command -v ueberzug > /dev/null");
|
||||||
|
return spawn(args, NULL, exitcode, NULL, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
int server_listen(char const *id_s)
|
||||||
|
{
|
||||||
|
int ret = OK;
|
||||||
|
|
||||||
|
int exitcode;
|
||||||
|
ERRCHK_GOTO_OK(check_ueberzug(&exitcode), ret, exit);
|
||||||
|
|
||||||
|
if (exitcode == 127) {
|
||||||
|
print_error("ueberzug is not installed");
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
char fifo[256];
|
||||||
|
snprintf(fifo, LEN(fifo)-1, "/tmp/ctpvfifo.%s", id_s);
|
||||||
|
|
||||||
|
ERRCHK_GOTO(mkfifo(fifo, 0600) == -1 && errno != EEXIST, ret, exit,
|
||||||
|
FUNCFAILED("mkfifo"), ERRNOS);
|
||||||
|
|
||||||
|
int fifo_fd;
|
||||||
|
ERRCHK_GOTO((fifo_fd = open(fifo, O_RDONLY | O_NONBLOCK)) == -1, ret, fifo,
|
||||||
|
FUNCFAILED("open"), ERRNOS);
|
||||||
|
|
||||||
|
ERRCHK_GOTO_OK(listen(fifo_fd), ret, fifo_fd);
|
||||||
|
|
||||||
|
fifo_fd:
|
||||||
|
close(fifo_fd);
|
||||||
|
|
||||||
|
fifo:
|
||||||
|
if (remove(fifo) == -1)
|
||||||
|
PRINTINTERR(FUNCFAILED("remove"), ERRNOS);
|
||||||
|
|
||||||
|
exit:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int server_clear(void)
|
||||||
|
{
|
||||||
|
char *args[] = SHELL_ARGS(scr_clear_sh);
|
||||||
|
int exitcode;
|
||||||
|
ERRCHK_RET_OK(spawn(args, NULL, &exitcode, NULL, NULL));
|
||||||
|
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int server_end(const char *id_s)
|
||||||
|
{
|
||||||
|
char *args[] = SHELL_ARGS(scr_end_sh, (char *)id_s);
|
||||||
|
int exitcode;
|
||||||
|
ERRCHK_RET_OK(spawn(args, NULL, &exitcode, NULL, NULL));
|
||||||
|
|
||||||
|
return OK;
|
||||||
|
}
|
8
server.h
Normal file
8
server.h
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
#ifndef SERVER_H
|
||||||
|
#define SERVER_H
|
||||||
|
|
||||||
|
int server_listen(char const *id_s);
|
||||||
|
int server_clear(void);
|
||||||
|
int server_end(const char *id_s);
|
||||||
|
|
||||||
|
#endif
|
7
shell.h
Normal file
7
shell.h
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
#ifndef SHELL_H
|
||||||
|
#define SHELL_H
|
||||||
|
|
||||||
|
#define SHELL_ARGS(script, ...) \
|
||||||
|
{ "sh", "-c", script, "sh", __VA_ARGS__ __VA_OPT__(,) NULL }
|
||||||
|
|
||||||
|
#endif
|
33
utils.c
33
utils.c
@ -10,12 +10,21 @@ char *program;
|
|||||||
|
|
||||||
int spawn_redirect(const void *arg)
|
int spawn_redirect(const void *arg)
|
||||||
{
|
{
|
||||||
int **fds = (int **)arg;
|
int *fds = (int *)arg;
|
||||||
int *pipe = fds[0];
|
|
||||||
int *fd = fds[1];
|
|
||||||
|
|
||||||
ERRCHK_RET(close(pipe[0]) == -1, FUNCFAILED("close"), ERRNOS);
|
ERRCHK_RET(close(fds[0]) == -1, FUNCFAILED("close"), ERRNOS);
|
||||||
ERRCHK_RET(dup2(pipe[1], *fd) == -1, FUNCFAILED("dup2"), ERRNOS);
|
ERRCHK_RET(dup2(fds[1], fds[2]) == -1, FUNCFAILED("dup2"), ERRNOS);
|
||||||
|
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int spawn_wait(pid_t pid, int *exitcode)
|
||||||
|
{
|
||||||
|
int stat;
|
||||||
|
ERRCHK_RET(waitpid(pid, &stat, 0) == -1, FUNCFAILED("waitpid"), ERRNOS);
|
||||||
|
|
||||||
|
if (exitcode && WIFEXITED(stat))
|
||||||
|
*exitcode = WEXITSTATUS(stat);
|
||||||
|
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
@ -43,20 +52,18 @@ int spawn(char *args[], pid_t *cpid, int *exitcode, int (*cfunc)(const void *),
|
|||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
|
|
||||||
execvp(args[0], args);
|
execvp(args[0], args);
|
||||||
|
if (errno == ENOENT)
|
||||||
|
exit(NOTEXIST_EC);
|
||||||
|
|
||||||
PRINTINTERR(FUNCFAILED("exec"), ERRNOS);
|
PRINTINTERR(FUNCFAILED("exec"), ERRNOS);
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cpid) {
|
if (cpid)
|
||||||
*cpid = pid;
|
*cpid = pid;
|
||||||
} else {
|
|
||||||
int stat;
|
|
||||||
ERRCHK_RET(waitpid(pid, &stat, 0) == -1, FUNCFAILED("waitpid"),
|
|
||||||
ERRNOS);
|
|
||||||
|
|
||||||
if (exitcode && WIFEXITED(stat))
|
if (exitcode)
|
||||||
*exitcode = WEXITSTATUS(stat);
|
ERRCHK_RET_OK(spawn_wait(pid, exitcode));
|
||||||
}
|
|
||||||
|
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
3
utils.h
3
utils.h
@ -4,6 +4,8 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
#define NOTEXIST_EC 127
|
||||||
|
|
||||||
#define LEN(a) (sizeof(a) / sizeof((a)[0]))
|
#define LEN(a) (sizeof(a) / sizeof((a)[0]))
|
||||||
#define MAX(a, b) ((a) > (b) ? (a) : (b))
|
#define MAX(a, b) ((a) > (b) ? (a) : (b))
|
||||||
#define MIN(a, b) ((a) < (b) ? (a) : (b))
|
#define MIN(a, b) ((a) < (b) ? (a) : (b))
|
||||||
@ -27,6 +29,7 @@ typedef struct {
|
|||||||
extern char *program;
|
extern char *program;
|
||||||
|
|
||||||
int spawn_redirect(const void *arg);
|
int spawn_redirect(const void *arg);
|
||||||
|
int spawn_wait(pid_t pid, int *exitcode);
|
||||||
int spawn(char *args[], pid_t *cpid, int *exitcode, int (*cfunc)(const void *),
|
int spawn(char *args[], pid_t *cpid, int *exitcode, int (*cfunc)(const void *),
|
||||||
const void *carg);
|
const void *carg);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user