Browse Source

Completely changed slock, added imapfilter and removed quark

main
Yigit Colakoglu 4 years ago
parent
commit
2865e5cc08
39 changed files with 3049 additions and 3472 deletions
  1. +52
    -0
      .config/imapfilter/config.lua
  2. +0
    -1
      .config/vim/plugin/csyntaxafter.vim
  3. +1
    -1
      .config/weechat/irc.conf
  4. +4
    -4
      .config/weechat/sec.conf
  5. +1
    -0
      .config/zsh/aliases
  6. +3
    -1
      .local/bin/mailsync
  7. +1
    -1
      .local/share/dwm/autostart.sh
  8. +1
    -0
      .local/src/darkhttpd/.gitignore
  9. +19
    -0
      .local/src/darkhttpd/Makefile
  10. +2853
    -0
      .local/src/darkhttpd/darkhttpd.c
  11. +0
    -27
      .local/src/quark/LICENSE
  12. +0
    -46
      .local/src/quark/Makefile
  13. +0
    -50
      .local/src/quark/arg.h
  14. +0
    -40
      .local/src/quark/config.h
  15. +0
    -16
      .local/src/quark/config.mk
  16. +0
    -314
      .local/src/quark/connection.c
  17. +0
    -32
      .local/src/quark/connection.h
  18. +0
    -231
      .local/src/quark/data.c
  19. +0
    -18
      .local/src/quark/data.h
  20. +0
    -1044
      .local/src/quark/http.c
  21. +0
    -97
      .local/src/quark/http.h
  22. +0
    -364
      .local/src/quark/main.c
  23. +0
    -137
      .local/src/quark/quark.1
  24. +0
    -217
      .local/src/quark/queue.c
  25. +0
    -33
      .local/src/quark/queue.h
  26. +0
    -177
      .local/src/quark/server.c
  27. +0
    -35
      .local/src/quark/server.h
  28. +0
    -209
      .local/src/quark/sock.c
  29. +0
    -18
      .local/src/quark/sock.h
  30. +0
    -281
      .local/src/quark/util.c
  31. +0
    -42
      .local/src/quark/util.h
  32. +0
    -21
      .local/src/slock/.ccls-cache/@home@yigit@.local@src@a@s/config.h
  33. BIN
      .local/src/slock/.ccls-cache/@home@yigit@.local@src@a@s/config.h.blob
  34. +21
    -2
      .local/src/slock/config.h
  35. +11
    -3
      .local/src/slock/config.mk
  36. BIN
      .local/src/slock/slock
  37. +81
    -10
      .local/src/slock/slock.c
  38. BIN
      .local/src/slock/slock.o
  39. +1
    -0
      .profile

+ 52
- 0
.config/imapfilter/config.lua View File

@ -0,0 +1,52 @@
-- According to the IMAP specification, when trying to write a message
-- to a non-existent mailbox, the server must send a hint to the client,
-- whether it should create the mailbox and try again or not. However
-- some IMAP servers don't follow the specification and don't send the
-- correct response code to the client. By enabling this option the
-- client tries to create the mailbox, despite of the server's response.
-- This variable takes a boolean as a value. Default is “false”.
options.create = true
-- By enabling this option new mailboxes that were automatically created,
-- get auto subscribed
options.subscribe = true
-- How long to wait for servers response.
options.timeout = 120
function trim(s)
return (s:gsub("^%s*(.-)%s*$", "%1"))
end
-- Gets password from pass
status, dom_password = pipe_from('pass show Email/privateemail.com/yigit@yigitcolakoglu.com')
domain = IMAP {
server = "mail.privateemail.com",
port = 143,
username = "yigit@yigitcolakoglu.com",
password = trim(dom_password ),
ssl = auto
}
-- Gets password from pass
status, hot_password = pipe_from('pass show AppPass/microsoft.com/yigitcolakoglu@hotmail.com')
-- Setup an imap account called hotmail
hotmail = IMAP {
server = "outlook.office365.com",
port = 143,
username = "yigitcolakoglu@hotmail.com",
password = trim(hot_password),
ssl = auto
}
-- Block fucking Aleksandr. LEAVE ME ALONE DUDE
function fuckAleksandr()
mailboxes, folders = domain:list_all("/")
for _, v in pairs(mailboxes) do
messages = domain[v]:contain_subject("Предложение")
messages:delete_messages()
end
end
print("Fuck Aleksandr")
fuckAleksandr {}
print("Done fucking Aleksandr")

+ 0
- 1
.config/vim/plugin/csyntaxafter.vim View File

@ -1 +0,0 @@
autocmd! FileType c,cpp,java,php call CSyntaxAfter()

+ 1
- 1
.config/weechat/irc.conf View File

@ -188,7 +188,7 @@ freenode.local_hostname
freenode.usermode
freenode.command
freenode.command_delay
freenode.autojoin = "#vim,#archlinux,#lf,##C,#python,##java,#xorg-devel,#pass"
freenode.autojoin = "#vim,#gentoo,#lf,##C,#python,##java,#xorg-devel,#pass"
freenode.autorejoin
freenode.autorejoin_delay
freenode.connection_timeout


+ 4
- 4
.config/weechat/sec.conf View File

@ -17,7 +17,7 @@ salt = on
[data]
__passphrase__ = on
oftc_password = "7EDB64DA64B13CC9ACEE277089CA61B4F3F1DCB04FA16CEFDA10AAC151B2CBF1C22D9AC25CC4F84F13DBD7EC497D554995AE7298B88670"
sec.data.oftc_password = "55893BA77CE986F45826C39825BDA41E84F5CF6258853AD74648C617EF30AA9CCF00179E5975FFC39450A635994B588CCF94FA8BD220A25BE25600E75A4FDA0A2992"
freenode = "94AAE6F37BC7B07C7B34F57F0CE581F966BE2919404337819E8228F99C412BC7D0FDF6FFDC7CBADBC64F646B6926EB3DA5AEAC72BB1D1511B836AF"
rizon_password = "21D6088B8200A24BE75C7A671308EED61759E688ABBBCC2E47463D127622D9CF98E6793E17FB8FF0081C82C889EFF61D376FD75280BB71429FE7387BA8FB15AF7F78"
oftc_password = "936C665BADDD99B55848AE19992B3873FBE68A074B1CE52CED6844A3CA3560376116A605980F02C7F9C8ED139044FBDA77090ED6953197"
sec.data.oftc_password = "E03D86B8F0B9601B5EC92FEA1A564671F3CFEBF7B63539878A6BC028FB906790199D450D342F019C493DB31BF6BC59C144270F1C7495FDB6739626B615404CF59FDD"
freenode = "06841832E731EB8D00293CCB6334BD328B117D661E99279ADE699F8331387315C713F852E3C65AB3AF6A3D6A401F05B456CE6032DBF30B8F244799"
rizon_password = "3F6AAECFAA67DBC3636B60B3E05695F354158BB329F90F51320808BF06A3088D6C727CCA642332A96E0DF79CA15176B07B89E38D31F553D72B6D1C1E117F7EBDDFEE"

+ 1
- 0
.config/zsh/aliases View File

@ -43,6 +43,7 @@ alias yarn="yarn --use-yarnrc $XDG_CONFIG_HOME/yarn/config"
alias tmate="tmate -f $XDG_CONFIG_HOME/tmate/tmate.conf"
alias mc="mc --config-dir=$XDG_CONFIG_HOME/mc"
alias abook="abook --config \"$XDG_CONFIG_HOME\"/abook/abookrc --datafile \"$XDG_DATA_HOME\"/abook/addressbook"
alias imapfilter="imapfilter -c \"$IMAPFILTER_CONFIG\""
alias dots="git --git-dir=$HOME/.dotfiles.git/ --work-tree=$HOME"
alias dpall="dots remote | xargs -I R git --git-dir=$HOME/.dotfiles.git/ --work-tree=$HOME push R"


+ 3
- 1
.local/bin/mailsync View File

@ -21,7 +21,7 @@ pgrep -x mbsync >/dev/null && { echo "mbsync is already running." ; exit ;}
# files for variable assignments. This is ugly, but there are few options that
# will work on the maximum number of machines.
eval "$(grep -h -- \
"^\s*\(export \)\?\(MBSYNCRC\|PASSWORD_STORE_DIR\|NOTMUCH_CONFIG\|GNUPGHOME\|XDG_DATA_HOME\|XDG_CONFIG_HOME\|XDG_RUNTIME_DIR\|XDG_CACHE_HOME\)=" \
"^\s*\(export \)\?\(MBSYNCRC\|IMAPFILTER_CONFIG\|PASSWORD_STORE_DIR\|NOTMUCH_CONFIG\|GNUPGHOME\|XDG_DATA_HOME\|XDG_CONFIG_HOME\|XDG_RUNTIME_DIR\|XDG_CACHE_HOME\)=" \
"$HOME/.profile" "$HOME/.bash_profile" "$HOME/.zprofile" "$HOME/.config/zsh/.zprofile" "$HOME/.zshenv" \
"$HOME/.bashrc" "$HOME/.zshrc" "$HOME/.config/zsh/.zshrc" "$HOME/.pam_environment" 2>/dev/null)"
@ -77,6 +77,8 @@ syncandnotify() {
fi
}
imapfilter -c "$IMAPFILTER_CONFIG"
# Sync accounts passed as argument or all.
if [ "$#" -eq "0" ]; then
accounts="$(awk '/^Channel/ {print $2}' "$MBSYNCRC")"


+ 1
- 1
.local/share/dwm/autostart.sh View File

@ -1,6 +1,5 @@
#!/bin/sh
~/.local/bin/daily-update
redshift -x 2> /dev/null > /dev/null
@ -53,3 +52,4 @@ tmux new-session -s weechat -d weechat > /dev/null 2> /dev/null
clipmenud > $XDG_RUNTIME_DIR/clipmenud.out 2> $XDG_RUNTIME_DIR/clipmenud.err &
rm -f ~/.surf/tabbed-surf.xid
/bin/polkit-dumb-agent &
darkhttpd $HOME/.local/share/startpage/dist --port 9999 --daemon --addr 127.0.0.1

+ 1
- 0
.local/src/darkhttpd/.gitignore View File

@ -0,0 +1 @@
darkhttpd

+ 19
- 0
.local/src/darkhttpd/Makefile View File

