From aa5a5558856b1e8fa73db0d747d95e143a613c76 Mon Sep 17 00:00:00 2001 From: elioat Date: Wed, 5 Jun 2024 21:10:36 -0400 Subject: cooking with fire --- lua/sandborb/sandbird.c | 979 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 979 insertions(+) create mode 100644 lua/sandborb/sandbird.c (limited to 'lua/sandborb/sandbird.c') diff --git a/lua/sandborb/sandbird.c b/lua/sandborb/sandbird.c new file mode 100644 index 0000000..e08c287 --- /dev/null +++ b/lua/sandborb/sandbird.c @@ -0,0 +1,979 @@ +/** + * Copyright (c) 2016 rxi + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the MIT license. See LICENSE for details. + */ + + +#ifdef _WIN32 + #ifndef _WIN32_WINNT + #define _WIN32_WINNT 0x501 + #endif + #ifndef _CRT_SECURE_NO_WARNINGS + #define _CRT_SECURE_NO_WARNINGS + #endif + #ifndef FD_SETSIZE + #define FD_SETSIZE 2048 + #endif + #include + #include + #include +#else + #ifndef _POSIX_C_SOURCE + #define _POSIX_C_SOURCE 200809L + #endif + #include + #include + #include + #include + #include + #include + #include + #include +#endif +#include +#include +#include +#include +#include +#include +#include + +#include "sandbird.h" + + +#ifdef _WIN32 + #define close(a) closesocket(a) + #define setsockopt(a, b, c, d, e) setsockopt(a, b, c, (char*)(d), e) + + #undef errno + #define errno WSAGetLastError() + + #undef EWOULDBLOCK + #define EWOULDBLOCK WSAEWOULDBLOCK + + const char *inet_ntop(int af, const void *src, char *dst, socklen_t size) { + union { struct sockaddr sa; struct sockaddr_in sai; + struct sockaddr_in6 sai6; } addr; + int res; + memset(&addr, 0, sizeof(addr)); + addr.sa.sa_family = af; + if (af == AF_INET6) { + memcpy(&addr.sai6.sin6_addr, src, sizeof(addr.sai6.sin6_addr)); + } else { + memcpy(&addr.sai.sin_addr, src, sizeof(addr.sai.sin_addr)); + } + res = WSAAddressToStringA(&addr.sa, sizeof(addr), 0, dst, (LPDWORD) &size); + if (res != 0) return NULL; + return dst; + } +#endif + +#ifdef _WIN32 + typedef SOCKET sb_Socket; +#else + typedef int sb_Socket; + #define INVALID_SOCKET -1 +#endif + +typedef struct sb_Buffer sb_Buffer; + +struct sb_Buffer { char *s; size_t len, cap; }; + +struct sb_Stream { + int state; /* Current state of the stream */ + sb_Server *server; /* The server object which owns this stream */ + char address[46]; /* Remote IP address */ + time_t init_time; /* Time the stream was created */ + time_t last_activity; /* Time of Last I/O activity on the stream */ + size_t expected_recv_len; /* Expected length of the stream's request */ + size_t data_idx; /* Index of data section in recv_buf */ + sb_Socket sockfd; /* Socket for this streams connection */ + sb_Buffer recv_buf; /* Data received from client */ + sb_Buffer send_buf; /* Data waiting to be sent to client */ + FILE *send_fp; /* File currently being sent to client */ + sb_Stream *next; /* Next stream in linked list */ +}; + +struct sb_Server { + sb_Stream *streams; /* Linked list of all streams */ + sb_Handler handler; /* Event handler callback function */ + sb_Socket sockfd; /* Listeneing server socket */ + void *udata; /* User data value passed to all events */ + time_t now; /* The current time */ + time_t timeout; /* Stream no-activity timeout */ + time_t max_lifetime; /* Maximum time a stream can exist */ + size_t max_request_size; /* Maximum request size in bytes */ +}; + +enum { + STATE_RECEIVING_HEADER, + STATE_RECEIVING_REQUEST, + STATE_SENDING_STATUS, + STATE_SENDING_HEADER, + STATE_SENDING_DATA, + STATE_SENDING_FILE, + STATE_CLOSING +}; + + +/*=========================================================================== + * Utility + *===========================================================================*/ + +static void set_socket_non_blocking(sb_Socket sockfd) { +#ifdef _WIN32 + u_long mode = 1; + ioctlsocket(sockfd, FIONBIO, &mode); +#else + int flags = fcntl(sockfd, F_GETFL); + fcntl(sockfd, F_SETFL, flags | O_NONBLOCK); +#endif +} + + +static int get_socket_address(sb_Socket sockfd, char *dst) { + int err; + union { struct sockaddr sa; struct sockaddr_storage sas; + struct sockaddr_in sai; struct sockaddr_in6 sai6; } addr; + socklen_t sz = sizeof(addr); + err = getpeername(sockfd, &addr.sa, &sz); + if (err == -1) { + *dst = '\0'; + return SB_EFAILURE; + } + if (addr.sas.ss_family == AF_INET6) { + inet_ntop(AF_INET6, &addr.sai6.sin6_addr, dst, INET6_ADDRSTRLEN); + } else { + inet_ntop(AF_INET, &addr.sai.sin_addr, dst, INET_ADDRSTRLEN); + } + return SB_ESUCCESS; +} + + +static unsigned str_to_uint(const char *str) { + unsigned n; + if (!str || sscanf(str, "%u", &n) != 1) return 0; + return n; +} + + +static int hex_to_int(int chr) { + return isdigit(chr) ? (chr - '0') : (tolower(chr) - 'a' + 10); +} + + +static int url_decode(char *dst, const char *src, size_t len) { + len--; + while (*src && !strchr("?& \t\r\n", *src) && len) { + if (src[0] == '%' && src[1] && src[2]) { + *dst = (hex_to_int(src[1]) << 4) | hex_to_int(src[2]); + src += 2; + } else if (*src == '+') { + *dst = ' '; + } else { + *dst = *src; + } + dst++, src++, len--; + } + *dst = '\0'; + return (len == 0) ? SB_ETRUNCATED : SB_ESUCCESS; +} + + +static int mem_equal(const void *a, const void *b, size_t len) { + const char *p = a, *q = b; + while (len) { + if (*p != *q) return 0; + p++, q++, len--; + } + return 1; +} + + +static int mem_case_equal(const void *a, const void *b, size_t len) { + const char *p = a, *q = b; + while (len) { + if (tolower(*p) != tolower(*q)) return 0; + p++, q++, len--; + } + return 1; +} + + +static const char *find_header_value(const char *str, const char *field) { + size_t len = strlen(field); + while (*str && !mem_equal(str, "\r\n", 2)) { + if (mem_case_equal(str, field, len) && str[len] == ':') { + str += len + 1; + return str + strspn(str, " \t"); + } + str += strcspn(str, "\r"); + str += mem_equal(str, "\r\n", 2) ? 2 : 0; + } + return NULL; +} + + +static const char *find_var_value(const char *str, const char *name) { + size_t len = strlen(name); + for (;;) { + if (mem_equal(str, name, len) && str[len] == '=') { + return str + len + 1; + } + str += strcspn(str, "& \t\r\n"); + if (*str != '&') break; + str++; + } + return NULL; +} + + +const char *sb_error_str(int code) { + switch (code) { + case SB_ESUCCESS : return "success"; + case SB_EFAILURE : return "failure"; + case SB_EOUTOFMEM : return "out of memory"; + case SB_ETRUNCATED : return "result truncated"; + case SB_EBADSTATE : return "bad stream state for this operation"; + case SB_EBADRESULT : return "bad result code from event handler"; + case SB_ECANTOPEN : return "cannot open file"; + case SB_ENOTFOUND : return "not found"; + case SB_EFDTOOBIG : return "got socket fd larger than FD_SETSIZE"; + default : return "unknown"; + } +} + + +/*=========================================================================== + * Buffer + *===========================================================================*/ + +static void sb_buffer_init(sb_Buffer *buf) { + memset(buf, 0, sizeof(*buf)); +} + + +static void sb_buffer_deinit(sb_Buffer *buf) { + free(buf->s); +} + + +static void sb_buffer_shift(sb_Buffer *buf, size_t n) { + buf->len -= n; + memmove(buf->s, buf->s + n, buf->len); +} + + +static int sb_buffer_reserve(sb_Buffer *buf, size_t n) { + void *p; + if (buf->cap >= n) return SB_ESUCCESS; + p = realloc(buf->s, n); + if (!p) return SB_EOUTOFMEM; + buf->s = p; + buf->cap = n; + return SB_ESUCCESS; +} + + +static int sb_buffer_push_char(sb_Buffer *buf, char chr) { + if (buf->len == buf->cap) { + int err = sb_buffer_reserve(buf, (buf->cap << 1) | (!buf->cap)); + if (err) return err; + } + buf->s[buf->len++] = chr; + return SB_ESUCCESS; +} + + +static int sb_buffer_push_str(sb_Buffer *buf, const char *p, size_t len) { + int err; + size_t orig_len = buf->len; + while (len) { + err = sb_buffer_push_char(buf, *p); + if (err) { + buf->len = orig_len; + return err; + } + p++, len--; + } + return SB_ESUCCESS; +} + + +static int sb_buffer_vwritef(sb_Buffer *buf, const char *fmt, va_list args) { + int err; + size_t orig_len = buf->len; + char fbuf[64]; + char lbuf[512]; + char *s; + + while (*fmt) { + if (*fmt == '%') { + switch (*++fmt) { + + case 's': + s = va_arg(args, char*); + if (s == NULL) s = "(null)"; + err = sb_buffer_push_str(buf, s, strlen(s)); + if (err) goto fai
/* See LICENSE file for copyright and license details. */
#include "dwm.h"
#include <stdlib.h>

