diff options
| -rw-r--r-- | Makefile | 26 | ||||
| -rw-r--r-- | arg.h | 88 | ||||
| -rw-r--r-- | common.c | 146 | ||||
| -rw-r--r-- | common.h | 22 | ||||
| -rw-r--r-- | config.mk | 10 |
5 files changed, 292 insertions, 0 deletions
diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..c7aa8fd --- /dev/null +++ b/Makefile @@ -0,0 +1,26 @@ +.POSIX: + +CONFIGFILE = config.mk +include $(CONFIGFILE) + + +BIN =\ + bff-premultiply\ + bff-unpremultiply + + +HDR =\ + arg.h\ + common.h + +all: $(BIN) + +$(BIN:=.o): $(HDR) +common.o: $(HDR) +$(BIN): common.o + +clean: + -rm -- *.o $(BIN) + +.PHONY: all clean +.PRECIOUS: common.o @@ -0,0 +1,88 @@ +/* + * Copy me if you can. + * by 20h + */ + +#ifndef ARG_H__ +#define ARG_H__ + +extern char *argv0; + +/* use main(int argc, char *argv[]) */ +#define ARGBEGIN for (argv0 = *argv, argv++, argc--;\ + argv[0] && argv[0][1];\ + argc--, argv++) {\ + char argc_;\ + char **argv_;\ + int brk_;\ + if (argv[0][0] == '-') {\ + if (argv[0][1] == '-' && argv[0][2] == '\0') {\ + argv++;\ + argc--;\ + break;\ + }\ + for (brk_ = 0, argv[0]++, argv_ = argv;\ + argv[0][0] && !brk_;\ + argv[0]++) {\ + if (argv_ != argv)\ + break;\ + argc_ = argv[0][0];\ + switch (argc_) + +/* Handles obsolete -NUM syntax */ +#define ARGNUM case '0':\ + case '1':\ + case '2':\ + case '3':\ + case '4':\ + case '5':\ + case '6':\ + case '7':\ + case '8':\ + case '9' + +#define ARGALT(SYMBOL) }\ + } else if (argv[0][0] == SYMBOL) {\ + for (brk_ = 0, argv[0]++, argv_ = argv;\ + argv[0][0] && !brk_;\ + argv[0]++) {\ + if (argv_ != argv)\ + break;\ + argc_ = argv[0][0];\ + switch (argc_) + +#define ARGEND }\ + } else {\ + break;\ + }\ + } + +#define ARGC() argc_ + +#define ARGNUMF() (brk_ = 1, estrtonum(argv[0], 0, INT_MAX)) + +#define EARGF(x) ((argv[0][1] == '\0' && argv[1] == NULL)?\ + ((x), abort(), (char *)0) :\ + (brk_ = 1, (argv[0][1] != '\0')?\ + (&argv[0][1]) :\ + (argc--, argv++, argv[0]))) + +#define ARGF() ((argv[0][1] == '\0' && argv[1] == NULL)?\ + (char *)0 :\ + (brk_ = 1, (argv[0][1] != '\0')?\ + (&argv[0][1]) :\ + (argc--, argv++, argv[0]))) + +#define UARGF() EARGF(usage()) + +#define LNGARG() &argv[0][0] + +#define UNOFLAGS(...) ARGBEGIN {\ + default:\ + usage();\ + } ARGEND;\ + if (__VA_ARGS__)\ + usage() + + +#endif diff --git a/common.c b/common.c new file mode 100644 index 0000000..b39fbd6 --- /dev/null +++ b/common.c @@ -0,0 +1,146 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + +char *argv0; + +static pid_t image_decoder_pid; +static pid_t image_encoder_pid; + + +void +eprintf(const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + + if (argv0 && strncmp(fmt, "usage", strlen("usage"))) + fprintf(stderr, "%s: ", argv0); + + vfprintf(stderr, fmt, ap); + + if (fmt[0] && fmt[strlen(fmt)-1] == ':') { + fputc(' ', stderr); + perror(NULL); + } + + va_end(ap); + exit(1); +} + + +void +bff_begin(void) +{ + int rw[2]; + + if (pipe(rw)) + eprintf("pipe:"); + switch (image_decoder_pid = fork()) { + case -1: + eprintf("fork:"); + break; + case 0: + if (prctl(PR_SET_PDEATHSIG, SIGKILL)) + eprintf("prctl PR_SET_PDEATHSIG SIGKILL:"); + close(rw[0]); + if (dup2(rw[1], STDOUT_FILENO) < 0) + eprintf("dup2 <pipe> <stdout>:"); + close(rw[1]); + execlp("blind-from-image", "blind-from-image", "-f", NULL); + eprintf("execlp blind-from-image:"); + break; + default: + break; + } + close(rw[1]); + if (dup2(rw[0], STDIN_FILENO) < 0) + eprintf("dup2 <pipe> <stdin>:"); + close(rw[0]); + + if (pipe(rw)) + eprintf("pipe:"); + switch (image_encoder_pid = fork()) { + case -1: + eprintf("fork:"); + break; + case 0: + if (prctl(PR_SET_PDEATHSIG, SIGKILL)) + eprintf("prctl PR_SET_PDEATHSIG SIGKILL:"); + close(rw[1]); + if (dup2(rw[0], STDIN_FILENO) < 0) + eprintf("dup2 <pipe> <stdin>:"); + close(rw[0]); + execlp("blind-to-image", "blind-to-image", "-f", NULL); + eprintf("execlp blind-to-image:"); + break; + default: + break; + } + close(rw[0]); + if (dup2(rw[1], STDOUT_FILENO) < 0) + eprintf("dup2 <pipe> <stdout>:"); + close(rw[1]); +} + + +void +bff_end(void) +{ + int status; + + if (waitpid(image_decoder_pid, &status, 0) < 0) + eprintf("waitpid blind-from-image:"); + if (status) + exit(1); + + if (waitpid(image_encoder_pid, &status, 0) < 0) + eprintf("waitpid blind-to-image:"); + if (status) + exit(1); +} + + +pid_t +bff_run(const char **args, int in, int out) +{ + pid_t pid; + + switch (pid = fork()) { + case -1: + eprintf("fork:"); + break; + case 0: + if (prctl(PR_SET_PDEATHSIG, SIGKILL)) + eprintf("prctl PR_SET_PDEATHSIG SIGKILL:"); + if (in != STDIN_FILENO) { + if (dup2(in, STDIN_FILENO) < 0) + eprintf("dup2 <pipe> <stdin>:"); + close(in); + } + if (out != STDOUT_FILENO) { + if (dup2(out, STDOUT_FILENO) < 0) + eprintf("dup2 <pipe> <stdout>:"); + close(out); + } + execvp(*args, (void *)args); + eprintf("execlp %s:", *args); + break; + default: + break; + } + close(in); + close(out); + + return pid; +} + + +void +bff_wait(pid_t pid, const char *cmd) +{ + int status; + if (waitpid(pid, &status, 0) < 0) + eprintf("waitpid %s:", cmd); + if (status) + exit(1); +} diff --git a/common.h b/common.h new file mode 100644 index 0000000..ff9732c --- /dev/null +++ b/common.h @@ -0,0 +1,22 @@ +/* See LICENSE file for copyright and license details. */ +#include <sys/prctl.h> +#include <sys/wait.h> +#include <signal.h> +#include <stdarg.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include "arg.h" + +#define USAGE(SYNOPSIS)\ + static void usage(void)\ + { eprintf("usage: %s%s%s\n", argv0, *SYNOPSIS ? " " : "", SYNOPSIS); } + +void eprintf(const char *fmt, ...); + +void bff_begin(void); +void bff_end(void); +pid_t bff_run(const char **args, int in, int out); +void bff_wait(pid_t pid, const char *cmd); diff --git a/config.mk b/config.mk new file mode 100644 index 0000000..4cafaa4 --- /dev/null +++ b/config.mk @@ -0,0 +1,10 @@ +# BFF version +VERSION = 1.0 + +# Paths +PREFIX = /usr/local +MANPREFIX = $(PREFIX)/share/man + +CFLAGS = -std=c99 -Wall -pedantic -O2 +CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_XOPEN_SOURCE=700 +LDFLAGS = -s |