@ -0,0 +1,19 @@
CC?=cc
CFLAGS?=-O
LIBS=`[ \`uname\` = "SunOS" ] && echo -lsocket -lnsl`
all: darkhttpd
install: darkhttpd
cp darkhttpd /usr/bin/darkhttpd
darkhttpd: darkhttpd.c
$(CC) $(CFLAGS) $(LDFLAGS) $(LIBS) darkhttpd.c -o $@
darkhttpd-static: darkhttpd.c
$(CC) -static $(CFLAGS) $(LDFLAGS) $(LIBS) darkhttpd.c -o $@
clean:
rm -f darkhttpd core darkhttpd.core darkhttpd-static darkhttpd-static.core
.PHONY: all clean

+ 2853
- 0
.local/src/darkhttpd/darkhttpd.c
File diff suppressed because it is too large
View File


+ 0
- 27
.local/src/quark/LICENSE View File

@ -1,27 +0,0 @@
ISC-License
Copyright 2016-2021 Laslo Hunhold <dev@frign.de>
Copyright 2004 Ted Unangst <tedu@openbsd.org>
Copyright 2004 Todd C. Miller <Todd.Miller@courtesan.com>
Copyright 2008 Otto Moerbeek <otto@drijf.net>
Copyright 2017-2018 Hiltjo Posthuma <hiltjo@codemadness.org>
Copyright 2017-2021 Quentin Rameau <quinq@fifth.space>
Copyright 2018 Josuah Demangeon <mail@josuah.net>
Copyright 2018 Dominik Schmidt <domischmidt@swissonline.ch>
Copyright 2018 Aaron Burrow <burrows@charstarstar.com>
Copyright 2020 Nihal Jere <nihal@nihaljere.xyz>
Copyright 2020 Rainer Holzner <rholzner@web.de>
Copyright 2020 Jeremy Bobbin <jer@jer.cx>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

+ 0
- 46
.local/src/quark/Makefile View File

@ -1,46 +0,0 @@
# See LICENSE file for copyright and license details
# quark - simple web server
.POSIX:
include config.mk
COMPONENTS = connection data http queue server sock util
all: quark
connection.o: connection.c config.h connection.h data.h http.h server.h sock.h util.h config.mk
data.o: data.c config.h data.h http.h server.h util.h config.mk
http.o: http.c config.h http.h server.h util.h config.mk
main.o: main.c arg.h config.h server.h sock.h util.h config.mk
server.o: server.c config.h connection.h http.h queue.h server.h util.h config.mk
sock.o: sock.c config.h sock.h util.h config.mk
util.o: util.c config.h util.h config.mk
quark: config.h $(COMPONENTS:=.o) $(COMPONENTS:=.h) main.o config.mk
$(CC) -o $@ $(CPPFLAGS) $(CFLAGS) $(COMPONENTS:=.o) main.o $(LDFLAGS)
config.h:
cp config.def.h $@
clean:
rm -f quark main.o $(COMPONENTS:=.o)
dist:
rm -rf "quark-$(VERSION)"
mkdir -p "quark-$(VERSION)"
cp -R LICENSE Makefile arg.h config.def.h config.mk quark.1 \
$(COMPONENTS:=.c) $(COMPONENTS:=.h) main.c "quark-$(VERSION)"
tar -cf - "quark-$(VERSION)" | gzip -c > "quark-$(VERSION).tar.gz"
rm -rf "quark-$(VERSION)"
install: all
mkdir -p "$(DESTDIR)$(PREFIX)/bin"
cp -f quark "$(DESTDIR)$(PREFIX)/bin"
chmod 755 "$(DESTDIR)$(PREFIX)/bin/quark"
mkdir -p "$(DESTDIR)$(MANPREFIX)/man1"
cp quark.1 "$(DESTDIR)$(MANPREFIX)/man1/quark.1"
chmod 644 "$(DESTDIR)$(MANPREFIX)/man1/quark.1"
uninstall:
rm -f "$(DESTDIR)$(PREFIX)/bin/quark"
rm -f "$(DESTDIR)$(MANPREFIX)/man1/quark.1"

+ 0
- 50
.local/src/quark/arg.h View File

@ -1,50 +0,0 @@
/*
* ISC-License
*
* Copyright 2004-2017 Christoph Lohmann <20h@r-36.net>
* Copyright 2017-2018 Laslo Hunhold <dev@frign.de>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef ARG_H
#define ARG_H
extern char *argv0;
/* int main(int argc, char *argv[]) */
#define ARGBEGIN for (argv0 = *argv, *argv ? (argc--, argv++) : ((void *)0); \
*argv && (*argv)[0] == '-' && (*argv)[1]; argc--, argv++) { \
int i_, argused_; \
if ((*argv)[1] == '-' && !(*argv)[2]) { \
argc--, argv++; \
break; \
} \
for (i_ = 1, argused_ = 0; (*argv)[i_]; i_++) { \
switch((*argv)[i_])
#define ARGEND if (argused_) { \
if ((*argv)[i_ + 1]) { \
break; \
} else { \
argc--, argv++; \
break; \
} \
} \
} \
}
#define ARGC() ((*argv)[i_])
#define ARGF_(x) (((*argv)[i_ + 1]) ? (argused_ = 1, &((*argv)[i_ + 1])) : \
(*(argv + 1)) ? (argused_ = 1, *(argv + 1)) : (x))
#define EARGF(x) ARGF_(((x), exit(1), (char *)0))
#define ARGF() ARGF_((char *)0)
#endif

+ 0
- 40
.local/src/quark/config.h View File

@ -1,40 +0,0 @@
#ifndef CONFIG_H
#define CONFIG_H
#define BUFFER_SIZE 4096
#define FIELD_MAX 200
/* mime-types */
static const struct {
char *ext;
char *type;
} mimes[] = {
{ "xml", "application/xml; charset=utf-8" },
{ "xhtml", "application/xhtml+xml; charset=utf-8" },
{ "html", "text/html; charset=utf-8" },
{ "js", "text/javascript; charset=utf-8" },
{ "htm", "text/html; charset=utf-8" },
{ "css", "text/css; charset=utf-8" },
{ "txt", "text/plain; charset=utf-8" },
{ "md", "text/plain; charset=utf-8" },
{ "c", "text/plain; charset=utf-8" },
{ "h", "text/plain; charset=utf-8" },
{ "gz", "application/x-gtar" },
{ "tar", "application/tar" },
{ "pdf", "application/x-pdf" },
{ "png", "image/png" },
{ "gif", "image/gif" },
{ "jpeg", "image/jpg" },
{ "jpg", "image/jpg" },
{ "iso", "application/x-iso9660-image" },
{ "webp", "image/webp" },
{ "svg", "image/svg+xml; charset=utf-8" },
{ "flac", "audio/flac" },
{ "mp3", "audio/mpeg" },
{ "ogg", "audio/ogg" },
{ "mp4", "video/mp4" },
{ "ogv", "video/ogg" },
{ "webm", "video/webm" },
};
#endif /* CONFIG_H */

+ 0
- 16
.local/src/quark/config.mk View File

@ -1,16 +0,0 @@
# quark version
VERSION = 0
# Customize below to fit your system
# paths
PREFIX = /usr/local
MANPREFIX = $(PREFIX)/share/man
# flags
CPPFLAGS = -DVERSION=\"$(VERSION)\" -D_DEFAULT_SOURCE -D_XOPEN_SOURCE=700 -D_BSD_SOURCE
CFLAGS = -std=c99 -pedantic -Wall -Wextra -Os
LDFLAGS = -lpthread -s
# compiler and linker
CC = cc

+ 0
- 314
.local/src/quark/connection.c View File