/* static */

typedef struct {
	const char *symbol;
	void (*arrange)(void);
} Layout;

unsigned int blw = 0;
static Layout *lt = NULL;

static void
floating(void) { /* default floating layout */
	Client *c;

	for(c = clients; c; c = c->next)
		if(isvisible(c))
			resize(c, c->x, c->y, c->w, c->h, True);
}

static unsigned int nlayouts = 0;

LAYOUTS

/* extern */

void
arrange(void) {
	Client *c;

	for(c = clients; c; c = c->next)
		if(isvisible(c))
			unban(c);
		else
			ban(c);
	lt->arrange();
	focus(NULL);
	restack();
}

void
focusnext(const char *arg) {
	Client *c;

	if(!sel)
		return;
	for(c = sel->next; c && !isvisible(c); c = c->next);
	if(!c)
		for(c = clients; c && !isvisible(c); c = c->next);
	if(c) {
		focus(c);
		restack();
	}
}

void
focusprev(const char *arg) {
	Client *c;

	if(!sel)
		return;
	for(c = sel->prev; c && !isvisible(c); c = c->prev);
	if(!c) {
		for(c = clients; c && c->next; c = c->next);
		for(; c && !isvisible(c); c = c->prev);
	}
	if(c) {
		focus(c);
		restack();
	}
}

