move wip stuff to wip
This commit is contained in:
21
wip/bitch/Makefile
Normal file
21
wip/bitch/Makefile
Normal file
@@ -0,0 +1,21 @@
|
||||
CFLAGS = -g
|
||||
RM = rm -f
|
||||
SOURCE = bitch.c
|
||||
TARGETS = bitch
|
||||
|
||||
all: $(TARGETS)
|
||||
motif: $(SOURCE)
|
||||
$(CC) $(CFLAGS) -o $@ \
|
||||
-DMOTIF -I/usr/pkg/include/ -I/usr/X11R7/include/ \
|
||||
-L/usr/pkg/lib/ -L/usr/X11R7/lib -lXm -lX11 \
|
||||
$(SOURCE)
|
||||
gtk4: $(SOURCE)
|
||||
$(CC) $(CFLAGS) -o $@ \
|
||||
-DGTK4 `pkg-config --cflags gtk4` `pkg-config --libs gtk4` \
|
||||
$(SOURCE)
|
||||
clean:
|
||||
$(RM) $(TARGETS)
|
||||
%: %.c
|
||||
$(CC) -o $@ $(CFLAGS) $@.c
|
||||
|
||||
.PHONY: all clean
|
||||
45
wip/bitch/bitch.1
Normal file
45
wip/bitch/bitch.1
Normal file
@@ -0,0 +1,45 @@
|
||||
.TH BITCH 1
|
||||
|
||||
.SH NAME
|
||||
|
||||
bitch \(en a pretty interface from which to select tasks
|
||||
|
||||
.SH SYNOPSIS
|
||||
|
||||
bitch
|
||||
.RB ( -rx )
|
||||
.RB [ -h
|
||||
.BR horizontal ]
|
||||
.RB [ -v
|
||||
.BR vertical ]
|
||||
|
||||
.SH GRAPHICS
|
||||
|
||||
Bitch is written for the GNU Image Manipulation Program's Graphical Toolkit 4.
|
||||
A windowing system is required to use bitch.
|
||||
|
||||
.SH DESCRIPTION
|
||||
|
||||
Bitch reads a list of newline-delimited items from standard input and presents a menu with the options.
|
||||
.PP
|
||||
With the
|
||||
.B -x
|
||||
option, bitch will eXit when the first item is chosen, otherwise bitch will print or execute subsequent selections.
|
||||
.PP
|
||||
With the
|
||||
.B -r
|
||||
option, bitch will execute the selected item with system(3). Otherwise, bitch will print the selection text.
|
||||
.PP
|
||||
The window bitch presents will be of the horizontal and vertical resolution specified with
|
||||
.B -h
|
||||
and
|
||||
.B -v
|
||||
respectively.
|
||||
|
||||
.SH BUGS
|
||||
|
||||
He who calls bitches bitches gets no bitches.
|
||||
|
||||
.SH COPYRIGHT
|
||||
|
||||
Public domain.
|
||||
208
wip/bitch/bitch.c
Normal file
208
wip/bitch/bitch.c
Normal file
@@ -0,0 +1,208 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h> /* stderr, atoi(3) */
|
||||
#include <string.h> /* strchr(3) */
|
||||
#include <sysexits.h> /* EX_USAGE */
|
||||
#include <unistd.h> /* getopt(3) */
|
||||
|
||||
#ifdef GTK4
|
||||
# include <gtk/gtk.h>
|
||||
#endif
|
||||
|
||||
#ifdef MOTIF
|
||||
# include <Xm/Xm.h>
|
||||
# include <Xm/PushB.h>
|
||||
#endif
|
||||
|
||||
#define BUF 100
|
||||
|
||||
/* Pinephone dimensions as default */
|
||||
static unsigned int h = 720;
|
||||
static unsigned int v = 1440;
|
||||
|
||||
static char *argv0;
|
||||
static char buf[BUF];
|
||||
static char f;
|
||||
static unsigned char shy = 0;
|
||||
|
||||
static int fake_argc = 1;
|
||||
static char *fake_argv[2] = { NULL, NULL };
|
||||
|
||||
#ifdef GTK4
|
||||
static GtkApplication *app;
|
||||
|
||||
static void activate(GtkApplication *app, gpointer user_data);
|
||||
static void button_pressed(GtkWidget *button, gpointer data);
|
||||
#endif
|
||||
|
||||
#ifdef MOTIF
|
||||
static XtAppContext app_context;
|
||||
|
||||
static void activate(void);
|
||||
static void button_pressed(
|
||||
Widget w, XtPointer client_data, XmPushButtonCallbackStruct *cbs
|
||||
);
|
||||
#endif
|
||||
|
||||
int main(int argc, char *argv[]){
|
||||
int c;
|
||||
extern char *optarg;
|
||||
int status;
|
||||
|
||||
argv0 = argv[0];
|
||||
fake_argv[0] = argv0;
|
||||
f = 'x';
|
||||
|
||||
while((c = getopt(argc, argv, "h:v:wx")) != -1)
|
||||
switch(c){
|
||||
case 'h':
|
||||
h = atoi(optarg);
|
||||
break;
|
||||
case 'w':
|
||||
f = 'w';
|
||||
break;
|
||||
case 'v':
|
||||
v = atoi(optarg);
|
||||
break;
|
||||
case 'x':
|
||||
shy = 1;
|
||||
break;
|
||||
default: usage:
|
||||
fprintf(stderr, "\
|
||||
Usage: %s (-rx)\n\
|
||||
\t(-h [horizontal resolution]) (-v [vertical resolution])\n",
|
||||
argv0
|
||||
);
|
||||
return EX_USAGE;
|
||||
}
|
||||
|
||||
#ifdef GTK4
|
||||
app = gtk_application_new(
|
||||
"org.trinity.femaledog", G_APPLICATION_FLAGS_NONE
|
||||
);
|
||||
g_signal_connect(app, "activate", G_CALLBACK(activate), NULL);
|
||||
status = g_application_run(G_APPLICATION(app), 1, fake_argv);
|
||||
g_object_unref(app);
|
||||
#endif
|
||||
|
||||
#ifdef MOTIF
|
||||
activate();
|
||||
#endif
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
char *
|
||||
sip(void){
|
||||
int c;
|
||||
char *s;
|
||||
|
||||
if(fgets(buf, sizeof(buf) / sizeof(*buf), stdin) == NULL){
|
||||
if(ferror(stdin) != 0)
|
||||
#ifdef GTK4
|
||||
g_print
|
||||
#else
|
||||
printf
|
||||
#endif
|
||||
("%s: stdin: file read error\n", argv0);
|
||||
return NULL;
|
||||
}
|
||||
if((s = strchr(buf, '\n')) == NULL) /* flush */
|
||||
while((c = getc(stdin)) != '\n' && c != EOF);
|
||||
else
|
||||
*s = '\0';
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
#ifdef GTK4
|
||||
static void
|
||||
activate(GtkApplication *app, gpointer user_data){
|
||||
GtkWidget *box;
|
||||
GtkWidget *button;
|
||||
int c;
|
||||
char *s;
|
||||
GtkWidget *scrolledwindow;
|
||||
GtkWidget *window;
|
||||
|
||||
window = gtk_application_window_new(app);
|
||||
gtk_window_set_title(GTK_WINDOW(window), "Bitch");
|
||||
gtk_window_set_default_size(GTK_WINDOW(window), h, v);
|
||||
|
||||
scrolledwindow = gtk_scrolled_window_new();
|
||||
gtk_scrolled_window_set_overlay_scrolling(GTK_SCROLLED_WINDOW(scrolledwindow), 1);
|
||||
gtk_window_set_child(GTK_WINDOW(window), scrolledwindow);
|
||||
|
||||
box = gtk_list_box_new();
|
||||
//gtk_widget_set_halign(box, GTK_ALIGN_CENTER);
|
||||
//gtk_widget_set_valign(box, GTK_ALIGN_CENTER);
|
||||
gtk_scrolled_window_set_child(GTK_SCROLLED_WINDOW(scrolledwindow), box);
|
||||
|
||||
for(;;){
|
||||
if(sip() == NULL)
|
||||
break;
|
||||
button = gtk_button_new_with_label(buf);
|
||||
g_signal_connect(
|
||||
button, "clicked", G_CALLBACK(button_pressed), NULL
|
||||
);
|
||||
gtk_list_box_insert(GTK_LIST_BOX(box), button, -1);
|
||||
}
|
||||
|
||||
gtk_window_present(GTK_WINDOW(window));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
button_pressed(GtkWidget *button, gpointer data){
|
||||
|
||||
switch(f){
|
||||
case 'w':
|
||||
g_print("%s\n", gtk_button_get_label(GTK_BUTTON(button)));
|
||||
break;
|
||||
case 'x':
|
||||
system(gtk_button_get_label(GTK_BUTTON(button)));
|
||||
break;
|
||||
}
|
||||
if(shy)
|
||||
g_application_quit(G_APPLICATION(app));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
#endif /* ifdef GTK4 */
|
||||
|
||||
#ifdef MOTIF
|
||||
static void
|
||||
activate(void){
|
||||
Widget button;
|
||||
Widget top_wid;
|
||||
|
||||
top_wid = XtVaAppInitialize(
|
||||
&app_context, "Bitch", NULL, 0, &fake_argc, fake_argv, NULL,
|
||||
NULL
|
||||
);
|
||||
|
||||
for(;;){
|
||||
if(sip() == NULL)
|
||||
break;
|
||||
|
||||
button = XmCreatePushButton(top_wid, buf, NULL, 0);
|
||||
XtManageChild(button);
|
||||
XtAddCallback(button, XmNactivateCallback, button_pressed, NULL);
|
||||
}
|
||||
|
||||
XtRealizeWidget(top_wid);
|
||||
XtAppMainLoop(app_context);
|
||||
}
|
||||
|
||||
static void
|
||||
button_pressed(
|
||||
Widget w,
|
||||
XtPointer client_data,
|
||||
XmPushButtonCallbackStruct *cbs
|
||||
){
|
||||
printf("pressed\n");
|
||||
if(shy)
|
||||
XtAppSetExitFlag(app_context);
|
||||
}
|
||||
#endif
|
||||
7
wip/bitch/bitch_please
Executable file
7
wip/bitch/bitch_please
Executable file
@@ -0,0 +1,7 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -ex
|
||||
|
||||
$(for folder in $(printf "%s\n" "$PATH" | tr ':' '\n');
|
||||
do ls $folder
|
||||
done | sort | $(command -v bitch))
|
||||
84
wip/com/com
Normal file
84
wip/com/com
Normal file
@@ -0,0 +1,84 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -e
|
||||
|
||||
# http://www.iq0.com/duffgram/com.html implementation
|
||||
# (consulted source to see what -n did)
|
||||
|
||||
arv0="$0"; shell='sh -c'
|
||||
|
||||
usage(){
|
||||
printf 'Usage: %s (-n) (file...)\n' "$argv0" >&2
|
||||
exit 64 # sysexits(3) EX_USAGE
|
||||
}
|
||||
|
||||
for arg in "$@"
|
||||
do
|
||||
printf '%s\n' "$arg" \
|
||||
| grep '^-' >/dev/null 2>&1 \
|
||||
|| break
|
||||
shift
|
||||
printf '%s\n' "$arg" \
|
||||
| grep 'n' >/dev/null 2>&1 \
|
||||
&& shell=echo \
|
||||
|| true
|
||||
printf '%s\n' "$arg" \
|
||||
| grep '[^-n]' >/dev/null 2>&1 \
|
||||
&& usage \
|
||||
|| true
|
||||
printf '%s\n' "$arg" \
|
||||
| grep -- '-.*-' >/dev/null 2>&1 \
|
||||
&& break \
|
||||
|| true
|
||||
done
|
||||
|
||||
test -n "$1" \
|
||||
|| set -- "$(cat .comfile 2>/dev/null)" \
|
||||
&& test -n "$1" \
|
||||
|| usage
|
||||
|
||||
>.comfile
|
||||
|
||||
awk -v argv0="$argv0" -v shell="$shell" '
|
||||
# https://www.gnu.org/software/gawk/manual/html_node/Filetrans-Function.html
|
||||
FILENAME != current_file {
|
||||
processed = 0;
|
||||
if(current_file != 0){
|
||||
print current_file >>".comfile";
|
||||
if(cmd == ""){
|
||||
# https://www.gnu.org/software/gawk/manual/html_node/
|
||||
# Special-FD.html
|
||||
printf("%s: no command\n", ARGV[2]) >"/dev/stderr";
|
||||
exit 65 # sysexits(3) EX_DATAERR
|
||||
}else{
|
||||
print cmd | shell;
|
||||
cmd = "";
|
||||
}
|
||||
}
|
||||
current_file = FILENAME;
|
||||
}
|
||||
cmd == "" && /\/\*%/ {
|
||||
sub(/.*\/\*%[:space:]*/, "");
|
||||
stem = FILENAME;
|
||||
sub(/\.[^.]*$/, "", stem);
|
||||
for(i = 0; i < length($0) - 1; ++i)
|
||||
cmd = cmd ((substr($0, i, 2) == "##" || substr($0, i, 2) == "%%") \
|
||||
? substr($0, i++, 1) \
|
||||
: (substr($0, i, 1) == "%") \
|
||||
? FILENAME \
|
||||
: (substr($0, i, 1) == "#") \
|
||||
? stem \
|
||||
: substr($0, i, 1)) \
|
||||
;
|
||||
cmd = cmd substr($0, i, 2);
|
||||
}
|
||||
END {
|
||||
print current_file >>".comfile";
|
||||
if(cmd != "")
|
||||
print cmd | shell;
|
||||
if(processed == 0){
|
||||
printf("%s: no command\n", argv0) > "/dev/stderr";
|
||||
exit 65; # sysexits(3) EX_DATAERR
|
||||
}
|
||||
}
|
||||
'
|
||||
55
wip/cstdlib/ctype.c
Normal file
55
wip/cstdlib/ctype.c
Normal file
@@ -0,0 +1,55 @@
|
||||
int
|
||||
isblank(int c){
|
||||
return c == '\t'
|
||||
|| c == ' ';
|
||||
}
|
||||
|
||||
int
|
||||
isspace(int c){
|
||||
return isblank(c)
|
||||
|| c == '\n'
|
||||
|| c == '\v'
|
||||
|| c == '\f'
|
||||
|| c == '\r';
|
||||
}
|
||||
|
||||
int
|
||||
isgraph(int c){ return c >= '!' && c <= '~'; }
|
||||
|
||||
int
|
||||
isprint(int c){ return c == ' ' || isgraph(c); }
|
||||
|
||||
int
|
||||
iscntrl(int c){ return !isprint(c); }
|
||||
|
||||
int
|
||||
isdigit(int c){ return c >= '0' && c <= '9'; }
|
||||
|
||||
int
|
||||
islower(int c){ return c >= 'a' && c <= 'z'; }
|
||||
|
||||
int
|
||||
isupper(int c){ return c >= 'A' && c <= 'Z'; }
|
||||
|
||||
int
|
||||
isxdigit(int c){
|
||||
return
|
||||
isdigit(c)
|
||||
|| (c >= 'a' && c <= 'f')
|
||||
|| (c >= 'A' && c <= 'F');
|
||||
}
|
||||
|
||||
int
|
||||
isalpha(int c){ return islower(c) || isupper(c); }
|
||||
|
||||
int
|
||||
isalnum(int c){ return isalpha(c) || isdigit(c) };
|
||||
|
||||
int
|
||||
ispunct(int c){ return c != ' ' && !isalnum(c) };
|
||||
|
||||
int
|
||||
tolower(int c){ return c - isupper(c) * ('A' - 'a'); }
|
||||
|
||||
int
|
||||
toupper(int c){ return c + islower(c) * ('A' - 'a'); }
|
||||
17
wip/cstdlib/ctype.h
Normal file
17
wip/cstdlib/ctype.h
Normal file
@@ -0,0 +1,17 @@
|
||||
#ifndef _CTYPE_H
|
||||
# define CTYPE_H
|
||||
int isblank(int c);
|
||||
int isspace(int c);
|
||||
int isgraph(int c);
|
||||
int isprint(int c);
|
||||
int iscntrl(int c);
|
||||
int isdigit(int c);
|
||||
int islower(int c);
|
||||
int isupper(int c);
|
||||
int isxdigit(int c);
|
||||
int isalpha(int c);
|
||||
int isalnum(int c);
|
||||
int ispunct(int c);
|
||||
int tolower(int c);
|
||||
int toupper(int c);
|
||||
#endif /* ifndef _CTYPE_H */
|
||||
53
wip/cstdlib/string.c
Normal file
53
wip/cstdlib/string.c
Normal file
@@ -0,0 +1,53 @@
|
||||
char *
|
||||
strchr(const char *s, int c){
|
||||
char *r;
|
||||
|
||||
for(r = s; ; ++r){
|
||||
if(*r == c)
|
||||
return r;
|
||||
if(*r == '\0')
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
char *
|
||||
strrchr(const char *s, int c){
|
||||
char *r;
|
||||
char *p;
|
||||
|
||||
for(p = s, r = NULL; ; ++p){
|
||||
if(*p == c)
|
||||
r = p;
|
||||
if(*p == '\0')
|
||||
break;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
char *
|
||||
strchrnul(const char *s, int c){
|
||||
char *r;
|
||||
|
||||
for(r = s; ; ++r)
|
||||
if(*r == c || r == '\0')
|
||||
return r;
|
||||
}
|
||||
|
||||
size_t
|
||||
strlen(const char *s){
|
||||
size_t r;
|
||||
|
||||
for(r = 0; s[r] != '\0'; ++r);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
size_t
|
||||
strnlen(const char *s, size_t maxlen){
|
||||
size_t r;
|
||||
|
||||
for(r = 0; s[r] != '\0' && r < maxlen; ++r);
|
||||
|
||||
return r;
|
||||
}
|
||||
8
wip/cstdlib/string.h
Normal file
8
wip/cstdlib/string.h
Normal file
@@ -0,0 +1,8 @@
|
||||
#ifndef _STRING_H
|
||||
# define _STRING_H
|
||||
char * strchr(const char *s, int c);
|
||||
char * strrchr(const char *s, int c);
|
||||
char *strchrnul(const char *s, int c);
|
||||
size_t strlen(const char *s);
|
||||
size_t strnlen(const char *s, size_t maxlen);
|
||||
#endif /* ifndef _STRING_H */
|
||||
67
wip/cut/cut.c
Normal file
67
wip/cut/cut.c
Normal file
@@ -0,0 +1,67 @@
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sysexits.h>
|
||||
#include <unistd.h>
|
||||
#include "noargvzero.h"
|
||||
|
||||
extern char *optarg; /* getopt(3); unistd.h */
|
||||
extern int optind, opterr, optopt; /* getopt(3); unistd.h */
|
||||
|
||||
void
|
||||
occurrences(FILE *f, char *s){
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
usage(char *name){
|
||||
fprintf(stderr,
|
||||
"Usage: %s (-b [list] (-n))"
|
||||
"\t|(-c [list])"
|
||||
"\t|(-f [list] (-d [delim]) (-s))"
|
||||
"\t[file...]\n", name);
|
||||
exit(EX_USAGE);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[]){
|
||||
int c;
|
||||
char *delimiter;
|
||||
char *list;
|
||||
char mode;
|
||||
|
||||
NOARGVZERO(argv[0]);
|
||||
|
||||
/* perhaps mode could be specified after submodal stuff. this would
|
||||
* move checks to after argument parsing though which could take more
|
||||
* time. */
|
||||
mode = 0;
|
||||
submode = 0;
|
||||
while((c = getopt(argc, argv, "b:c:d:f:ns")) != -1)
|
||||
switch(c){
|
||||
case 'b': case 'c': case 'f':
|
||||
if(mode != 0)
|
||||
usage(argv[0]);
|
||||
mode = c;
|
||||
list = optarg;
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
if(mode != 'f')
|
||||
usage(argv[0]);
|
||||
delimiter = optarg;
|
||||
break;
|
||||
|
||||
case 'n': case 's':
|
||||
if((c == 's' && mode != 'f')
|
||||
|| (c == 'b' && mode != 'b'))
|
||||
usage(argv[0]);
|
||||
submode = c;
|
||||
break;
|
||||
|
||||
default:
|
||||
usage(argv[0]);
|
||||
}
|
||||
|
||||
return EX_OK;
|
||||
}
|
||||
161
wip/fortune/trinitydotmoe
Normal file
161
wip/fortune/trinitydotmoe
Normal file
@@ -0,0 +1,161 @@
|
||||
Special thanks to Ками for their help with this quotes script.
|
||||
-- trinity.moe/js/quotes.json
|
||||
%
|
||||
Yeah, that's just how it is. Just, nothing. So much nothing that it hurts.
|
||||
-- danger/u/ aefd79
|
||||
%
|
||||
Reason has always existed, but not always in a reasonable form.
|
||||
-- Katy Perry
|
||||
%
|
||||
Consult your pineal gland.
|
||||
-- Eris
|
||||
%
|
||||
Back to 8chan please
|
||||
-- Skyglider on wirechan.org
|
||||
%
|
||||
No, I am your father.
|
||||
-- Darth Vader, "Star Wars: The Empire Strikes Back"
|
||||
%
|
||||
A checklist can aid here.
|
||||
-- Lance Leventhal, "Z80 Assembly Language Programming"
|
||||
%
|
||||
You never know.
|
||||
-- Mr. McSweeney of Winthrop, Maine
|
||||
%
|
||||
You lost the game.
|
||||
-- Anonymous on 4chan.org
|
||||
%
|
||||
Jerma isn't particularly religious.
|
||||
-- Jerma985 Wikitubia Fandom article
|
||||
%
|
||||
put me on here now
|
||||
-- arsonist catboy on twitter.com
|
||||
%
|
||||
These are no longer memes this is y'all repressed anger
|
||||
-- Khalifist on twitter.com
|
||||
%
|
||||
C makes it easy to shoot yourself in the foot; C++ makes it harder, but when
|
||||
you do, it blows away your whole leg.
|
||||
-- Bjarne Stroustrup
|
||||
%
|
||||
I'll sleep when I'm dead.
|
||||
-- Warren Zevon
|
||||
%
|
||||
I would have made a good pope.
|
||||
-- Richard M. Nixon
|
||||
%
|
||||
To sit alone with my conscience will be judgement enough for me.
|
||||
-- Charles William Stubbs
|
||||
%
|
||||
Your enemy is where you are not.
|
||||
-- Sun Tzu, "The Art of War" (paraphrased; purportedly)
|
||||
%
|
||||
Be everywhere.
|
||||
-- social media influencing 101
|
||||
%
|
||||
I wish everyone was bald.
|
||||
-- Anonymous on 4chan.org
|
||||
%
|
||||
Nah
|
||||
-- Soldier G65434-2
|
||||
%
|
||||
The kill command is a basic UNIX system command.
|
||||
-- Matthew Helmke, "Ubuntu Linux Unleashed 2021 Edition, page
|
||||
283"
|
||||
%
|
||||
If you raise the effing hot dog, I will kill you. Figure it out.
|
||||
-- Craig Jelinek
|
||||
%
|
||||
Don't think. Feel and you'll be tanasinn.
|
||||
-- 名無 on 2chan
|
||||
%
|
||||
They had overshadowed her in life. They would obliterate her in death.
|
||||
-- Khaled Hosseini, "A Thousand Splendid Suns"
|
||||
%
|
||||
are your bones made out of fucking depleted uranium
|
||||
-- Anonymous on the 4chan.org/x/ tulpa peridot thread
|
||||
%
|
||||
Giving the Linus Torvalds award to the Free Software Foundation is sort of like
|
||||
giving the Han Solo award to the Rebel Fleet.
|
||||
-- Richard Stallman, "Revolution OS (2001)"
|
||||
%
|
||||
Filthy Frank is the embodiment of everything a person should not be.
|
||||
-- George Miller
|
||||
%
|
||||
It should be noted that no ethically-trained software engineer would ever
|
||||
consent to write a DestroyBaghdad procedure. Basic professional ethics would
|
||||
instead require him to write a DestroyCity procedure, to which Baghdad could be
|
||||
given as a parameter.
|
||||
-- Nathaniel Borenstein
|
||||
%
|
||||
An idiot admires complexity. A genius admires simplicity.
|
||||
-- Terry A. Davis
|
||||
%
|
||||
When in doubt, use brute force.
|
||||
-- Ken Thompson
|
||||
%
|
||||
Where MS Word is WYSIWYG (What You See Is What You Get), and Latex is WYGIWYW
|
||||
(What You Get Is What You Want), HTML is WYGIWYD (What You Get Is What You
|
||||
Deserve).
|
||||
-- Trinity
|
||||
%
|
||||
Easy is the opposite of hard, not the opposite of time-consuming.
|
||||
-- Brad Fitzpatrick, "discussion about plan9 support with Go"
|
||||
%
|
||||
Blame the Nazis for making me become a gun designer. I always wanted to
|
||||
construct agricultural machinery.
|
||||
-- Mikhail Kalashnikov
|
||||
%
|
||||
since KFC fired me the 11 herbs and spices are coriander, onion powder, garlic
|
||||
powder, salt, white pepper, black pepper basil, parsley, chili pepper, lemon
|
||||
powder, thyme, and sage.
|
||||
-- @ashley.shoy on Tiktok
|
||||
%
|
||||
Sooner or later there has to be peace.
|
||||
-- Abigail Thorn, "Identity: A Trans Coming Out Story"
|
||||
%
|
||||
Ich bin ein Berliner.
|
||||
-- John F. Kennedy
|
||||
%
|
||||
I am a Bangor!
|
||||
-- Erwin Kreuz
|
||||
%
|
||||
It's not enough that I should succeed - others should fail.
|
||||
-- Unknown
|
||||
%
|
||||
Secundus says hello to his Prima, wherever she is. I ask, my mistress, that you
|
||||
love me.
|
||||
-- Unknown in the House and Office of Volusius Iuvencus
|
||||
%
|
||||
Debugging on windows is like trying to fix spelling mistakes but you can't see
|
||||
the words
|
||||
-- arwn in the 9fans Discord
|
||||
%
|
||||
I believe this rabble does not deserve to be given the means for its
|
||||
emancipation.
|
||||
-- Catboy Deleuze (deleuzian_catboy) on instagram.com
|
||||
%
|
||||
Nothing human makes it out of the near-future.
|
||||
-- Nick Land, "Meltdown (1994)"
|
||||
%
|
||||
144hz doesn’t help much with writing C
|
||||
-- henesy on the 9fans Discord
|
||||
%
|
||||
It could be a monkey. You never know.
|
||||
-- Peter, overheard in a Burger King
|
||||
%
|
||||
There's no law apart from Man's will.
|
||||
-- Alex Alex, 'Only Blackjack' group on facebook.com
|
||||
%
|
||||
You will see by it, that the Opinion of this mischievous Effect from lead, is
|
||||
at least above Sixty years old; and you will observe with Concern how long a
|
||||
useful Truth may be known, and exist, before it is generally receiv'd and
|
||||
practis'd on.
|
||||
-- Benjamin Franklin in a private letter
|
||||
%
|
||||
You claim to seek progress, but you succeed mainly in whining.
|
||||
-- Dennis Ritchie, "The UNIX-HATERS Handbook Anti-Foreword"
|
||||
%
|
||||
nemoj da juriŝ zene i autobusi, biĉe uvek novi
|
||||
-- meatgrinder's pop, relayed by meatgrinder in metaspinoza's
|
||||
nightmare wheelhouse
|
||||
3
wip/ftesosd/LICENSE
Normal file
3
wip/ftesosd/LICENSE
Normal file
@@ -0,0 +1,3 @@
|
||||
Derived from
|
||||
https://gist.github.com/artixnous/41f4bde311442aba6a4f5523db921415
|
||||
without license.
|
||||
257
wip/ftesosd/eyesockets.sh
Executable file
257
wip/ftesosd/eyesockets.sh
Executable file
@@ -0,0 +1,257 @@
|
||||
#!/bin/sh
|
||||
# nous,2019-2020
|
||||
# trinity,2021
|
||||
|
||||
# fork from the original FUCKTHESKULLOFSYSTEMD on GitHub Gists:
|
||||
# https://gist.github.com/artixnous/41f4bde311442aba6a4f5523db921415
|
||||
|
||||
# Test Arch ISO installation:
|
||||
# cfdisk /dev/sda
|
||||
# mkfs.ext4 /dev/sda1
|
||||
# mount /dev/sda1 /mnt
|
||||
# pacstrap /mnt base linux linux-firmware openssh wget rsync dhcpcd grub
|
||||
# arch-chroot /mnt
|
||||
# grub-install /dev/sda
|
||||
# mkinitcpio -P
|
||||
# grub-mkconfig -o /boot/grub/grub.cfg
|
||||
|
||||
# the package name MUST be the same as the editor itself
|
||||
# e.g. vim, ed, nano, ne, vis
|
||||
# nous' default was nano, most people know how to use that one so that's what's
|
||||
# being used here
|
||||
DEFAULT_EDITOR="nano"
|
||||
|
||||
if [ -z "$VISUAL" ] && [ -n "$EDITOR" ]; then
|
||||
VISUAL="$EDITOR"
|
||||
elif [ -z "$VISUAL" ] && [ -z "$EDITOR" ]; then
|
||||
VISUAL="$DEFAULT_EDITOR"
|
||||
fi
|
||||
|
||||
. /usr/share/makepkg/util/message.sh
|
||||
colorize
|
||||
|
||||
printf "$BOLD\
|
||||
You should run this from inside screen(1) or tmux(1), especially if this is a
|
||||
remote box. Use a terminal/session with a large scrollback buffer.
|
||||
"
|
||||
read -n 1 -p "$RED Last chance to press CTRL-C, ENTER to continue. "
|
||||
printf "$CYAN\
|
||||
Starting operation $RED\ FUCKTHESKULLOFSYSTEMD
|
||||
"
|
||||
error
|
||||
|
||||
error() {
|
||||
printf "$RED\
|
||||
An error occured, aborting to prevent incomplete conversion. Fix it and re-run
|
||||
the script FROM THE LAST STEP ONWARDS.
|
||||
"
|
||||
exit 1
|
||||
}
|
||||
|
||||
[ "$1" = "openrc" ] && target="openrc"
|
||||
[ "$1" = "runit" ] && target="runit"
|
||||
|
||||
# runit not yet implemented
|
||||
#[[ $target ]] || { echo "Usage: $0 <openrc|runit>" ; exit 1; }
|
||||
#echo "Target: $target"
|
||||
|
||||
rm -f /var/lib/pacman/db.lck
|
||||
sed -i s/Arch/Artix/g /etc/default/grub
|
||||
# A full systemd update is needed, because libsystemd->systemd-libs
|
||||
printf "$GREEN\
|
||||
Updating Arch system first, if this fails abort and update manually;
|
||||
then re-run the script \
|
||||
$ALL_OFF"
|
||||
pacman -Syu --noconfirm \
|
||||
|| error
|
||||
pacman -S --needed --noconfirm wget "$VISUAL" rsync \
|
||||
|| error
|
||||
|
||||
cd /etc
|
||||
printf "$GREEN\
|
||||
Replacing Arch repositories with Artix\
|
||||
$ALL_OFF"
|
||||
mv -vf pacman.conf pacman.conf.arch
|
||||
wget https://gitea.artixlinux.org/packagesP/pacman/raw/branch/master/trunk/pacman.conf -O /etc/pacman.conf \
|
||||
|| error
|
||||
mv -vf pacman.d/mirrorlist pacman.d/mirrorlist-arch
|
||||
wget https://gitea.artixlinux.org/packagesA/artix-mirrorlist/raw/branch/master/trunk/mirrorlist -O pacman.d/mirrorlist \
|
||||
|| error
|
||||
cp -vf pacman.d/mirrorlist pacman.d/mirrorlist.artix
|
||||
sed -i 's/Required DatabaseOptional/Never/' pacman.conf
|
||||
|
||||
printf "$GREEN\
|
||||
Refreshing package databases\
|
||||
$ALL_OFF"
|
||||
pacman -Syy --noconfirm \
|
||||
|| error
|
||||
printf "\n"
|
||||
read -n 1 -p "$GREEN Press ENTER and answer <yes> to the next question to make sure all packages come from Artix repos $ALL_OFF "
|
||||
echo
|
||||
pacman -Scc
|
||||
|
||||
echo "$GREEN Importing Artix keys $ALL_OFF"
|
||||
pacman -S --noconfirm artix-keyring \
|
||||
|| error
|
||||
pacman-key --populate artix \
|
||||
|| error
|
||||
pacman-key --lsign-key 95AEC5D0C1E294FC9F82B253573A673A53C01BC2 \
|
||||
|| error
|
||||
|
||||
systemctl list-units --state=running | grep -v systemd | awk '{print $1}' | grep service > /root/daemon.list
|
||||
printf "$MAGENTA\
|
||||
Your systemd running units are saved in /root/daemon.list.\n
|
||||
$ALL_OFF"
|
||||
read -n 1 -p "$RED\
|
||||
Do not proceed if you've seen errors above.
|
||||
Press CTRL-C to abort or ENTER to continue
|
||||
$ALL_OFF"
|
||||
printf "$GREEN
|
||||
Downloading systemd-free packages from Artix
|
||||
$ALL_OFF"
|
||||
pacman -Sw --noconfirm \
|
||||
base \
|
||||
base-devel \
|
||||
openrc-system \
|
||||
grub linux-lts \
|
||||
linux-lts-headers \
|
||||
elogind-openrc \
|
||||
openrc \
|
||||
netifrc \
|
||||
grub mkinitcpio \
|
||||
archlinux-mirrorlist \
|
||||
net-tools \
|
||||
rsync \
|
||||
"$VISUAL" \
|
||||
lsb-release \
|
||||
esysusers \
|
||||
etmpfiles \
|
||||
|| error
|
||||
printf "$YELLOW\
|
||||
This is the best part: removing systemd
|
||||
$ALL_OFF"
|
||||
pacman -Rdd --noconfirm \
|
||||
systemd \
|
||||
systemd-libs \
|
||||
systemd-sysvcompat \
|
||||
pacman-mirrorlist \
|
||||
dbus \
|
||||
|| error
|
||||
|
||||
# Previous pacman-mirrorlist removal also deleted this, restoring
|
||||
cp -vf pacman.d/mirrorlist.artix pacman.d/mirrorlist
|
||||
|
||||
echo "$GREEN Installing clean Artix packages $ALL_OFF"
|
||||
pacman -Qqn | pacman -S --noconfirm --overwrite '*' - \
|
||||
|| error
|
||||
echo "$GREEN Installing Artix system packages $ALL_OFF"
|
||||
pacman -S --noconfirm --needed --overwrite '*' \
|
||||
base \
|
||||
base-devel \
|
||||
openrc-system \
|
||||
linux-lts \
|
||||
linux-lts-headers \
|
||||
elogind-openrc \
|
||||
openrc \
|
||||
netifrc \
|
||||
grub \
|
||||
mkinitcpio \
|
||||
archlinux-mirrorlist \
|
||||
net-tools \
|
||||
rsync \
|
||||
"$DEFAULT_EDITOR" \
|
||||
lsb-release \
|
||||
connman \
|
||||
esysusers \
|
||||
etmpfiles \
|
||||
artix-branding-base \
|
||||
|| error
|
||||
echo "$GREEN Installing service files $ALL_OFF"
|
||||
pacman -S --noconfirm --needed \
|
||||
at-openrc \
|
||||
xinetd-openrc \
|
||||
cronie-openrc \
|
||||
haveged-openrc \
|
||||
hdparm-openrc \
|
||||
openssh-openrc \
|
||||
syslog-ng-openrc \
|
||||
connman-openrc \
|
||||
|| error
|
||||
|
||||
echo "$YELLOW Removing left-over cruft $ALL_OFF"
|
||||
rm -fv /etc/resolv.conf
|
||||
|
||||
echo "$GREEN Enabling basic services $ALL_OFF"
|
||||
rc-update add haveged sysinit
|
||||
rc-update add udev sysinit
|
||||
rc-update add sshd default
|
||||
|
||||
echo
|
||||
echo "$BOLD Activating standard network interface naming (i.e. enp72^7s128%397 --> eth0)."
|
||||
echo "$BOLD If you prefer the persistent naming, remove the last line from /etc/default/grub"
|
||||
echo "$BOLD and run $ALL_OFF grub-mkconfig -o /boot/grub/grub.cfg $BOLD when this script prompts for reboot."
|
||||
echo
|
||||
read -n 1 -p "Press ENTER $ALL_OFF"
|
||||
echo 'GRUB_CMDLINE_LINUX="net.ifnames=0"' >>/etc/default/grub
|
||||
|
||||
pacman -S --needed --noconfirm netifrc
|
||||
printf "\
|
||||
============================= $BOLD
|
||||
Write down your IP and route. $ALL_OFF
|
||||
=============================
|
||||
"
|
||||
ifconfig
|
||||
route
|
||||
printf " \
|
||||
=============================================================== $BOLD
|
||||
Press ENTER to edit conf.d/net to configure static networking.
|
||||
No editing is needed if you use dhcp or a network manager, but
|
||||
you MUST enable the daemon manually BEFORE rebooting.
|
||||
You will be given the option at the end of this procedure.
|
||||
Default setting is DHCP for eth0, should be enough for most. $ALL_OFF
|
||||
===============================================================
|
||||
"
|
||||
read -n 1 -p " "
|
||||
"$VISUAL" /etc/conf.d/net
|
||||
ln -sf /etc/init.d/net.lo /etc/init.d/net.eth0
|
||||
rc-update add net.eth0 default \
|
||||
|| error
|
||||
|
||||
# Good riddance
|
||||
echo "$YELLOW Removing more systemd cruft $ALL_OFF"
|
||||
for user in journal journal-gateway timesync network bus-proxy journal-remote journal-upload resolve coredump;
|
||||
do userdel systemd-$user
|
||||
done
|
||||
rm -vfr /{etc,var/lib}/systemd
|
||||
|
||||
echo "$GREEN Restoring pacman.conf security settings $ALL_OFF"
|
||||
sed -i 's/= Never/= Required DatabaseOptional/' /etc/pacman.conf
|
||||
echo "$GREEN Making OpenRC start faster $ALL_OFF"
|
||||
sed -i 's/#rc_parallel="NO"/rc_parallel="YES"/' /etc/rc.conf
|
||||
echo "$GREEN Replacing Arch with Artix in hostname and issue $ALL_OFF"
|
||||
sed -i 's/Arch/Artix/ig' /etc/hostname /etc/issue 2>/dev/null
|
||||
echo "$GREEN Recreating initrds $ALL_OFF"
|
||||
mkinitcpio -P
|
||||
echo "$GREEN Recreating grub.cfg $ALL_OFF"
|
||||
cp -vf /boot/grub/grub.cfg /boot/grub/grub.cfg.arch
|
||||
grub-mkconfig -o /boot/grub/grub.cfg \
|
||||
|| error
|
||||
|
||||
echo "============================================="
|
||||
echo "= If you haven't seen any errors ="
|
||||
echo "= press ENTER to reboot ="
|
||||
echo "= Otherwise switch console and fix them ="
|
||||
echo "= ="
|
||||
echo "= ="
|
||||
echo "= Press CTRL-C to stop reboot ="
|
||||
echo "=(mandatory if you need a networking daemon)="
|
||||
echo "=Or switch console/terminal and type as root="
|
||||
echo "= $BOLD rc-service add connmand $ALL_OFF ="
|
||||
echo "= then switch back here and continue ="
|
||||
echo "============================================="
|
||||
read -n 1 -p " "
|
||||
sync
|
||||
mount -f / -o remount,ro
|
||||
echo s >| /proc/sysrq-trigger
|
||||
echo u >| /proc/sysrq-trigger
|
||||
echo b >| /proc/sysrq-trigger
|
||||
12
wip/head.c
Normal file
12
wip/head.c
Normal file
@@ -0,0 +1,12 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/* The philosophical bits - /should this be a shell script?/ -
|
||||
* are more complicated than the actual program. sed(1) is not currently a part
|
||||
* of this project so there shouldn't be reliance on it. */
|
||||
|
||||
int main(int argc, char *argv[]){
|
||||
char *argv0 = argv[0];
|
||||
size_t i;
|
||||
|
||||
|
||||
3
wip/ht16k33/Makefile
Normal file
3
wip/ht16k33/Makefile
Normal file
@@ -0,0 +1,3 @@
|
||||
CFLAGS += -I/usr/local/include -L/usr/local/lib
|
||||
ht16k33: ht16k33.c
|
||||
$(CC) $(CFLAGS) -lwiringPi -o ht16k33 ht16k33.c
|
||||
2
wip/ht16k33/README.txt
Normal file
2
wip/ht16k33/README.txt
Normal file
@@ -0,0 +1,2 @@
|
||||
This program depends on WiringPi. Build instructions can be found in the
|
||||
Makefile in the root of this project.
|
||||
14
wip/ht16k33/ht16k33.c
Normal file
14
wip/ht16k33/ht16k33.c
Normal file
@@ -0,0 +1,14 @@
|
||||
#include <unistd.h>
|
||||
#include <wiringPiI2C.h>
|
||||
#include "ht16k33.h"
|
||||
|
||||
/* https://cdn-shop.adafruit.com/datasheets/ht16K33v110.pdf */
|
||||
|
||||
#define ADDRESS 0x70
|
||||
|
||||
int main(int argc, char *argv[]){
|
||||
int fd;
|
||||
|
||||
fd = wiringPiI2CSetup(ADDRESS);
|
||||
close(fd);
|
||||
}
|
||||
11
wip/ht16k33/ht16k33.h
Normal file
11
wip/ht16k33/ht16k33.h
Normal file
@@ -0,0 +1,11 @@
|
||||
/* Definitions were determined by reading Adafruit code and the datasheet. */
|
||||
|
||||
#define HT16K33_SYSTEM_CMD 0x20 /* 0b0010???x */
|
||||
#define HT16K33_SYSTEM_ON 0x01 /* 0b00000001 */
|
||||
#define HT16K33_SYSTEM_OFF 0x00 /* 0b00000000 */
|
||||
|
||||
/* `0xE0 | n`, where 0 <= n <= 15 and the display dims to (n+1)/16 duty */
|
||||
#define HT16K33_CMD_BRIGHTNESS 0xE0 /* 0b1110xxxx */
|
||||
|
||||
#define HT16K33_BLINK_CMD 0x80 /* 0b1000?xxx */
|
||||
#define HT16K33_BLINK_DISPLAYON 0x01 /* 0b1000???x */
|
||||
3
wip/http/config.h
Normal file
3
wip/http/config.h
Normal file
@@ -0,0 +1,3 @@
|
||||
#define Server "UNIX"
|
||||
#define HTTP_ROOT "/var/www"
|
||||
#define SERVER_ADDRESS "www.example.com"
|
||||
94
wip/http/url.c
Normal file
94
wip/http/url.c
Normal file
@@ -0,0 +1,94 @@
|
||||
#include "url.h"
|
||||
|
||||
/* safely frees URL struct */
|
||||
struct Url *
|
||||
free_url(struct Url *url){
|
||||
free(url->s);
|
||||
free(url->ssp);
|
||||
free(url);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* turns scheme specific part of URL from string into SSP struct */
|
||||
/* returns NULL on allocation error or scheme syntax error */
|
||||
struct CommonInternetScheme *
|
||||
disassemble_commoninternetscheme(char *ssp){
|
||||
int i;
|
||||
char *p;
|
||||
struct CommonInternetScheme *retval;
|
||||
|
||||
if( /* embarrassingly long if statement */
|
||||
(retval
|
||||
= (struct CommonInternetScheme *)
|
||||
malloc(sizeof(struct CommonInternetScheme))
|
||||
) == NULL
|
||||
)
|
||||
return NULL;
|
||||
|
||||
parsed = 0;
|
||||
|
||||
/* the scheme-specific data starts with a double slash to indicate that
|
||||
* it complies with the common Internet scheme syntax (RFC 1738 3.1) */
|
||||
if(ssp[0] != '/' || ssp[1] != '/')
|
||||
return NULL;
|
||||
ssp += 2;
|
||||
|
||||
/* probe to determine what areas of the SSP are filled */
|
||||
p = ssp;
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/* turns URL string into URL struct */
|
||||
struct Url *
|
||||
disassemble_url(char *url){
|
||||
char *p;
|
||||
struct Url *retval;
|
||||
size_t s_s;
|
||||
size_t ssp_s;
|
||||
size_t *s;
|
||||
|
||||
if((retval = (struct Url *)malloc(sizeof(struct Url))) == NULL)
|
||||
return NULL;
|
||||
s_s = 0;
|
||||
ssp_s = 0;
|
||||
|
||||
/* get the lengths of the scheme and scheme specific part, excluding
|
||||
* the nul byte */
|
||||
p = url;
|
||||
s = &s_s;
|
||||
while(*p != '\0'){
|
||||
/* standard; scheme names can't contain colons so the first
|
||||
* colon must delimit the scheme from the scheme specific part
|
||||
* (RFC 1738 2.1) */
|
||||
if(s == &s_s && *p == ':'){
|
||||
s = &ssp_s;
|
||||
++p;
|
||||
}
|
||||
++*p;
|
||||
}
|
||||
|
||||
/* malloc the lengths, including the nul byte */
|
||||
if((retval->s = (char *)malloc(sizeof(char) * (s_s + 1))) == NULL)
|
||||
goto free_retval;
|
||||
if((retval->ssp = (char *)malloc(sizeof(char) * (ssp_s + 1))) == NULL)
|
||||
goto free_s;
|
||||
|
||||
/* copy over the scheme and scheme specific part strings */
|
||||
p = retval->s;
|
||||
while(*url != ':')
|
||||
*(p++) = *(url++);
|
||||
*p = '\0';
|
||||
p = retval->ssp;
|
||||
while(*url != '\0')
|
||||
*(p++) = *(url++);
|
||||
*p = '\0';
|
||||
|
||||
return retval;
|
||||
|
||||
free_s:
|
||||
free(retval->s);
|
||||
free_retval:
|
||||
free(retval);
|
||||
return NULL;
|
||||
}
|
||||
20
wip/http/url.h
Normal file
20
wip/http/url.h
Normal file
@@ -0,0 +1,20 @@
|
||||
/* #include <stdlib.h> /* free(3), malloc(3), NULL */
|
||||
|
||||
/* RFC 1738 3.1 */
|
||||
struct CommonInternetScheme{
|
||||
char *user;
|
||||
char *password;
|
||||
char *host; /* FQDN, IPv4, or IPv6 address */
|
||||
char *port; /* Can have default; must be supplied in decimal. */
|
||||
char *url_path;
|
||||
};
|
||||
|
||||
/* standard; RFC 1738 */
|
||||
struct Url{
|
||||
char *s; /* scheme */
|
||||
/* char * or some sort of struct SchemeSpecificPart * */
|
||||
void *ssp; /* scheme-specific-part */
|
||||
};
|
||||
|
||||
struct Url *disassemble_url(char *url);
|
||||
struct Url *free_url(struct Url *url);
|
||||
66
wip/id/id.c
Normal file
66
wip/id/id.c
Normal file
@@ -0,0 +1,66 @@
|
||||
#include <limits.h> /* LOGIN_NAME_MAX */
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h> /* fprintf(3) */
|
||||
#include <stdlib.h> /* stderr, stdout */
|
||||
#include <sysexits.h>
|
||||
#include <unistd.h> /* getuid(2), geteuid(2), getopt(3) */
|
||||
#include "usefulmacros.h"
|
||||
|
||||
int main(int argc, char *argv[]){
|
||||
int c;
|
||||
char mode;
|
||||
bool n;
|
||||
char name[LOGIN_NAME_MAX];
|
||||
bool r;
|
||||
uid_t euid;
|
||||
uid_t uid;
|
||||
|
||||
NOARGVZERO(argv);
|
||||
|
||||
mode = 0;
|
||||
n = false;
|
||||
r = false;
|
||||
|
||||
while((c = getopt(argc, argv, "Gghnru")) != -1)
|
||||
switch(c){
|
||||
case 'G': case 'g': case 'u':
|
||||
if(mode == 0){
|
||||
mode = c;
|
||||
break;
|
||||
}
|
||||
/* FALLTHROUGH */
|
||||
case 'h': default: usage:
|
||||
fprintf(stderr, "Usage: %s [-G]|[-g]|[-u] (-rn) (user)\n", argv[0]);
|
||||
return EX_USAGE;
|
||||
case 'n':
|
||||
n = true;
|
||||
break;
|
||||
case 'r':
|
||||
r = true;
|
||||
break;
|
||||
}
|
||||
|
||||
switch(mode){
|
||||
case 0:
|
||||
goto usage;
|
||||
case 'G':
|
||||
case 'g':
|
||||
return EX_SOFTWARE;
|
||||
case 'u':
|
||||
euid = geteuid();
|
||||
uid = getuid();
|
||||
if(!n){
|
||||
if(r || euid != uid)
|
||||
fprintf(stdout, "%u\n", uid);
|
||||
if(!r)
|
||||
fprintf(stdout, "%u\n", euid);
|
||||
}else
|
||||
{}
|
||||
/* Both busybox and GNU coreutils (according to straces) parse passwd(5)
|
||||
* for this. TODO. */
|
||||
break;
|
||||
default:
|
||||
return EX_SOFTWARE;
|
||||
}
|
||||
return EX_OK;
|
||||
}
|
||||
16
wip/irc/irc.c
Normal file
16
wip/irc/irc.c
Normal file
@@ -0,0 +1,16 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/* RFC 1459 1.2
|
||||
* 9 characters + nul terminator */
|
||||
static int nickname[9 + 1];
|
||||
|
||||
/* RFC 1459 1.3
|
||||
* 200 characters + nul terminator */
|
||||
static int channel[200 + 1];
|
||||
|
||||
/* RFC 1459 1.3
|
||||
* channel names cannot contain these characters */
|
||||
static int channel_restricted[] = { 0x07, ' ', ',', '\0' };
|
||||
|
||||
|
||||
4
wip/irc/irc.h
Normal file
4
wip/irc/irc.h
Normal file
@@ -0,0 +1,4 @@
|
||||
#ifndef _IRC_H
|
||||
# define _IRC_H
|
||||
|
||||
#endif /* ifndef _IRC_H */
|
||||
139
wip/irc/irc.sh
Normal file
139
wip/irc/irc.sh
Normal file
@@ -0,0 +1,139 @@
|
||||
#!/bin/sh
|
||||
|
||||
# irc; Deven Blake 2022; Public domain
|
||||
# I stopped understanding this at 81 lines.
|
||||
|
||||
alias cat='cat -u'
|
||||
alias sed='sed -u'
|
||||
|
||||
# defaults
|
||||
DEFAULT_HOST="example.com"
|
||||
PORT=6667
|
||||
[ -n "$IRC_QUIT_MESSAGE" ] \
|
||||
|| IRC_QUIT_MESSAGE="Bye bye!"
|
||||
|
||||
# defaults (standard-defined)
|
||||
URI_FRAGMENT_DELIMITER='#' # RFC 3986
|
||||
|
||||
argv0="$0"
|
||||
URL="$1"
|
||||
|
||||
usage(){
|
||||
printf "Usage: %s [url]\n" "$argv0"
|
||||
exit 1
|
||||
}
|
||||
|
||||
one_character_per_line(){
|
||||
sed 's/./&\n/g'
|
||||
}
|
||||
|
||||
host_ex_url(){
|
||||
# filter out scheme URI subcomponent
|
||||
# filter out userinfo URI subcomponent
|
||||
# filter out port
|
||||
# filter out heirarchy path
|
||||
# filter out query
|
||||
# filter out fragment
|
||||
printf "%s\n" "$URL" \
|
||||
| sed 's/.*:\/\///' \
|
||||
| sed 's/.*@//' \
|
||||
| sed 's/:.*$//' \
|
||||
| sed 's/\/.*$//' \
|
||||
| sed 's/\?.*$//' \
|
||||
| sed 's/#.*$//'
|
||||
}
|
||||
|
||||
port_ex_url(){
|
||||
# filter out scheme URI subcomponent
|
||||
# filter out userinfo URI subcomponent
|
||||
local_url="$(printf "%s\n" "$URL" \
|
||||
| sed 's/.*:\/\///' \
|
||||
| sed 's/.*@//')"
|
||||
|
||||
# check to ensure there Is a port in the URL
|
||||
# this will also catch if we fucked up
|
||||
if ! [ "$(printf "%s\n" "$local_url" \
|
||||
| one_character_per_line \
|
||||
| grep ':' \
|
||||
| wc -l)" \
|
||||
= 1 ]
|
||||
then
|
||||
# give up, gracefully
|
||||
printf "%s\n" "$PORT"
|
||||
return 0
|
||||
fi
|
||||
|
||||
# filter out query URI subcomponent
|
||||
# filter out heirarchy path
|
||||
# filter out everything preceding the port
|
||||
local_url="$(printf "%s\n" "$local_url" \
|
||||
| sed 's/\?.*$//' \
|
||||
| sed 's/\/.*$//' \
|
||||
| sed 's/.*://')"
|
||||
|
||||
printf "%s\n" "$local_url"
|
||||
}
|
||||
|
||||
username_ex_url(){
|
||||
# only go if there's actually userinfo in the URL
|
||||
# filter out scheme URI subcomponent
|
||||
# filter out everything after userinfo URI subcomponent
|
||||
# filter out password in userinfo, if present
|
||||
printf "%s\n" "$URL" \
|
||||
| grep '@' \
|
||||
| sed 's/.*:\/\///' \
|
||||
| sed 's/@.*$//' \
|
||||
| sed 's/:.*$//'
|
||||
}
|
||||
|
||||
[ -n "$URL" ] \
|
||||
|| usage
|
||||
|
||||
[ -n "$IRC_NICK" ] \
|
||||
|| IRC_NICK="$USER"
|
||||
|
||||
# check if URL matches /^irc:\/\//
|
||||
if ! printf "%s\n" "$URL" | grep "^irc://" >/dev/null 2>&1; then
|
||||
printf "%s: %s: URL incorrectly formatted or scheme not specified.\n" "$argv0" "$URL"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# easy; the fragment is the last part of the URI
|
||||
CHANNEL="#$(printf "%s\n" "$URL" \
|
||||
| sed 's/.*#//' )"
|
||||
|
||||
# not easy
|
||||
PORT="$(port_ex_url)"
|
||||
|
||||
# slow, so don't rerun
|
||||
a="$(username_ex_url)"
|
||||
[ -z "$a" ] \
|
||||
|| IRC_NICK="$a"
|
||||
|
||||
HOST="$(host_ex_url)"
|
||||
|
||||
[ -n "$HOST" ] \
|
||||
|| HOST="$DEFAULT_HOST"
|
||||
|
||||
if ! TEMP="$(mktemp)" || ! TEMP_FIN="$(mktemp)"; then
|
||||
printf "%s: mktemp: Could not make temporary file.\n" "$argv0"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# RFC 1459 section 4.1.2
|
||||
printf "NICK %s\n" "$IRC_NICK" >"$TEMP"
|
||||
|
||||
# RFC 1459 section 4.1.3; USER <username> <hostname> <servername> <realname>
|
||||
# not really important
|
||||
printf "USER %s 0 0 :\n" "$IRC_NICK" >>"$TEMP"
|
||||
|
||||
# RFC 1459 section 4.2.1
|
||||
printf "JOIN %s\n" "$CHANNEL" >>"$TEMP"
|
||||
|
||||
# RFC 1459 section 4.1.6
|
||||
printf "QUIT :%s\n" "$IRC_QUIT_MESSAGE" >"$TEMP_FIN"
|
||||
|
||||
# RFC 1459 section 4.4.1
|
||||
sed "s/^/PRIVMSG $CHANNEL :/g" \
|
||||
| cat "$TEMP" /dev/stdin "$TEMP_FIN" \
|
||||
| nc "$HOST" "$PORT"
|
||||
24
wip/it/LICENSE
Normal file
24
wip/it/LICENSE
Normal file
@@ -0,0 +1,24 @@
|
||||
This is free and unencumbered software released into the public domain.
|
||||
|
||||
Anyone is free to copy, modify, publish, use, compile, sell, or
|
||||
distribute this software, either in source code form or as a compiled
|
||||
binary, for any purpose, commercial or non-commercial, and by any
|
||||
means.
|
||||
|
||||
In jurisdictions that recognize copyright laws, the author or authors
|
||||
of this software dedicate any and all copyright interest in the
|
||||
software to the public domain. We make this dedication for the benefit
|
||||
of the public at large and to the detriment of our heirs and
|
||||
successors. We intend this dedication to be an overt act of
|
||||
relinquishment in perpetuity of all present and future rights to this
|
||||
software under copyright law.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
For more information, please refer to <https://unlicense.org>
|
||||
4
wip/it/Q.py
Normal file
4
wip/it/Q.py
Normal file
@@ -0,0 +1,4 @@
|
||||
from sys import exit
|
||||
|
||||
def main(buffer, argv):
|
||||
return 0
|
||||
67
wip/it/README.md
Normal file
67
wip/it/README.md
Normal file
@@ -0,0 +1,67 @@
|
||||
# it
|
||||
|
||||
*UNIX ed for a new age...*
|
||||
|
||||
Just kidding, no need to use this over ed.
|
||||
This is just my take on a line editor, heavily inspired by ed.
|
||||
|
||||
For disambiguation it's suggested that this project be referred to as "ited", pronounced however one likes (suggested: "iht-ehd").
|
||||
|
||||
## Included commands
|
||||
|
||||
### !
|
||||
|
||||
Passes arguments to Python `subprocess.run`.
|
||||
|
||||
### buffer
|
||||
|
||||
This is where code relating to the Buffer class is kept but calling this from within the editor will allow you to view the current buffer's attributes.
|
||||
|
||||
### dot
|
||||
|
||||
Change the current position within the buffer.
|
||||
### exit
|
||||
|
||||
Will exit via sys.exit rather than telling main.py to break out of the main loop. Functionally identical to `Q`.
|
||||
|
||||
### f
|
||||
|
||||
Displays or changes the filename associated with the current buffer.
|
||||
|
||||
### it
|
||||
|
||||
Launches a new instance of `it`.
|
||||
|
||||
It should be noted that quitting a nested instance of `it` through the usual means (`exit`, `q`, or `Q`) will exit all nested instances of `it` as well.
|
||||
To return to a higher instance of `it`, send an EOF character via your terminal. In xterm this is CTRL+d.
|
||||
|
||||
### load\_module
|
||||
|
||||
Manually loads a module, whether or not it was already loaded.
|
||||
|
||||
### parse\_command
|
||||
|
||||
Used by `it`'s main Python module but calling this from within the editor will allow you to test the command argument splitting.
|
||||
|
||||
### Q
|
||||
|
||||
Quits.
|
||||
|
||||
### q
|
||||
|
||||
Quits, unless your current buffer is unsaved.
|
||||
|
||||
### saved
|
||||
|
||||
With no arguments given, flips the buffer's "saved" boolean attribute.
|
||||
Otherwise, sets the buffer's "saved" attribute to the first argument or errors if multiple arguments given.
|
||||
|
||||
### version
|
||||
|
||||
Prints the versions of given modules.
|
||||
If no modules are specified, prints the version of module "it".
|
||||
|
||||
## Making new commands
|
||||
|
||||
Making new commands is very easy.
|
||||
Read `buffer.py` and `it.py` (<100 LOC total).
|
||||
11
wip/it/bang.py
Normal file
11
wip/it/bang.py
Normal file
@@ -0,0 +1,11 @@
|
||||
import subprocess
|
||||
|
||||
def main(buffer, command):
|
||||
if len(command) == 1:
|
||||
print("?")
|
||||
else:
|
||||
try:
|
||||
print("[%d]" % subprocess.run(command[1:]).returncode)
|
||||
except Exception as err:
|
||||
print("%s" % str(err))
|
||||
return buffer
|
||||
74
wip/it/buffer.py
Normal file
74
wip/it/buffer.py
Normal file
@@ -0,0 +1,74 @@
|
||||
#!/usr/bin/env python3
|
||||
import importlib
|
||||
|
||||
class Buffer: # all the information about the current file
|
||||
def carat(self):
|
||||
return self.index
|
||||
def dollar(self):
|
||||
return self.length() - 1 + self.index
|
||||
|
||||
# Rather than get the content as it's presented in the buffer object
|
||||
# (as one big string), get it as a list.
|
||||
def content_list(self):
|
||||
return self.content.rstrip(self.delimiter).split(self.delimiter)
|
||||
|
||||
# Build a string with the same format as the buffer.content and set the
|
||||
# buffer.content to that string, from the kind of list output by
|
||||
# buffer.content_list().
|
||||
# buffer.content_set_list(buffer.content_list()) is an expensive nop.
|
||||
def content_set_list(self, content_as_list):
|
||||
content = ""
|
||||
for line in content_as_list:
|
||||
content += line + self.delimiter
|
||||
self.content = content
|
||||
return None
|
||||
|
||||
# this is really bad because any module can call import_module_ just as
|
||||
# easily as any other. so malicious modules that, say, take 'q' and
|
||||
# make it upload a file to some external server before exiting would be
|
||||
# super easy to make.
|
||||
# the solution I see is OS-level permissions but this needs to be
|
||||
# talked about like all the time if this tool gets popular
|
||||
# [why would it?] lest some fool runs a zelda.sh script that changes
|
||||
# ~/src/it/w.py and doesn't realize in time
|
||||
def import_module_(self, name):
|
||||
try:
|
||||
self.modules[name] = importlib.import_module(name)
|
||||
except (ModuleNotFoundError, TypeError) as err:
|
||||
print(err)
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
|
||||
def length(self):
|
||||
return self.content.count(self.delimiter)
|
||||
|
||||
def __init__(self):
|
||||
self.content = "" # content of the file
|
||||
self.delimiter = "\n" # line delimiter
|
||||
self.env = {} # configuration dictionary
|
||||
self.filename = "" # name of where we'll save the file
|
||||
self.index = 0 # indexing of dot
|
||||
self.dot = self.index - 1 # invalid position to start
|
||||
self.modules = {} # see it.py
|
||||
self.saved = 1 # is buffer saved?
|
||||
|
||||
def main(buffer, command):
|
||||
if len(command) == 1:
|
||||
command += list(vars(buffer))
|
||||
for attrib in command[1:]:
|
||||
if attrib in list(vars(buffer)):
|
||||
val = vars(buffer)[attrib]
|
||||
# so self.modules shows as <class 'dict'>
|
||||
if not(type(val) is int or type(val) is str):
|
||||
val = str(type(val))
|
||||
# special case usually for self.delimiter
|
||||
elif val == "\n":
|
||||
val = "<newline>"
|
||||
# only affects it if type(val) is int
|
||||
else:
|
||||
val = str(val)
|
||||
print("%s:\t%s" % (attrib, val))
|
||||
else:
|
||||
print("No attribute: %s\n" % attrib, end='')
|
||||
return buffer
|
||||
10
wip/it/config.py
Normal file
10
wip/it/config.py
Normal file
@@ -0,0 +1,10 @@
|
||||
def main(buffer, command):
|
||||
# hard-coded for consistency across multiple people's configs
|
||||
config_delimiter = "\t"
|
||||
for i in range(len(buffer.content_list())):
|
||||
line = buffer.content_list()[i].split(config_delimiter)
|
||||
if len(line) != 2:
|
||||
print("%s: %d: Bad column quantity" % (command[0], i+buffer.index))
|
||||
else:
|
||||
buffer.env[line[0]] = line[1]
|
||||
return buffer
|
||||
20
wip/it/dot.py
Normal file
20
wip/it/dot.py
Normal file
@@ -0,0 +1,20 @@
|
||||
def main(buffer, command):
|
||||
if len(command) == 2 and (command[1].isdigit() or command[1] in {"^","$"}):
|
||||
if command[1].isdigit():
|
||||
dot = int(command[1])
|
||||
elif command[1] == "^":
|
||||
dot = buffer.carat()
|
||||
elif command[1] == "$":
|
||||
dot = buffer.dollar()
|
||||
elif len(command) == 3 and command[1] in {"+","-"} and command[2].isdigit():
|
||||
if command[1] == "+":
|
||||
dot = buffer.dot + int(command[2])
|
||||
elif command[1] == "-":
|
||||
dot = buffer.dot - int(command[2])
|
||||
|
||||
if not("dot" in locals()) or dot < buffer.carat() or dot > buffer.dollar():
|
||||
print("?")
|
||||
else:
|
||||
buffer.dot = dot
|
||||
|
||||
return buffer
|
||||
4
wip/it/exit.py
Normal file
4
wip/it/exit.py
Normal file
@@ -0,0 +1,4 @@
|
||||
import sys
|
||||
|
||||
def main(buffer, command):
|
||||
sys.exit(0)
|
||||
8
wip/it/f.py
Normal file
8
wip/it/f.py
Normal file
@@ -0,0 +1,8 @@
|
||||
def main(buffer, argv):
|
||||
if len(argv) > 2:
|
||||
print("?")
|
||||
elif len(argv) == 1:
|
||||
print(buffer.filename)
|
||||
else:
|
||||
buffer.filename = argv[1]
|
||||
return buffer
|
||||
13
wip/it/get_command.py
Normal file
13
wip/it/get_command.py
Normal file
@@ -0,0 +1,13 @@
|
||||
from parse_command import parse_command
|
||||
|
||||
def get_command(prompt):
|
||||
try:
|
||||
return parse_command(input(prompt))
|
||||
except KeyboardInterrupt: # bastard behavior from ed
|
||||
pass
|
||||
except EOFError:
|
||||
return 0
|
||||
|
||||
def main(buffer, command):
|
||||
print("Command returned as %s" % get_command("Input command (won't be executed): "))
|
||||
return buffer
|
||||
3
wip/it/hello_world.py
Normal file
3
wip/it/hello_world.py
Normal file
@@ -0,0 +1,3 @@
|
||||
def main(buffer, command):
|
||||
print("Hello, world!")
|
||||
return buffer
|
||||
31
wip/it/i.py
Normal file
31
wip/it/i.py
Normal file
@@ -0,0 +1,31 @@
|
||||
def main(buffer, command):
|
||||
if len(command) > 1:
|
||||
print("?")
|
||||
return buffer
|
||||
|
||||
i = []
|
||||
while True:
|
||||
try:
|
||||
line = input()
|
||||
# unintuitive behavior from ed
|
||||
except KeyboardInterrupt:
|
||||
print("?")
|
||||
return buffer
|
||||
except EOFError:
|
||||
break
|
||||
|
||||
if line == ".":
|
||||
break
|
||||
|
||||
i.append(line)
|
||||
|
||||
if buffer.dot < buffer.index:
|
||||
buffer.content_set_list(i)
|
||||
else:
|
||||
buffer.content_set_list(
|
||||
buffer.content_list()[:buffer.dot]
|
||||
+ i
|
||||
+ buffer.content_list()[buffer.dot:]
|
||||
)
|
||||
buffer.dot += len(i)
|
||||
return buffer
|
||||
38
wip/it/it
Executable file
38
wip/it/it
Executable file
@@ -0,0 +1,38 @@
|
||||
#!/usr/bin/env python3
|
||||
import sys
|
||||
from buffer import Buffer
|
||||
from get_command import get_command
|
||||
|
||||
def version():
|
||||
print("it.py line editor; ALPHA 2021")
|
||||
return None
|
||||
|
||||
def main(buffer, supplied_command):
|
||||
if supplied_command != [] and len(supplied_command) > 1:
|
||||
command = supplied_command[1:]
|
||||
else:
|
||||
command = get_command("")
|
||||
|
||||
while True:
|
||||
# EOFError in get_command(); ^D
|
||||
if command == 0:
|
||||
break
|
||||
|
||||
if command == []:
|
||||
continue
|
||||
|
||||
if command[0] in buffer.modules.keys() or buffer.import_module_(command[0]):
|
||||
buffer = buffer.modules[command[0]].main(buffer, command)
|
||||
if type(buffer) is int:
|
||||
break
|
||||
|
||||
command = get_command("")
|
||||
|
||||
return buffer
|
||||
|
||||
if __name__ == "__main__":
|
||||
buffer = main(Buffer(), [])
|
||||
if type(buffer) is int:
|
||||
sys.exit(buffer)
|
||||
else:
|
||||
sys.exit(0)
|
||||
8
wip/it/load_module.py
Normal file
8
wip/it/load_module.py
Normal file
@@ -0,0 +1,8 @@
|
||||
def main(buffer, command):
|
||||
if len(command) == 1:
|
||||
print("?")
|
||||
else:
|
||||
for module in command[1:]:
|
||||
if buffer.import_module_(module):
|
||||
print("Loaded %s" % module)
|
||||
return buffer
|
||||
7
wip/it/p.py
Normal file
7
wip/it/p.py
Normal file
@@ -0,0 +1,7 @@
|
||||
def main(buffer, command):
|
||||
if len(command) < 1 or len(command) > 2:
|
||||
|
||||
if buffer.dot < buffer.index:
|
||||
buffer.content = i
|
||||
buffer.dot += len(i)
|
||||
return buffer
|
||||
65
wip/it/parse_command.py
Normal file
65
wip/it/parse_command.py
Normal file
@@ -0,0 +1,65 @@
|
||||
#!/usr/bin/env python3
|
||||
import sys
|
||||
|
||||
def parse_command(command):
|
||||
casesensitive = True
|
||||
escapes = {"\\"}
|
||||
quotes = {"'", '"'}
|
||||
spaces = {" ", "\t"}
|
||||
|
||||
command = command.strip()
|
||||
|
||||
in_quotes = 0
|
||||
word = ""
|
||||
parsed_command = []
|
||||
|
||||
for i in range(len(command)):
|
||||
# if this char is a quote char
|
||||
# , we're in quotes
|
||||
if ((command[i] in quotes)
|
||||
and in_quotes == 0
|
||||
and (i == 0
|
||||
or (i > 0 and not(command[i-1] in escapes)))):
|
||||
in_quotes = command[i]
|
||||
|
||||
# if this char matches the char by which we're in quotes
|
||||
# , we're not in quotes
|
||||
elif (command[i] == in_quotes
|
||||
and (i > 0 and not(command[i-1] in escapes))):
|
||||
in_quotes = 0
|
||||
|
||||
# if this char is an arg delimiter
|
||||
# and we're not in quotes
|
||||
# and the last char isn't an escape
|
||||
# , this word is an argument
|
||||
elif (command[i] in spaces and in_quotes == 0
|
||||
and (i > 0 and not(command[i-1] in escapes))):
|
||||
parsed_command += [word]
|
||||
word = ""
|
||||
|
||||
elif (not(command[i] in escapes) or (i == len(command) - 1)
|
||||
or not(command[i+1] in spaces + quotes)):
|
||||
word += command[i]
|
||||
|
||||
parsed_command += [word]
|
||||
return [] if parsed_command == [''] else parsed_command
|
||||
|
||||
def main(*args):
|
||||
while True:
|
||||
try:
|
||||
command = input()
|
||||
except:
|
||||
break
|
||||
|
||||
if command == ".":
|
||||
break
|
||||
|
||||
command = parse_command(command)
|
||||
|
||||
for i in range(len(command)):
|
||||
print("\t%d:\t%s" % (i, command[i]))
|
||||
|
||||
return 0 if len(args) != 2 else args[0]
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
8
wip/it/q.py
Normal file
8
wip/it/q.py
Normal file
@@ -0,0 +1,8 @@
|
||||
from sys import exit
|
||||
|
||||
def main(buffer, argv):
|
||||
if not(buffer.saved):
|
||||
print("?")
|
||||
else:
|
||||
buffer = 0
|
||||
return buffer
|
||||
15
wip/it/saved.py
Normal file
15
wip/it/saved.py
Normal file
@@ -0,0 +1,15 @@
|
||||
def main(buffer, command):
|
||||
if len(command) > 2:
|
||||
print("?")
|
||||
elif len(command) == 2:
|
||||
if command[1].isdigit():
|
||||
buffer.saved = int(command[1])
|
||||
elif command[1].lower() in {"true","false"}:
|
||||
buffer.saved = command[1].lower == "true"
|
||||
else:
|
||||
print("?")
|
||||
else:
|
||||
buffer.saved = not(buffer.saved)
|
||||
print("Buffer marked as %sSAVED" % ("" if buffer.saved else "NOT "))
|
||||
|
||||
return buffer
|
||||
16
wip/it/version.py
Normal file
16
wip/it/version.py
Normal file
@@ -0,0 +1,16 @@
|
||||
def version():
|
||||
print("it.py version querying; ALPHA 2021")
|
||||
return None
|
||||
|
||||
def main(buffer, command):
|
||||
if len(command) > 1:
|
||||
fetching = command[1:]
|
||||
else:
|
||||
fetching = ["it"]
|
||||
for module in fetching:
|
||||
if module in list(buffer.modules) or buffer.import_module_(module):
|
||||
try:
|
||||
buffer.modules[module].version()
|
||||
except AttributeError as err:
|
||||
print(err)
|
||||
return buffer
|
||||
47
wip/levenshtein.c
Normal file
47
wip/levenshtein.c
Normal file
@@ -0,0 +1,47 @@
|
||||
#include <stdio.h>
|
||||
#include <stddef.h>
|
||||
#include <sysexits.h>
|
||||
#include <unistd.h>
|
||||
#include "putd.c"
|
||||
|
||||
/* this helped a LOT:
|
||||
* https://medium.com/@ethannam/understanding-the-levenshtein-distance-equation-for-beginners-c4285a5604f0
|
||||
*/
|
||||
|
||||
int
|
||||
levenstein(char *a, char *b){
|
||||
return 100;
|
||||
size_t i;
|
||||
size_t j;
|
||||
int *m;
|
||||
size_t s_a;
|
||||
size_t s_b;
|
||||
for(s_a = 0; a[s_a] != '\0'; ++s_a);
|
||||
for(s_b = 0; b[s_b] != '\0'; ++s_b);
|
||||
/* Levenshtein formula using 2d matrix */
|
||||
int m[s_a][s_b];
|
||||
|
||||
for(i = 0; i < s_a; ++i) /* iterate over a */
|
||||
for(j = 0; j < s_b; ++j) /* iterate over b */
|
||||
//m[i][j]
|
||||
;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]){
|
||||
size_t i;
|
||||
|
||||
if(argc != 3){
|
||||
write(1, "Usage: ", 7);
|
||||
if(argv[0] != NULL){
|
||||
for(i = 0; argv[0][i] != '\0'; ++i);
|
||||
write(1, argv[0], i);
|
||||
}else
|
||||
write(1, "levenshtein", 11);
|
||||
write(1, " [word] [word]\n", 15);
|
||||
return EX_USAGE;
|
||||
}
|
||||
|
||||
// putd(levenstein(argv[1], argv[2]));
|
||||
putd(10);
|
||||
return 0;
|
||||
}
|
||||
24
wip/lsd/LICENSE
Normal file
24
wip/lsd/LICENSE
Normal file
@@ -0,0 +1,24 @@
|
||||
This is free and unencumbered software released into the public domain.
|
||||
|
||||
Anyone is free to copy, modify, publish, use, compile, sell, or
|
||||
distribute this software, either in source code form or as a compiled
|
||||
binary, for any purpose, commercial or non-commercial, and by any
|
||||
means.
|
||||
|
||||
In jurisdictions that recognize copyright laws, the author or authors
|
||||
of this software dedicate any and all copyright interest in the
|
||||
software to the public domain. We make this dedication for the benefit
|
||||
of the public at large and to the detriment of our heirs and
|
||||
successors. We intend this dedication to be an overt act of
|
||||
relinquishment in perpetuity of all present and future rights to this
|
||||
software under copyright law.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
For more information, please refer to <http://unlicense.org/>
|
||||
5
wip/lsd/README.md
Normal file
5
wip/lsd/README.md
Normal file
@@ -0,0 +1,5 @@
|
||||
# trilsd
|
||||
|
||||
*trinity's linux software distribution*
|
||||
|
||||
See `/dist/documentation/trilsd.7'.
|
||||
112
wip/lsd/dist/Makefile
vendored
Normal file
112
wip/lsd/dist/Makefile
vendored
Normal file
@@ -0,0 +1,112 @@
|
||||
include mk.conf
|
||||
|
||||
all: fhs learn
|
||||
|
||||
destroy:
|
||||
cd "$(PREFIX)"
|
||||
git clean -f -d
|
||||
|
||||
fhs:
|
||||
# Filesystem Hierarchy Standard 3.0, 2015
|
||||
# https://refspecs.linuxfoundation.org/FHS_3.0/fhs-3.0.pdf
|
||||
|
||||
# section 3.2
|
||||
mkdir -p "$(PREFIX)/bin"
|
||||
mkdir -p "$(PREFIX)/boot"
|
||||
mkdir -p "$(PREFIX)/dev"
|
||||
mkdir -p "$(PREFIX)/etc"
|
||||
mkdir -p "$(PREFIX)/lib"
|
||||
mkdir -p "$(PREFIX)/media"
|
||||
mkdir -p "$(PREFIX)/mnt"
|
||||
mkdir -p "$(PREFIX)/opt"
|
||||
mkdir -p "$(PREFIX)/run"
|
||||
mkdir -p "$(PREFIX)/sbin"
|
||||
mkdir -p "$(PREFIX)/srv"
|
||||
mkdir -p "$(PREFIX)/tmp"
|
||||
mkdir -p "$(PREFIX)/usr"
|
||||
mkdir -p "$(PREFIX)/var"
|
||||
|
||||
# section 3.7.4
|
||||
mkdir -p "$(PREFIX)/etc/opt"
|
||||
|
||||
# section 4.2
|
||||
mkdir -p "$(PREFIX)/usr/bin"
|
||||
mkdir -p "$(PREFIX)/usr/lib"
|
||||
mkdir -p "$(PREFIX)/usr/local"
|
||||
mkdir -p "$(PREFIX)/usr/sbin"
|
||||
mkdir -p "$(PREFIX)/usr/share"
|
||||
|
||||
# section 4.3
|
||||
mkdir -p "$(PREFIX)/usr/include"
|
||||
mkdir -p "$(PREFIX)/var/spool"
|
||||
mkdir -p "$(PREFIX)/var/tmp"
|
||||
mkdir -p "$(PREFIX)/var/lock"
|
||||
ln -s "$(PREFIX)/usr/spool" "$(PREFIX)/var/spool"
|
||||
ln -s "$(PREFIX)/usr/tmp" "$(PREFIX)/var/tmp"
|
||||
ln -s "$(PREFIX)/usr/spool/locks" "$(PREFIX)/var/lock"
|
||||
|
||||
# section 4.6
|
||||
mkdir -p "$(PREFIX)/usr/lib"
|
||||
|
||||
# section 4.9
|
||||
mkdir -p "$(PREFIX)/usr/local"
|
||||
|
||||
# section 4.9.2
|
||||
mkdir -p "$(PREFIX)/usr/local/bin"
|
||||
#mkdir -p "$(PREFIX)/usr/local/etc" # see section 4.9.3
|
||||
mkdir -p "$(PREFIX)/usr/local/games"
|
||||
mkdir -p "$(PREFIX)/usr/local/include"
|
||||
mkdir -p "$(PREFIX)/usr/local/lib"
|
||||
mkdir -p "$(PREFIX)/usr/local/man"
|
||||
mkdir -p "$(PREFIX)/usr/local/sbin"
|
||||
mkdir -p "$(PREFIX)/usr/local/share"
|
||||
mkdir -p "$(PREFIX)/usr/local/src"
|
||||
|
||||
# section 4.9.3
|
||||
ln -s "$(PREFIX)/usr/local/etc" "$(PREFIX)/etc/local"
|
||||
|
||||
# section 4.11.6
|
||||
mkdir -p "$(PREFIX)/usr/share/man"
|
||||
|
||||
# section 4.11.7
|
||||
mkdir -p "$(PREFIX)/usr/share/misc"
|
||||
|
||||
# section 4.12
|
||||
mkdir -p "$(PREFIX)/usr/src"
|
||||
|
||||
# section 5.2
|
||||
mkdir -p "$(PREFIX)/var/lib"
|
||||
mkdir -p "$(PREFIX)/var/local"
|
||||
mkdir -p "$(PREFIX)/var/log"
|
||||
mkdir -p "$(PREFIX)/var/opt"
|
||||
#mkdir -p "$(PREFIX)/var/run" # see section 5.13.2
|
||||
|
||||
# section 5.8.2
|
||||
mkdir -p "$(PREFIX)/var/lib/misc"
|
||||
|
||||
# section 5.13.2
|
||||
ln -s "$(PREFIX)/var/run" "$(PREFIX)/run"
|
||||
|
||||
# section 6.1.10
|
||||
mkdir -p "$(PREFIX)/var/spool/cron"
|
||||
|
||||
learn: fhs
|
||||
mkdir -p "$(PREFIX)/usr/man/man1"
|
||||
cp "$(PREFIX)/dist/doc/*.1" "$(PREFIX)/usr/man/man1/"
|
||||
mkdir -p "$(PREFIX)/usr/man/man7"
|
||||
cp "$(PREFIX)/dist/doc/*.7" "$(PREFIX)/usr/man/man7/"
|
||||
|
||||
musl_fetch: "$(PREFIX)/usr/src/musl"
|
||||
git clone "$(MUSL_UPSTREAM)" "$(PREFIX)/usr/src/musl" || true
|
||||
|
||||
musl: musl_fetch
|
||||
cd "$(PREFIX)/usr/src/musl"
|
||||
./configure --prefix="$(PREFIX)"
|
||||
$(MAKE) install
|
||||
|
||||
unrepo:
|
||||
rm -rf "$(PREFIX)/.git"
|
||||
rm -f "$(PREFIX)/LICENSE"
|
||||
rm -f "$(PREFIX)/README.md"
|
||||
|
||||
.PHONY: all destroy
|
||||
65
wip/lsd/dist/doc/trilsd.7
vendored
Normal file
65
wip/lsd/dist/doc/trilsd.7
vendored
Normal file
@@ -0,0 +1,65 @@
|
||||
.TH TRINITX 7
|
||||
|
||||
.SH PRONUNCIATION
|
||||
"Try LSD"
|
||||
|
||||
.SH SYNOPSIS
|
||||
.I TriLSD
|
||||
is a UNIX-like software distribution built upon the Linux kernel and the
|
||||
musl C standard library, with nearly all configuration options left to the
|
||||
user's own device.
|
||||
|
||||
.SH BASE SYSTEM
|
||||
A
|
||||
.I TriLSD
|
||||
system always has the following packages:
|
||||
dash,
|
||||
the GNU compiler collection,
|
||||
GNU make,
|
||||
musl,
|
||||
and
|
||||
linux and util-linux.
|
||||
.PP
|
||||
In addition,
|
||||
.I TriLSD
|
||||
needs a core utilities package.
|
||||
The GNU coreutils are a popular choice but Busybox or your own may be used.
|
||||
.PP
|
||||
.I TriLSD
|
||||
also needs an initialization system.
|
||||
OpenRC is the suggested choice but others may be used.
|
||||
SystemD is discouraged; it's mentioned for its popularity and frowned upon for
|
||||
its generally lax security.
|
||||
|
||||
.SH INSTALLATION
|
||||
To install
|
||||
.I TriLSD
|
||||
most of the POSIX specified utilities including awk, git(1), GNU make, and a C
|
||||
compiler that can build the GNU compiler collection must be installed.
|
||||
|
||||
.PP
|
||||
For the installation process see
|
||||
.RB try (1)
|
||||
|
||||
.SH PACKAGE MANAGEMENT
|
||||
.I TriLSD
|
||||
does not come with a package manager; the user may choose whatever
|
||||
system-independent package manager they prefer.
|
||||
|
||||
.SH CONTRIBUTING
|
||||
Pay attention to projects' guidelines for distributions.
|
||||
.PP
|
||||
musl guidelines: https://wiki.musl-libc.org/guidelines-for-distributions.html
|
||||
|
||||
.SH HISTORY
|
||||
The
|
||||
.I TriLSD
|
||||
project was started 2021-12-28 as Trinitx.
|
||||
|
||||
.SH COPYRIGHT
|
||||
.I TriLSD
|
||||
documentation and all in-house tools are part of the public domain.
|
||||
Components of the distribution are of course subject to their own licenses.
|
||||
|
||||
.SH SEE ALSO
|
||||
.RB try (1)
|
||||
3
wip/lsd/dist/mk.conf
vendored
Normal file
3
wip/lsd/dist/mk.conf
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
GCC_UPSTREAM=git://gcc.gnu.org/git/gcc.git
|
||||
MUSL_UPSTREAM=git://git.musl-libc.org/musl
|
||||
PKGSRC_UPSTREAM=https://cdn.netbsd.org/pub/pkgsrc/current/pkgsrc.tar.xz
|
||||
105
wip/nutshell.c
Normal file
105
wip/nutshell.c
Normal file
@@ -0,0 +1,105 @@
|
||||
#include <ctype.h> /* isspace(3) */
|
||||
#include <stddef.h> /* NULL */
|
||||
#include <stdio.h> /* getc(3) */
|
||||
#include <stdlib.h> /* getenv(3), rand(3), srand(3) */
|
||||
#include <string.h> /* strcmp(3) */
|
||||
#include <sys/wait.h> /* wait(2) */
|
||||
#include <time.h> /* time(3) */
|
||||
#include <unistd.h> /* fork(2), write(2) */
|
||||
#include "libio.h"
|
||||
#include "usefulmacros.h"
|
||||
|
||||
#include "nutshell.h"
|
||||
#include "nutshell_builtins.c"
|
||||
|
||||
static int
|
||||
parse_argv(char *buffer, char **argv, int argc_max){
|
||||
int i;
|
||||
int j;
|
||||
int s;
|
||||
|
||||
for(i = 0, j = 0, s = 1; buffer[i] != '\0' && j < argc_max; ++i){
|
||||
while(isspace(buffer[i])){
|
||||
s = 1;
|
||||
buffer[i++] = '\0';
|
||||
}
|
||||
if(s)
|
||||
argv[j++] = buffer + i;
|
||||
}
|
||||
|
||||
return j;
|
||||
}
|
||||
|
||||
static char *
|
||||
read_buffer(char *buf, size_t buf_s){
|
||||
int i;
|
||||
|
||||
for(i = 0; ; ++i){
|
||||
/* ..., '\0', buf_s */
|
||||
/* This isn't perfect but is simple and doesn't matter for
|
||||
* longer buffers that much. */
|
||||
if(i == buf_s - 1 - 1){
|
||||
buf[i] = '\0';
|
||||
break;
|
||||
}
|
||||
|
||||
buf[i] = getc(stdin);
|
||||
|
||||
if(buf[i] == EOF)
|
||||
return NULL;
|
||||
|
||||
else if(buf[i] == '\n'){
|
||||
buf[i + 1] = '\0';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
static int
|
||||
run(char *buf){
|
||||
int argc;
|
||||
static char *argv[ARGV_MAX];
|
||||
int i;
|
||||
|
||||
/* get argv and argc */
|
||||
for(i = 0; i < ARRAYLEN(argv); ++i){
|
||||
if(argv[i] == NULL)
|
||||
break;
|
||||
argv[i] = NULL;
|
||||
}
|
||||
|
||||
argc = parse_argv(buf, argv, ARRAYLEN(argv));
|
||||
|
||||
/* builtins get priority */
|
||||
if((i = isbuiltin(argv[0])) != 0)
|
||||
return builtins[i - 1].f(argc, argv);
|
||||
|
||||
if(state.jailed)
|
||||
goto runerr;
|
||||
|
||||
runerr:
|
||||
/* This is what busybox ash(1) does. */
|
||||
return 127;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]){
|
||||
static char buf[BUF_MAX];
|
||||
static char prompt[] = DEFAULT_PROMPT;
|
||||
|
||||
builtin_init(0, empty_argv);
|
||||
|
||||
for(;;){
|
||||
write(1, prompt, ARRAYLEN(prompt));
|
||||
if(read_buffer(buf, ARRAYLEN(buf)) == NULL){
|
||||
write(1, "EOF\n", 4);
|
||||
state.status = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
state.status = run(buf);
|
||||
}
|
||||
|
||||
return state.status;
|
||||
}
|
||||
15
wip/nutshell.h
Normal file
15
wip/nutshell.h
Normal file
@@ -0,0 +1,15 @@
|
||||
/* conservative defaults */
|
||||
#define ARGV_MAX 10
|
||||
#define BUF_MAX 100
|
||||
|
||||
#define DEFAULT_PROMPT "^_^?: "
|
||||
|
||||
char *empty_argv[1] = { NULL };
|
||||
|
||||
struct {
|
||||
int jailed;
|
||||
int status;
|
||||
}state = {
|
||||
0,
|
||||
0
|
||||
};
|
||||
104
wip/nutshell_builtins.c
Normal file
104
wip/nutshell_builtins.c
Normal file
@@ -0,0 +1,104 @@
|
||||
#define NETHACK_NAME "nethack"
|
||||
|
||||
int builtin_builtin (int, char **);
|
||||
int builtin_escape (int, char **);
|
||||
int builtin_init (int, char **);
|
||||
int builtin_jail (int, char **);
|
||||
int builtin_nethack (int, char **);
|
||||
int builtin_reassure (int, char **);
|
||||
int builtin_status (int, char **);
|
||||
|
||||
struct {
|
||||
char *name;
|
||||
int (*f)(int, char **);
|
||||
}builtins[] = {
|
||||
/* guaranteed to exist */
|
||||
{"builtin", builtin_builtin},
|
||||
{"init", builtin_init},
|
||||
|
||||
/* optional additions */
|
||||
{"escape", builtin_escape},
|
||||
{"jail", builtin_jail},
|
||||
{"nethack", builtin_nethack},
|
||||
{"status", builtin_status}
|
||||
};
|
||||
|
||||
int
|
||||
isbuiltin(char *s){
|
||||
int i;
|
||||
|
||||
for(i = 0; i < ARRAYLEN(builtins); ++i)
|
||||
if(strcmp(builtins[i].name, s) == 0)
|
||||
return i + 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
builtin_builtin(int argc, char **argv){
|
||||
int i;
|
||||
|
||||
if(argc < 2){
|
||||
fdputs(2, "%s: needs argument(s)");
|
||||
return 1;
|
||||
}
|
||||
|
||||
++argv;
|
||||
|
||||
while(*argv != NULL)
|
||||
if(!isbuiltin(*argv))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
builtin_escape(int argc, char **argv){
|
||||
char *s;
|
||||
|
||||
if((s = getenv("SHELL")) == NULL){
|
||||
fdputs(1, "$SHELL seems to be empty. This is an OS error.\n");
|
||||
}else if(fork() == 0)
|
||||
execl(s, s, NULL);
|
||||
else
|
||||
wait(NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
builtin_init(int argc, char **argv){
|
||||
srand(time(NULL));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
builtin_jail(int argc, char **argv){
|
||||
printf("%s\n", argv[1]);
|
||||
if(argv[1] == NULL)
|
||||
fdputd(1, state.jailed);
|
||||
else if(strcmp(argv[1], "break") == 0 || strcmp(argv[1], "build") == 0)
|
||||
state.jailed = (argv[1][1] - 'r') / ('u' - 'r'); /* cheap */
|
||||
else
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
builtin_nethack(int argc, char **argv){
|
||||
static char *nethack_name = NETHACK_NAME;
|
||||
char *a[2];
|
||||
|
||||
if(fork() == 0){
|
||||
a[0] = nethack_name;
|
||||
a[1] = NULL;
|
||||
execvp("nethack", a);
|
||||
}else
|
||||
wait(NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
builtin_status(int argc, char **argv){
|
||||
fdputd(1, state.status);
|
||||
return 0;
|
||||
}
|
||||
37
wip/rss/pig.md
Normal file
37
wip/rss/pig.md
Normal file
@@ -0,0 +1,37 @@
|
||||
# pig\_birth
|
||||
|
||||
Initializes the pig.
|
||||
|
||||
# pig\_feed
|
||||
|
||||
Refreshes all the feed in the pigpen.
|
||||
|
||||
# pig\_fetch
|
||||
|
||||
Fetches the feed for the pigpen.
|
||||
|
||||
Not intended to be called on its own.
|
||||
|
||||
# pig\_latin
|
||||
|
||||
Prints internal pig details for a given feed file.
|
||||
|
||||
# pig\_name
|
||||
|
||||
Prints the file name for a given pig feed.
|
||||
|
||||
# pig\_pen
|
||||
|
||||
Prints the location of the pigpen, which houses all stowed pig feed.
|
||||
|
||||
A given feed will be stored as `"$(pig_pen)/$(pig_name)`.
|
||||
|
||||
# pig\_recall
|
||||
|
||||
Prints the contents of a given feed URL.
|
||||
|
||||
If the URL isn't already stowed, stows it before printing.
|
||||
|
||||
# pig\_stow
|
||||
|
||||
Stows fetched feed in the pigpen.
|
||||
19
wip/rss/pig_birth
Normal file
19
wip/rss/pig_birth
Normal file
@@ -0,0 +1,19 @@
|
||||
#!/bin/sh
|
||||
set -e
|
||||
|
||||
argv0="$0"
|
||||
|
||||
depend(){
|
||||
if ! command -v "$1" >/dev/null 2>&1; then
|
||||
printf "%s: %s: Could not find dependency.\n" "$argv0" "$1" \
|
||||
1>&2
|
||||
exit 69 # sysexits(3) EX_UNAVAILABLE
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
depend curl
|
||||
depend jq
|
||||
depend xq
|
||||
|
||||
mkdir "$(pig_pen)"
|
||||
7
wip/rss/pig_feed
Executable file
7
wip/rss/pig_feed
Executable file
@@ -0,0 +1,7 @@
|
||||
#!/bin/sh
|
||||
|
||||
for file in "$(pig_pen)"/*; do
|
||||
pig_latin "$file" \
|
||||
| jq '.feed_url' \
|
||||
| xargs pig_stow &
|
||||
done
|
||||
3
wip/rss/pig_fetch
Executable file
3
wip/rss/pig_fetch
Executable file
@@ -0,0 +1,3 @@
|
||||
#!/bin/sh
|
||||
|
||||
curl -so - -- "$1"
|
||||
10
wip/rss/pig_latin
Executable file
10
wip/rss/pig_latin
Executable file
@@ -0,0 +1,10 @@
|
||||
#!/bin/sh
|
||||
|
||||
while str isvalue "$1"; do
|
||||
case "$1" in
|
||||
*xml)
|
||||
xq '.feed.pig' <"$1" ;;
|
||||
*json)
|
||||
jq '.feed.pig' <"$1" ;;
|
||||
esac
|
||||
done
|
||||
4
wip/rss/pig_name
Executable file
4
wip/rss/pig_name
Executable file
@@ -0,0 +1,4 @@
|
||||
#!/bin/sh
|
||||
|
||||
printf "%s\n" "$1" \
|
||||
| tr -cd '[:alnum:]'
|
||||
15
wip/rss/pig_pen
Executable file
15
wip/rss/pig_pen
Executable file
@@ -0,0 +1,15 @@
|
||||
#!/bin/sh
|
||||
set -e
|
||||
|
||||
str isvalue "$1" \
|
||||
&& printf "Usage: %s\n" "$0" 1>&2 \
|
||||
&& exit 64 \
|
||||
|| str isvalue "$PIGPEN" \
|
||||
&& printf "%s\n" "$PIGPEN" \
|
||||
&& exit 0 \
|
||||
|| str isvalue "$XDG_CONFIG_HOME" \
|
||||
&& printf "%s\n" "$XDG_CONFIG_HOME" \
|
||||
&& exit 0 \
|
||||
|| printf "%s/.pigpen\n" "$HOME" \
|
||||
&& exit 0 \
|
||||
|| exit 1
|
||||
7
wip/rss/pig_recall
Executable file
7
wip/rss/pig_recall
Executable file
@@ -0,0 +1,7 @@
|
||||
#!/bin/sh
|
||||
set -e
|
||||
|
||||
filename="$(pig_pen)/$(pig_name "$1")"
|
||||
|
||||
test -e "$filename" || pig_stow "$1"
|
||||
cat "$filename"
|
||||
18
wip/rss/pig_stow
Executable file
18
wip/rss/pig_stow
Executable file
@@ -0,0 +1,18 @@
|
||||
#!/bin/sh
|
||||
set -e
|
||||
|
||||
while str isvalue "$1"; do
|
||||
|
||||
pig_fetch "$1" | xq -x "$(
|
||||
printf '.
|
||||
* { feed: { pig: {
|
||||
feed_url: "%b",
|
||||
pet_sound: "oink",
|
||||
stow_date: "%b",
|
||||
version: "0"
|
||||
} } }' "$1" "$(date '+%Y-%m-%dT%T')"\
|
||||
| tr -d '[:space:]' \
|
||||
)" >"$(pig_pen)/$(pig_name "$1")"
|
||||
|
||||
shift
|
||||
done
|
||||
182
wip/rss/youtube
Executable file
182
wip/rss/youtube
Executable file
@@ -0,0 +1,182 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -e
|
||||
|
||||
argv0="$0"
|
||||
|
||||
PIGPEN="$(pig_pen)"
|
||||
|
||||
latin(){
|
||||
case "$1" in
|
||||
*json) jq '.feed.pig' <"$1" ;;
|
||||
*xml) xq '.feed.pig' <"$1" ;;
|
||||
esac
|
||||
}
|
||||
|
||||
list_channels(){
|
||||
pscat \
|
||||
[ sh -c "for file in \"$PIGPEN\"/*.xml; \
|
||||
do xq '{(.feed.link[0].\"@href\"): .feed.title}' \"\$file\"; \
|
||||
done 2>/dev/null" ] \
|
||||
[ sh -c "for file in \"$PIGPEN\"/*.json; \
|
||||
do jq '{(.feed.link[0].\"@href\"): .feed.title}' \"\$file\"; \
|
||||
done 2>/dev/null" ] \
|
||||
[ printf "\n" ] \
|
||||
| sed \
|
||||
-e '/{/d' \
|
||||
-e '/}/d' \
|
||||
-e 's/^ \"//g' \
|
||||
-e 's/\": \"/ /g' \
|
||||
-e 's/\,$//g' \
|
||||
-e 's/\"$//g'
|
||||
}
|
||||
|
||||
list_videos(){
|
||||
file="$(printf "$PIGPEN"/$( \
|
||||
list_channels \
|
||||
| sed "/$1/q" \
|
||||
| tail -n 1 \
|
||||
| cut -f 1 \
|
||||
| xargs pig_name \
|
||||
)*)"
|
||||
case "$file" in
|
||||
*json)
|
||||
jq \
|
||||
'reduce .feed.entry[] as $item (
|
||||
{};
|
||||
. + { ($item.link."@href"): $item.title }
|
||||
)' "$file"
|
||||
;;
|
||||
*xml)
|
||||
xq \
|
||||
'reduce .feed.entry[] as $item (
|
||||
{};
|
||||
. + { ($item.link."@href"): $item.title }
|
||||
)' "$file"
|
||||
;;
|
||||
*)
|
||||
printf "No file found!\n" 1>&2
|
||||
true
|
||||
;;
|
||||
esac | sed \
|
||||
-e '1d' \
|
||||
-e '$d' \
|
||||
-e 's/\": \"/ /g' \
|
||||
-e 's/^ \"//g' \
|
||||
-e 's/\,$//g' \
|
||||
-e 's/\"$//g' # this is really hacky
|
||||
|
||||
}
|
||||
|
||||
stow(){
|
||||
name="$PIGPEN/$(pig_name "$1")"
|
||||
pig_fetch "$1" | xq "$(
|
||||
date '+%Y-%m-%dT%T' \
|
||||
| xargs printf '
|
||||
. * { feed: { pig: {
|
||||
feed_url: "%b",
|
||||
pet_sound: "choo",
|
||||
stow_date: "%b",
|
||||
version: "0"
|
||||
} } }' "$1" \
|
||||
)" >"$name.json"
|
||||
rm -f "$name.xml"
|
||||
}
|
||||
|
||||
watch(){
|
||||
youtube-dl -F "$1"
|
||||
printf "Pick a format [22]: "
|
||||
input="$(head -n 1 | tr -d '\n')"
|
||||
str isalnum "$input" \
|
||||
&& str isdigit $input \
|
||||
|| input=22 \
|
||||
&& youtube-dl -f $input "$1" -o - \
|
||||
| mpv -
|
||||
}
|
||||
|
||||
usage(){
|
||||
printf "\
|
||||
Usage: %s
|
||||
list_channels
|
||||
list_videos [channel name]
|
||||
listen [video URL]
|
||||
refresh (channel name...)
|
||||
subscribe [channel URL...]
|
||||
watch [video URL]
|
||||
watch_latest [channel name]
|
||||
" "$argv0" 1>&2
|
||||
}
|
||||
|
||||
case "$1" in
|
||||
list_channels)
|
||||
! str isvalue "$2" \
|
||||
|| usage
|
||||
list_channels
|
||||
;;
|
||||
list_videos) # do something with youtube-dl?
|
||||
list_videos "$2"
|
||||
;;
|
||||
listen)
|
||||
str isvalue "$2" \
|
||||
|| usage
|
||||
while str isvalue "$2"
|
||||
do youtube-dl "$2" -f bestaudio -o - \
|
||||
| mpv -
|
||||
shift
|
||||
done
|
||||
;;
|
||||
refresh)
|
||||
if ! str isvalue "$2"
|
||||
then for file in "$PIGPEN"/*
|
||||
do stow "$( \
|
||||
latin "$file" \
|
||||
| jq -r '.feed_url' \
|
||||
)"
|
||||
done
|
||||
else
|
||||
while str isvalue "$2"
|
||||
do stow "$( \
|
||||
latin "$( \
|
||||
list_channels \
|
||||
| grep "$2" \
|
||||
| cut -f 2 \
|
||||
)" | jq '.feed_url' \
|
||||
)"
|
||||
shift
|
||||
done
|
||||
fi
|
||||
;;
|
||||
subscribe)
|
||||
str isvalue "$2" \
|
||||
|| usage
|
||||
while str isvalue "$2"
|
||||
do stow "http://www.youtube.com/feeds/videos.xml?channel_id=$(
|
||||
youtube-dl \
|
||||
--get-filename \
|
||||
--playlist-items 1 \
|
||||
-o '%(channel_id)s' \
|
||||
"$2" \
|
||||
)"
|
||||
shift
|
||||
done
|
||||
;;
|
||||
watch) # needs work
|
||||
str isvalue "$2" \
|
||||
|| usage
|
||||
while str isvalue "$2"
|
||||
do watch "$2"
|
||||
done
|
||||
;;
|
||||
watch_latest)
|
||||
str isvalue "$2" \
|
||||
|| usage
|
||||
watch "$( \
|
||||
list_videos "$2" \
|
||||
| head -n 1 \
|
||||
| cut -f 1 \
|
||||
)"
|
||||
;;
|
||||
*) usage ;;
|
||||
esac
|
||||
|
||||
exit 0
|
||||
107
wip/runlength.c
Normal file
107
wip/runlength.c
Normal file
@@ -0,0 +1,107 @@
|
||||
#include <ctype.h> /* isdigit(3) */
|
||||
#include <stdio.h> /* fprintf(3), getc(3), putc(3) */
|
||||
#include <stdlib.h> /* stdin, stderr, stdout */
|
||||
#include <sysexits.h> /* EX_DATAERR, EX_OK */
|
||||
|
||||
/* Unicode compatibility coming someday */
|
||||
#define GETC getc
|
||||
#define PUTC putc
|
||||
|
||||
#define NUMBER_TERMINATOR '*'
|
||||
|
||||
/* syntax error if a decoding file ends with [char][char] */
|
||||
/* if(STRICT) just print it out */
|
||||
#define STRICT 0
|
||||
|
||||
static int decode(FILE *input, FILE *output){
|
||||
int c[2];
|
||||
unsigned int num;
|
||||
enum{NUMBER_PARSING = 1} state;
|
||||
|
||||
c[0] = EOF;
|
||||
|
||||
/* reading -> (current char == prev char)> number parsing -> reading */
|
||||
while((c[1] = GETC(input)) != EOF)
|
||||
if(state == NUMBER_PARSING){
|
||||
if(isdigit(c[1]))
|
||||
num = num * 10 + c[1] - '0';
|
||||
else if(c[1] == NUMBER_TERMINATOR){
|
||||
for(; num > 0; --num)
|
||||
PUTC(c[0], output);
|
||||
c[0] = EOF; c[1] = EOF;
|
||||
state = 0;
|
||||
}else
|
||||
return EX_DATAERR;
|
||||
}else if(c[1] == c[0]){
|
||||
num = 0;
|
||||
state = NUMBER_PARSING;
|
||||
}else{
|
||||
if(c[0] != EOF)
|
||||
PUTC(c[0], output);
|
||||
c[0] = c[1];
|
||||
}
|
||||
|
||||
if(state == NUMBER_PARSING && !STRICT)
|
||||
/* it doesn't make sense to put this in a loop */
|
||||
{ PUTC(c[0], output); PUTC(c[0], output); }
|
||||
else if(state == NUMBER_PARSING)
|
||||
return EX_DATAERR;
|
||||
else if(c[0] != EOF)
|
||||
PUTC(c[0], output);
|
||||
|
||||
return EX_OK;
|
||||
}
|
||||
|
||||
static int encode(FILE *input, FILE *output){
|
||||
int c[2];
|
||||
unsigned int num;
|
||||
enum{COUNTING = 1} state;
|
||||
|
||||
/* It was more fun to use gotos than to use sane structure. */
|
||||
for(c[0] = EOF, num = 2, state = 0; ;)
|
||||
if((c[1] = GETC(input)) == EOF){
|
||||
if(state == COUNTING)
|
||||
goto dump;
|
||||
else
|
||||
goto place;
|
||||
}else if(state == COUNTING){
|
||||
if(c[1] != c[0]){
|
||||
dump: PUTC(c[0], output);
|
||||
fprintf(output,
|
||||
"%d%c",
|
||||
num, NUMBER_TERMINATOR
|
||||
);
|
||||
num = 2;
|
||||
state = 0;
|
||||
goto next;
|
||||
}else
|
||||
++num;
|
||||
}else if(c[1] == c[0])
|
||||
state = COUNTING;
|
||||
else{ /* c[1] != c[0] */
|
||||
if(c[0] != EOF) /* c[0] will be EOF at first */
|
||||
place: PUTC(c[0], output);
|
||||
next: if(c[1] == EOF)
|
||||
return EX_OK;
|
||||
c[0] = c[1];
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]){
|
||||
int r;
|
||||
|
||||
if(argc != 1){
|
||||
fprintf(stderr,
|
||||
"Usage: %s\n",
|
||||
argv[0] == NULL ?
|
||||
(f == decode ? "decode" : "encode")
|
||||
: argv[0]
|
||||
);
|
||||
return EX_USAGE;
|
||||
}
|
||||
|
||||
if((r = f(stdin, stdout)) == EX_DATAERR)
|
||||
fprintf(stderr, "%s: syntax error.\n", argv[0]);
|
||||
|
||||
return r;
|
||||
}
|
||||
112
wip/substitute.c
Normal file
112
wip/substitute.c
Normal file
@@ -0,0 +1,112 @@
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include "liberror.h"
|
||||
|
||||
void
|
||||
exhaust_buffer(char *b, size_t s){
|
||||
size_t i;
|
||||
for(i = 0; i < s; ++i)
|
||||
if(b[i] != 0)
|
||||
putc(b[i], stdout);
|
||||
free(b);
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
print_stdin(void){
|
||||
char c;
|
||||
while((c = getc(stdin)) != EOF)
|
||||
putc(c, stdout);
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
substitute(char *phrase, char *substitution, bool exit_on_first, char *name){
|
||||
char *b = (char *)calloc(strlen(phrase)+1, sizeof(char));
|
||||
size_t i;
|
||||
if(b == NULL)
|
||||
error(name, ALLOCATION_ERROR);
|
||||
while((b[strlen(phrase)-1] = getc(stdin)) != EOF){
|
||||
for(i = 0;
|
||||
b[i] == phrase[i]
|
||||
&& b[i] != 0
|
||||
&& phrase[i] != 0;
|
||||
++i);
|
||||
if(i == strlen(phrase)){
|
||||
fputs(substitution, stdout);
|
||||
for(i = 0; i < strlen(phrase);)
|
||||
b[i++] = 0;
|
||||
if(exit_on_first){
|
||||
exhaust_buffer(b, strlen(phrase)+1);
|
||||
print_stdin();
|
||||
}
|
||||
}else
|
||||
putc(*b, stdout);
|
||||
|
||||
/* There's a more efficient way to maintain a buffer here,
|
||||
* where I keep an unordered string of chars and form an
|
||||
* ordered string when I need to check against the phrase
|
||||
* to match. However it's math-intensive, which sucks not just
|
||||
* for a self-taught lamer but in general in regards to muh
|
||||
* simplicity, and the math undercuts the performance gain
|
||||
* from avoiding touching memory. Also, come on, you're never
|
||||
* gonna have a phrase longer than 100 bytes! Who cares?! */
|
||||
for(i = 0; i < strlen(phrase); ++i)
|
||||
b[i] = b[i+1];
|
||||
}
|
||||
exhaust_buffer(b, strlen(phrase)+1);
|
||||
}
|
||||
|
||||
void
|
||||
usage(char *name){
|
||||
fprintf(stdout, "Usage: %s (-fhr) [phrase] [substitution]\n", name);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]){
|
||||
extern char *optarg;
|
||||
extern int optind;
|
||||
bool exit_on_first = 0;
|
||||
char c;
|
||||
char *argv0 = argv[0];
|
||||
bool regex_mode = 0;
|
||||
|
||||
while((c = getopt(argc, argv, "fhr")) != -1){
|
||||
switch(c){
|
||||
/* -f exists because there exist uses of `sed 's/foo/bar/'`
|
||||
* without the trailing `g` for global substitution that
|
||||
* would be borked if made global. Perhaps there are other ways
|
||||
* to do so that mean that this option doesn't need to be
|
||||
* implemented, but it's kind of easy to just add so
|
||||
* whatever. */
|
||||
case 'f': exit_on_first = 1;
|
||||
case 'h': usage(argv0);
|
||||
/* By default regex is not parsed; this is because regular
|
||||
* expressions are not known to the GENERAL user. The kind of
|
||||
* user that uses this utility /does/ know regex, but the kind
|
||||
* of user this utility targets does not, so don't implement
|
||||
* potentially undesirable functionality by default.
|
||||
* If you know regex you know how to look up a manpage. */
|
||||
case 'r':
|
||||
regex_mode = 1;
|
||||
break;
|
||||
case '?': default: usage(argv0);
|
||||
}
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
if(argc < 2 || argc > 3)
|
||||
usage(argv0);
|
||||
|
||||
if(regex_mode == 0)
|
||||
substitute(argv[0], argv[1], exit_on_first, argv0);
|
||||
else
|
||||
{ printf("Not implemented.\n"); exit(1); }
|
||||
// substitute_regex(argv[0], argv[1], exit_on_first, argv0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
152
wip/tail.c
Normal file
152
wip/tail.c
Normal file
@@ -0,0 +1,152 @@
|
||||
#include <ctype.h>
|
||||
#include <limits.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include "args.h"
|
||||
#include "libcharin.h"
|
||||
#include "libstris.h"
|
||||
|
||||
#define DEFAULT_LENGTH 10
|
||||
#define OFLOW(STR) (STR[strlen(STR)-1] != '\n')
|
||||
#ifndef PAGE_SIZE
|
||||
# ifndef PAGESIZE
|
||||
# define PAGE_SIZE 1024
|
||||
# else
|
||||
# define PAGE_SIZE PAGESIZE
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
TODO
|
||||
* fix limits.h stuff; if limits.h isn't on the system define
|
||||
reasonable limits in its place
|
||||
* don't use unsafe string functions
|
||||
* fix bugs
|
||||
*/
|
||||
|
||||
|
||||
void
|
||||
tail(FILE *input, FILE *output, int length){
|
||||
bool loop = 1;
|
||||
char *lines[length];
|
||||
size_t ls[length];
|
||||
int i;
|
||||
int filelines = 0;
|
||||
size_t offset = 0;
|
||||
|
||||
for(i = 0; i < length; i++){
|
||||
ls[i] = PAGE_SIZE;
|
||||
lines[i] = (char *)calloc(ls[i], sizeof(char));
|
||||
}
|
||||
|
||||
i = 0;
|
||||
|
||||
while(fgets(lines[i] + offset, ls[i], input)){
|
||||
if(OFLOW(lines[i])){
|
||||
offset += ls[i] - 1;
|
||||
ls[i] += PAGE_SIZE;
|
||||
/* should be more resilient */
|
||||
if(realloc(lines[i], ls[i]) == NULL){
|
||||
fprintf(stderr, "tail: Couldn't re-allocate memory (%d bytes)\n", ls[i] * sizeof(char));
|
||||
exit(1);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
offset = 0;
|
||||
++filelines;
|
||||
i = (i + 1) % length;
|
||||
}
|
||||
|
||||
for(i = filelines % length; loop || i != filelines % length; i = (i + 1) % length){
|
||||
if(loop && i == filelines % length)
|
||||
loop = 0;
|
||||
printf("%s", lines[i]);
|
||||
}
|
||||
|
||||
/* glitch here when `tail`ing normal files */
|
||||
for(i = 0; i < length; i++){
|
||||
free(lines[i]);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
usage(char *name){
|
||||
fprintf(stderr, "Usage: %s [-ht] [-n integer] [file...]\n", name);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[]){
|
||||
char **argsv = getargsv(argc, argv);
|
||||
char *flags = getflags(argc, argv);
|
||||
char mode[3] = "rb";
|
||||
char filepath[NAME_MAX+PATH_MAX];
|
||||
char *lengthstr;
|
||||
size_t fplen = NAME_MAX+PATH_MAX;
|
||||
FILE *input;
|
||||
FILE *output = stdout;
|
||||
int argsc = getargsc(argc, argv);
|
||||
int i;
|
||||
int length = DEFAULT_LENGTH;
|
||||
size_t s;
|
||||
|
||||
if(charin(flags, 'h'))
|
||||
usage(argv[0]);
|
||||
|
||||
if(charin(flags, 'n')){
|
||||
lengthstr = getflag(argc, argv, 'n');
|
||||
if(!strisint(lengthstr) || *lengthstr == '\0')
|
||||
usage(argv[0]);
|
||||
else
|
||||
length = atoi(lengthstr);
|
||||
}
|
||||
|
||||
if(charin(flags, 't'))
|
||||
/* Explicitly open files as text rather than as binary.
|
||||
* this changes "rb" to "r". Should have no effect on
|
||||
* POSIX systems but may change CRLF to just LF with
|
||||
* MS Windows. I don't know why anyone would need this
|
||||
* but it's here for those that do. */
|
||||
mode[1] = '\0';
|
||||
|
||||
if(argsc == 0)
|
||||
tail(stdin, output, length);
|
||||
else
|
||||
for(i = 1; i < argsc; ++i){
|
||||
if(i > 1)
|
||||
fprintf(output, "\n");
|
||||
|
||||
if(!strcmp(argv[i], "-")){
|
||||
realpath(argv[i], filepath);
|
||||
input = fopen(argv[i], "r");
|
||||
if(input == NULL){
|
||||
fprintf(stderr, "%s: %s: Could not open file for reading\n", argv[0], filepath);
|
||||
exit(1);
|
||||
}
|
||||
}else{
|
||||
input = stdin;
|
||||
|
||||
/* probably safe but could be vulnerable */
|
||||
/* just making filepath[] = "<stdin>" */
|
||||
s = strlen("<stdin>") + 1; /* minimum size for filepath */
|
||||
if(fplen >= s)
|
||||
strcpy(filepath, "<stdin>");
|
||||
else if(realloc(filepath, s) == NULL)
|
||||
fprintf(stderr, "%s: Failed to reallocate path string, using <stdin>\n", argv[0]);
|
||||
}
|
||||
|
||||
fprintf(output, "==> %s <==\n", filepath);
|
||||
tail(input, output, length);
|
||||
if(input != stdin && fclose(input) != 0){
|
||||
fprintf(stderr, "%s: %s: Could not close file. Exiting...\n", argv[0], filepath);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
41
wip/tekubi/Makefile
Normal file
41
wip/tekubi/Makefile
Normal file
@@ -0,0 +1,41 @@
|
||||
i2cdevlib_url = https://github.com/jrowberg/i2cdevlib.git
|
||||
|
||||
setup: I2Cdev.cpp I2Cdev.h MPU6050.cpp MPU6050.h
|
||||
|
||||
clean_setup:
|
||||
rm -rf i2cdevlib i2cdevlib_tmp
|
||||
rm -f I2Cdev.cpp I2Cdev.h
|
||||
rm -f MPU6050.cpp MPU6050.h
|
||||
|
||||
i2cdevlib:
|
||||
rm -rf i2cdevlib_tmp
|
||||
git init i2cdevlib_tmp
|
||||
git -C i2cdevlib_tmp remote add -f origin $(i2cdevlib_url)
|
||||
git -C i2cdevlib_tmp config core.sparseCheckout true
|
||||
git -C i2cdevlib_tmp sparse-checkout set
|
||||
git -C i2cdevlib_tmp checkout master
|
||||
mv i2cdevlib_tmp i2cdevlib
|
||||
|
||||
i2cdevlib/Arduino/I2Cdev: i2cdevlib
|
||||
git -C i2cdevlib sparse-checkout add Arduino/I2Cdev
|
||||
git -C i2cdevlib sparse-checkout reapply
|
||||
git fetch
|
||||
|
||||
i2cdevlib/Arduino/MPU6050: i2cdevlib
|
||||
git -C i2cdevlib sparse-checkout add Arduino/MPU6050
|
||||
git -C i2cdevlib sparse-checkout reapply
|
||||
git fetch
|
||||
|
||||
I2Cdev.cpp: i2cdevlib/Arduino/I2Cdev
|
||||
cp i2cdevlib/Arduino/I2Cdev/I2Cdev.cpp ./
|
||||
|
||||
I2Cdev.h: i2cdevlib/Arduino/I2Cdev
|
||||
cp i2cdevlib/Arduino/I2Cdev/I2Cdev.h ./
|
||||
|
||||
MPU6050.cpp: i2cdevlib/Arduino/MPU6050
|
||||
cp i2cdevlib/Arduino/MPU6050/MPU6050.cpp ./
|
||||
|
||||
MPU6050.h: i2cdevlib/Arduino/MPU6050
|
||||
cp i2cdevlib/Arduino/MPU6050/MPU6050.h ./
|
||||
|
||||
.PHONY: setup clean_setup
|
||||
89
wip/tekubi/main.ino
Normal file
89
wip/tekubi/main.ino
Normal file
@@ -0,0 +1,89 @@
|
||||
#define RAD_PIN 0
|
||||
#define ECG_PIN 14 /* A0 */
|
||||
/* TEKUBI
|
||||
* ___________ ________________________________
|
||||
* | | | |
|
||||
* | USB POWER | | TEENSY 4.0 |
|
||||
* | | | |
|
||||
* |__GND__5V__| |__Vin__GND__D0__SDA0__SCL0__A0__|
|
||||
* | | | | | | | |
|
||||
* | +--------+----|---|-+--|-----|----|----------+
|
||||
* | | | | | | | | |
|
||||
* +----|-------------+---|-|--|-----|----|-----+ |
|
||||
* | | | | | | | | | |
|
||||
* | | +---------|---+ | +---+ | +-+ | |
|
||||
* __ | __ |__ | __ __ | __ |____ | | | ____ | __ | __
|
||||
* | GND 5V INT | | GND Vcc | | | | | GND Vcc |
|
||||
* | (100mA?) | | (10mA) SDA--+ | +-A (4mA) |
|
||||
* | | | | | | |
|
||||
* | GEIGER COUNTER | | GYRO SCL----+ | ECG |
|
||||
* |________________| |______________| |______________| */
|
||||
|
||||
/* geiger counter
|
||||
* https://www.rhelectronics.store
|
||||
* /radiation-detector-geiger-counter-diy-kit-second-edition */
|
||||
#include <SPI.h>
|
||||
#define RAD_LOG_PERIOD 5000 /* milliseconds; sample rate */
|
||||
#define MINUTE 60000 /* milliseconds in a minute */
|
||||
/* https://www.arduino.cc/reference/en/language/variables/data-types/
|
||||
* unsignedlong/ - 32 bit */
|
||||
unsigned long rad_count = 0;
|
||||
unsigned long rad_cpm;
|
||||
void rad_interrupt(){ ++rad_count; }
|
||||
/* https://www.pjrc.com/teensy/td_timing_elaspedMillis.html */
|
||||
elapsedMillis rad_period = 0;
|
||||
void geiger_setup(){
|
||||
pinMode(RAD_PIN, INPUT);
|
||||
digitalWrite(RAD_PIN, HIGH);
|
||||
attachInterrupt(0, rad_interrupt, FALLING);
|
||||
}
|
||||
void geiger_loop(){
|
||||
if(rad_period > RAD_LOG_PERIOD){
|
||||
rad_cpm = rad_count * (MINUTE / RAD_LOG_PERIOD);
|
||||
rad_period = 0;
|
||||
}
|
||||
/* use rad_cpm */
|
||||
}
|
||||
|
||||
/* gyro
|
||||
* https://www.elecrow.com/crowtail-mpu6050-accelerometer-gyro.html */
|
||||
/* https://github.com/jrowberg/i2cdevlib/
|
||||
* Most inexplicable stuff is because it was in Arduino/MPU6050/examples/
|
||||
* MPU6050_raw/MPU6050_raw.ino */
|
||||
#include "I2Cdev.h"
|
||||
#include "MPU6050.h"
|
||||
#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
|
||||
# include "Wire.h"
|
||||
#endif
|
||||
MPU6050 accelgyro;
|
||||
int16_t accel_x, accel_y, accel_z, gyro_x, gyro_y, gyro_z;
|
||||
void gyro_setup(){
|
||||
#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
|
||||
Wire.begin();
|
||||
#elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE
|
||||
Fastwire::setup(400, true);
|
||||
#endif
|
||||
accelgyro.initialize();
|
||||
}
|
||||
void gyro_loop(){
|
||||
accelgyro.getMotion6(&accel_x, &accel_y, &accel_z,
|
||||
&gyro_x, &gyro_y, &gyro_z);
|
||||
/* use accel_*, gyro_* */
|
||||
}
|
||||
|
||||
/* ecg
|
||||
* https://www.elecrow.com/crowtail-pulse-sensor-p-1673.html */
|
||||
void ecg_setup(){
|
||||
}
|
||||
|
||||
/* teensy 4.0
|
||||
* https://www.pjrc.com/store/teensy40.html */
|
||||
void setup(){
|
||||
geiger_setup();
|
||||
gyro_setup();
|
||||
ecg_setup();
|
||||
}
|
||||
void loop(){
|
||||
geiger_loop();
|
||||
gyro_loop();
|
||||
}
|
||||
3
wip/toki/README.txt
Normal file
3
wip/toki/README.txt
Normal file
@@ -0,0 +1,3 @@
|
||||
- move executables somewhere in path
|
||||
- `$ toki_update` to fetch dictionary
|
||||
- `$ toki_sitelen` to tokiponize
|
||||
5
wip/toki/toki_sitelen
Executable file
5
wip/toki/toki_sitelen
Executable file
@@ -0,0 +1,5 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -e
|
||||
|
||||
toki_ucsur "$@" | utf8
|
||||
2
wip/unicode/1.expected
Normal file
2
wip/unicode/1.expected
Normal file
@@ -0,0 +1,2 @@
|
||||
0000000 41 e2 89 a2 ce 91 2e
|
||||
0000007
|
||||
3
wip/unicode/1.test
Executable file
3
wip/unicode/1.test
Executable file
@@ -0,0 +1,3 @@
|
||||
#!/bin/sh
|
||||
|
||||
printf '%s\n%s\n%s\n%s\n' U+0041 U+0391 U+002E | ./utf 8 | od -t x1
|
||||
2
wip/unicode/2.expected
Normal file
2
wip/unicode/2.expected
Normal file
@@ -0,0 +1,2 @@
|
||||
0000000 ed 95 9c ea b5 ad ec 96 b4
|
||||
0000009
|
||||
3
wip/unicode/2.test
Executable file
3
wip/unicode/2.test
Executable file
@@ -0,0 +1,3 @@
|
||||
#!/bin/sh
|
||||
|
||||
printf '%s\n%s\n%s\n' U+D55C U+AD6D U+C5B4 | ./utf 8 | od -t x1
|
||||
2
wip/unicode/3.expected
Normal file
2
wip/unicode/3.expected
Normal file
@@ -0,0 +1,2 @@
|
||||
0000000 e6 97 a5 e6 9c ac e8 aa 9e
|
||||
0000009
|
||||
3
wip/unicode/3.test
Executable file
3
wip/unicode/3.test
Executable file
@@ -0,0 +1,3 @@
|
||||
#!/bin/sh
|
||||
|
||||
printf '%s\n%s\n%s\n' U+65E5 U+672C U+8A9E | ./utf 8 | od -t x1
|
||||
1
wip/unicode/HACKING
Normal file
1
wip/unicode/HACKING
Normal file
@@ -0,0 +1 @@
|
||||
Tests are from RFC3629, section 7.
|
||||
15
wip/unicode/Makefile
Normal file
15
wip/unicode/Makefile
Normal file
@@ -0,0 +1,15 @@
|
||||
test: utf
|
||||
sh ../testing/test.sh
|
||||
|
||||
utf: utf.o libunicode.o
|
||||
$(CC) -g -o utf libunicode.o utf.o
|
||||
|
||||
libunicode.o:
|
||||
|
||||
utf.o: libunicode.h utf.c
|
||||
$(CC) -I../ascii -c -g -o utf.o utf.c
|
||||
|
||||
clean:
|
||||
rm -f *.o utf
|
||||
|
||||
.PHONY: clean test
|
||||
23
wip/unicode/libunicode.c
Normal file
23
wip/unicode/libunicode.c
Normal file
@@ -0,0 +1,23 @@
|
||||
#include "libunicode.h"
|
||||
|
||||
utf32_t utf8(utf32_t c){
|
||||
unsigned char n; /* 4 - number of bytes - 1 */
|
||||
utf8_t r;
|
||||
|
||||
if(c > UTF8_MAX) /* return 0 if c exceeds max */
|
||||
c = 0;
|
||||
|
||||
switch(n = (c >= 0x010000) + (c >= 0x0800) + (c >= 0x0080)){
|
||||
case 3: r = 0xF0 + ((c >> 18) & 0x07); /* 11110xxx */
|
||||
case 2: r = (r << 8) + (n == 2
|
||||
? 0xE0 + ((c >> 12) & 0x0F) /* 1110xxxx */
|
||||
: 0x50 + ((c >> 12) & 0x3F)); /* 10xxxxxx */
|
||||
case 1: r = (r << 8) + (n == 1
|
||||
? 0xC0 + ((c >> 6) & 0x1F) /* 110xxxxx */
|
||||
: 0x50 + ((c >> 6) & 0x3F)); /* 10xxxxxx */
|
||||
case 0: r = (r << 8) + (n == 0
|
||||
? (c & 0x7F) /* 0xxxxxxx */
|
||||
: 0x50 + ((c >> 6) & 0x3F)); /* 10xxxxxx */
|
||||
}
|
||||
return r;
|
||||
}
|
||||
16
wip/unicode/libunicode.h
Normal file
16
wip/unicode/libunicode.h
Normal file
@@ -0,0 +1,16 @@
|
||||
#if defined UINT32_MAX /* indicator <stdint.h> is included */
|
||||
# define unicode_codepoint_t uint32_t
|
||||
#else
|
||||
/* C99 draft 5.2.4.2.1 Sizes of integer types says unsigned long must be able
|
||||
* to hold 32b */
|
||||
# define unicode_codepoint_t unsigned long
|
||||
#endif
|
||||
#define utf32_t unicode_codepoint_t
|
||||
/* for holding the literal numeric value of a utf8 rune, not for assembling
|
||||
* strings; >=32b value */
|
||||
#define utf8_t unicode_codepoint_t
|
||||
|
||||
#define UTF8_MAX 0x10FFFF
|
||||
|
||||
/* encode UTF-32 value into UTF-8 */
|
||||
utf32_t utf8(utf32_t c);
|
||||
58
wip/unicode/utf.c
Normal file
58
wip/unicode/utf.c
Normal file
@@ -0,0 +1,58 @@
|
||||
#include <stdio.h> /* fprintf(3), getc(3), putc(3) stderr, stdin, EOF */
|
||||
#include <string.h> /* strchr(3) */
|
||||
#include "ascii.h" /* ASCII_HEXADECIMAL_DIGITS_LOWER,
|
||||
* ASCII_HEXADECIMAL_DIGITS_UPPER */
|
||||
#include "libunicode.h" /* utf8(3) */
|
||||
|
||||
static struct {
|
||||
char *name;
|
||||
utf32_t (*f)(utf32_t);
|
||||
}
|
||||
|
||||
static char *hex = ASCII_HEXADECIMAL_DIGITS_UPPER
|
||||
ASCII_HEXADECIMAL_DIGITS_LOWER;
|
||||
|
||||
int main(int argc, char *argv[]){
|
||||
int c;
|
||||
int i;
|
||||
int l; /* line counter */
|
||||
char *n;
|
||||
utf32_t codepoint;
|
||||
utf8_t encoded;
|
||||
|
||||
l = 0;
|
||||
|
||||
init: codepoint = 0;
|
||||
i = 0;
|
||||
++l;
|
||||
n = NULL;
|
||||
while((c = getc(stdin)) != EOF){
|
||||
if(c == '\n'){
|
||||
if(i < 2 && i > 0) /* empty lines are fine */
|
||||
fprintf(stderr, "%s: %s: Syntax error.\n",
|
||||
argv[0], l);
|
||||
else if(i >= 2){
|
||||
encoded = utf8(codepoint);
|
||||
for(i = 3; i >= 0; --i)
|
||||
if((encoded >> 8 * i) > 0 || i == 0)
|
||||
putc(encoded >> 8 * i, stdout);
|
||||
}
|
||||
goto init;
|
||||
}
|
||||
if(
|
||||
(i == 0 && c != 'U')
|
||||
|| (i == 1 && c != '+')
|
||||
|| i > 8 /* strlen("U+10FFFF") */
|
||||
|| (i > 1 && ((n = strchr(hex, c)) == NULL))
|
||||
){
|
||||
fprintf(stderr, "%s: %s: Syntax error.\n",
|
||||
argv[0], l);
|
||||
while((c = getc(stdin)) != '\n' && c != EOF);
|
||||
++l;
|
||||
continue;
|
||||
}
|
||||
if(n != NULL)
|
||||
codepoint = (codepoint << 4) + (n - hex) % 16;
|
||||
++i;
|
||||
}
|
||||
}
|
||||
97
wip/which.c
Normal file
97
wip/which.c
Normal file
@@ -0,0 +1,97 @@
|
||||
#include <errno.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h> /* fprintf(3) */
|
||||
#include <stdlib.h> /* exit(3) */
|
||||
#include <sysexits.h>
|
||||
#include <unistd.h> /* access(2), chdir(2) */
|
||||
|
||||
#include "libshell.h" /* getpaths(3) */
|
||||
|
||||
void
|
||||
usage(char *name){
|
||||
fprintf(stderr, "Usage: %s (-a) [name]\n", name);
|
||||
exit(EX_USAGE);
|
||||
}
|
||||
|
||||
int
|
||||
which(char *program, char **paths, char *name, bool breakonfirst){
|
||||
char **q;
|
||||
int retval;
|
||||
retval = 0;
|
||||
|
||||
for(q = paths; *q != NULL; ++q){
|
||||
if(chdir(*q) != 0)
|
||||
switch(retval = errno){
|
||||
/* Non-issues in the context of this program */
|
||||
case EACCES: /* Access denied */
|
||||
case ELOOP: /* Too many symlinks in path */
|
||||
case ENAMETOOLONG: /* Name too long */
|
||||
case ENOENT: /* Directory doesn't exist */
|
||||
case ENOTDIR: /* Not a directory */
|
||||
continue;
|
||||
case EFAULT:
|
||||
goto apology;
|
||||
case EIO:
|
||||
goto ioerr;
|
||||
}
|
||||
/* Changed dir, now check for file in dir */
|
||||
if(access(program, R_OK | X_OK) != 0)
|
||||
switch(retval = errno){
|
||||
case EACCES:
|
||||
case ELOOP:
|
||||
case ENAMETOOLONG:
|
||||
case ENOENT:
|
||||
case EROFS:
|
||||
continue;
|
||||
case EFAULT:
|
||||
goto apology;
|
||||
case EIO:
|
||||
goto ioerr;
|
||||
}
|
||||
else{
|
||||
fprintf(stdout, "%s%s\n", *q, program);
|
||||
if(breakonfirst != 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
end:
|
||||
return retval;
|
||||
apology:
|
||||
fprintf(stderr,
|
||||
/* EFAULT means the pointer passed to either chdir(2) or access(2) was outside
|
||||
* of the address space available to the program. This means something's Very
|
||||
* Wrong with getpaths(3) and libshell has to be fixed. That'd be a serious,
|
||||
* common error, so try to reassure the user and solicit a bug report. */
|
||||
"%s: EFAULT\n"
|
||||
"You the user did nothing to invoke this error message. This is an error in\n"
|
||||
"which, a program you or another program executed. PLEASE e-mail the creator\n"
|
||||
"of this program (the address can be found in the corresponding manual page)\n"
|
||||
"and tell them you got this error and what you were doing when it happened.\n"
|
||||
"Sorry!\n", name);
|
||||
goto end;
|
||||
ioerr:
|
||||
fprintf(stderr, "%s: filesystem I/O error\n", name);
|
||||
goto end;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]){
|
||||
int i;
|
||||
char **paths;
|
||||
int retval;
|
||||
|
||||
if(argc <= 1)
|
||||
usage(argv[0]);
|
||||
|
||||
if((paths = getpaths()) == NULL){
|
||||
fprintf(stderr, "%s: Could not get the value of $PATH\n", argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
for(i = 1; i < argc; ++i)
|
||||
if((retval = which(argv[i], paths, argv[0], 1)) != 0)
|
||||
break;
|
||||
|
||||
free(*paths);
|
||||
free(paths);
|
||||
return retval;
|
||||
}
|
||||
12897
wip/wordle/dictionary
Normal file
12897
wip/wordle/dictionary
Normal file
File diff suppressed because it is too large
Load Diff
2315
wip/wordle/solutions
Normal file
2315
wip/wordle/solutions
Normal file
File diff suppressed because it is too large
Load Diff
115
wip/wordle/wordle.c
Normal file
115
wip/wordle/wordle.c
Normal file
@@ -0,0 +1,115 @@
|
||||
#include <ctype.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
/* TODO: sysexits.h */
|
||||
|
||||
#define PROGRAM_NAME "wordle"
|
||||
#define DEFAULT_DICTIONARY_FILENAME "/usr/share/" PROGRAM_NAME "/dictionary.txt"
|
||||
#define DEFAULT_SOLUTIONS_FILENAME "/usr/share/" PROGRAM_NAME "/solutions.txt"
|
||||
#define WORD_LENGTH 5
|
||||
#define GUESSES 6
|
||||
|
||||
int
|
||||
dictionary_has(char *s, int fd){
|
||||
char buf[WORD_LENGTH + 2];
|
||||
if(lseek(fd, 0, SEEK_SET) != 0){
|
||||
fprintf(stderr, "%s: Could not seek to the start of the"
|
||||
" dictionary (errno %d).\n", PROGRAM_NAME, errno
|
||||
);
|
||||
close(fd);
|
||||
exit(1);
|
||||
}
|
||||
/* unused, but just in case */
|
||||
buf[WORD_LENGTH + 1] = '\0';
|
||||
|
||||
if(read(fd, buf, WORD_LENGTH + 1) < WORD_LENGTH)
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
strisuint(char *s){
|
||||
while(*s != '\0')
|
||||
if(!isdigit(*(s++)))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
usage(char *name){
|
||||
fprintf(stderr, "Usage: %s [index] (-d [dictionary file])"
|
||||
" (-s [solutions file])\n", name
|
||||
);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]){
|
||||
int c;
|
||||
int dictionary_fd;
|
||||
size_t i;
|
||||
size_t index;
|
||||
size_t j;
|
||||
FILE *solutions_file;
|
||||
char word[WORD_LENGTH + 1];
|
||||
|
||||
/* arg parse */
|
||||
if(argc < 2)
|
||||
usage(argv[0] != NULL ? argv[0] : PROGRAM_NAME);
|
||||
while((c = getopt(argc, argv, "d:hs:")) != -1)
|
||||
switch(c){
|
||||
case 'd':
|
||||
dictionary_filename = optarg;
|
||||
break;
|
||||
case 's':
|
||||
solutions_filename = optarg;
|
||||
break;
|
||||
case 'h':
|
||||
usage(argv[0] != NULL ? argv[0] : PROGRAM_NAME);
|
||||
}
|
||||
if(!strisuint(argv[optind])){
|
||||
fprintf(stderr, "%s: index must be a number.\n",
|
||||
argv[0] != NULL ? argv[0] : PROGRAM_NAME
|
||||
);
|
||||
exit(1);
|
||||
}
|
||||
index = (size_t)atoi(argv[optind]);
|
||||
|
||||
/* get word */
|
||||
if((solutions_file = fopen(solutions_filename, "rb")) == NULL){
|
||||
fprintf(stderr, "%s: %s: Error opening solutions file.\n",
|
||||
argv[0] != NULL ? argv[0] : PROGRAM_NAME, solutions_filename
|
||||
);
|
||||
exit(1);
|
||||
}
|
||||
i = j = 0;
|
||||
while((c = getc(solutions_file)) != EOF)
|
||||
if(i == index){
|
||||
if(j == WORD_LENGTH){
|
||||
word[WORD_LENGTH] = '\0';
|
||||
j = 0;
|
||||
break;
|
||||
}else
|
||||
word[j++] = c;
|
||||
}else
|
||||
i += c == '\n';
|
||||
if(j != '\0'){
|
||||
word[j] = '\0';
|
||||
fprintf(stderr, "%s: %s: Word is too few characters.\n",
|
||||
argv[0] != NULL ? argv[0] : PROGRAM_NAME, word
|
||||
);
|
||||
exit(1);
|
||||
}
|
||||
fclose(solutions_file);
|
||||
|
||||
if(dictionary_fd = open(dictionary_filename, O_RDONLY) == NULL){
|
||||
fprintf(stderr, "%s: %s: Error opening dictionary file.\n",
|
||||
argv[0] != NULL ? argv[0] : PROGRAM_NAME, dictionary_filename
|
||||
);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
close(dictionary_fd);
|
||||
exit(0);
|
||||
}
|
||||
Reference in New Issue
Block a user