@ -1,314 +0,0 @@
/* See LICENSE file for copyright and license details. */
#include <errno.h>
#include <netinet/in.h>
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <time.h>
#include <unistd.h>
#include "connection.h"
#include "data.h"
#include "http.h"
#include "server.h"
#include "sock.h"
#include "util.h"
struct worker_data {
int insock;
size_t nslots;
const struct server *srv;
};
void
connection_log(const struct connection *c)
{
char inaddr_str[INET6_ADDRSTRLEN /* > INET_ADDRSTRLEN */];
char tstmp[21];
/* create timestamp */
if (!strftime(tstmp, sizeof(tstmp), "%Y-%m-%dT%H:%M:%SZ",
gmtime(&(time_t){time(NULL)}))) {
warn("strftime: Exceeded buffer capacity");
/* continue anyway (we accept the truncation) */
}
/* generate address-string */
if (sock_get_inaddr_str(&c->ia, inaddr_str, LEN(inaddr_str))) {
warn("sock_get_inaddr_str: Couldn't generate adress-string");
inaddr_str[0] = '\0';
}
printf("%s\t%s\t%s%.*d\t%s\t%s%s%s%s%s\n",
tstmp,
inaddr_str,
(c->res.status == 0) ? "dropped" : "",
(c->res.status == 0) ? 0 : 3,
c->res.status,
c->req.field[REQ_HOST][0] ? c->req.field[REQ_HOST] : "-",
c->req.path[0] ? c->req.path : "-",
c->req.query[0] ? "?" : "",
c->req.query,
c->req.fragment[0] ? "#" : "",
c->req.fragment);
}
void
connection_reset(struct connection *c)
{
if (c != NULL) {
shutdown(c->fd, SHUT_RDWR);
close(c->fd);
memset(c, 0, sizeof(*c));
}
}
void
connection_serve(struct connection *c, const struct server *srv)
{
enum status s;
int done;
switch (c->state) {
case C_VACANT:
/*
* we were passed a "fresh" connection which should now
* try to receive the header, reset buf beforehand
*/
memset(&c->buf, 0, sizeof(c->buf));
c->state = C_RECV_HEADER;
/* fallthrough */
case C_RECV_HEADER:
/* receive header */
done = 0;
if ((s = http_recv_header(c->fd, &c->buf, &done))) {
http_prepare_error_response(&c->req, &c->res, s);
goto response;
}
if (!done) {
/* not done yet */
return;
}
/* parse header */
if ((s = http_parse_header(c->buf.data, &c->req))) {
http_prepare_error_response(&c->req, &c->res, s);
goto response;
}
/* prepare response struct */
http_prepare_response(&c->req, &c->res, srv);
response:
/* generate response header */
if ((s = http_prepare_header_buf(&c->res, &c->buf))) {
http_prepare_error_response(&c->req, &c->res, s);
if ((s = http_prepare_header_buf(&c->res, &c->buf))) {
/* couldn't generate the header, we failed for good */
c->res.status = s;
goto err;
}
}
c->state = C_SEND_HEADER;
/* fallthrough */
case C_SEND_HEADER:
if ((s = http_send_buf(c->fd, &c->buf))) {
c->res.status = s;
goto err;
}
if (c->buf.len > 0) {
/* not done yet */
return;
}
c->state = C_SEND_BODY;
/* fallthrough */
case C_SEND_BODY:
if (c->req.method == M_GET) {
if (c->buf.len == 0) {
/* fill buffer with body data */
if ((s = data_fct[c->res.type](&c->res, &c->buf,
&c->progress))) {
/* too late to do any real error handling */
c->res.status = s;
goto err;
}
/* if the buffer remains empty, we are done */
if (c->buf.len == 0) {
break;
}
} else {
/* send buffer */
if ((s = http_send_buf(c->fd, &c->buf))) {
/* too late to do any real error handling */
c->res.status = s;
goto err;
}
}
return;
}
break;
default:
warn("serve: invalid connection state");
return;
}
err:
connection_log(c);
connection_reset(c);
}
static struct connection *
connection_get_drop_candidate(struct connection *connection, size_t nslots)
{
struct connection *c, *minc;
size_t i, j, maxcnt, cnt;
/*
* determine the most-unimportant connection 'minc' of the in-address
* with most connections; this algorithm has a complexity of O(n²)
* in time but is O(1) in space; there are algorithms with O(n) in
* time and space, but this would require memory allocation,
* which we avoid. Given the simplicity of the inner loop and
* relatively small number of slots per thread, this is fine.
*/
for (i = 0, minc = NULL, maxcnt = 0; i < nslots; i++) {
/*
* we determine how many connections have the same
* in-address as connection[i], but also minimize over
* that set with other criteria, yielding a general
* minimizer c. We first set it to connection[i] and
* update it, if a better candidate shows up, in the inner
* loop
*/
c = &connection[i];
for (j = 0, cnt = 0; j < nslots; j++) {
if (!sock_same_addr(&connection[i].ia,
&connection[j].ia)) {
continue;
}
cnt++;
/* minimize over state */
if (connection[j].state < c->state) {
c = &connection[j];
} else if (connection[j].state == c->state) {
/* minimize over progress */
if (c->state == C_SEND_BODY &&
connection[i].res.type != c->res.type) {
/*
* mixed response types; progress
* is not comparable
*
* the res-type-enum is ordered as
* DIRLISTING, ERROR, FILE, i.e.
* in rising priority, because a
* file transfer is most important,
* followed by error-messages.
* Dirlistings as an "interactive"
* feature (that take up lots of
* resources) have the lowest
* priority
*/
if (connection[i].res.type <
c->res.type) {
c = &connection[j];
}
} else if (connection[j].progress <
c->progress) {
/*
* for C_SEND_BODY with same response
* type, C_RECV_HEADER and C_SEND_BODY
* it is sufficient to compare the
* raw progress
*/
c = &connection[j];
}
}
}
if (cnt > maxcnt) {
/* this run yielded an even greedier in-address */
minc = c;
maxcnt = cnt;
}
}
return minc;
}
struct connection *
connection_accept(int insock, struct connection *connection, size_t nslots)
{
struct connection *c = NULL;
size_t i;
/* find vacant connection (i.e. one with no fd assigned to it) */
for (i = 0; i < nslots; i++) {
if (connection[i].fd == 0) {
c = &connection[i];
break;
}
}
if (i == nslots) {
/*
* all our connection-slots are occupied and the only
* way out is to drop another connection, because not
* accepting this connection just kicks this can further
* down the road (to the next queue_wait()) without
* solving anything.
*
* This may sound bad, but this case can only be hit
* either when there's a (D)DoS-attack or a massive
* influx of requests. The latter is impossible to solve
* at this moment without expanding resources, but the
* former has certain characteristics allowing us to
* handle this gracefully.
*
* During an attack (e.g. Slowloris, R-U-Dead-Yet, Slow
* Read or just plain flooding) we can not see who is
* waiting to be accept()ed.
* However, an attacker usually already has many
* connections open (while well-behaved clients could
* do everything with just one connection using
* keep-alive). Inferring a likely attacker-connection
* is an educated guess based on which in-address is
* occupying the most connection slots. Among those,
* connections in early stages (receiving or sending
* headers) are preferred over connections in late
* stages (sending body).
*
* This quantitative approach effectively drops malicious
* connections while preserving even long-running
* benevolent connections like downloads.
*/
c = connection_get_drop_candidate(connection, nslots);
c->res.status = 0;
connection_log(c);
connection_reset(c);
}
/* accept connection */
if ((c->fd = accept(insock, (struct sockaddr *)&c->ia,
&(socklen_t){sizeof(c->ia)})) < 0) {
if (errno != EAGAIN && errno != EWOULDBLOCK) {
/*
* this should not happen, as we received the
* event that there are pending connections here
*/
warn("accept:");
}
return NULL;
}
/* set socket to non-blocking mode */
if (sock_set_nonblocking(c->fd)) {
/* we can't allow blocking sockets */
return NULL;
}
return c;
}

+ 0
- 32
.local/src/quark/connection.h View File

@ -1,32 +0,0 @@
/* See LICENSE file for copyright and license details. */
#ifndef CONNECTION_H
#define CONNECTION_H
#include "http.h"
#include "server.h"
#include "util.h"
enum connection_state {
C_VACANT,
C_RECV_HEADER,
C_SEND_HEADER,
C_SEND_BODY,
NUM_CONN_STATES,
};
struct connection {
enum connection_state state;
int fd;
struct sockaddr_storage ia;
struct request req;
struct response res;
struct buffer buf;
size_t progress;
};
struct connection *connection_accept(int, struct connection *, size_t);
void connection_log(const struct connection *);
void connection_reset(struct connection *);
void connection_serve(struct connection *, const struct server *);
#endif /* CONNECTION_H */

+ 0
- 231
.local/src/quark/data.c View File

@ -1,231 +0,0 @@
/* See LICENSE file for copyright and license details. */
#include <dirent.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <time.h>
#include <unistd.h>
#include "data.h"
#include "http.h"
#include "util.h"
enum status (* const data_fct[])(const struct response *,
struct buffer *, size_t *) = {
[RESTYPE_DIRLISTING] = data_prepare_dirlisting_buf,
[RESTYPE_ERROR] = data_prepare_error_buf,
[RESTYPE_FILE] = data_prepare_file_buf,
};
static int
compareent(const struct dirent **d1, const struct dirent **d2)
{
int v;
v = ((*d2)->d_type == DT_DIR ? 1 : -1) -
((*d1)->d_type == DT_DIR ? 1 : -1);
if (v) {
return v;
}
return strcmp((*d1)->d_name, (*d2)->d_name);
}
static char *
suffix(int t)
{
switch (t) {
case DT_FIFO: return "|";
case DT_DIR: return "/";
case DT_LNK: return "@";
case DT_SOCK: return "=";
}
return "";
}
static void
html_escape(const char *src, char *dst, size_t dst_siz)
{
const struct {
char c;
char *s;
} escape[] = {
{ '&', "&amp;" },
{ '<', "&lt;" },
{ '>', "&gt;" },
{ '"', "&quot;" },
{ '\'', "&#x27;" },
};
size_t i, j, k, esclen;
for (i = 0, j = 0; src[i] != '\0'; i++) {
for (k = 0; k < LEN(escape); k++) {
if (src[i] == escape[k].c) {
break;
}
}
if (k == LEN(escape)) {
/* no escape char at src[i] */
if (j == dst_siz - 1) {
/* silent truncation */
break;
} else {
dst[j++] = src[i];
}
} else {
/* escape char at src[i] */
esclen = strlen(escape[k].s);
if (j >= dst_siz - esclen) {
/* silent truncation */
break;
} else {
memcpy(&dst[j], escape[k].s, esclen);
j += esclen;
}
}
}
dst[j] = '\0';
}
enum status
data_prepare_dirlisting_buf(const struct response *res,
struct buffer *buf, size_t *progress)
{
enum status s = 0;
struct dirent **e;
size_t i;
int dirlen;
char esc[PATH_MAX /* > NAME_MAX */ * 6]; /* strlen("&...;") <= 6 */
/* reset buffer */
memset(buf, 0, sizeof(*buf));
/* read directory */
if ((dirlen = scandir(res->internal_path, &e, NULL, compareent)) < 0) {
return S_FORBIDDEN;
}
if (*progress == 0) {
/* write listing header (sizeof(esc) >= PATH_MAX) */
html_escape(res->path, esc, MIN(PATH_MAX, sizeof(esc)));
if (buffer_appendf(buf,
"<!DOCTYPE html>\n<html>\n\t<head>"
"<title>Index of %s</title></head>\n"
"\t<body>\n\t\t<a href=\"..\">..</a>",
esc) < 0) {
s = S_REQUEST_TIMEOUT;
goto cleanup;
}
}
/* listing entries */
for (i = *progress; i < (size_t)dirlen; i++) {
/* skip hidden files, "." and ".." */
if (e[i]->d_name[0] == '.') {
continue;
}
/* entry line */
html_escape(e[i]->d_name, esc, sizeof(esc));
if (buffer_appendf(buf,
"<br />\n\t\t<a href=\"%s%s\">%s%s</a>",
esc,
(e[i]->d_type == DT_DIR) ? "/" : "",
esc,
suffix(e[i]->d_type))) {
/* buffer full */
break;
}
}
*progress = i;
if (*progress == (size_t)dirlen) {
/* listing footer */
if (buffer_appendf(buf, "\n\t</body>\n</html>\n") < 0) {
s = S_REQUEST_TIMEOUT;
goto cleanup;
}
(*progress)++;
}
cleanup:
while (dirlen--) {
free(e[dirlen]);
}
free(e);
return s;
}
enum status
data_prepare_error_buf(const struct response *res, struct buffer *buf,
size_t *progress)
{
/* reset buffer */
memset(buf, 0, sizeof(*buf));
if (*progress == 0) {
/* write error body */
if (buffer_appendf(buf,
"<!DOCTYPE html>\n<html>\n\t<head>\n"
"\t\t<title>%d %s</title>\n\t</head>\n"
"\t<body>\n\t\t<h1>%d %s</h1>\n"
"\t</body>\n</html>\n",
res->status, status_str[res->status],
res->status, status_str[res->status])) {
return S_INTERNAL_SERVER_ERROR;
}
(*progress)++;
}
return 0;
}
enum status
data_prepare_file_buf(const struct response *res, struct buffer *buf,
size_t *progress)
{
FILE *fp;
enum status s = 0;
ssize_t r;
size_t remaining;
/* reset buffer */
memset(buf, 0, sizeof(*buf));
/* open file */
if (!(fp = fopen(res->internal_path, "r"))) {
s = S_FORBIDDEN;
goto cleanup;
}
/* seek to lower bound + progress */
if (fseek(fp, res->file.lower + *progress, SEEK_SET)) {
s = S_INTERNAL_SERVER_ERROR;
goto cleanup;
}
/* read data into buf */
remaining = res->file.upper - res->file.lower + 1 - *progress;
while ((r = fread(buf->data + buf->len, 1,
MIN(sizeof(buf->data) - buf->len,
remaining), fp))) {
if (r < 0) {
s = S_INTERNAL_SERVER_ERROR;
goto cleanup;
}
buf->len += r;
*progress += r;
remaining -= r;
}
cleanup:
if (fp) {
fclose(fp);
}
return s;
}

