From 6ff956880b8dde199fe9ac1314e43b66e0046f71 Mon Sep 17 00:00:00 2001 From: June McEnroe Date: Sat, 10 Jun 2017 16:49:51 -0400 Subject: Move actual dotfiles into home directory --- home/.bin/bri.c | 78 +++++++++++++++ home/.bin/clock.c | 33 +++++++ home/.bin/jrp.c | 273 +++++++++++++++++++++++++++++++++++++++++++++++++++++ home/.bin/manpager | 1 + home/.bin/pbcopy.c | 55 +++++++++++ home/.bin/pbd.c | 73 ++++++++++++++ home/.bin/xx.c | 116 +++++++++++++++++++++++ 7 files changed, 629 insertions(+) create mode 100755 home/.bin/bri.c create mode 100755 home/.bin/clock.c create mode 100755 home/.bin/jrp.c create mode 100755 home/.bin/manpager create mode 100755 home/.bin/pbcopy.c create mode 100755 home/.bin/pbd.c create mode 100755 home/.bin/xx.c (limited to 'home/.bin') diff --git a/home/.bin/bri.c b/home/.bin/bri.c new file mode 100755 index 00000000..4c53475f --- /dev/null +++ b/home/.bin/bri.c @@ -0,0 +1,78 @@ +#if 0 +cc -Wall -Wextra -pedantic $@ -o $(dirname $0)/bri $0 && \ +sudo chown root:root $(dirname $0)/bri && \ +sudo chmod u+s $(dirname $0)/bri +exit +#endif + +// Backlight brightness control. + +#include +#include +#include +#include +#include +#include +#include + +static const char *CLASS = "/sys/class/backlight"; + +int main(int argc, char *argv[]) { + int error; + + if (argc < 2) errx(EX_USAGE, "usage: bri N | +... | -..."); + + error = chdir(CLASS); + if (error) err(EX_IOERR, "%s", CLASS); + + DIR *dir = opendir("."); + if (!dir) err(EX_IOERR, "%s", CLASS); + + struct dirent *entry; + while (NULL != (errno = 0, entry = readdir(dir))) { + if (entry->d_name[0] == '.') continue; + + error = chdir(entry->d_name); + if (error) err(EX_IOERR, "%s", entry->d_name); + break; + } + if (!entry) { + if (errno) err(EX_IOERR, "%s", CLASS); + errx(EX_CONFIG, "empty %s", CLASS); + } + + char *value = argv[1]; + + if (value[0] == '+' || value[0] == '-') { + FILE *actual = fopen("actual_brightness", "r"); + if (!actual) err(EX_IOERR, "actual_brightness"); + + unsigned int brightness; + int match = fscanf(actual, "%u", &brightness); + if (match == EOF) err(EX_IOERR, "actual_brightness"); + if (match < 1) err(EX_DATAERR, "actual_brightness"); + + size_t count = strnlen(value, 15); + if (value[0] == '+') { + brightness += 16 * count; + } else { + brightness -= 16 * count; + } + + char buf[15]; + snprintf(buf, sizeof(buf), "%u", brightness); + + value = buf; + } + + error = setuid(0); + if (error) err(EX_NOPERM, "setuid(0)"); + + FILE *brightness = fopen("brightness", "w"); + if (!brightness) err(EX_IOERR, "brightness"); + + int count = fprintf(brightness, "%s", value); + if (count < 0) err(EX_IOERR, "brightness"); + + return EX_OK; +} diff --git a/home/.bin/clock.c b/home/.bin/clock.c new file mode 100755 index 00000000..288884d8 --- /dev/null +++ b/home/.bin/clock.c @@ -0,0 +1,33 @@ +#if 0 +exec cc -Wall -Wextra -pedantic $@ -o $(dirname $0)/clock $0 +#endif + +// Fuzzy clock for display in tmux. + +#include +#include +#include +#include + +int main() { + time_t ts = time(NULL); + if (ts < 0) err(EX_OSERR, "time"); + + struct tm *time = localtime(&ts); + if (!time) err(EX_OSERR, "localtime"); + + int hour = time->tm_hour; + int next = (hour + 1) % 24; + + switch ((time->tm_min + 5) / 10) { + case 0: printf("..%02d..\n", hour); break; + case 1: printf(".%02d...\n", hour); break; + case 2: printf("%02d....\n", hour); break; + case 3: printf("%d....%d\n", hour % 10, next / 10); break; + case 4: printf("....%02d\n", next); break; + case 5: printf("...%02d.\n", next); break; + case 6: printf("..%02d..\n", next); break; + } + + return EX_OK; +} diff --git a/home/.bin/jrp.c b/home/.bin/jrp.c new file mode 100755 index 00000000..9317ac8e --- /dev/null +++ b/home/.bin/jrp.c @@ -0,0 +1,273 @@ +#if 0 +exec cc -Wall -Wextra -pedantic $@ $0 -ledit -o $(dirname $0)/jrp +#endif + +// JIT RPN calculator. + +#include +#include +#include +#include +#include +#include +#include +#include + +typedef unsigned long qop; +typedef unsigned int dop; + +typedef long qvalue; +typedef int dvalue; +typedef unsigned long uvalue; + +typedef qvalue *(*jitFn)(qvalue *); +typedef void (*rtFn)(qvalue); + +static char *formatBin(qvalue val) { + static char buf[sizeof(qvalue) * 8 + 1]; + uvalue uval = val; + size_t i = sizeof(buf); + do { + buf[--i] = '0' + (uval & 1); + } while (uval >>= 1); + return &buf[i]; +} + +static void rtPrintAscii(qvalue val) { + printf("%c\n", (char)val); +} +static void rtPrintBin(qvalue val) { + printf("%s\n", formatBin(val)); +} +static void rtPrintOct(qvalue val) { + printf("%lo\n", val); +} +static void rtPrintDec(qvalue val) { + printf("%ld\n", val); +} +static void rtPrintHex(qvalue val) { + printf("%lx\n", val); +} + +static const dop DOP_NOP = 0x90666666; // nop +static const dop DOP_PUSH = 0xc7c74857; // push rdi; mov rdi, strict dword 0 +static const dop DOP_DROP = 0x9066665f; // pop rdi +static const dop DOP_DUP = 0x90666657; // push rdi +static const dop DOP_SWAP = 0x243c8748; // xchg rdi, [rsp] +static const dop DOP_NEG = 0x90dff748; // neg rdi +static const dop DOP_ADD = 0xc7014858; // pop rax; add rdi, rax +static const dop DOP_QUO = 0x90c78948; // mov rdi, rax +static const dop DOP_REM = 0x90d78948; // mov rdi, rdx +static const dop DOP_NOT = 0x90d7f748; // not rdi +static const dop DOP_AND = 0xc7214858; // pop rax; and rdi, rax +static const dop DOP_OR = 0xc7094858; // pop rax; or rdi, rax +static const dop DOP_XOR = 0xc7314858; // pop rax; xor rdi, rax + +static const qop QOP_PROL = 0x5ffc8948e5894855; // push rbp; mov rbp, rsp; mov rsp, rdi; pop rdi +static const qop QOP_EPIL = 0x5dec8948e0894857; // push rdi; mov rax, rsp; mov rsp, rbp; pop rbp +static const qop QOP_RET = 0x90666666906666c3; // ret +static const qop QOP_CRT = 0xb848906690e58748; // xchg rsp, rbp; mov rax, strict qword 0 +static const qop QOP_CALL = 0x90665fe58748d0ff; // call rax; xchg rsp, rbp; pop rdi +static const qop QOP_PUSH = 0xbf48906690666657; // push rdi; mov rdi, strict qword 0 +static const qop QOP_SUB = 0x9066665f243c2948; // sub [rsp], rdi; pop rdi +static const qop QOP_MUL = 0x906666f8af0f4858; // pop rax; imul rdi, rax +static const qop QOP_DIV = 0x9066fff748994858; // pop rax; cqo; idiv rdi +static const qop QOP_SHL = 0x5f2424d348f98948; // mov rcx, rdi; shl qword [rsp], cl; pop rdi +static const qop QOP_SHR = 0x5f242cd348f98948; // mov rcx, rdi; shr qword [rsp], cl; pop rdi + +static int radix = 10; + +static struct { + qop *base; + qop *ptr; + dop dop; +} code; + +static struct { + qvalue *base; + qvalue *limit; + qvalue *ptr; +} stack; + +static void jitDop(dop op) { + if (code.dop) { + *code.ptr++ = (qop)op << 32 | code.dop; + code.dop = 0; + } else { + code.dop = op; + } +} + +static void jitQop(qop op) { + if (code.dop) jitDop(DOP_NOP); + *code.ptr++ = op; +} + +static void jitPush(qvalue imm) { + if ((dvalue)imm == imm) { + jitQop(DOP_PUSH | (qop)imm << 32); + } else { + jitQop(QOP_PUSH); + jitQop((qop)imm); + } +} + +static void jitCall(rtFn fn) { + jitQop(QOP_CRT); + jitQop((qop)fn); + jitQop(QOP_CALL); +} + +static void jitBegin(void) { + code.ptr = code.base; + jitQop(QOP_PROL); +} + +static void jitEnd(void) { + jitQop(QOP_EPIL); + jitQop(QOP_RET); +} + +static void jitInit(void) { + code.base = mmap(0, getpagesize(), PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0); + if (code.base == MAP_FAILED) err(EX_OSERR, "mmap"); +} + +static void stackInit(void) { + stack.base = mmap(0, 2 * getpagesize(), PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0); + if (stack.base == MAP_FAILED) err(EX_OSERR, "mmap"); + stack.limit = stack.base + getpagesize() / sizeof(qvalue); + stack.ptr = stack.limit; +} + +static void jitExec(void) { + int error; + error = mprotect(code.base, getpagesize(), PROT_READ | PROT_EXEC); + if (error) err(EX_OSERR, "mprotect"); + stack.ptr = ((jitFn)code.base)(stack.ptr); + if (stack.ptr > stack.limit) stack.ptr = stack.limit; + error = mprotect(code.base, getpagesize(), PROT_READ | PROT_WRITE); + if (error) err(EX_OSERR, "mprotect"); +} + +static void jitSrc(const char *src) { + bool quote = false; + while (*src) { + if (quote) { + jitPush(*src++); + quote = false; + continue; + } + + switch (*src) { + case ' ': break; + case 39: quote = true; break; + case 'B': radix = 2; break; + case 'O': radix = 8; break; + case 'D': radix = 10; break; + case 'X': radix = 16; break; + case ';': jitDop(DOP_DROP); break; + case ':': jitDop(DOP_DUP); break; + case 92: jitDop(DOP_SWAP); break; + case '_': jitDop(DOP_NEG); break; + case '+': jitDop(DOP_ADD); break; + case '-': jitQop(QOP_SUB); break; + case '*': jitQop(QOP_MUL); break; + case '/': jitQop(QOP_DIV); jitDop(DOP_QUO); break; + case '%': jitQop(QOP_DIV); jitDop(DOP_REM); break; + case '~': jitDop(DOP_NOT); break; + case '&': jitDop(DOP_AND); break; + case '|': jitDop(DOP_OR); break; + case '^': jitDop(DOP_XOR); break; + case '<': jitQop(QOP_SHL); break; + case '>': jitQop(QOP_SHR); break; + case ',': jitCall(rtPrintAscii); break; + case '.': switch (radix) { + case 2: jitCall(rtPrintBin); break; + case 8: jitCall(rtPrintOct); break; + case 10: jitCall(rtPrintDec); break; + case 16: jitCall(rtPrintHex); break; + } break; + + default: { + char *rest; + qvalue val = strtol(src, &rest, radix); + if (rest != src) { + src = rest; + jitPush(val); + continue; + } + } + } + + src++; + } +} + +static void jitDump(const char *path, FILE *file) { + size_t nitems = code.ptr - code.base; + size_t written = fwrite(code.base, sizeof(qop), nitems, file); + if (written < nitems) err(EX_IOERR, "%s", path); +} + +static char *prompt(EditLine *el __attribute((unused))) { + static char buf[4096]; + char *bufPtr = buf; + for (qvalue *stackPtr = stack.limit - 1; stackPtr >= stack.ptr; --stackPtr) { + size_t bufLen = sizeof(buf) - (bufPtr - buf) - 2; + switch (radix) { + case 2: bufPtr += snprintf(bufPtr, bufLen, " %s", formatBin(*stackPtr)); break; + case 8: bufPtr += snprintf(bufPtr, bufLen, " %lo", *stackPtr); break; + case 10: bufPtr += snprintf(bufPtr, bufLen, " %ld", *stackPtr); break; + case 16: bufPtr += snprintf(bufPtr, bufLen, " %lx", *stackPtr); break; + } + } + buf[0] = '['; + if (bufPtr == buf) bufPtr++; + *bufPtr++ = ']'; + *bufPtr++ = ' '; + *bufPtr = 0; + return buf; +} + +int main(int argc, char *argv[]) { + FILE *file = NULL; + char *path = getenv("JRP_DUMP"); + if (path) { + file = fopen(path, "w"); + if (!file) err(EX_CANTCREAT, "%s", path); + } + + jitInit(); + stackInit(); + + if (argc > 1) { + jitBegin(); + for (int i = 1; i < argc; ++i) + jitSrc(argv[i]); + jitEnd(); + if (file) jitDump(path, file); + jitExec(); + return EX_OK; + } + + EditLine *el = el_init(argv[0], stdin, stdout, stderr); + el_set(el, EL_PROMPT, prompt); + el_set(el, EL_SIGNAL, true); + + for (;;) { + int count; + const char *line = el_gets(el, &count); + if (count < 0) err(EX_IOERR, "el_gets"); + if (!line) break; + + jitBegin(); + jitSrc(line); + jitEnd(); + if (file) jitDump(path, file); + jitExec(); + } + + el_end(el); + return EX_OK; +} diff --git a/home/.bin/manpager b/home/.bin/manpager new file mode 100755 index 00000000..f358f5d9 --- /dev/null +++ b/home/.bin/manpager @@ -0,0 +1 @@ +exec nvim -c 'set ft=man' - 1< /dev/tty 2< /dev/tty diff --git a/home/.bin/pbcopy.c b/home/.bin/pbcopy.c new file mode 100755 index 00000000..23403d2d --- /dev/null +++ b/home/.bin/pbcopy.c @@ -0,0 +1,55 @@ +#if 0 +cc -Wall -Wextra -pedantic $@ -o $(dirname $0)/pbcopy $0 && \ +exec cc -Wall -Wextra -pedantic -DPBPASTE $@ -o $(dirname $0)/pbpaste $0 +#endif + +// pbcopy and pbpaste implementation which connects to pbd. + +#include +#include +#include +#include +#include +#include +#include + +int main() { + int error; + + int client = socket(PF_INET, SOCK_STREAM, 0); + if (client < 0) err(EX_OSERR, "socket"); + + struct sockaddr_in addr = { + .sin_family = AF_INET, + .sin_port = htons(7062), + .sin_addr = { .s_addr = htonl(0x7f000001) }, + }; + + error = connect(client, (struct sockaddr *)&addr, sizeof(addr)); + if (error) err(EX_OSERR, "connect"); + +#ifdef PBPASTE + int fdIn = client; + int fdOut = STDOUT_FILENO; + error = shutdown(client, SHUT_WR); + if (error) err(EX_OSERR, "shutdown"); +#else + int fdIn = STDIN_FILENO; + int fdOut = client; +#endif + + char readBuf[4096]; + ssize_t readLen; + while (0 < (readLen = read(fdIn, readBuf, sizeof(readBuf)))) { + char *writeBuf = readBuf; + ssize_t writeLen; + while (0 < (writeLen = write(fdOut, writeBuf, readLen))) { + writeBuf += writeLen; + readLen -= writeLen; + } + if (writeLen < 0) err(EX_IOERR, "write"); + } + if (readLen < 0) err(EX_IOERR, "read"); + + return EX_OK; +} diff --git a/home/.bin/pbd.c b/home/.bin/pbd.c new file mode 100755 index 00000000..e7b61d12 --- /dev/null +++ b/home/.bin/pbd.c @@ -0,0 +1,73 @@ +#if 0 +exec cc -Wall -Wextra -pedantic $@ -o $(dirname $0)/pbd $0 +#endif + +// TCP server which pipes between macOS pbcopy and pbpaste. + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static void spawn(const char *cmd, int childFd, int parentFd) { + pid_t pid = fork(); + if (pid < 0) err(EX_OSERR, "fork"); + + if (pid) { + int status; + pid_t wait = waitpid(pid, &status, 0); + if (wait < 0) err(EX_OSERR, "waitpid"); + + if (status) { + warnx("child %s status %d", cmd, status); + } + } else { + int fd = dup2(parentFd, childFd); + if (fd < 0) err(EX_OSERR, "dup2"); + + int error = execlp(cmd, cmd); + if (error) err(EX_OSERR, "execlp"); + } +} + +int main() { + int error; + + int server = socket(PF_INET, SOCK_STREAM, 0); + if (server < 0) err(EX_OSERR, "socket"); + + struct sockaddr_in addr = { + .sin_family = AF_INET, + .sin_port = htons(7062), + .sin_addr = { .s_addr = htonl(0x7f000001) }, + }; + + error = bind(server, (struct sockaddr *)&addr, sizeof(addr)); + if (error) err(EX_OSERR, "bind"); + + error = listen(server, 1); + if (error) err(EX_OSERR, "listen"); + + for (;;) { + int client = accept(server, NULL, NULL); + if (client < 0) err(EX_OSERR, "accept"); + + spawn("pbpaste", STDOUT_FILENO, client); + + uint8_t p; + ssize_t peek = recv(client, &p, 1, MSG_PEEK); + if (peek < 0) err(EX_IOERR, "recv"); + + if (peek) { + spawn("pbcopy", STDIN_FILENO, client); + } + + error = close(client); + if (error) err(EX_IOERR, "close"); + } +} diff --git a/home/.bin/xx.c b/home/.bin/xx.c new file mode 100755 index 00000000..269c9d55 --- /dev/null +++ b/home/.bin/xx.c @@ -0,0 +1,116 @@ +#if 0 +exec cc -Wall -Wextra -pedantic $@ -o $(dirname $0)/xx $0 +#endif + +// Hexdump. + +#include +#include +#include +#include +#include +#include +#include +#include + +static bool allZero(const uint8_t *buf, size_t len) { + for (size_t i = 0; i < len; ++i) + if (buf[i]) return false; + return true; +} + +enum { + FLAG_ASCII = 1, + FLAG_OFFSET = 2, + FLAG_SKIP = 4, + FLAG_UNDUMP = 8, +}; + +void dump(size_t cols, size_t group, uint8_t flags, FILE *file) { + uint8_t buf[cols]; + size_t offset = 0, len = 0; + for (;;) { + offset += len; + len = fread(buf, 1, sizeof(buf), file); + if (!len) break; + + if ((flags & FLAG_SKIP) && len == sizeof(buf)) { + static bool skip; + if (allZero(buf, len)) { + if (!skip) printf("*\n"); + skip = true; + continue; + } + skip = false; + } + + if (flags & FLAG_OFFSET) { + printf("%08zx: ", offset); + } + + for (size_t i = 0; i < len; ++i) { + if (group && i && !(i % group)) printf(" "); + printf("%02x ", buf[i]); + } + + if (flags & FLAG_ASCII) { + for (size_t i = len; i < cols; ++i) { + printf((group && !(i % group)) ? " " : " "); + } + printf(" "); + for (size_t i = 0; i < len; ++i) { + printf("%c", isprint(buf[i]) ? buf[i] : '.'); + } + } + + printf("\n"); + if (len < sizeof(buf)) break; + } +} + +void undump(FILE *file) { + uint8_t byte; + int match; + while (1 == (match = fscanf(file, " %hhx", &byte))) { + printf("%c", byte); + } + if (match == 0) errx(EX_DATAERR, "invalid input"); +} + +int main(int argc, char *argv[]) { + size_t cols = 16; + size_t group = 8; + uint8_t flags = FLAG_ASCII | FLAG_OFFSET; + char *path = NULL; + + int opt; + while (0 < (opt = getopt(argc, argv, "ac:fg:hku"))) { + switch (opt) { + case 'a': flags ^= FLAG_ASCII; break; + case 'f': flags ^= FLAG_OFFSET; break; + case 'k': flags ^= FLAG_SKIP; break; + case 'u': flags ^= FLAG_UNDUMP; break; + case 'c': cols = strtoul(optarg, NULL, 10); break; + case 'g': group = strtoul(optarg, NULL, 10); break; + default: + fprintf(stderr, "usage: xx [-afku] [-c cols] [-g group] [file]\n"); + return (opt == 'h') ? EX_OK : EX_USAGE; + } + } + if (!cols) return EX_USAGE; + if (argc > optind) { + path = argv[optind]; + } + + FILE *file = path ? fopen(path, "r") : stdin; + if (!file) err(EX_NOINPUT, "%s", path); + + if (flags & FLAG_UNDUMP) { + undump(file); + } else { + dump(cols, group, flags, file); + } + + if (ferror(file)) err(EX_IOERR, "%s", path); + return EX_OK; +} -- cgit 1.4.1