spring cleaning 1
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;
|
||||
}
|
||||
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/head.c
Normal file
12
Wip/head/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;
|
||||
}
|
||||
16
Wip/libcards/libcards.c
Normal file
16
Wip/libcards/libcards.c
Normal file
@@ -0,0 +1,16 @@
|
||||
#include "libcards.h"
|
||||
|
||||
int
|
||||
card_color(int card){
|
||||
|
||||
return card < CARD_HEART_A ? -1 : card_rank(card) < CARD_SUIT_CLOVER;
|
||||
}
|
||||
|
||||
int
|
||||
card_rank(int card){ return card < CARD_HEART_A ? -1 : card % 0x10; }
|
||||
|
||||
int
|
||||
card_suit(int card){
|
||||
|
||||
return card < CARD_HEART_A ? -1 : card / CARD_SUIT_HEART;
|
||||
}
|
||||
45
Wip/libcards/libcards.h
Normal file
45
Wip/libcards/libcards.h
Normal file
@@ -0,0 +1,45 @@
|
||||
enum{
|
||||
CARD_SUIT_HEART = 0x1,
|
||||
CARD_SUIT_TILE = 0x2,
|
||||
CARD_SUIT_CLOVER = 0x3,
|
||||
CARD_SUIT_PIKE = 0x4,
|
||||
|
||||
CARD_RANK_A = 0x00,
|
||||
CARD_RANK_2, CARD_RANK_3, CARD_RANK_4,
|
||||
CARD_RANK_5, CARD_RANK_6, CARD_RANK_7,
|
||||
CARD_RANK_8, CARD_RANK_9, CARD_RANK_10,
|
||||
CARD_RANK_J, CARD_RANK_Q, CARD_RANK_K,
|
||||
CARD_RANK_JOKER /* = 0x0D */
|
||||
|
||||
CARD_HEART_A = 0x10,
|
||||
CARD_HEART_2, CARD_HEART_3, CARD_HEART_4,
|
||||
CARD_HEART_5, CARD_HEART_6, CARD_HEART_7,
|
||||
CARD_HEART_8, CARD_HEART_9, CARD_HEART_10,
|
||||
CARD_HEART_J, CARD_HEART_Q, CARD_HEART_K,
|
||||
CARD_HEART_JOKER /* = 0x1D */,
|
||||
|
||||
CARD_TILE_A = 0x20,
|
||||
CARD_TILE_2, CARD_TILE_3, CARD_TILE_4,
|
||||
CARD_TILE_5, CARD_TILE_6, CARD_TILE_7,
|
||||
CARD_TILE_8, CARD_TILE_9, CARD_TILE_10,
|
||||
CARD_TILE_J, CARD_TILE_Q, CARD_TILE_K,
|
||||
CARD_TILE_JOKER /* = 0x2D */
|
||||
|
||||
CARD_CLOVER_A = 0x30,
|
||||
CARD_CLOVER_2, CARD_CLOVER_3, CARD_CLOVER_4,
|
||||
CARD_CLOVER_5, CARD_CLOVER_6, CARD_CLOVER_7,
|
||||
CARD_CLOVER_8, CARD_CLOVER_9, CARD_CLOVER_10,
|
||||
CARD_CLOVER_J, CARD_CLOVER_Q, CARD_CLOVER_K,
|
||||
CARD_CLOVER_JOKER /* = 0x3D */,
|
||||
|
||||
CARD_PIKE_A = 0x40,
|
||||
CARD_PIKE_2, CARD_PIKE_3, CARD_PIKE_4,
|
||||
CARD_PIKE_5, CARD_PIKE_6, CARD_PIKE_7,
|
||||
CARD_PIKE_8, CARD_PIKE_9, CARD_PIKE_10,
|
||||
CARD_PIKE_J, CARD_PIKE_Q, CARD_PIKE_K,
|
||||
CARD_PIKE_JOKER /* = 0x4D */
|
||||
}
|
||||
|
||||
int card_color(int card);
|
||||
int card_rank(int card);
|
||||
int card_suit(int card);
|
||||
52
Wip/libshell/getpaths.3
Normal file
52
Wip/libshell/getpaths.3
Normal file
@@ -0,0 +1,52 @@
|
||||
.TH GETPATHS 3
|
||||
|
||||
.SH NAME
|
||||
getpaths \- get an array of the current executable PATHs
|
||||
|
||||
.SH LIBRARY
|
||||
libshell
|
||||
|
||||
.SH SYNOPSIS
|
||||
.In stdlib.h
|
||||
.In string.h
|
||||
.In libshell.h
|
||||
.Ft char **
|
||||
.Fn getpaths void
|
||||
|
||||
.SH DESCRIPTION
|
||||
.Fn getpaths
|
||||
returns the system PATHs as an array of null-terminated strings ordered from highest to lowest priority.
|
||||
The last address in the array is NULL.
|
||||
The first address in the array, and the array address itself, should be passed to
|
||||
.Xr free 3
|
||||
to release the allocated storage when the returned array is no longer needed.
|
||||
|
||||
.SH EXAMPLES
|
||||
To print the current PATHs, from highest to lowest priority:
|
||||
.Bd -literal -offset indent
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <libshell.h>
|
||||
int main(){
|
||||
char **paths;
|
||||
int i;
|
||||
paths = getpaths();
|
||||
if(paths == NULL)
|
||||
exit(EXIT_FAILURE);
|
||||
for(i = 0; paths[i] != NULL; ++i)
|
||||
printf("%s\n", paths[i]);
|
||||
free(*paths);
|
||||
free(paths);
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
.Ed
|
||||
|
||||
.SH SEE ALSO
|
||||
.Xr getenv 3
|
||||
|
||||
.SH STANDARDS
|
||||
.Fn getpaths
|
||||
is not part of any current standard.
|
||||
|
||||
.SH BUGS
|
||||
Certainly existent but not yet known.
|
||||
59
Wip/libshell/libshell.c
Normal file
59
Wip/libshell/libshell.c
Normal file
@@ -0,0 +1,59 @@
|
||||
#include "libshell.h"
|
||||
|
||||
char **
|
||||
getpaths(void)
|
||||
{
|
||||
char *p;
|
||||
char **q;
|
||||
char *path;
|
||||
size_t path_s;
|
||||
char *path_temp;
|
||||
char **paths;
|
||||
size_t paths_s;
|
||||
|
||||
if((path_temp = getenv(PATH_NAME)) == NULL){
|
||||
errno = ENOMEM; /* Cannot allocate memory */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* How long is path? */
|
||||
for(path_s = 0; path_temp[path_s] != '\0'; ++path_s);
|
||||
/* path_s has the size of the path string, not including the null
|
||||
* terminator */
|
||||
|
||||
/* getenv's return value mustn't be modified so copy it into memory we
|
||||
* control */
|
||||
if((path = malloc(sizeof(char) * (path_s + 1))) == NULL){
|
||||
errno = ENOMEM; /* Cannot allocate memory */
|
||||
return NULL;
|
||||
}
|
||||
memcpy(path, path_temp, path_s + 1);
|
||||
path_temp = NULL;
|
||||
path_s = 0; /* This shouldn't be necessary anymore */
|
||||
|
||||
/* How many paths in $PATH? */
|
||||
for(paths_s = 1, p = path; *p != '\0'; paths_s += *p++ == PATH_DELIMITER);
|
||||
|
||||
if((paths = malloc(sizeof(char *) * (paths_s + 1))) == NULL){
|
||||
free(path);
|
||||
errno = ENOMEM; /* Cannot allocate memory */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Replace all instances of the path delimiter with 0, and then put the
|
||||
* next path beginning into paths. */
|
||||
/* This way we can get multiple strings out of one span of memory. */
|
||||
for(*paths = p = path, q = paths + 1; *p != '\0';)
|
||||
if(*p++ == PATH_DELIMITER){
|
||||
*(p - 1) = '\0';
|
||||
*q++ = p;
|
||||
}
|
||||
|
||||
paths[path_s] = NULL;
|
||||
|
||||
/* Because paths[0] will always be path, we can just free(*paths) at
|
||||
* the end and discard path */
|
||||
path = NULL;
|
||||
|
||||
return paths;
|
||||
}
|
||||
11
Wip/libshell/libshell.h
Normal file
11
Wip/libshell/libshell.h
Normal file
@@ -0,0 +1,11 @@
|
||||
#include <errno.h>
|
||||
#include <stdlib.h> /* getenv(3), malloc(3) */
|
||||
#include <string.h> /* memcpy(3) */
|
||||
|
||||
/* For the shell variable $PATH */
|
||||
#define PATH_NAME "PATH"
|
||||
#define PATH_DELIMITER ':'
|
||||
|
||||
/* Returns a list of the current paths ordered from first to last priority.
|
||||
* output must be freed and *output must be freed! */
|
||||
char **getpaths(void);
|
||||
21
Wip/libwakeonlan/libwakeonlan.c
Normal file
21
Wip/libwakeonlan/libwakeonlan.c
Normal file
@@ -0,0 +1,21 @@
|
||||
#include "libwakeonlan.h"
|
||||
|
||||
/* Returns a byte array of 6 0xFF and 16 repetitions of the 6-byte MAC. */
|
||||
unsigned int*
|
||||
magic_packet(unsigned int *mac){
|
||||
size_t i;
|
||||
size_t j;
|
||||
int *retval;
|
||||
|
||||
if((retval = malloc(sizeof(unsigned int) * 6 + 6*16)) == NULL)
|
||||
return NULL;
|
||||
|
||||
for(i = 0; i < 6; ++i)
|
||||
retval[i] = 255;
|
||||
|
||||
for(i = 1; i < 16; ++i)
|
||||
for(j = 0; j < 6; ++j)
|
||||
retval[i*j] = mac[j];
|
||||
|
||||
return retval; /* must be freed */
|
||||
}
|
||||
4
Wip/libwakeonlan/libwakeonlan.h
Normal file
4
Wip/libwakeonlan/libwakeonlan.h
Normal file
@@ -0,0 +1,4 @@
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
unsigned int *magic_packet(unsigned int *mac);
|
||||
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
|
||||
2
Wip/nutshell/Makefile
Normal file
2
Wip/nutshell/Makefile
Normal file
@@ -0,0 +1,2 @@
|
||||
nutshell: nutshell.c nutshell.h nutshell_builtins.c
|
||||
$(CC) $(CFLAGS) -o nutshell nutshell.c
|
||||
103
Wip/nutshell/nutshell.c
Normal file
103
Wip/nutshell/nutshell.c
Normal file
@@ -0,0 +1,103 @@
|
||||
#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 "nutshell.h"
|
||||
#include "nutshell_builtins.c"
|
||||
|
||||
static int
|
||||
parse_argv(int *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 int *
|
||||
read_buffer(int *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(int *buf){
|
||||
int argc;
|
||||
static char *argv[ARGV_MAX];
|
||||
int i;
|
||||
|
||||
/* get argv and argc */
|
||||
for(i = 0; i < (sizeof argv) / (sizeof *argv); ++i){
|
||||
if(argv[i] == NULL)
|
||||
break;
|
||||
argv[i] = NULL;
|
||||
}
|
||||
|
||||
argc = parse_argv(buf, argv, (sizeof argv) / (sizeof *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 int buf[BUF_MAX];
|
||||
static char prompt[] = DEFAULT_PROMPT;
|
||||
|
||||
builtin_init(0, empty_argv);
|
||||
|
||||
for(;;){
|
||||
fprintf(stdout, "%s", prompt);
|
||||
if(read_buffer(buf, (sizeof buf)/(sizeof *buf)) == NULL){
|
||||
fprintf(stdout, "EOF\n");
|
||||
state.status = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
state.status = run(buf);
|
||||
}
|
||||
|
||||
return state.status;
|
||||
}
|
||||
15
Wip/nutshell/nutshell.h
Normal file
15
Wip/nutshell/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/nutshell_builtins.c
Normal file
104
Wip/nutshell/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 < (sizeof builtins) / (sizeof *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){
|
||||
fprintf(stderr, "needs argument(s)\n");
|
||||
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){
|
||||
fprintf(stdout, "$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)
|
||||
fprintf(stdout, "%d", 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){
|
||||
fprintf(stdout, "%d", state.status);
|
||||
return 0;
|
||||
}
|
||||
2
Wip/playlist/playlist
Normal file
2
Wip/playlist/playlist
Normal file
@@ -0,0 +1,2 @@
|
||||
#!/bin/sh
|
||||
argv0="$0"; shift; "$argv0"_"$0" "$@"
|
||||
24
Wip/playlist/playlist_package
Normal file
24
Wip/playlist/playlist_package
Normal file
@@ -0,0 +1,24 @@
|
||||
#!/bin/sh
|
||||
|
||||
while read -r resource
|
||||
do case "$resource" in
|
||||
*://*) case "$resource" in # remote
|
||||
*.m3u) file="$(curl -LO -w '%{filename_effective}' \
|
||||
"$resource")"
|
||||
"$0" <"$file" >"$file".tar
|
||||
printf '%s.tar\n' "$file"
|
||||
;;
|
||||
*) youtube-dl -f bestaudio "$resource" --id \
|
||||
&& youtube-dl --get-id "$resource" \
|
||||
| xargs printf '%s.*\n' \
|
||||
|| curl -LO -w '%{filename_effective}' \
|
||||
"$resource"
|
||||
;;
|
||||
esac ;;
|
||||
*.m3u) "$0" <"$resource" >"$resource".tar
|
||||
printf '%s.tar\n' "$resource"
|
||||
;;
|
||||
*) printf '%s\n' "$resource"
|
||||
;;
|
||||
esac
|
||||
done | xargs tar c
|
||||
20
Wip/psops/Makefile
Normal file
20
Wip/psops/Makefile
Normal file
@@ -0,0 +1,20 @@
|
||||
CFLAGS += -g -I../libpsargs
|
||||
|
||||
all: pscat
|
||||
|
||||
pscat: pscat.o ../libpsargs/libpsargs.o
|
||||
$(CC) $(CFLAGS) -o $@ pscat.o ../libpsargs/libpsargs.o
|
||||
|
||||
pscat.o: pscat.c psops.c
|
||||
$(CC) $(CFLAGS) -DPSCAT=1 -c -o $@ pscat.c
|
||||
|
||||
pspipe: pspipe.o ../libpsargs/libpsargs.o
|
||||
$(CC) $(CFLAGS) -o $@ pspipe.o ../libpsargs/libpsargs.o
|
||||
|
||||
pspipe.o: pscat.c psops.c
|
||||
$(CC) $(CFLAGS) -DPSPIPE=1 -c -o $@ pscat.c
|
||||
|
||||
../libpsargs/libpsargs.o:
|
||||
$(MAKE) -C ../libpsargs
|
||||
|
||||
.PHONY: all
|
||||
39
Wip/psops/pscat.1
Normal file
39
Wip/psops/pscat.1
Normal file
@@ -0,0 +1,39 @@
|
||||
.TH PSCAT 1
|
||||
|
||||
.SH NAME
|
||||
|
||||
pscat \- concatenate the output of processes
|
||||
|
||||
.SH SYNOPSIS
|
||||
|
||||
pscat
|
||||
"["
|
||||
.RB [ utility
|
||||
.RB [ argument... ]]
|
||||
"]" ...
|
||||
|
||||
.SH DESCRIPTION
|
||||
|
||||
Pscat executes multiple commands, one after the other.
|
||||
This allows multiple processes to be piped as one to another program.
|
||||
|
||||
.SH DIAGNOSTICS
|
||||
|
||||
Pscat will print an error message and exit with the appropriate status from sysexits(3) if executed improperly.
|
||||
Pscat will exit with the sum of the child processes' exit statuses if run correctly.
|
||||
|
||||
.SH BUGS
|
||||
|
||||
Pscat's exit status isn't useful when run correctly; there's no way to tell which process failed if one did.
|
||||
This issue of ergonomics isn't obviously mendable as processes' standard outputs and standard errors are meant to both be conveyed.
|
||||
If either could be ignored the individual exit statuses could simply be printed.
|
||||
.PP
|
||||
Pscat's function is redundant to the sh(1) construct
|
||||
.RB { utility ; utility ;}
|
||||
- this is a feature, not a bug.
|
||||
.PP
|
||||
pscat [ cat | cat ] will pipe "pscat [ cat" into "cat ]", which is a potentially unexpected result of a command.
|
||||
|
||||
.SH COPYRIGHT
|
||||
|
||||
Public domain.
|
||||
33
Wip/psops/pscat.c
Normal file
33
Wip/psops/pscat.c
Normal file
@@ -0,0 +1,33 @@
|
||||
#include <errno.h> /* errno */
|
||||
#include <stdio.h> /* fprintf(3), stderr, "psops.c" */
|
||||
#include <string.h> /* strerror(3) */
|
||||
#include <sysexits.h> /* EX_OSERR, "psops.c" */
|
||||
#include <unistd.h> /* execvp(3) */
|
||||
#include <sys/types.h> /* <sys/wait.h> */
|
||||
#include <sys/wait.h> /* wait(2) */
|
||||
|
||||
#include "libpsargs.h" /* corresponding_arg(3), "psops.c" */
|
||||
|
||||
static char *program_name = "pscat";
|
||||
|
||||
int
|
||||
f(char **argv){
|
||||
int child;
|
||||
char **corr;
|
||||
|
||||
*(corr = corresponding_arg(argv)) = NULL;
|
||||
switch(fork()){
|
||||
case -1:
|
||||
fprintf(stderr, "%s: %s\n", program_name, strerror(errno));
|
||||
return EX_OSERR;
|
||||
case 0: execvp(argv[1], argv+1);
|
||||
default:
|
||||
wait(&child);
|
||||
argv = corr;
|
||||
return *++argv == NULL
|
||||
? WIFEXITED(child) * WEXITSTATUS(child)
|
||||
: f(argv);
|
||||
}
|
||||
}
|
||||
|
||||
#include "psops.c"
|
||||
20
Wip/psops/psops.c
Normal file
20
Wip/psops/psops.c
Normal file
@@ -0,0 +1,20 @@
|
||||
/* #include <stdio.h> /* fprintf(3), stderr */
|
||||
|
||||
#ifndef EX_USAGE
|
||||
# define EX_USAGE 64 /* NetBSD sysexits(3) compat */
|
||||
#endif
|
||||
|
||||
/* #include "libpsargs.h" /* check_arg(3) */
|
||||
|
||||
int main(int argc, char *argv[]){
|
||||
|
||||
if(argc != 0)
|
||||
program_name = argv[0];
|
||||
if(check_arg(++argv) == 0){
|
||||
fprintf(stderr,
|
||||
"Usage: %s \"[\" [utility [argument...]] \"]\" ...\n",
|
||||
program_name
|
||||
);
|
||||
return EX_USAGE;
|
||||
}else return f(argv);
|
||||
}
|
||||
53
Wip/psops/pspipe.c
Normal file
53
Wip/psops/pspipe.c
Normal file
@@ -0,0 +1,53 @@
|
||||
#include <errno.h> /* errno */
|
||||
#include <stdio.h> /* fprintf(3), stderr, "psops.c" */
|
||||
#include <string.h> /* strerror(3) */
|
||||
#include <sysexits.h> /* EX_OSERR */
|
||||
#include <unistd.h> /* execvp(3) */
|
||||
#include <sys/types.h> /* <sys/wait.h> */
|
||||
#include <sys/wait.h> /* wait(2) */
|
||||
|
||||
#include "libpsargs.h" /* corresponding_arg(3), "psops.c" */
|
||||
|
||||
static char *program_name = "pspipe";
|
||||
|
||||
/* At the start of the loop argv[0] is { '[', '\0' } and file descriptor 0 is
|
||||
* the intended standard input */
|
||||
int
|
||||
f(char **argv){
|
||||
static int child;
|
||||
char **corr;
|
||||
int fd[2];
|
||||
int r;
|
||||
|
||||
*(corr = corresponding_arg(argv)) = NULL;
|
||||
if(corr[1] != NULL){
|
||||
if(pipe(fd) != 0){
|
||||
fprintf(stderr,
|
||||
"%s: %s: %s\n",
|
||||
program_name, argv[1], strerror(errno)
|
||||
);
|
||||
return EX_OSERR;
|
||||
}
|
||||
if((r = fork()) == -1){
|
||||
fprintf(stderr, "%s: %s\n",
|
||||
program_name, strerror(errno)
|
||||
);
|
||||
return EX_OSERR;
|
||||
}
|
||||
if(r == 0)
|
||||
dup2(fd[0], 0);
|
||||
else
|
||||
dup2(fd[1], 1);
|
||||
close(fd[1]);
|
||||
close(fd[0]);
|
||||
if(r == 1)
|
||||
execvp(argv[1], argv+1);
|
||||
}
|
||||
|
||||
argv = corr;
|
||||
return *++argv == NULL
|
||||
? WEXITSTATUS(child)
|
||||
: f(corr + 1);
|
||||
}
|
||||
|
||||
#include "psops.c"
|
||||
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;
|
||||
}
|
||||
13
Wip/sysexits/Makefile
Normal file
13
Wip/sysexits/Makefile
Normal file
@@ -0,0 +1,13 @@
|
||||
TARGETS = sysexits sysexits.h
|
||||
CFLAGS = -I..
|
||||
|
||||
all: $(TARGETS)
|
||||
|
||||
clean:
|
||||
rm -f $(TARGETS)
|
||||
|
||||
%: %.c
|
||||
$(CC) $(CFLAGS) -o $@ $@.c
|
||||
|
||||
sysexits.h: sysexits
|
||||
./sysexits >sysexits.h
|
||||
182
Wip/sysexits/sysexits.c
Normal file
182
Wip/sysexits/sysexits.c
Normal file
@@ -0,0 +1,182 @@
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include "arraylen.h"
|
||||
|
||||
/* Thanks to u/smcameron on Reddit. */
|
||||
|
||||
#define TAB_WIDTH 8
|
||||
|
||||
/* Changing ENUM to DEFINE will make this output the traditional BSD header
|
||||
* verbatim, without copyright notice. I don't have any idea if that's a
|
||||
* copyright violation, but let's keep this as ENUM to skirt by that little
|
||||
* technicality.
|
||||
* I implemented sysexits(3) in the enum method before reading the BSD 4.0
|
||||
* source to see how they did it. */
|
||||
#define ENUM 1
|
||||
|
||||
static char *program_name = "sysexits";
|
||||
|
||||
static const char comment_prefix[] = "/* ";
|
||||
static const char comment_prefix_ongoing[] = " * ";
|
||||
static const char comment_suffix[] = " */\n";
|
||||
|
||||
static const char header_prefix[] =
|
||||
"#ifndef _SYSEXITS_H\n"
|
||||
"#\tdefine _SYSEXITS_H\n"
|
||||
"enum{\n"
|
||||
;
|
||||
|
||||
/* ASSUMPTIONS:
|
||||
* - This array is always organized.
|
||||
* - All characters in descriptions are one space wide.
|
||||
* - The only whitespace in descriptions is ASCII_SP. */
|
||||
static const struct {
|
||||
char *desc;
|
||||
char *name;
|
||||
int status;
|
||||
}sysexits[] = {
|
||||
/* sysexit descriptions copied from FreeBSD's sysexits(3). */
|
||||
|
||||
{ "All is well.", /* except this one */
|
||||
"EX_OK", 0 },
|
||||
|
||||
{ "The command was used incorrectly, e.g., with the wrong number of"
|
||||
" arguments, a bad flag, a bad syntax in a parameter, or whatever.",
|
||||
"EX_USAGE", 64 },
|
||||
|
||||
{ "The input data was incorrect in some way. This should only be used"
|
||||
" for user's data and not system files.",
|
||||
"EX_DATAERR", 65 },
|
||||
|
||||
{ "An input file (not a system file) did not exist or was not readable."
|
||||
" This could also include errors like \"No message\" to a mailer (if it"
|
||||
" cared to catch it).",
|
||||
"EX_NOINPUT", 66 },
|
||||
|
||||
{ "The user specified did not exist. This might be used for mail"
|
||||
" addresses or remote logins.",
|
||||
"EX_NOUSER", 67 },
|
||||
|
||||
{ "The host specified did not exist. This is used in mail addresses or"
|
||||
" network requests.",
|
||||
"EX_NOHOST", 68 },
|
||||
|
||||
{ "A service is unavailable. This can occur if a support program or"
|
||||
" file does not exist. This can also be used as a catchall message"
|
||||
" when something you wanted to do does not work, but you do not know"
|
||||
" why.",
|
||||
"EX_UNAVAILABLE", 69 },
|
||||
|
||||
{ "An internal software error has been detected. This should be limited"
|
||||
" to non-operating system related errors as possible.",
|
||||
"EX_SOFTWARE", 70 },
|
||||
|
||||
{ "An operating system error has been detected. This is intended to be"
|
||||
" used for such things as \"cannot fork\", \"cannot create pipe\", or"
|
||||
" the like. It includes things like getuid returning a user that does"
|
||||
" not exist in the passwd file.",
|
||||
"EX_OSERR", 71 },
|
||||
|
||||
{ "Some system file (e.g., /etc/passwd, /var/run/utx.active, etc.) does"
|
||||
" not exist, cannot be opened, or has some sort of error (e.g., syntax"
|
||||
" error).",
|
||||
"EX_OSFILE", 72 },
|
||||
|
||||
{ "A (user specified) output file cannot be created.",
|
||||
"EX_CANTCREAT", 73 },
|
||||
|
||||
{ "An error occurred while doing I/O on some file.",
|
||||
"EX_IOERR", 74 },
|
||||
|
||||
{ "Temporary failure, indicating something that is not really an error."
|
||||
" In sendmail, this means that a mailer (e.g.) could not create a"
|
||||
" connection, and the request should be reattempted later.",
|
||||
"EX_TEMPFAIL", 75 },
|
||||
|
||||
{ "The remote system returned something that was \"not possible\" during a"
|
||||
" protocol exchange.",
|
||||
"EX_PROTOCOL", 76 },
|
||||
|
||||
{ "You did not have sufficient permission to perform the operation."
|
||||
" This is not intended for file system problems, which should use"
|
||||
" EX_NOINPUT or EX_CANTCREAT, but rather for higher level"
|
||||
" permissions.",
|
||||
"EX_NOPERM", 77 },
|
||||
|
||||
{ "Something was found in an unconfigured or misconfigured state.",
|
||||
"EX_CONFIG", 78 }
|
||||
};
|
||||
|
||||
static const char header_suffix[] =
|
||||
"};\n"
|
||||
"#endif /* ifndef _SYSEXITS_H */\n"
|
||||
;
|
||||
|
||||
static size_t i;
|
||||
|
||||
static int findbyint(int status){
|
||||
for(i = 0; i < ARRAYLEN(sysexits); ++i)
|
||||
if(sysexits[i].status == status)
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void output_comment(int fd, int indentation, int width, char *comment){
|
||||
size_t word_start;
|
||||
size_t line_start;
|
||||
|
||||
for(i = 0, line_start = 0, word_start = 0; ; ++i)
|
||||
switch(comment[i]){
|
||||
case '\0':
|
||||
while( i - line_start
|
||||
+ ARRAYLEN(comment_suffix)
|
||||
+ indentation * TAB_WIDTH
|
||||
> width){
|
||||
i = word_start - 2; /* - current char, - space */
|
||||
write(
|
||||
fd, comment_prefix_ongoing,
|
||||
ARRAYLEN(comment_prefix_ongoing)
|
||||
);
|
||||
write(fd, comment + line_start, i - line_start);
|
||||
i += 2; /* + space, + next word char */
|
||||
write(fd, "\n", 1);
|
||||
}
|
||||
write(fd, comment + line_start, i - line_start);
|
||||
write(fd, comment_suffix, ARRAYLEN(comment_suffix));
|
||||
break;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void output_header(void){
|
||||
write(1, header_prefix, ARRAYLEN(header_prefix) - 1);
|
||||
for(i = 0; i < ARRAYLEN(sysexits); ++i){
|
||||
//output_comment(1, 1 * TAB_WIDTH, 80, sysexits[i].desc);
|
||||
#ifdef ENUM
|
||||
fprintf(stdout, "\t%s = %d%s",
|
||||
sysexits[i].name,
|
||||
sysexits[i].status,
|
||||
i < ARRAYLEN(sysexits) - 1 ? ",\n" : "\n"
|
||||
);
|
||||
#endif /* ifdef ENUM */
|
||||
#ifdef DEFINE
|
||||
fprintf(stdout, "#\tdefine %s %d\n",
|
||||
sysexits[i].name,
|
||||
sysexits[i].status
|
||||
);
|
||||
#endif /* ifdef DEFINE */
|
||||
}
|
||||
fflush(stdout);
|
||||
write(1, header_suffix, ARRAYLEN(header_suffix) - 1);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]){
|
||||
if(argv[0] == NULL){
|
||||
argv[0] = program_name;
|
||||
++argc;
|
||||
}
|
||||
|
||||
output_header();
|
||||
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();
|
||||
}
|
||||
17
Wip/ti83/Makefile
Normal file
17
Wip/ti83/Makefile
Normal file
@@ -0,0 +1,17 @@
|
||||
UNZIP = tar xf
|
||||
|
||||
LBLRW_UPSTREAM = https://www.ticalc.org/pub/83plus/asm/programs/lblrw.zip
|
||||
|
||||
all: Schedule Zonk
|
||||
|
||||
.PHONY: Zonk
|
||||
Zonk: Zonk.8xp
|
||||
|
||||
.PHONY: Schedule
|
||||
Schedule: LblRW.8xp Schedule.8xp
|
||||
|
||||
LblRW.8xp: lblrw.zip
|
||||
$(UNZIP) lblrw.zip LblRW.8xp
|
||||
|
||||
lblrw.zip:
|
||||
curl -O "$(LBLRW_UPSTREAM)"
|
||||
11
Wip/ti83/README.md
Normal file
11
Wip/ti83/README.md
Normal file
@@ -0,0 +1,11 @@
|
||||
## Schedule
|
||||
|
||||
A schedule app for the TI-83/84(+).
|
||||
|
||||
### Dependencies
|
||||
|
||||
- [LBLWR](https://www.ticalc.org/archives/files/fileinfo/470/47097.html) from [Zeda Thomas](https://github.com/Zeda)
|
||||
|
||||
## Zonk
|
||||
|
||||
A dungeon simulator.
|
||||
79
Wip/ti83/schedule.src
Normal file
79
Wip/ti83/schedule.src
Normal file
@@ -0,0 +1,79 @@
|
||||
//Menu
|
||||
Lbl M
|
||||
0→Z
|
||||
Menu("SCHEDULE","VIEW SCHEDULE",A,"EDIT SCHEDULE",B,"QUIT",C
|
||||
Stop
|
||||
|
||||
//View
|
||||
Lbl A
|
||||
ClrHome
|
||||
For(A,1,8
|
||||
"!D:→Str1
|
||||
A
|
||||
Asm(prgmLBLRW
|
||||
Output(A,1,Ans
|
||||
End
|
||||
0
|
||||
While Ans≠21
|
||||
getKey
|
||||
If Ans≠0
|
||||
Output(8,1,"2ND TO QUIT
|
||||
End
|
||||
Goto M
|
||||
|
||||
//Edit
|
||||
Lbl B
|
||||
ClrHome
|
||||
Output(1,1,"1-8 TO EDIT
|
||||
Output(2,1,"OTHERS TO QUIT
|
||||
0→A
|
||||
0
|
||||
While Ans=0
|
||||
getKey
|
||||
If Ans=72
|
||||
7→A
|
||||
If Ans=73
|
||||
8→A
|
||||
If Ans=82
|
||||
4→A
|
||||
If Ans=83
|
||||
5→A
|
||||
If Ans=84
|
||||
6→A
|
||||
If Ans=92
|
||||
1→A
|
||||
If Ans=93
|
||||
2→A
|
||||
If Ans=94
|
||||
3→A
|
||||
End
|
||||
If A=0
|
||||
Goto M
|
||||
ClrHome
|
||||
Disp "ENTER NEW DATA
|
||||
Input "",Str1
|
||||
"D:"+Str1→Str1
|
||||
A
|
||||
Asm(prgmLBLRW
|
||||
ClrHome
|
||||
Disp "DATA CHANGED!
|
||||
While Ans≠21
|
||||
getKey
|
||||
End
|
||||
Goto M
|
||||
|
||||
//Quit
|
||||
Lbl C
|
||||
ClrHome
|
||||
Stop
|
||||
|
||||
//Data
|
||||
Lbl D
|
||||
PERIOD ONE
|
||||
PERIOD TWO
|
||||
PERIOD THREE
|
||||
PERIOD FOUR
|
||||
PERIOD FIVE
|
||||
PERIOD SIX
|
||||
PERIOD SEVEN
|
||||
PERIOD EIGHT
|
||||
266
Wip/ti83/zonk.src
Normal file
266
Wip/ti83/zonk.src
Normal file
@@ -0,0 +1,266 @@
|
||||
//Initial setup
|
||||
Disp "NOW LOADING
|
||||
0→B
|
||||
0→D
|
||||
0→E
|
||||
randInt(0,50)→G
|
||||
10→H
|
||||
100→R
|
||||
0→T
|
||||
ClrHome
|
||||
Disp "----------------","ZONK FOR TI-84+","CREATED BY","DEVEN BLAKE 2018","----------------","ENTER A NAME,","MORTAL
|
||||
Input "> ",Str0
|
||||
ClrHome
|
||||
Disp Str0,"PREPARE TO DIE!
|
||||
Pause
|
||||
ClrHome
|
||||
|
||||
//Scenario chooser
|
||||
Lbl A
|
||||
If R=0
|
||||
Goto Z
|
||||
randInt(1,10)→D
|
||||
D+4→E
|
||||
R-1→R
|
||||
If remainder(100-R,5)=0 and G>4 and G<99
|
||||
Goto G
|
||||
Disp "ROOM",100-R,"HAS
|
||||
If D=1
|
||||
Disp "A GOBLIN
|
||||
If D=2
|
||||
Disp "AN IMP
|
||||
If D=3
|
||||
Disp "A THIEF
|
||||
If D=4
|
||||
Disp "A VAMPIRE
|
||||
If D=5
|
||||
Disp "A NINJA
|
||||
If D=6
|
||||
Disp "ELVIS PRESLEY
|
||||
If D=7
|
||||
Disp "YOUR CHILDHOOD","BULLY
|
||||
If D=8
|
||||
Disp "A POLITICIAN
|
||||
If D≥9
|
||||
Disp "A NAZI
|
||||
If D=10
|
||||
Disp "…ZOMBIE!
|
||||
Pause
|
||||
If D=3 or D=5 or D=8
|
||||
Then
|
||||
Disp "SNEAK ATTACK!!!!"," -01 HP
|
||||
H-1→H
|
||||
Pause
|
||||
End
|
||||
If H≤1
|
||||
Goto F
|
||||
|
||||
//Battle System
|
||||
Lbl B
|
||||
0->B
|
||||
Disp "YOUR MOVE,",Str0
|
||||
Input "> ",Str1
|
||||
If Str1="ATTACK" or Str1="A
|
||||
1→B
|
||||
If Str1="MAGIC" or Str1="M
|
||||
2→B
|
||||
If Str1="CONFRONT" or Str1="C
|
||||
3→B
|
||||
If Str1="RUN" or Str1="R
|
||||
4→B
|
||||
If B=0
|
||||
Disp "ATTACK OR A","MAGIC OR M","CONFRONT OR C","RUN OR R
|
||||
If B=0
|
||||
Goto B
|
||||
//Effect Processor
|
||||
If B=1
|
||||
Then
|
||||
If D<3 or D=6 or D=9
|
||||
Then
|
||||
E-1→E
|
||||
Disp "DID 1 DMG
|
||||
End
|
||||
If D=3 or remainder(D,5)=0
|
||||
Then
|
||||
E-2→E
|
||||
Disp "DID 2 DMG
|
||||
End
|
||||
If D=4
|
||||
Then
|
||||
E-3→E
|
||||
Disp "DID 3 DMG
|
||||
End
|
||||
If D=7 or D=8
|
||||
Then
|
||||
0→E
|
||||
Disp "WOWZERS!
|
||||
End
|
||||
End
|
||||
If B=2
|
||||
Then
|
||||
If D=1
|
||||
Then
|
||||
E-2→E
|
||||
Disp "DID 2 DMG
|
||||
End
|
||||
If remainder(D,2)=0 and D≠8
|
||||
Disp "LOL NOTHING
|
||||
If D=3 or D=7
|
||||
Then
|
||||
E-4→E
|
||||
Disp "DID 4 DMG
|
||||
End
|
||||
If D=5
|
||||
Then
|
||||
E-5→E
|
||||
Disp "DID 5 DMG
|
||||
End
|
||||
If D=9
|
||||
Then
|
||||
0→E
|
||||
Disp "WOWZERS!
|
||||
End
|
||||
End
|
||||
If B=3
|
||||
Then
|
||||
If D<3
|
||||
Disp "LOL NOTHING
|
||||
If remainder(D,3)=0 or D=8
|
||||
Then
|
||||
0→E
|
||||
Disp "WOWZERS!
|
||||
End
|
||||
If D=4
|
||||
Then
|
||||
E-1→E
|
||||
Disp "DID 1 DMG
|
||||
End
|
||||
If remainder(D,5)=0
|
||||
0→H
|
||||
If D=7
|
||||
Then
|
||||
E-5→E
|
||||
Disp "DID 5 DMG
|
||||
End
|
||||
End
|
||||
If B=4
|
||||
Then
|
||||
If D<4 or D=7
|
||||
Disp "LOL NOTHING
|
||||
If remainder(D,2)=0 and D≠2 and D≠10
|
||||
Then
|
||||
0→E
|
||||
Disp "WOWZERS!
|
||||
End
|
||||
If remainder(D,5)=0 or D=9
|
||||
0→H
|
||||
End
|
||||
Pause
|
||||
|
||||
//Battle Processor
|
||||
If E>0
|
||||
Then
|
||||
If D=1 and G>1
|
||||
Then
|
||||
G-2→G
|
||||
Disp "THEY TOOK 2 GOLD
|
||||
End
|
||||
If D=2 and G>0
|
||||
Then
|
||||
G-1→G
|
||||
Disp "THEY TOOK 1 GOLD
|
||||
End
|
||||
If T=0 and G≠0 and D=3
|
||||
Then
|
||||
G→T
|
||||
0→G
|
||||
Disp "TOOK ALL GOLD!
|
||||
End
|
||||
If D=4
|
||||
Then
|
||||
H-1→H
|
||||
Disp "THEY SUCKED","YOUR BLOOD","EH EH EHH
|
||||
End
|
||||
If D=5
|
||||
H-1→H
|
||||
If D=6
|
||||
Then
|
||||
G+1→G
|
||||
H-1→H
|
||||
Disp "DID DRUGS","GOT CASH
|
||||
End
|
||||
If D=7
|
||||
Then
|
||||
H-1→H
|
||||
Disp "TOOK 1 DMG
|
||||
End
|
||||
If D=8
|
||||
Then
|
||||
H-2→H
|
||||
Disp "THEY SLEAZED YOU
|
||||
End
|
||||
If D>8
|
||||
Then
|
||||
If G>3
|
||||
G-4→G
|
||||
H-2→H
|
||||
If D≠10
|
||||
Disp "UGH NAZIS","YOU'D THINK","WE WON THAT WAR
|
||||
End
|
||||
If D=10
|
||||
Then
|
||||
H-1→H
|
||||
Disp "BASICALLY JUST","A ZOMBIE
|
||||
End
|
||||
End
|
||||
If H<1
|
||||
Goto F
|
||||
If E<1
|
||||
T+G→G
|
||||
If E<1
|
||||
0→T
|
||||
If E<1
|
||||
G+10→G
|
||||
Pause
|
||||
|
||||
//Battle outcome
|
||||
If E>0
|
||||
Disp "ENEMY ALIVE
|
||||
Disp "HEALTH:",H
|
||||
Disp "GOLD:",G
|
||||
If E>0
|
||||
Disp "ENEMY HEALTH:",E
|
||||
Pause
|
||||
If T≠0
|
||||
Disp "THIEF'S LOOT:",T
|
||||
If E<1
|
||||
Goto A
|
||||
Goto B
|
||||
|
||||
//Death
|
||||
Lbl F
|
||||
Disp "GAME OVER, DUDE
|
||||
Stop
|
||||
|
||||
//Shop
|
||||
Lbl G
|
||||
Disp "----------------","STORE OF STORES!","----------------"," 5 GOLD => 1 HP","----------------","BUY
|
||||
Input Str2
|
||||
If Str2="Y"
|
||||
Then
|
||||
G-5→G
|
||||
H+1→H
|
||||
End
|
||||
If G<5 or Str2≠"Y
|
||||
Goto A
|
||||
Goto G
|
||||
|
||||
//Win
|
||||
Lbl Z
|
||||
Disp "----------------"," YOU WON!","----------------
|
||||
Pause
|
||||
Disp "I NEVER EXPECTED","SOMEONE TO","ACTUALLY WIN","THIS GAME,","THANKS FOR","PLAYING"
|
||||
Pause
|
||||
ClrHome
|
||||
Disp "THANKS,",Str0
|
||||
Stop
|
||||
16
Wip/todo/design.txt
Normal file
16
Wip/todo/design.txt
Normal file
@@ -0,0 +1,16 @@
|
||||
todod - todo daemon
|
||||
todoctl - todo control
|
||||
todoctl add [name] [job]
|
||||
todoctl del/rm/remove [name]
|
||||
todoctl move/mv [name] {under,above} [name]
|
||||
/etc/todo.list - todo data
|
||||
|
||||
todo stack
|
||||
top "next job" (above "job after next job")
|
||||
"job after next job" (under "next job", above "last job")
|
||||
bottom "last job"
|
||||
|
||||
the purpose is to have a job scheduler so you don't have to job && job and wait
|
||||
and hope for the best. maybe there should also be retry settings. this is
|
||||
similar to an init system in terms of design but should be simpler and not
|
||||
handle dependency trees or anything like that
|
||||
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;
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user