+ 0
- 18
.local/src/quark/data.h View File

@ -1,18 +0,0 @@
/* See LICENSE file for copyright and license details. */
#ifndef DATA_H
#define DATA_H
#include "http.h"
#include "util.h"
extern enum status (* const data_fct[])(const struct response *,
struct buffer *, size_t *);
enum status data_prepare_dirlisting_buf(const struct response *,
struct buffer *, size_t *);
enum status data_prepare_error_buf(const struct response *,
struct buffer *, size_t *);
enum status data_prepare_file_buf(const struct response *,
struct buffer *, size_t *);
#endif /* DATA_H */

+ 0
- 1044
.local/src/quark/http.c
File diff suppressed because it is too large
View File


+ 0
- 97
.local/src/quark/http.h View File

@ -1,97 +0,0 @@
/* See LICENSE file for copyright and license details. */
#ifndef HTTP_H
#define HTTP_H
#include <limits.h>
#include <sys/socket.h>
#include "config.h"
#include "server.h"
#include "util.h"
enum req_field {
REQ_HOST,
REQ_RANGE,
REQ_IF_MODIFIED_SINCE,
NUM_REQ_FIELDS,
};
extern const char *req_field_str[];
enum req_method {
M_GET,
M_HEAD,
NUM_REQ_METHODS,
};
extern const char *req_method_str[];
struct request {
enum req_method method;
char path[PATH_MAX];
char query[FIELD_MAX];
char fragment[FIELD_MAX];
char field[NUM_REQ_FIELDS][FIELD_MAX];
};
enum status {
S_OK = 200,
S_PARTIAL_CONTENT = 206,
S_MOVED_PERMANENTLY = 301,
S_NOT_MODIFIED = 304,
S_BAD_REQUEST = 400,
S_FORBIDDEN = 403,
S_NOT_FOUND = 404,
S_METHOD_NOT_ALLOWED = 405,
S_REQUEST_TIMEOUT = 408,
S_RANGE_NOT_SATISFIABLE = 416,
S_REQUEST_TOO_LARGE = 431,
S_INTERNAL_SERVER_ERROR = 500,
S_VERSION_NOT_SUPPORTED = 505,
};
extern const char *status_str[];
enum res_field {
RES_ACCEPT_RANGES,
RES_ALLOW,
RES_LOCATION,
RES_LAST_MODIFIED,
RES_CONTENT_LENGTH,
RES_CONTENT_RANGE,
RES_CONTENT_TYPE,
NUM_RES_FIELDS,
};
extern const char *res_field_str[];
enum res_type {
RESTYPE_DIRLISTING,
RESTYPE_ERROR,
RESTYPE_FILE,
NUM_RES_TYPES,
};
struct response {
enum res_type type;
enum status status;
char field[NUM_RES_FIELDS][FIELD_MAX];
char path[PATH_MAX];
char internal_path[PATH_MAX];
struct vhost *vhost;
struct {
size_t lower;
size_t upper;
} file;
};
enum status http_prepare_header_buf(const struct response *, struct buffer *);
enum status http_send_buf(int, struct buffer *);
enum status http_recv_header(int, struct buffer *, int *);
enum status http_parse_header(const char *, struct request *);
void http_prepare_response(const struct request *, struct response *,
const struct server *);
void http_prepare_error_response(const struct request *,
struct response *, enum status);
#endif /* HTTP_H */

+ 0
- 364
.local/src/quark/main.c View File

@ -1,364 +0,0 @@
/* See LICENSE file for copyright and license details. */
#include <errno.h>
#include <grp.h>
#include <limits.h>
#include <pwd.h>
#include <regex.h>
#include <signal.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <sys/resource.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include "arg.h"
#include "server.h"
#include "sock.h"
#include "util.h"
static char *udsname;
static void
cleanup(void)
{
if (udsname) {
sock_rem_uds(udsname);
}
}
static void
sigcleanup(int sig)
{
cleanup();
kill(0, sig);
_exit(1);
}
static void
handlesignals(void(*hdl)(int))
{
struct sigaction sa = {
.sa_handler = hdl,
};
sigemptyset(&sa.sa_mask);
sigaction(SIGTERM, &sa, NULL);
sigaction(SIGHUP, &sa, NULL);
sigaction(SIGINT, &sa, NULL);
sigaction(SIGQUIT, &sa, NULL);
}
static void
usage(void)
{
const char *opts = "[-u user] [-g group] [-n num] [-d dir] [-l] "
"[-i file] [-v vhost] ... [-m map] ...";
die("usage: %s -p port [-h host] %s\n"
" %s -U file [-p port] %s", argv0,
opts, argv0, opts);
}
int
main(int argc, char *argv[])
{
struct group *grp = NULL;
struct passwd *pwd = NULL;
struct rlimit rlim;
struct server srv = {
.docindex = "index.html",
};
size_t i;
int insock, status = 0;
const char *err;
char *tok[4];
/* defaults */
size_t nthreads = 4;
size_t nslots = 64;
char *servedir = ".";
char *user = "nobody";
char *group = "nogroup";
ARGBEGIN {
case 'd':
servedir = EARGF(usage());
break;
case 'g':
group = EARGF(usage());
break;
case 'h':
srv.host = EARGF(usage());
break;
case 'i':
srv.docindex = EARGF(usage());
if (strchr(srv.docindex, '/')) {
die("The document index must not contain '/'");
}
break;
case 'l':
srv.listdirs = 1;
break;
case 'm':
if (spacetok(EARGF(usage()), tok, 3) || !tok[0] || !tok[1]) {
usage();
}
if (!(srv.map = reallocarray(srv.map, ++srv.map_len,
sizeof(struct map)))) {
die("reallocarray:");
}
srv.map[srv.map_len - 1].from = tok[0];
srv.map[srv.map_len - 1].to = tok[1];
srv.map[srv.map_len - 1].chost = tok[2];
break;
case 's':
err = NULL;
nslots = strtonum(EARGF(usage()), 1, INT_MAX, &err);
if (err) {
die("strtonum '%s': %s", EARGF(usage()), err);
}
break;
case 't':
err = NULL;
nthreads = strtonum(EARGF(usage()), 1, INT_MAX, &err);
if (err) {
die("strtonum '%s': %s", EARGF(usage()), err);
}
break;
case 'p':
srv.port = EARGF(usage());
break;
case 'U':
udsname = EARGF(usage());
break;
case 'u':
user = EARGF(usage());
break;
case 'v':
if (spacetok(EARGF(usage()), tok, 4) || !tok[0] || !tok[1] ||
!tok[2]) {
usage();
}
if (!(srv.vhost = reallocarray(srv.vhost, ++srv.vhost_len,
sizeof(*srv.vhost)))) {
die("reallocarray:");
}
srv.vhost[srv.vhost_len - 1].chost = tok[0];
srv.vhost[srv.vhost_len - 1].regex = tok[1];
srv.vhost[srv.vhost_len - 1].dir = tok[2];
srv.vhost[srv.vhost_len - 1].prefix = tok[3];
break;
default:
usage();
} ARGEND
if (argc) {
usage();
}
/* can't have both host and UDS but must have one of port or UDS*/
if ((srv.host && udsname) || !(srv.port || udsname)) {
usage();
}
if (udsname && (!access(udsname, F_OK) || errno != ENOENT)) {
die("UNIX-domain socket '%s': %s", udsname, errno ?
strerror(errno) : "File exists");
}
/* compile and check the supplied vhost regexes */
for (i = 0; i < srv.vhost_len; i++) {
if (regcomp(&srv.vhost[i].re, srv.vhost[i].regex,
REG_EXTENDED | REG_ICASE | REG_NOSUB)) {
die("regcomp '%s': invalid regex",
srv.vhost[i].regex);
}
}
/* validate user and group */
errno = 0;
if (!user || !(pwd = getpwnam(user))) {
die("getpwnam '%s': %s", user ? user : "null",
errno ? strerror(errno) : "Entry not found");
}
errno = 0;
if (!group || !(grp = getgrnam(group))) {
die("getgrnam '%s': %s", group ? group : "null",
errno ? strerror(errno) : "Entry not found");
}
/* open a new process group */
setpgid(0, 0);
handlesignals(sigcleanup);
/*
* set the maximum number of open file descriptors as needed
* - 3 initial fd's
* - nthreads fd's for the listening socket
* - (nthreads * nslots) fd's for the connection-fd
* - (5 * nthreads) fd's for general purpose thread-use
*/
rlim.rlim_cur = rlim.rlim_max = 3 + nthreads + nthreads * nslots +
5 * nthreads;
if (setrlimit(RLIMIT_NOFILE, &rlim) < 0) {
if (errno == EPERM) {
die("You need to run as root or have "
"CAP_SYS_RESOURCE set, or are asking for more "
"file descriptors than the system can offer");
} else {
die("setrlimit:");
}
}
/*
* create the (non-blocking) listening socket
*
* we could use SO_REUSEPORT and create a listening socket for
* each thread (for better load-balancing, given each thread
* would get his own kernel-queue), but this increases latency
* (as a thread might get stuck on a larger request, making all
* other request wait in line behind it).
*
* socket contention with a single listening socket is a
* non-issue and thread-load-balancing is better fixed in the
* kernel by changing epoll-sheduling from a FIFO- to a
* LIFO-model, especially as it doesn't affect performance
*/
insock = udsname ? sock_get_uds(udsname, pwd->pw_uid, grp->gr_gid) :
sock_get_ips(srv.host, srv.port);
if (sock_set_nonblocking(insock)) {
return 1;
}
/*
* before dropping privileges, we fork, as we need to remove
* the UNIX-domain socket when we shut down, which we need
* privileges for
*/
switch (fork()) {
case -1:
warn("fork:");
break;
case 0:
/* restore default handlers */
handlesignals(SIG_DFL);
/* reap children automatically */
if (signal(SIGCHLD, SIG_IGN) == SIG_ERR) {
die("signal: Failed to set SIG_IGN on SIGCHLD");
}
if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) {
die("signal: Failed to set SIG_IGN on SIGPIPE");
}
/*
* try increasing the thread-limit by the number
* of threads we need (which is the only reliable
* workaround I know given the thread-limit is per user
* rather than per process), but ignore EPERM errors,
* because this most probably means the user has already
* set the value to the kernel's limit, and there's not
* much we can do in any other case.
* There's also no danger of overflow as the value
* returned by getrlimit() is way below the limits of the
* rlim_t datatype.
*/
if (getrlimit(RLIMIT_NPROC, &rlim) < 0) {
die("getrlimit:");
}
if (rlim.rlim_max == RLIM_INFINITY) {
if (rlim.rlim_cur != RLIM_INFINITY) {
/* try increasing current limit by nthreads */
rlim.rlim_cur += nthreads;
}
} else {
/* try increasing current and hard limit by nthreads */
rlim.rlim_cur = rlim.rlim_max += nthreads;
}
if (setrlimit(RLIMIT_NPROC, &rlim) < 0 && errno != EPERM) {
die("setrlimit()");
}
/* limit ourselves to reading the servedir and block further unveils */
eunveil(servedir, "r");
eunveil(NULL, NULL);
/* chroot */
if (chdir(servedir) < 0) {
die("chdir '%s':", servedir);
}
if (chroot(".") < 0) {
if (errno == EPERM) {
die("You need to run as root or have "
"CAP_SYS_CHROOT set");
} else {
die("chroot:");
}
}
/* drop root */
if (pwd->pw_uid == 0 || grp->gr_gid == 0) {
die("Won't run under root %s for hopefully obvious reasons",
(pwd->pw_uid == 0) ? (grp->gr_gid == 0) ?
"user and group" : "user" : "group");
}
if (setgroups(1, &(grp->gr_gid)) < 0) {
if (errno == EPERM) {
die("You need to run as root or have "
"CAP_SETGID set");
} else {
die("setgroups:");
}
}
if (setgid(grp->gr_gid) < 0) {
if (errno == EPERM) {
die("You need to run as root or have "
"CAP_SETGID set");
} else {
die("setgid:");
}
}
if (setuid(pwd->pw_uid) < 0) {
if (errno == EPERM) {
die("You need to run as root or have "
"CAP_SETUID set");
} else {
die("setuid:");
}
}
if (udsname) {
epledge("stdio rpath proc unix", NULL);
} else {
epledge("stdio rpath proc inet", NULL);
}
/* accept incoming connections */
server_init_thread_pool(insock, nthreads, nslots, &srv);
exit(0);
default:
/* limit ourselves even further while we are waiting */
if (udsname) {
eunveil(udsname, "c");
eunveil(NULL, NULL);
epledge("stdio cpath", NULL);
} else {
eunveil("/", "");
eunveil(NULL, NULL);
epledge("stdio", NULL);
}
while (wait(&status) > 0)
;
}
cleanup();
return status;
}