const char *
getsymbol(void)
{
	return lt->symbol;
}

Bool
isfloating(void) {
	return lt->arrange == floating;
}

Bool
isarrange(void (*func)())
{
	return func == lt->arrange;
}

void
initlayouts(void) {
	unsigned int i, w;

	lt = &layout[0];
	nlayouts = sizeof layout / sizeof layout[0];
	for(blw = i = 0; i < nlayouts; i++) {
		w = textw(layout[i].symbol);
		if(w > blw)
			blw = w;
	}
}

Client *
nexttiled(Client *c) {
	for(; c && (c->isfloating || !isvisible(c)); c = c->next);
	return c;
}

void
restack(void) {
	Client *c;
	XEvent ev;
	XWindowChanges wc;

	drawstatus();
	if(!sel)
		return;
	if(sel->isfloating || lt->arrange == floating)
		XRaiseWindow(dpy, sel->win);
	if(lt->arrange != floating) {
		wc.stack_mode = Below;
		wc.sibling = barwin;
		if(!sel->isfloating) {
			XConfigureWindow(dpy, sel->win, CWSibling | CWStackMode, &wc);
			wc.sibling = sel->win;
		}
		for(c = nexttiled(clients); c; c = nexttiled(c->next)) {
			if(c == sel)
				continue;
			XConfigureWindow(dpy, c->win, CWSibling | CWStackMode, &wc);
			wc.sibling = c->win;
		}
	}
	XSync(dpy, False);
	while(XCheckMaskEvent(dpy, EnterWindowMask, &ev));
}

void
setlayout(const char *arg) {
	int i;

	if(!arg) {
		lt++;
		if(lt == layout + nlayouts)
			lt = layout;
	}
	else {
		i = atoi(arg);
		if(i < 0 || i >= nlayouts)
			return;
		lt = &layout[i];
	}
	if(sel)
		arrange();
	else
		drawstatus();
}

void
togglebar(const char *arg) {
	if(bpos == BarOff)
		bpos = (BARPOS == BarOff) ? BarTop : BARPOS;
	else
		bpos = BarOff;
	updatebarpos();
	arrange();
}

void
togglemax(const char *arg) {
	XEvent ev;

	if(!sel || (lt->arrange != floating && !sel->isfloating) || sel->isfixed)
		return;
	if((sel->ismax = !sel->ismax)) {
		sel->rx = sel->x;
		sel->ry = sel->y;
		sel->rw = sel->w;
		sel->rh = sel->h;
		resize(sel, wax, way, waw - 2 * sel->border, wah - 2 * sel->border, True);
	}
	else
		resize(sel, sel->rx, sel->ry, sel->rw, sel->rh, True);
	drawstatus();
	while(XCheckMaskEvent(dpy, EnterWindowMask, &ev));
}