+ 0
- 137
.local/src/quark/quark.1 View File

@ -1,137 +0,0 @@
.Dd 2020-09-27
.Dt QUARK 1
.Os suckless.org
.Sh NAME
.Nm quark
.Nd simple static web server
.Sh SYNOPSIS
.Nm
.Fl p Ar port
.Op Fl h Ar host
.Op Fl u Ar user
.Op Fl g Ar group
.Op Fl s Ar num
.Op Fl t Ar num
.Op Fl d Ar dir
.Op Fl l
.Op Fl i Ar file
.Oo Fl v Ar vhost Oc ...
.Oo Fl m Ar map Oc ...
.Nm
.Fl U Ar file
.Op Fl p Ar port
.Op Fl u Ar user
.Op Fl g Ar group
.Op Fl s Ar num
.Op Fl t Ar num
.Op Fl d Ar dir
.Op Fl l
.Op Fl i Ar file
.Oo Fl v Ar vhost Oc ...
.Oo Fl m Ar map Oc ...
.Sh DESCRIPTION
.Nm
is a simple HTTP GET/HEAD-only web server for static content.
It supports virtual hosts (see
.Fl v ) ,
explicit redirects (see
.Fl m ) ,
directory listings (see
.Fl l ) ,
conditional "If-Modified-Since"-requests (RFC 7232), range requests
(RFC 7233) and well-known URIs (RFC 8615), while refusing to serve
hidden files and directories.
.Sh OPTIONS
.Bl -tag -width Ds
.It Fl d Ar dir
Serve
.Ar dir
after chrooting into it.
The default is ".".
.It Fl g Ar group
Set group ID when dropping privileges, and in socket mode the group of the
socket file, to the ID of
.Ar group .
The default is "nogroup".
.It Fl h Ar host
Use
.Ar host
as the server hostname.
The default is the loopback interface (i.e. localhost).
.It Fl i Ar file
Set
.Ar file
as the directory index.
The default is "index.html".
.It Fl l
Enable directory listing.
.It Fl m Ar map
Add the URI prefix mapping rule specified by
.Ar map ,
which has the form
.Qq Pa from to [chost] ,
where each element is separated with spaces (0x20) that can be
escaped with '\\'.
.Pp
The prefix
.Pa from
of all matching URIs is replaced with
.Pa to ,
optionally limited to the canonical virtual host
.Pa chost .
If no virtual hosts are given,
.Pa chost
is ignored.
.It Fl p Ar port
In host mode, listen on port
.Ar port
for incoming connections.
In socket mode, use
.Ar port
for constructing proper virtual host
redirects on non-standard ports.
.It Fl U Ar file
Create the UNIX-domain socket
.Ar file ,
listen on it for incoming connections and remove it on exit.
.It Fl s Ar num
Set the number of connection slots per worker thread to
.Ar num .
The default is 64.
.It Fl t Ar num
Set the number of worker threads to
.Ar num .
The default is 4.
.It Fl u Ar user
Set user ID when dropping privileges,
and in socket mode the user of the socket file,
to the ID of
.Ar user .
The default is "nobody".
.It Fl v Ar vhost
Add the virtual host specified by
.Ar vhost ,
which has the form
.Qq Pa chost regex dir [prefix] ,
where each element is separated with spaces (0x20) that can be
escaped with '\\'.
.Pp
A request matching the virtual host regular expression
.Pa regex
(see
.Xr regex 3 )
is redirected to the canonical host
.Pa chost ,
if they differ, using the directory
.Pa dir
as the root directory, optionally prefixing the URI with
.Pa prefix .
If any virtual hosts are specified, all requests on non-matching
hosts are discarded.
.El
.Sh CUSTOMIZATION
.Nm
can be customized by creating a custom config.h from config.def.h and
(re)compiling the source code. This keeps it fast, secure and simple.
.Sh AUTHORS
.An Laslo Hunhold Aq Mt dev@frign.de

+ 0
- 217
.local/src/quark/queue.c View File

@ -1,217 +0,0 @@
/* See LICENSE file for copyright and license details. */
#include <stddef.h>
#ifdef __linux__
#include <sys/epoll.h>
#else
#include <sys/types.h>
#include <sys/event.h>
#include <sys/time.h>
#endif
#include "queue.h"
#include "util.h"
int
queue_create(void)
{
int qfd;
#ifdef __linux__
if ((qfd = epoll_create1(0)) < 0) {
warn("epoll_create1:");
}
#else
if ((qfd = kqueue()) < 0) {
warn("kqueue:");
}
#endif
return qfd;
}
int
queue_add_fd(int qfd, int fd, enum queue_event_type t, int shared,
const void *data)
{
#ifdef __linux__
struct epoll_event e;
/* set event flag */
if (shared) {
/*
* if the fd is shared, "exclusive" is the only
* way to avoid spurious wakeups and "blocking"
* accept()'s.
*/
e.events = EPOLLEXCLUSIVE;
} else {
/*
* if we have the fd for ourselves (i.e. only
* within the thread), we want to be
* edge-triggered, as our logic makes sure
* that the buffers are drained when we return
* to epoll_wait()
*/
e.events = EPOLLET;
}
switch (t) {
case QUEUE_EVENT_IN:
e.events |= EPOLLIN;
break;
case QUEUE_EVENT_OUT:
e.events |= EPOLLOUT;
break;
}
/* set data pointer */
e.data.ptr = (void *)data;
/* register fd in the interest list */
if (epoll_ctl(qfd, EPOLL_CTL_ADD, fd, &e) < 0) {
warn("epoll_ctl:");
return -1;
}
#else
struct kevent e;
int events;
/* prepare event flag */
events = (shared) ? 0 : EV_CLEAR;
switch (t) {
case QUEUE_EVENT_IN:
events |= EVFILT_READ;
break;
case QUEUE_EVENT_OUT:
events |= EVFILT_WRITE;
break;
}
EV_SET(&e, fd, events, EV_ADD, 0, 0, (void *)data);
if (kevent(qfd, &e, 1, NULL, 0, NULL) < 0) {
warn("kevent:");
return -1;
}
#endif
return 0;
}
int
queue_mod_fd(int qfd, int fd, enum queue_event_type t, const void *data)
{
#ifdef __linux__
struct epoll_event e;
/* set event flag (only for non-shared fd's) */
e.events = EPOLLET;
switch (t) {
case QUEUE_EVENT_IN:
e.events |= EPOLLIN;
break;
case QUEUE_EVENT_OUT:
e.events |= EPOLLOUT;
break;
}
/* set data pointer */
e.data.ptr = (void *)data;
/* register fd in the interest list */
if (epoll_ctl(qfd, EPOLL_CTL_MOD, fd, &e) < 0) {
warn("epoll_ctl:");
return -1;
}
#else
struct kevent e;
int events;
events = EV_CLEAR;
switch (t) {
case QUEUE_EVENT_IN:
events |= EVFILT_READ;
break;
case QUEUE_EVENT_OUT:
events |= EVFILT_WRITE;
break;
}
EV_SET(&e, fd, events, EV_ADD, 0, 0, (void *)data);
if (kevent(qfd, &e, 1, NULL, 0, NULL) < 0) {
warn("kevent:");
return -1;
}
#endif
return 0;
}
int
queue_rem_fd(int qfd, int fd)
{
#ifdef __linux__
struct epoll_event e;
if (epoll_ctl(qfd, EPOLL_CTL_DEL, fd, &e) < 0) {
warn("epoll_ctl:");
return -1;
}
#else
struct kevent e;
EV_SET(&e, fd, 0, EV_DELETE, 0, 0, 0);
if (kevent(qfd, &e, 1, NULL, 0, NULL) < 0) {
warn("kevent:");
return -1;
}
#endif
return 0;
}
ssize_t
queue_wait(int qfd, queue_event *e, size_t elen)
{
ssize_t nready;
#ifdef __linux__
if ((nready = epoll_wait(qfd, e, elen, -1)) < 0) {
warn("epoll_wait:");
return -1;
}
#else
if ((nready = kevent(qfd, NULL, 0, e, elen, NULL)) < 0) {
warn("kevent:");
return -1;
}
#endif
return nready;
}
void *
queue_event_get_data(const queue_event *e)
{
#ifdef __linux__
return e->data.ptr;
#else
return e->udata;
#endif
}
int
queue_event_is_error(const queue_event *e)
{
#ifdef __linux__
return (e->events & ~(EPOLLIN | EPOLLOUT)) ? 1 : 0;
#else
return (e->flags & EV_EOF) ? 1 : 0;
#endif
}

+ 0
- 33
.local/src/quark/queue.h View File

@ -1,33 +0,0 @@
#ifndef QUEUE_H
#define QUEUE_H
#include <stddef.h>
#ifdef __linux__
#include <sys/epoll.h>
typedef struct epoll_event queue_event;
#else
#include <sys/types.h>
#include <sys/event.h>
#include <sys/time.h>
typedef struct kevent queue_event;
#endif
enum queue_event_type {
QUEUE_EVENT_IN,
QUEUE_EVENT_OUT,
};
int queue_create(void);
int queue_add_fd(int, int, enum queue_event_type, int, const void *);
int queue_mod_fd(int, int, enum queue_event_type, const void *);
int queue_rem_fd(int, int);
ssize_t queue_wait(int, queue_event *, size_t);
void *queue_event_get_data(const queue_event *);
int queue_event_is_error(const queue_event *e);
#endif /* QUEUE_H */

+ 0
- 177
.local/src/quark/server.c View File

@ -1,177 +0,0 @@
/* See LICENSE file for copyright and license details. */
#include <errno.h>
#include <pthread.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include "connection.h"
#include "queue.h"
#include "server.h"
#include "util.h"
struct worker_data {
int insock;
size_t nslots;
const struct server *srv;
};
static void *
server_worker(void *data)
{
queue_event *event = NULL;
struct connection *connection, *c, *newc;
struct worker_data *d = (struct worker_data *)data;
int qfd;
ssize_t nready;
size_t i;
/* allocate connections */
if (!(connection = calloc(d->nslots, sizeof(*connection)))) {
die("calloc:");
}
/* create event queue */
if ((qfd = queue_create()) < 0) {
exit(1);
}
/* add insock to the interest list (with data=NULL) */
if (queue_add_fd(qfd, d->insock, QUEUE_EVENT_IN, 1, NULL) < 0) {
exit(1);
}
/* allocate event array */
if (!(event = reallocarray(event, d->nslots, sizeof(*event)))) {
die("reallocarray:");
}
for (;;) {
/* wait for new activity */
if ((nready = queue_wait(qfd, event, d->nslots)) < 0) {
exit(1);
}
/* handle events */
for (i = 0; i < (size_t)nready; i++) {
c = queue_event_get_data(&event[i]);
if (queue_event_is_error(&event[i])) {
if (c != NULL) {
queue_rem_fd(qfd, c->fd);
c->res.status = 0;
connection_log(c);
connection_reset(c);
}
continue;
}
if (c == NULL) {
/* add new connection to the interest list */
if (!(newc = connection_accept(d->insock,
connection,
d->nslots))) {
/*
* the socket is either blocking
* or something failed.
* In both cases, we just carry on
*/
continue;
}
/*
* add event to the interest list
* (we want IN, because we start
* with receiving the header)
*/
if (queue_add_fd(qfd, newc->fd,
QUEUE_EVENT_IN,
0, newc) < 0) {
/* not much we can do here */
continue;
}
} else {
/* serve existing connection */
connection_serve(c, d->srv);
if (c->fd == 0) {
/* we are done */
memset(c, 0, sizeof(struct connection));
continue;
}
/*
* rearm the event based on the state
* we are "stuck" at
*/
switch(c->state) {
case C_RECV_HEADER:
if (queue_mod_fd(qfd, c->fd,
QUEUE_EVENT_IN,
c) < 0) {
connection_reset(c);
break;
}
break;
case C_SEND_HEADER:
case C_SEND_BODY:
if (queue_mod_fd(qfd, c->fd,
QUEUE_EVENT_OUT,
c) < 0) {
connection_reset(c);
break;
}
break;
default:
break;
}
}
}
}
return NULL;
}
void
server_init_thread_pool(int insock, size_t nthreads, size_t nslots,
const struct server *srv)
{
pthread_t *thread = NULL;
struct worker_data *d = NULL;
size_t i;
/* allocate worker_data structs */
if (!(d = reallocarray(d, nthreads, sizeof(*d)))) {
die("reallocarray:");
}
for (i = 0; i < nthreads; i++) {
d[i].insock = insock;
d[i].nslots = nslots;
d[i].srv = srv;
}
/* allocate and initialize thread pool */
if (!(thread = reallocarray(thread, nthreads, sizeof(*thread)))) {
die("reallocarray:");
}
for (i = 0; i < nthreads; i++) {
if (pthread_create(&thread[i], NULL, server_worker, &d[i]) != 0) {
if (errno == EAGAIN) {
die("You need to run as root or have "
"CAP_SYS_RESOURCE set, or are trying "
"to create more threads than the "
"system can offer");
} else {
die("pthread_create:");
}
}
}
/* wait for threads */
for (i = 0; i < nthreads; i++) {
if ((errno = pthread_join(thread[i], NULL))) {
warn("pthread_join:");
}
}
}

+ 0
- 35
.local/src/quark/server.h View File

@ -1,35 +0,0 @@
/* See LICENSE file for copyright and license details. */
#ifndef SERVER_H
#define SERVER_H
#include <regex.h>
#include <stddef.h>
struct vhost {
char *chost;
char *regex;
char *dir;
char *prefix;
regex_t re;
};
struct map {
char *chost;
char *from;
char *to;
};
struct server {
char *host;
char *port;
char *docindex;
int listdirs;
struct vhost *vhost;
size_t vhost_len;
struct map *map;
size_t map_len;
};
void server_init_thread_pool(int, size_t, size_t, const struct server *);
#endif /* SERVER_H */

+ 0
- 209
.local/src/quark/sock.c View File

@ -1,209 +0,0 @@
/* See LICENSE file for copyright and license details. */
#include <arpa/inet.h>
#include <errno.h>
#include <fcntl.h>
#include <netdb.h>
#include <netinet/in.h>
#include <stddef.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/un.h>
#include <unistd.h>
#include "sock.h"
#include "util.h"
int
sock_get_ips(const char *host, const char* port)
{
struct addrinfo hints = {
.ai_flags = AI_NUMERICSERV,
.ai_family = AF_UNSPEC,
.ai_socktype = SOCK_STREAM,
};
struct addrinfo *ai, *p;
int ret, insock = 0;
if ((ret = getaddrinfo(host, port, &hints, &ai))) {
die("getaddrinfo: %s", gai_strerror(ret));
}
for (p = ai; p; p = p->ai_next) {
if ((insock = socket(p->ai_family, p->ai_socktype,
p->ai_protocol)) < 0) {
continue;
}
if (setsockopt(insock, SOL_SOCKET, SO_REUSEADDR,
&(int){1}, sizeof(int)) < 0) {
die("setsockopt:");
}
if (bind(insock, p->ai_addr, p->ai_addrlen) < 0) {
/* bind failed, close the insock and retry */
if (close(insock) < 0) {
die("close:");
}
continue;
}
break;
}
freeaddrinfo(ai);
if (!p) {
/* we exhaustet the addrinfo-list and found no connection */
if (errno == EACCES) {
die("You need to run as root or have "
"CAP_NET_BIND_SERVICE set to bind to "
"privileged ports");
} else {
die("bind:");
}
}
if (listen(insock, SOMAXCONN) < 0) {
die("listen:");
}
return insock;
}
int
sock_get_uds(const char *udsname, uid_t uid, gid_t gid)
{
struct sockaddr_un addr = {
.sun_family = AF_UNIX,
};
size_t udsnamelen;
int insock, sockmode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP |
S_IROTH | S_IWOTH;
if ((insock = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
die("socket:");
}
if ((udsnamelen = strlen(udsname)) > sizeof(addr.sun_path) - 1) {
die("UNIX-domain socket name truncated");
}
memcpy(addr.sun_path, udsname, udsnamelen + 1);
if (bind(insock, (const struct sockaddr *)&addr, sizeof(addr)) < 0) {
die("bind '%s':", udsname);
}
if (listen(insock, SOMAXCONN) < 0) {
sock_rem_uds(udsname);
die("listen:");
}
if (chmod(udsname, sockmode) < 0) {
sock_rem_uds(udsname);
die("chmod '%s':", udsname);
}
if (chown(udsname, uid, gid) < 0) {
sock_rem_uds(udsname);
die("chown '%s':", udsname);
}
return insock;
}
void
sock_rem_uds(const char *udsname)
{
if (unlink(udsname) < 0) {
die("unlink '%s':", udsname);
}
}
int
sock_set_timeout(int fd, int sec)
{
struct timeval tv;
tv.tv_sec = sec;
tv.tv_usec = 0;
if (setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0 ||
setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)) < 0) {
warn("setsockopt:");
return 1;
}
return 0;
}
int
sock_set_nonblocking(int fd)
{
int flags;
if ((flags = fcntl(fd, F_GETFL, 0)) < 0) {
warn("fcntl:");
return 1;
}
flags |= O_NONBLOCK;
if (fcntl(fd, F_SETFL, flags) < 0) {
warn("fcntl:");
return 1;
}
return 0;
}
int
sock_get_inaddr_str(const struct sockaddr_storage *in_sa, char *str,
size_t len)
{
switch (in_sa->ss_family) {
case AF_INET:
if (!inet_ntop(AF_INET,
&(((struct sockaddr_in *)in_sa)->sin_addr),
str, len)) {
warn("inet_ntop:");
return 1;
}
break;
case AF_INET6:
if (!inet_ntop(AF_INET6,
&(((struct sockaddr_in6 *)in_sa)->sin6_addr),
str, len)) {
warn("inet_ntop:");
return 1;
}
break;
case AF_UNIX:
snprintf(str, len, "uds");
break;
default:
snprintf(str, len, "-");
}
return 0;
}
int
sock_same_addr(const struct sockaddr_storage *sa1, const struct sockaddr_storage *sa2)
{
/* return early if address-families don't match */
if (sa1->ss_family != sa2->ss_family) {
return 0;
}
switch (sa1->ss_family) {
case AF_INET6:
return memcmp(((struct sockaddr_in6 *)sa1)->sin6_addr.s6_addr,
((struct sockaddr_in6 *)sa2)->sin6_addr.s6_addr,
sizeof(((struct sockaddr_in6 *)sa1)->sin6_addr.s6_addr));
case AF_INET:
return ntohl(((struct sockaddr_in *)sa1)->sin_addr.s_addr) ==
ntohl(((struct sockaddr_in *)sa2)->sin_addr.s_addr);
default: /* AF_UNIX */
return strcmp(((struct sockaddr_un *)sa1)->sun_path,
((struct sockaddr_un *)sa2)->sun_path) == 0;
}
}

+ 0
- 18
.local/src/quark/sock.h View File

@ -1,18 +0,0 @@
/* See LICENSE file for copyright and license details. */
#ifndef SOCK_H
#define SOCK_H
#include <stddef.h>
#include <sys/socket.h>
#include <sys/types.h>
int sock_get_ips(const char *, const char *);
int sock_get_uds(const char *, uid_t, gid_t);
void sock_rem_uds(const char *);
int sock_set_timeout(int, int);
int sock_set_nonblocking(int);
int sock_get_inaddr_str(const struct sockaddr_storage *, char *, size_t);
int sock_same_addr(const struct sockaddr_storage *,
const struct sockaddr_storage *);
#endif /* SOCK_H */

+ 0
- 281
.local/src/quark/util.c View File

@ -1,281 +0,0 @@
/* See LICENSE file for copyright and license details. */
#include <errno.h>
#include <limits.h>
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <time.h>
#ifdef __OpenBSD__
#include <unistd.h>
#endif /* __OpenBSD__ */
#include "util.h"
char *argv0;
static void
verr(const char *fmt, va_list ap)
{
if (argv0 && strncmp(fmt, "usage", sizeof("usage") - 1)) {
fprintf(stderr, "%s: ", argv0);
}
vfprintf(stderr, fmt, ap);
if (fmt[0] && fmt[strlen(fmt) - 1] == ':') {
fputc(' ', stderr);
perror(NULL);
} else {
fputc('\n', stderr);
}
}
void
warn(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
verr(fmt, ap);
va_end(ap);
}
void
die(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
verr(fmt, ap);
va_end(ap);
exit(1);
}
void
epledge(const char *promises, const char *execpromises)
{
(void)promises;
(void)execpromises;
#ifdef __OpenBSD__
if (pledge(promises, execpromises) == -1) {
die("pledge:");
}
#endif /* __OpenBSD__ */
}
void
eunveil(const char *path, const char *permissions)
{
(void)path;
(void)permissions;
#ifdef __OpenBSD__
if (unveil(path, permissions) == -1) {
die("unveil:");
}
#endif /* __OpenBSD__ */
}
int
timestamp(char *buf, size_t len, time_t t)
{
struct tm tm;
if (gmtime_r(&t, &tm) == NULL ||
strftime(buf, len, "%a, %d %b %Y %T GMT", &tm) == 0) {
return 1;
}
return 0;
}
int
esnprintf(char *str, size_t size, const char *fmt, ...)
{
va_list ap;
int ret;
va_start(ap, fmt);
ret = vsnprintf(str, size, fmt, ap);
va_end(ap);
return (ret < 0 || (size_t)ret >= size);
}
int
prepend(char *str, size_t size, const char *prefix)
{
size_t len = strlen(str), prefixlen = strlen(prefix);
if (len + prefixlen + 1 > size) {
return 1;
}
memmove(str + prefixlen, str, len + 1);
memcpy(str, prefix, prefixlen);
return 0;
}
int
spacetok(const char *s, char **t, size_t tlen)
{
const char *tok;
size_t i, j, toki, spaces;
/* fill token-array with NULL-pointers */
for (i = 0; i < tlen; i++) {
t[i] = NULL;
}
toki = 0;
/* don't allow NULL string or leading spaces */
if (!s || *s == ' ') {
return 1;
}
start:
/* skip spaces */
for (; *s == ' '; s++)
;
/* don't allow trailing spaces */
if (*s == '\0') {
goto err;
}
/* consume token */
for (tok = s, spaces = 0; ; s++) {
if (*s == '\\' && *(s + 1) == ' ') {
spaces++;
s++;
continue;
} else if (*s == ' ') {
/* end of token */
goto token;
} else if (*s == '\0') {
/* end of string */
goto token;
}
}
token:
if (toki >= tlen) {
goto err;
}
if (!(t[toki] = malloc(s - tok - spaces + 1))) {
die("malloc:");
}
for (i = 0, j = 0; j < s - tok - spaces + 1; i++, j++) {
if (tok[i] == '\\' && tok[i + 1] == ' ') {
i++;
}
t[toki][j] = tok[i];
}
t[toki][s - tok - spaces] = '\0';
toki++;
if (*s == ' ') {
s++;
goto start;
}
return 0;
err:
for (i = 0; i < tlen; i++) {
free(t[i]);
t[i] = NULL;
}
return 1;
}
#define INVALID 1
#define TOOSMALL 2
#define TOOLARGE 3
long long
strtonum(const char *numstr, long long minval, long long maxval,
const char **errstrp)
{
long long ll = 0;
int error = 0;
char *ep;
struct errval {
const char *errstr;
int err;
} ev[4] = {
{ NULL, 0 },
{ "invalid", EINVAL },
{ "too small", ERANGE },
{ "too large", ERANGE },
};
ev[0].err = errno;
errno = 0;
if (minval > maxval) {
error = INVALID;
} else {
ll = strtoll(numstr, &ep, 10);
if (numstr == ep || *ep != '\0')
error = INVALID;
else if ((ll == LLONG_MIN && errno == ERANGE) || ll < minval)
error = TOOSMALL;
else if ((ll == LLONG_MAX && errno == ERANGE) || ll > maxval)
error = TOOLARGE;
}
if (errstrp != NULL)
*errstrp = ev[error].errstr;
errno = ev[error].err;
if (error)
ll = 0;
return ll;
}
/*
* This is sqrt(SIZE_MAX+1), as s1*s2 <= SIZE_MAX
* if both s1 < MUL_NO_OVERFLOW and s2 < MUL_NO_OVERFLOW
*/
#define MUL_NO_OVERFLOW ((size_t)1 << (sizeof(size_t) * 4))
void *
reallocarray(void *optr, size_t nmemb, size_t size)
{
if ((nmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) &&
nmemb > 0 && SIZE_MAX / nmemb < size) {
errno = ENOMEM;
return NULL;
}
return realloc(optr, size * nmemb);
}
int
buffer_appendf(struct buffer *buf, const char *suffixfmt, ...)
{
va_list ap;
int ret;
va_start(ap, suffixfmt);
ret = vsnprintf(buf->data + buf->len,
sizeof(buf->data) - buf->len, suffixfmt, ap);
va_end(ap);
if (ret < 0 || (size_t)ret >= (sizeof(buf->data) - buf->len)) {
/* truncation occured, discard and error out */
memset(buf->data + buf->len, 0,
sizeof(buf->data) - buf->len);
return 1;
}
/* increase buffer length by number of bytes written */
buf->len += ret;
return 0;
}

+ 0
- 42
.local/src/quark/util.h View File

@ -1,42 +0,0 @@
/* See LICENSE file for copyright and license details. */
#ifndef UTIL_H
#define UTIL_H
#include <regex.h>
#include <stddef.h>
#include <time.h>
#include "config.h"
/* general purpose buffer */
struct buffer {
char data[BUFFER_SIZE];
size_t len;
};
#undef MIN
#define MIN(x,y) ((x) < (y) ? (x) : (y))
#undef MAX
#define MAX(x,y) ((x) > (y) ? (x) : (y))
#undef LEN
#define LEN(x) (sizeof (x) / sizeof *(x))
extern char *argv0;
void warn(const char *, ...);
void die(const char *, ...);
void epledge(const char *, const char *);
void eunveil(const char *, const char *);
int timestamp(char *, size_t, time_t);
int esnprintf(char *, size_t, const char *, ...);
int prepend(char *, size_t, const char *);
int spacetok(const char *, char **, size_t);
void *reallocarray(void *, size_t, size_t);
long long strtonum(const char *, long long, long long, const char **);
int buffer_appendf(struct buffer *, const char *, ...);
#endif /* UTIL_H */

+ 0
- 21
.local/src/slock/.ccls-cache/@home@yigit@.local@src@a@s/config.h View File

@ -1,21 +0,0 @@
/* user and group to drop privileges to */
static const char *user = "nobody";
static const char *group = "nogroup";
static const char *colorname[NUMCOLS] = {
[INIT] = "black", /* after initialization */
[INPUT] = "#005577", /* during input */
[FAILED] = "#CC3333", /* wrong password */
};
/* treat a cleared input like a wrong password (color) */
static const int failonclear = 1;
/*Enable blur*/
//#define BLUR
/*Set blur radius*/
static const int blurRadius=5;
/*Enable Pixelation*/
#define PIXELATION
/*Set pixelation radius*/
static const int pixelSize=6;

BIN
.local/src/slock/.ccls-cache/@home@yigit@.local@src@a@s/config.h.blob View File


+ 21
- 2
.local/src/slock/config.h View File

@ -3,13 +3,13 @@ static const char *user = "nobody";
static const char *group = "nogroup";
static const char *colorname[NUMCOLS] = {
[INIT] = "black", /* after initialization */
[INIT] = "#black", /* after initialization */
[INPUT] = "#005577", /* during input */
[FAILED] = "#CC3333", /* wrong password */
};
/* treat a cleared input like a wrong password (color) */
static const int failonclear = 1;
static const int failonclear = 0;
/*Enable blur*/
//#define BLUR
@ -19,3 +19,22 @@ static const int blurRadius=5;
#define PIXELATION
/*Set pixelation radius*/
static const int pixelSize=10;
/* insert grid pattern with scale 1:1, the size can be changed with logosize */
static const int logosize = 75;
static const int logow = 12; /* grid width and height for right center alignment*/
static const int logoh = 6;
static XRectangle rectangles[9] = {
/* x y w h */
{ 0, 3, 1, 3 },
{ 1, 3, 2, 1 },
{ 0, 5, 8, 1 },
{ 3, 0, 1, 5 },
{ 5, 3, 1, 2 },
{ 7, 3, 1, 2 },
{ 8, 3, 4, 1 },
{ 9, 4, 1, 2 },
{ 11, 4, 1, 2 },
};

+ 11
- 3
.local/src/slock/config.mk View File

@ -10,12 +10,20 @@ MANPREFIX = ${PREFIX}/share/man
X11INC = /usr/X11R6/include
X11LIB = /usr/X11R6/lib
# Xinerama, comment if you don't want it
XINERAMALIBS = -lXinerama
XINERAMAFLAGS = -DXINERAMA
# freetype
FREETYPELIBS = -lXft
FREETYPEINC = /usr/include/freetype2
# includes and libs
INCS = -I. -I/usr/include -I${X11INC}
LIBS = -L/usr/lib -lc -lcrypt -L${X11LIB} -lX11 -lXext -lXrandr -lImlib2
INCS = -I. -I/usr/include -I${X11INC} -I${FREETYPEINC}
LIBS = -L/usr/lib -lc -lcrypt -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} -lXext -lXrandr -lImlib2
# flags
CPPFLAGS = -DVERSION=\"${VERSION}\" -D_DEFAULT_SOURCE -DHAVE_SHADOW_H
CPPFLAGS = -DVERSION=\"${VERSION}\" -D_DEFAULT_SOURCE -DHAVE_SHADOW_H ${XINERAMAFLAGS}
CFLAGS = -std=c99 -pedantic -Wall -Ofast ${INCS} ${CPPFLAGS}
LDFLAGS = -s ${LIBS}
COMPATSRC = explicit_bzero.c


BIN
.local/src/slock/slock View File


+ 81
- 10
.local/src/slock/slock.c View File

@ -1,5 +1,6 @@
/* See LICENSE file for license details. */
#define _XOPEN_SOURCE 500
#define LENGTH(X) (sizeof X / sizeof X[0])
#if HAVE_SHADOW_H
#include <shadow.h>
#endif
@ -15,9 +16,13 @@
#include <unistd.h>
#include <sys/types.h>
#include <X11/extensions/Xrandr.h>
#ifdef XINERAMA
#include <X11/extensions/Xinerama.h>
#endif
#include <X11/keysym.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xft/Xft.h>
#include <Imlib2.h>
#include "arg.h"
@ -32,12 +37,19 @@ enum {
NUMCOLS
};
#include "config.h"
struct lock {
int screen;
Window root, win;
Pixmap pmap;
Pixmap bgmap;
unsigned long colors[NUMCOLS];
unsigned int x, y;
unsigned int xoff, yoff, mw, mh;
Drawable drawable;
GC gc;
XRectangle rectangles[LENGTH(rectangles)];
};
struct xrandr {
@ -46,8 +58,6 @@ struct xrandr {
int errbase;
};
#include "config.h"
Imlib_Image image;
static void
@ -61,6 +71,30 @@ die(const char *errstr, ...)
exit(1);
}
static void
resizerectangles(struct lock *lock)
{
int i;
for (i = 0; i < LENGTH(rectangles); i++){
lock->rectangles[i].x = (rectangles[i].x * logosize)
+ lock->xoff + ((lock->mw) / 2) - (logow / 2 * logosize);
lock->rectangles[i].y = (rectangles[i].y * logosize)
+ lock->yoff + ((lock->mh) / 2) - (logoh / 2 * logosize);
lock->rectangles[i].width = rectangles[i].width * logosize;
lock->rectangles[i].height = rectangles[i].height * logosize;
}
}
static void
drawlogo(Display *dpy, struct lock *lock, int color)
{
XSetForeground(dpy, lock->gc, lock->colors[color]);
XFillRectangles(dpy, lock->win, lock->gc, lock->rectangles, LENGTH(rectangles));
XSync(dpy, False);
}
#ifdef __linux__
#include <fcntl.h>
#include <linux/oom.h>
@ -194,11 +228,15 @@ readpw(Display *dpy, struct xrandr *rr, struct lock **locks, int nscreens,
color = len ? INPUT : ((failure || failonclear) ? FAILED : INIT);
if (running && oldc != color) {
for (screen = 0; screen < nscreens; screen++) {
if(locks[screen]->bgmap)
if(locks[screen]->bgmap){
XSetWindowBackgroundPixmap(dpy, locks[screen]->win, locks[screen]->bgmap);
}
else
XSetWindowBackground(dpy, locks[screen]->win, locks[screen]->colors[0]);
XClearWindow(dpy, locks[screen]->win);
if ( len || failure || failonclear)
drawlogo(dpy, locks[screen], color);
}
oldc = color;
}
@ -233,14 +271,37 @@ lockscreen(Display *dpy, struct xrandr *rr, int screen)
XColor color, dummy;
XSetWindowAttributes wa;
Cursor invisible;
#ifdef XINERAMA
XineramaScreenInfo *info;
int n;
#endif
if (dpy == NULL || screen < 0 || !(lock = malloc(sizeof(struct lock))))
return NULL;
lock->screen = screen;
lock->root = RootWindow(dpy, lock->screen);
lock->x = DisplayWidth(dpy, lock->screen);
lock->y = DisplayHeight(dpy, lock->screen);
#ifdef XINERAMA
if ((info = XineramaQueryScreens(dpy, &n))) {
lock->xoff = info[0].x_org;
lock->yoff = info[0].y_org;
lock->mw = info[0].width;
lock->mh = info[0].height;
} else
#endif
{
lock->xoff = lock->yoff = 0;
lock->mw = lock->x;
lock->mh = lock->y;
}
lock->drawable = XCreatePixmap(dpy, lock->root,
lock->x, lock->y, DefaultDepth(dpy, screen));
lock->gc = XCreateGC(dpy, lock->root, 0, NULL);
XSetLineAttributes(dpy, lock->gc, 1, LineSolid, CapButt, JoinMiter);
if(image)
if(image)
{
lock->bgmap = XCreatePixmap(dpy, lock->root, DisplayWidth(dpy, lock->screen), DisplayHeight(dpy, lock->screen), DefaultDepth(dpy, lock->screen));
imlib_context_set_image(image);
@ -274,6 +335,8 @@ lockscreen(Display *dpy, struct xrandr *rr, int screen)
&color, &color, 0, 0);
XDefineCursor(dpy, lock->win, invisible);
resizerectangles(lock);
/* Try to grab mouse pointer *and* keyboard for 600ms, else fail the lock */
for (i = 0, ptgrab = kbgrab = -1; i < 6; i++) {
if (ptgrab != GrabSuccess) {
@ -379,20 +442,20 @@ main(int argc, char **argv) {
imlib_context_set_image(image);
imlib_context_set_display(dpy);
imlib_context_set_visual(DefaultVisual(dpy,0));
imlib_context_set_drawable(RootWindow(dpy,XScreenNumberOfScreen(scr)));
imlib_context_set_drawable(RootWindow(dpy,XScreenNumberOfScreen(scr)));
imlib_copy_drawable_to_image(0,0,0,scr->width,scr->height,0,0,1);
#ifdef BLUR
/*Blur function*/
imlib_image_blur(blurRadius);
#endif // BLUR
#endif // BLUR
#ifdef PIXELATION
/*Pixelation*/
int width = scr->width;
int height = scr->height;
for(int y = 0; y < height; y += pixelSize)
{
for(int x = 0; x < width; x += pixelSize)
@ -401,7 +464,7 @@ main(int argc, char **argv) {
int green = 0;
int blue = 0;
Imlib_Color pixel;
Imlib_Color pixel;
Imlib_Color* pp;
pp = &pixel;
for(int j = 0; j < pixelSize && j < height; j++)
@ -424,8 +487,8 @@ main(int argc, char **argv) {
blue = 0;
}
}
#endif
/* check for Xrandr support */
rr.active = XRRQueryExtension(dpy, &rr.evbase, &rr.errbase);
@ -463,5 +526,13 @@ main(int argc, char **argv) {
/* everything is now blank. Wait for the correct password */
readpw(dpy, &rr, locks, nscreens, hash);
for (nlocks = 0, s = 0; s < nscreens; s++) {
XFreePixmap(dpy, locks[s]->drawable);
XFreeGC(dpy, locks[s]->gc);
}
XSync(dpy, 0);
XCloseDisplay(dpy);
return 0;
}

BIN
.local/src/slock/slock.o View File


+ 1
- 0
.profile View File

@ -33,6 +33,7 @@ export NPM_CONFIG_USERCONFIG=$XDG_CONFIG_HOME/npm/npmrc
export NVM_DIR="$XDG_DATA_HOME"/nvm
export GNUPGHOME="$XDG_DATA_HOME"/gnupg
export MBSYNCRC="$XDG_CONFIG_HOME"/isync/mbsyncrc
export IMAPFILTER_CONFIG="$XDG_CONFIG_HOME/imapfilter/config.lua"
export VIMINIT="set nocp | source ${XDG_CONFIG_HOME:-$HOME/.config}/vim/vimrc"
export MYSQL_HISTFILE="$XDG_DATA_HOME"/mysql_history
export TASKDATA="$XDG_DATA_HOME"/task


Loading…
Cancel
Save