1
0

move wip stuff to wip

This commit is contained in:
dtb
2023-11-18 15:10:00 -07:00
parent b70d3c08a7
commit 4a7483a0ae
87 changed files with 0 additions and 37 deletions

21
wip/bitch/Makefile Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View File

@@ -0,0 +1,67 @@
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <sysexits.h>
#include <unistd.h>
#include "noargvzero.h"
extern char *optarg; /* getopt(3); unistd.h */
extern int optind, opterr, optopt; /* getopt(3); unistd.h */
void
occurrences(FILE *f, char *s){
}
void
usage(char *name){
fprintf(stderr,
"Usage: %s (-b [list] (-n))"
"\t|(-c [list])"
"\t|(-f [list] (-d [delim]) (-s))"
"\t[file...]\n", name);
exit(EX_USAGE);
}
int
main(int argc, char *argv[]){
int c;
char *delimiter;
char *list;
char mode;
NOARGVZERO(argv[0]);
/* perhaps mode could be specified after submodal stuff. this would
* move checks to after argument parsing though which could take more
* time. */
mode = 0;
submode = 0;
while((c = getopt(argc, argv, "b:c:d:f:ns")) != -1)
switch(c){
case 'b': case 'c': case 'f':
if(mode != 0)
usage(argv[0]);
mode = c;
list = optarg;
break;
case 'd':
if(mode != 'f')
usage(argv[0]);
delimiter = optarg;
break;
case 'n': case 's':
if((c == 's' && mode != 'f')
|| (c == 'b' && mode != 'b'))
usage(argv[0]);
submode = c;
break;
default:
usage(argv[0]);
}
return EX_OK;
}

161
wip/fortune/trinitydotmoe Normal file
View File

@@ -0,0 +1,161 @@
Special thanks to Ками for their help with this quotes script.
-- trinity.moe/js/quotes.json
%
Yeah, that's just how it is. Just, nothing. So much nothing that it hurts.
-- danger/u/ aefd79
%
Reason has always existed, but not always in a reasonable form.
-- Katy Perry
%
Consult your pineal gland.
-- Eris
%
Back to 8chan please
-- Skyglider on wirechan.org
%
No, I am your father.
-- Darth Vader, "Star Wars: The Empire Strikes Back"
%
A checklist can aid here.
-- Lance Leventhal, "Z80 Assembly Language Programming"
%
You never know.
-- Mr. McSweeney of Winthrop, Maine
%
You lost the game.
-- Anonymous on 4chan.org
%
Jerma isn't particularly religious.
-- Jerma985 Wikitubia Fandom article
%
put me on here now
-- arsonist catboy on twitter.com
%
These are no longer memes this is y'all repressed anger
-- Khalifist on twitter.com
%
C makes it easy to shoot yourself in the foot; C++ makes it harder, but when
you do, it blows away your whole leg.
-- Bjarne Stroustrup
%
I'll sleep when I'm dead.
-- Warren Zevon
%
I would have made a good pope.
-- Richard M. Nixon
%
To sit alone with my conscience will be judgement enough for me.
-- Charles William Stubbs
%
Your enemy is where you are not.
-- Sun Tzu, "The Art of War" (paraphrased; purportedly)
%
Be everywhere.
-- social media influencing 101
%
I wish everyone was bald.
-- Anonymous on 4chan.org
%
Nah
-- Soldier G65434-2
%
The kill command is a basic UNIX system command.
-- Matthew Helmke, "Ubuntu Linux Unleashed 2021 Edition, page
283"
%
If you raise the effing hot dog, I will kill you. Figure it out.
-- Craig Jelinek
%
Don't think. Feel and you'll be tanasinn.
-- 名無 on 2chan
%
They had overshadowed her in life. They would obliterate her in death.
-- Khaled Hosseini, "A Thousand Splendid Suns"
%
are your bones made out of fucking depleted uranium
-- Anonymous on the 4chan.org/x/ tulpa peridot thread
%
Giving the Linus Torvalds award to the Free Software Foundation is sort of like
giving the Han Solo award to the Rebel Fleet.
-- Richard Stallman, "Revolution OS (2001)"
%
Filthy Frank is the embodiment of everything a person should not be.
-- George Miller
%
It should be noted that no ethically-trained software engineer would ever
consent to write a DestroyBaghdad procedure. Basic professional ethics would
instead require him to write a DestroyCity procedure, to which Baghdad could be
given as a parameter.
-- Nathaniel Borenstein
%
An idiot admires complexity. A genius admires simplicity.
-- Terry A. Davis
%
When in doubt, use brute force.
-- Ken Thompson
%
Where MS Word is WYSIWYG (What You See Is What You Get), and Latex is WYGIWYW
(What You Get Is What You Want), HTML is WYGIWYD (What You Get Is What You
Deserve).
-- Trinity
%
Easy is the opposite of hard, not the opposite of time-consuming.
-- Brad Fitzpatrick, "discussion about plan9 support with Go"
%
Blame the Nazis for making me become a gun designer. I always wanted to
construct agricultural machinery.
-- Mikhail Kalashnikov
%
since KFC fired me the 11 herbs and spices are coriander, onion powder, garlic
powder, salt, white pepper, black pepper basil, parsley, chili pepper, lemon
powder, thyme, and sage.
-- @ashley.shoy on Tiktok
%
Sooner or later there has to be peace.
-- Abigail Thorn, "Identity: A Trans Coming Out Story"
%
Ich bin ein Berliner.
-- John F. Kennedy
%
I am a Bangor!
-- Erwin Kreuz
%
It's not enough that I should succeed - others should fail.
-- Unknown
%
Secundus says hello to his Prima, wherever she is. I ask, my mistress, that you
love me.
-- Unknown in the House and Office of Volusius Iuvencus
%
Debugging on windows is like trying to fix spelling mistakes but you can't see
the words
-- arwn in the 9fans Discord
%
I believe this rabble does not deserve to be given the means for its
emancipation.
-- Catboy Deleuze (deleuzian_catboy) on instagram.com
%
Nothing human makes it out of the near-future.
-- Nick Land, "Meltdown (1994)"
%
144hz doesnt help much with writing C
-- henesy on the 9fans Discord
%
It could be a monkey. You never know.
-- Peter, overheard in a Burger King
%
There's no law apart from Man's will.
-- Alex Alex, 'Only Blackjack' group on facebook.com
%
You will see by it, that the Opinion of this mischievous Effect from lead, is
at least above Sixty years old; and you will observe with Concern how long a
useful Truth may be known, and exist, before it is generally receiv'd and
practis'd on.
-- Benjamin Franklin in a private letter
%
You claim to seek progress, but you succeed mainly in whining.
-- Dennis Ritchie, "The UNIX-HATERS Handbook Anti-Foreword"
%
nemoj da juriŝ zene i autobusi, biĉe uvek novi
-- meatgrinder's pop, relayed by meatgrinder in metaspinoza's
nightmare wheelhouse

3
wip/ftesosd/LICENSE Normal file
View File

@@ -0,0 +1,3 @@
Derived from
https://gist.github.com/artixnous/41f4bde311442aba6a4f5523db921415
without license.

257
wip/ftesosd/eyesockets.sh Executable file
View File

@@ -0,0 +1,257 @@
#!/bin/sh
# nous,2019-2020
# trinity,2021
# fork from the original FUCKTHESKULLOFSYSTEMD on GitHub Gists:
# https://gist.github.com/artixnous/41f4bde311442aba6a4f5523db921415
# Test Arch ISO installation:
# cfdisk /dev/sda
# mkfs.ext4 /dev/sda1
# mount /dev/sda1 /mnt
# pacstrap /mnt base linux linux-firmware openssh wget rsync dhcpcd grub
# arch-chroot /mnt
# grub-install /dev/sda
# mkinitcpio -P
# grub-mkconfig -o /boot/grub/grub.cfg
# the package name MUST be the same as the editor itself
# e.g. vim, ed, nano, ne, vis
# nous' default was nano, most people know how to use that one so that's what's
# being used here
DEFAULT_EDITOR="nano"
if [ -z "$VISUAL" ] && [ -n "$EDITOR" ]; then
VISUAL="$EDITOR"
elif [ -z "$VISUAL" ] && [ -z "$EDITOR" ]; then
VISUAL="$DEFAULT_EDITOR"
fi
. /usr/share/makepkg/util/message.sh
colorize
printf "$BOLD\
You should run this from inside screen(1) or tmux(1), especially if this is a
remote box. Use a terminal/session with a large scrollback buffer.
"
read -n 1 -p "$RED Last chance to press CTRL-C, ENTER to continue. "
printf "$CYAN\
Starting operation $RED\ FUCKTHESKULLOFSYSTEMD
"
error
error() {
printf "$RED\
An error occured, aborting to prevent incomplete conversion. Fix it and re-run
the script FROM THE LAST STEP ONWARDS.
"
exit 1
}
[ "$1" = "openrc" ] && target="openrc"
[ "$1" = "runit" ] && target="runit"
# runit not yet implemented
#[[ $target ]] || { echo "Usage: $0 <openrc|runit>" ; exit 1; }
#echo "Target: $target"
rm -f /var/lib/pacman/db.lck
sed -i s/Arch/Artix/g /etc/default/grub
# A full systemd update is needed, because libsystemd->systemd-libs
printf "$GREEN\
Updating Arch system first, if this fails abort and update manually;
then re-run the script \
$ALL_OFF"
pacman -Syu --noconfirm \
|| error
pacman -S --needed --noconfirm wget "$VISUAL" rsync \
|| error
cd /etc
printf "$GREEN\
Replacing Arch repositories with Artix\
$ALL_OFF"
mv -vf pacman.conf pacman.conf.arch
wget https://gitea.artixlinux.org/packagesP/pacman/raw/branch/master/trunk/pacman.conf -O /etc/pacman.conf \
|| error
mv -vf pacman.d/mirrorlist pacman.d/mirrorlist-arch
wget https://gitea.artixlinux.org/packagesA/artix-mirrorlist/raw/branch/master/trunk/mirrorlist -O pacman.d/mirrorlist \
|| error
cp -vf pacman.d/mirrorlist pacman.d/mirrorlist.artix
sed -i 's/Required DatabaseOptional/Never/' pacman.conf
printf "$GREEN\
Refreshing package databases\
$ALL_OFF"
pacman -Syy --noconfirm \
|| error
printf "\n"
read -n 1 -p "$GREEN Press ENTER and answer <yes> to the next question to make sure all packages come from Artix repos $ALL_OFF "
echo
pacman -Scc
echo "$GREEN Importing Artix keys $ALL_OFF"
pacman -S --noconfirm artix-keyring \
|| error
pacman-key --populate artix \
|| error
pacman-key --lsign-key 95AEC5D0C1E294FC9F82B253573A673A53C01BC2 \
|| error
systemctl list-units --state=running | grep -v systemd | awk '{print $1}' | grep service > /root/daemon.list
printf "$MAGENTA\
Your systemd running units are saved in /root/daemon.list.\n
$ALL_OFF"
read -n 1 -p "$RED\
Do not proceed if you've seen errors above.
Press CTRL-C to abort or ENTER to continue
$ALL_OFF"
printf "$GREEN
Downloading systemd-free packages from Artix
$ALL_OFF"
pacman -Sw --noconfirm \
base \
base-devel \
openrc-system \
grub linux-lts \
linux-lts-headers \
elogind-openrc \
openrc \
netifrc \
grub mkinitcpio \
archlinux-mirrorlist \
net-tools \
rsync \
"$VISUAL" \
lsb-release \
esysusers \
etmpfiles \
|| error
printf "$YELLOW\
This is the best part: removing systemd
$ALL_OFF"
pacman -Rdd --noconfirm \
systemd \
systemd-libs \
systemd-sysvcompat \
pacman-mirrorlist \
dbus \
|| error
# Previous pacman-mirrorlist removal also deleted this, restoring
cp -vf pacman.d/mirrorlist.artix pacman.d/mirrorlist
echo "$GREEN Installing clean Artix packages $ALL_OFF"
pacman -Qqn | pacman -S --noconfirm --overwrite '*' - \
|| error
echo "$GREEN Installing Artix system packages $ALL_OFF"
pacman -S --noconfirm --needed --overwrite '*' \
base \
base-devel \
openrc-system \
linux-lts \
linux-lts-headers \
elogind-openrc \
openrc \
netifrc \
grub \
mkinitcpio \
archlinux-mirrorlist \
net-tools \
rsync \
"$DEFAULT_EDITOR" \
lsb-release \
connman \
esysusers \
etmpfiles \
artix-branding-base \
|| error
echo "$GREEN Installing service files $ALL_OFF"
pacman -S --noconfirm --needed \
at-openrc \
xinetd-openrc \
cronie-openrc \
haveged-openrc \
hdparm-openrc \
openssh-openrc \
syslog-ng-openrc \
connman-openrc \
|| error
echo "$YELLOW Removing left-over cruft $ALL_OFF"
rm -fv /etc/resolv.conf
echo "$GREEN Enabling basic services $ALL_OFF"
rc-update add haveged sysinit
rc-update add udev sysinit
rc-update add sshd default
echo
echo "$BOLD Activating standard network interface naming (i.e. enp72^7s128%397 --> eth0)."
echo "$BOLD If you prefer the persistent naming, remove the last line from /etc/default/grub"
echo "$BOLD and run $ALL_OFF grub-mkconfig -o /boot/grub/grub.cfg $BOLD when this script prompts for reboot."
echo
read -n 1 -p "Press ENTER $ALL_OFF"
echo 'GRUB_CMDLINE_LINUX="net.ifnames=0"' >>/etc/default/grub
pacman -S --needed --noconfirm netifrc
printf "\
============================= $BOLD
Write down your IP and route. $ALL_OFF
=============================
"
ifconfig
route
printf " \
=============================================================== $BOLD
Press ENTER to edit conf.d/net to configure static networking.
No editing is needed if you use dhcp or a network manager, but
you MUST enable the daemon manually BEFORE rebooting.
You will be given the option at the end of this procedure.
Default setting is DHCP for eth0, should be enough for most. $ALL_OFF
===============================================================
"
read -n 1 -p " "
"$VISUAL" /etc/conf.d/net
ln -sf /etc/init.d/net.lo /etc/init.d/net.eth0
rc-update add net.eth0 default \
|| error
# Good riddance
echo "$YELLOW Removing more systemd cruft $ALL_OFF"
for user in journal journal-gateway timesync network bus-proxy journal-remote journal-upload resolve coredump;
do userdel systemd-$user
done
rm -vfr /{etc,var/lib}/systemd
echo "$GREEN Restoring pacman.conf security settings $ALL_OFF"
sed -i 's/= Never/= Required DatabaseOptional/' /etc/pacman.conf
echo "$GREEN Making OpenRC start faster $ALL_OFF"
sed -i 's/#rc_parallel="NO"/rc_parallel="YES"/' /etc/rc.conf
echo "$GREEN Replacing Arch with Artix in hostname and issue $ALL_OFF"
sed -i 's/Arch/Artix/ig' /etc/hostname /etc/issue 2>/dev/null
echo "$GREEN Recreating initrds $ALL_OFF"
mkinitcpio -P
echo "$GREEN Recreating grub.cfg $ALL_OFF"
cp -vf /boot/grub/grub.cfg /boot/grub/grub.cfg.arch
grub-mkconfig -o /boot/grub/grub.cfg \
|| error
echo "============================================="
echo "= If you haven't seen any errors ="
echo "= press ENTER to reboot ="
echo "= Otherwise switch console and fix them ="
echo "= ="
echo "= ="
echo "= Press CTRL-C to stop reboot ="
echo "=(mandatory if you need a networking daemon)="
echo "=Or switch console/terminal and type as root="
echo "= $BOLD rc-service add connmand $ALL_OFF ="
echo "= then switch back here and continue ="
echo "============================================="
read -n 1 -p " "
sync
mount -f / -o remount,ro
echo s >| /proc/sysrq-trigger
echo u >| /proc/sysrq-trigger
echo b >| /proc/sysrq-trigger

12
wip/head.c Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View File

@@ -0,0 +1,4 @@
#ifndef _IRC_H
# define _IRC_H
#endif /* ifndef _IRC_H */

139
wip/irc/irc.sh Normal file
View 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
View 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
View File

@@ -0,0 +1,4 @@
from sys import exit
def main(buffer, argv):
return 0

67
wip/it/README.md Normal file
View 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
View 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
View 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
View 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
View 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
View File

@@ -0,0 +1,4 @@
import sys
def main(buffer, command):
sys.exit(0)

8
wip/it/f.py Normal file
View 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
View 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
View File

@@ -0,0 +1,3 @@
def main(buffer, command):
print("Hello, world!")
return buffer

31
wip/it/i.py Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View File

@@ -0,0 +1,47 @@
#include <stdio.h>
#include <stddef.h>
#include <sysexits.h>
#include <unistd.h>
#include "putd.c"
/* this helped a LOT:
* https://medium.com/@ethannam/understanding-the-levenshtein-distance-equation-for-beginners-c4285a5604f0
*/
int
levenstein(char *a, char *b){
return 100;
size_t i;
size_t j;
int *m;
size_t s_a;
size_t s_b;
for(s_a = 0; a[s_a] != '\0'; ++s_a);
for(s_b = 0; b[s_b] != '\0'; ++s_b);
/* Levenshtein formula using 2d matrix */
int m[s_a][s_b];
for(i = 0; i < s_a; ++i) /* iterate over a */
for(j = 0; j < s_b; ++j) /* iterate over b */
//m[i][j]
;
}
int main(int argc, char *argv[]){
size_t i;
if(argc != 3){
write(1, "Usage: ", 7);
if(argv[0] != NULL){
for(i = 0; argv[0][i] != '\0'; ++i);
write(1, argv[0], i);
}else
write(1, "levenshtein", 11);
write(1, " [word] [word]\n", 15);
return EX_USAGE;
}
// putd(levenstein(argv[1], argv[2]));
putd(10);
return 0;
}

24
wip/lsd/LICENSE Normal file
View 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
View File

@@ -0,0 +1,5 @@
# trilsd
*trinity's linux software distribution*
See `/dist/documentation/trilsd.7'.

112
wip/lsd/dist/Makefile vendored Normal file
View 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
View 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
View File

@@ -0,0 +1,3 @@
GCC_UPSTREAM=git://gcc.gnu.org/git/gcc.git
MUSL_UPSTREAM=git://git.musl-libc.org/musl
PKGSRC_UPSTREAM=https://cdn.netbsd.org/pub/pkgsrc/current/pkgsrc.tar.xz

105
wip/nutshell.c Normal file
View File

@@ -0,0 +1,105 @@
#include <ctype.h> /* isspace(3) */
#include <stddef.h> /* NULL */
#include <stdio.h> /* getc(3) */
#include <stdlib.h> /* getenv(3), rand(3), srand(3) */
#include <string.h> /* strcmp(3) */
#include <sys/wait.h> /* wait(2) */
#include <time.h> /* time(3) */
#include <unistd.h> /* fork(2), write(2) */
#include "libio.h"
#include "usefulmacros.h"
#include "nutshell.h"
#include "nutshell_builtins.c"
static int
parse_argv(char *buffer, char **argv, int argc_max){
int i;
int j;
int s;
for(i = 0, j = 0, s = 1; buffer[i] != '\0' && j < argc_max; ++i){
while(isspace(buffer[i])){
s = 1;
buffer[i++] = '\0';
}
if(s)
argv[j++] = buffer + i;
}
return j;
}
static char *
read_buffer(char *buf, size_t buf_s){
int i;
for(i = 0; ; ++i){
/* ..., '\0', buf_s */
/* This isn't perfect but is simple and doesn't matter for
* longer buffers that much. */
if(i == buf_s - 1 - 1){
buf[i] = '\0';
break;
}
buf[i] = getc(stdin);
if(buf[i] == EOF)
return NULL;
else if(buf[i] == '\n'){
buf[i + 1] = '\0';
break;
}
}
return buf;
}
static int
run(char *buf){
int argc;
static char *argv[ARGV_MAX];
int i;
/* get argv and argc */
for(i = 0; i < ARRAYLEN(argv); ++i){
if(argv[i] == NULL)
break;
argv[i] = NULL;
}
argc = parse_argv(buf, argv, ARRAYLEN(argv));
/* builtins get priority */
if((i = isbuiltin(argv[0])) != 0)
return builtins[i - 1].f(argc, argv);
if(state.jailed)
goto runerr;
runerr:
/* This is what busybox ash(1) does. */
return 127;
}
int main(int argc, char *argv[]){
static char buf[BUF_MAX];
static char prompt[] = DEFAULT_PROMPT;
builtin_init(0, empty_argv);
for(;;){
write(1, prompt, ARRAYLEN(prompt));
if(read_buffer(buf, ARRAYLEN(buf)) == NULL){
write(1, "EOF\n", 4);
state.status = 0;
break;
}
state.status = run(buf);
}
return state.status;
}

15
wip/nutshell.h Normal file
View File

@@ -0,0 +1,15 @@
/* conservative defaults */
#define ARGV_MAX 10
#define BUF_MAX 100
#define DEFAULT_PROMPT "^_^?: "
char *empty_argv[1] = { NULL };
struct {
int jailed;
int status;
}state = {
0,
0
};

104
wip/nutshell_builtins.c Normal file
View File

@@ -0,0 +1,104 @@
#define NETHACK_NAME "nethack"
int builtin_builtin (int, char **);
int builtin_escape (int, char **);
int builtin_init (int, char **);
int builtin_jail (int, char **);
int builtin_nethack (int, char **);
int builtin_reassure (int, char **);
int builtin_status (int, char **);
struct {
char *name;
int (*f)(int, char **);
}builtins[] = {
/* guaranteed to exist */
{"builtin", builtin_builtin},
{"init", builtin_init},
/* optional additions */
{"escape", builtin_escape},
{"jail", builtin_jail},
{"nethack", builtin_nethack},
{"status", builtin_status}
};
int
isbuiltin(char *s){
int i;
for(i = 0; i < ARRAYLEN(builtins); ++i)
if(strcmp(builtins[i].name, s) == 0)
return i + 1;
return 0;
}
int
builtin_builtin(int argc, char **argv){
int i;
if(argc < 2){
fdputs(2, "%s: needs argument(s)");
return 1;
}
++argv;
while(*argv != NULL)
if(!isbuiltin(*argv))
return 1;
return 0;
}
int
builtin_escape(int argc, char **argv){
char *s;
if((s = getenv("SHELL")) == NULL){
fdputs(1, "$SHELL seems to be empty. This is an OS error.\n");
}else if(fork() == 0)
execl(s, s, NULL);
else
wait(NULL);
return 0;
}
int
builtin_init(int argc, char **argv){
srand(time(NULL));
return 0;
}
int
builtin_jail(int argc, char **argv){
printf("%s\n", argv[1]);
if(argv[1] == NULL)
fdputd(1, state.jailed);
else if(strcmp(argv[1], "break") == 0 || strcmp(argv[1], "build") == 0)
state.jailed = (argv[1][1] - 'r') / ('u' - 'r'); /* cheap */
else
return 1;
return 0;
}
int
builtin_nethack(int argc, char **argv){
static char *nethack_name = NETHACK_NAME;
char *a[2];
if(fork() == 0){
a[0] = nethack_name;
a[1] = NULL;
execvp("nethack", a);
}else
wait(NULL);
return 0;
}
int
builtin_status(int argc, char **argv){
fdputd(1, state.status);
return 0;
}

37
wip/rss/pig.md Normal file
View 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
View 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
View 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
View File

@@ -0,0 +1,3 @@
#!/bin/sh
curl -so - -- "$1"

10
wip/rss/pig_latin Executable file
View 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
View File

@@ -0,0 +1,4 @@
#!/bin/sh
printf "%s\n" "$1" \
| tr -cd '[:alnum:]'

15
wip/rss/pig_pen Executable file
View 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
View 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
View 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
View 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
View 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
View File

@@ -0,0 +1,112 @@
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "liberror.h"
void
exhaust_buffer(char *b, size_t s){
size_t i;
for(i = 0; i < s; ++i)
if(b[i] != 0)
putc(b[i], stdout);
free(b);
return;
}
void
print_stdin(void){
char c;
while((c = getc(stdin)) != EOF)
putc(c, stdout);
return;
}
void
substitute(char *phrase, char *substitution, bool exit_on_first, char *name){
char *b = (char *)calloc(strlen(phrase)+1, sizeof(char));
size_t i;
if(b == NULL)
error(name, ALLOCATION_ERROR);
while((b[strlen(phrase)-1] = getc(stdin)) != EOF){
for(i = 0;
b[i] == phrase[i]
&& b[i] != 0
&& phrase[i] != 0;
++i);
if(i == strlen(phrase)){
fputs(substitution, stdout);
for(i = 0; i < strlen(phrase);)
b[i++] = 0;
if(exit_on_first){
exhaust_buffer(b, strlen(phrase)+1);
print_stdin();
}
}else
putc(*b, stdout);
/* There's a more efficient way to maintain a buffer here,
* where I keep an unordered string of chars and form an
* ordered string when I need to check against the phrase
* to match. However it's math-intensive, which sucks not just
* for a self-taught lamer but in general in regards to muh
* simplicity, and the math undercuts the performance gain
* from avoiding touching memory. Also, come on, you're never
* gonna have a phrase longer than 100 bytes! Who cares?! */
for(i = 0; i < strlen(phrase); ++i)
b[i] = b[i+1];
}
exhaust_buffer(b, strlen(phrase)+1);
}
void
usage(char *name){
fprintf(stdout, "Usage: %s (-fhr) [phrase] [substitution]\n", name);
exit(1);
}
int main(int argc, char *argv[]){
extern char *optarg;
extern int optind;
bool exit_on_first = 0;
char c;
char *argv0 = argv[0];
bool regex_mode = 0;
while((c = getopt(argc, argv, "fhr")) != -1){
switch(c){
/* -f exists because there exist uses of `sed 's/foo/bar/'`
* without the trailing `g` for global substitution that
* would be borked if made global. Perhaps there are other ways
* to do so that mean that this option doesn't need to be
* implemented, but it's kind of easy to just add so
* whatever. */
case 'f': exit_on_first = 1;
case 'h': usage(argv0);
/* By default regex is not parsed; this is because regular
* expressions are not known to the GENERAL user. The kind of
* user that uses this utility /does/ know regex, but the kind
* of user this utility targets does not, so don't implement
* potentially undesirable functionality by default.
* If you know regex you know how to look up a manpage. */
case 'r':
regex_mode = 1;
break;
case '?': default: usage(argv0);
}
}
argc -= optind;
argv += optind;
if(argc < 2 || argc > 3)
usage(argv0);
if(regex_mode == 0)
substitute(argv[0], argv[1], exit_on_first, argv0);
else
{ printf("Not implemented.\n"); exit(1); }
// substitute_regex(argv[0], argv[1], exit_on_first, argv0);
return 0;
}

152
wip/tail.c Normal file
View 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
View 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
View File

@@ -0,0 +1,89 @@
#define RAD_PIN 0
#define ECG_PIN 14 /* A0 */
/* TEKUBI
* ___________ ________________________________
* | | | |
* | USB POWER | | TEENSY 4.0 |
* | | | |
* |__GND__5V__| |__Vin__GND__D0__SDA0__SCL0__A0__|
* | | | | | | | |
* | +--------+----|---|-+--|-----|----|----------+
* | | | | | | | | |
* +----|-------------+---|-|--|-----|----|-----+ |
* | | | | | | | | | |
* | | +---------|---+ | +---+ | +-+ | |
* __ | __ |__ | __ __ | __ |____ | | | ____ | __ | __
* | GND 5V INT | | GND Vcc | | | | | GND Vcc |
* | (100mA?) | | (10mA) SDA--+ | +-A (4mA) |
* | | | | | | |
* | GEIGER COUNTER | | GYRO SCL----+ | ECG |
* |________________| |______________| |______________| */
/* geiger counter
* https://www.rhelectronics.store
* /radiation-detector-geiger-counter-diy-kit-second-edition */
#include <SPI.h>
#define RAD_LOG_PERIOD 5000 /* milliseconds; sample rate */
#define MINUTE 60000 /* milliseconds in a minute */
/* https://www.arduino.cc/reference/en/language/variables/data-types/
* unsignedlong/ - 32 bit */
unsigned long rad_count = 0;
unsigned long rad_cpm;
void rad_interrupt(){ ++rad_count; }
/* https://www.pjrc.com/teensy/td_timing_elaspedMillis.html */
elapsedMillis rad_period = 0;
void geiger_setup(){
pinMode(RAD_PIN, INPUT);
digitalWrite(RAD_PIN, HIGH);
attachInterrupt(0, rad_interrupt, FALLING);
}
void geiger_loop(){
if(rad_period > RAD_LOG_PERIOD){
rad_cpm = rad_count * (MINUTE / RAD_LOG_PERIOD);
rad_period = 0;
}
/* use rad_cpm */
}
/* gyro
* https://www.elecrow.com/crowtail-mpu6050-accelerometer-gyro.html */
/* https://github.com/jrowberg/i2cdevlib/
* Most inexplicable stuff is because it was in Arduino/MPU6050/examples/
* MPU6050_raw/MPU6050_raw.ino */
#include "I2Cdev.h"
#include "MPU6050.h"
#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
# include "Wire.h"
#endif
MPU6050 accelgyro;
int16_t accel_x, accel_y, accel_z, gyro_x, gyro_y, gyro_z;
void gyro_setup(){
#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
Wire.begin();
#elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE
Fastwire::setup(400, true);
#endif
accelgyro.initialize();
}
void gyro_loop(){
accelgyro.getMotion6(&accel_x, &accel_y, &accel_z,
&gyro_x, &gyro_y, &gyro_z);
/* use accel_*, gyro_* */
}
/* ecg
* https://www.elecrow.com/crowtail-pulse-sensor-p-1673.html */
void ecg_setup(){
}
/* teensy 4.0
* https://www.pjrc.com/store/teensy40.html */
void setup(){
geiger_setup();
gyro_setup();
ecg_setup();
}
void loop(){
geiger_loop();
gyro_loop();
}

3
wip/toki/README.txt Normal file
View 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
View File

@@ -0,0 +1,5 @@
#!/bin/sh
set -e
toki_ucsur "$@" | utf8

2
wip/unicode/1.expected Normal file
View File

@@ -0,0 +1,2 @@
0000000 41 e2 89 a2 ce 91 2e
0000007

3
wip/unicode/1.test Executable file
View 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
View File

@@ -0,0 +1,2 @@
0000000 ed 95 9c ea b5 ad ec 96 b4
0000009

3
wip/unicode/2.test Executable file
View 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
View File

@@ -0,0 +1,2 @@
0000000 e6 97 a5 e6 9c ac e8 aa 9e
0000009

3
wip/unicode/3.test Executable file
View 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
View File

@@ -0,0 +1 @@
Tests are from RFC3629, section 7.

15
wip/unicode/Makefile Normal file
View 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
View File

@@ -0,0 +1,23 @@
#include "libunicode.h"
utf32_t utf8(utf32_t c){
unsigned char n; /* 4 - number of bytes - 1 */
utf8_t r;
if(c > UTF8_MAX) /* return 0 if c exceeds max */
c = 0;
switch(n = (c >= 0x010000) + (c >= 0x0800) + (c >= 0x0080)){
case 3: r = 0xF0 + ((c >> 18) & 0x07); /* 11110xxx */
case 2: r = (r << 8) + (n == 2
? 0xE0 + ((c >> 12) & 0x0F) /* 1110xxxx */
: 0x50 + ((c >> 12) & 0x3F)); /* 10xxxxxx */
case 1: r = (r << 8) + (n == 1
? 0xC0 + ((c >> 6) & 0x1F) /* 110xxxxx */
: 0x50 + ((c >> 6) & 0x3F)); /* 10xxxxxx */
case 0: r = (r << 8) + (n == 0
? (c & 0x7F) /* 0xxxxxxx */
: 0x50 + ((c >> 6) & 0x3F)); /* 10xxxxxx */
}
return r;
}

16
wip/unicode/libunicode.h Normal file
View File

@@ -0,0 +1,16 @@
#if defined UINT32_MAX /* indicator <stdint.h> is included */
# define unicode_codepoint_t uint32_t
#else
/* C99 draft 5.2.4.2.1 Sizes of integer types says unsigned long must be able
* to hold 32b */
# define unicode_codepoint_t unsigned long
#endif
#define utf32_t unicode_codepoint_t
/* for holding the literal numeric value of a utf8 rune, not for assembling
* strings; >=32b value */
#define utf8_t unicode_codepoint_t
#define UTF8_MAX 0x10FFFF
/* encode UTF-32 value into UTF-8 */
utf32_t utf8(utf32_t c);

58
wip/unicode/utf.c Normal file
View File

@@ -0,0 +1,58 @@
#include <stdio.h> /* fprintf(3), getc(3), putc(3) stderr, stdin, EOF */
#include <string.h> /* strchr(3) */
#include "ascii.h" /* ASCII_HEXADECIMAL_DIGITS_LOWER,
* ASCII_HEXADECIMAL_DIGITS_UPPER */
#include "libunicode.h" /* utf8(3) */
static struct {
char *name;
utf32_t (*f)(utf32_t);
}
static char *hex = ASCII_HEXADECIMAL_DIGITS_UPPER
ASCII_HEXADECIMAL_DIGITS_LOWER;
int main(int argc, char *argv[]){
int c;
int i;
int l; /* line counter */
char *n;
utf32_t codepoint;
utf8_t encoded;
l = 0;
init: codepoint = 0;
i = 0;
++l;
n = NULL;
while((c = getc(stdin)) != EOF){
if(c == '\n'){
if(i < 2 && i > 0) /* empty lines are fine */
fprintf(stderr, "%s: %s: Syntax error.\n",
argv[0], l);
else if(i >= 2){
encoded = utf8(codepoint);
for(i = 3; i >= 0; --i)
if((encoded >> 8 * i) > 0 || i == 0)
putc(encoded >> 8 * i, stdout);
}
goto init;
}
if(
(i == 0 && c != 'U')
|| (i == 1 && c != '+')
|| i > 8 /* strlen("U+10FFFF") */
|| (i > 1 && ((n = strchr(hex, c)) == NULL))
){
fprintf(stderr, "%s: %s: Syntax error.\n",
argv[0], l);
while((c = getc(stdin)) != '\n' && c != EOF);
++l;
continue;
}
if(n != NULL)
codepoint = (codepoint << 4) + (n - hex) % 16;
++i;
}
}

97
wip/which.c Normal file
View File

@@ -0,0 +1,97 @@
#include <errno.h>
#include <stdbool.h>
#include <stdio.h> /* fprintf(3) */
#include <stdlib.h> /* exit(3) */
#include <sysexits.h>
#include <unistd.h> /* access(2), chdir(2) */
#include "libshell.h" /* getpaths(3) */
void
usage(char *name){
fprintf(stderr, "Usage: %s (-a) [name]\n", name);
exit(EX_USAGE);
}
int
which(char *program, char **paths, char *name, bool breakonfirst){
char **q;
int retval;
retval = 0;
for(q = paths; *q != NULL; ++q){
if(chdir(*q) != 0)
switch(retval = errno){
/* Non-issues in the context of this program */
case EACCES: /* Access denied */
case ELOOP: /* Too many symlinks in path */
case ENAMETOOLONG: /* Name too long */
case ENOENT: /* Directory doesn't exist */
case ENOTDIR: /* Not a directory */
continue;
case EFAULT:
goto apology;
case EIO:
goto ioerr;
}
/* Changed dir, now check for file in dir */
if(access(program, R_OK | X_OK) != 0)
switch(retval = errno){
case EACCES:
case ELOOP:
case ENAMETOOLONG:
case ENOENT:
case EROFS:
continue;
case EFAULT:
goto apology;
case EIO:
goto ioerr;
}
else{
fprintf(stdout, "%s%s\n", *q, program);
if(breakonfirst != 0)
break;
}
}
end:
return retval;
apology:
fprintf(stderr,
/* EFAULT means the pointer passed to either chdir(2) or access(2) was outside
* of the address space available to the program. This means something's Very
* Wrong with getpaths(3) and libshell has to be fixed. That'd be a serious,
* common error, so try to reassure the user and solicit a bug report. */
"%s: EFAULT\n"
"You the user did nothing to invoke this error message. This is an error in\n"
"which, a program you or another program executed. PLEASE e-mail the creator\n"
"of this program (the address can be found in the corresponding manual page)\n"
"and tell them you got this error and what you were doing when it happened.\n"
"Sorry!\n", name);
goto end;
ioerr:
fprintf(stderr, "%s: filesystem I/O error\n", name);
goto end;
}
int main(int argc, char *argv[]){
int i;
char **paths;
int retval;
if(argc <= 1)
usage(argv[0]);
if((paths = getpaths()) == NULL){
fprintf(stderr, "%s: Could not get the value of $PATH\n", argv[0]);
exit(1);
}
for(i = 1; i < argc; ++i)
if((retval = which(argv[i], paths, argv[0], 1)) != 0)
break;
free(*paths);
free(paths);
return retval;
}

12897
wip/wordle/dictionary Normal file

File diff suppressed because it is too large Load Diff

2315
wip/wordle/solutions Normal file

File diff suppressed because it is too large Load Diff

115
wip/wordle/wordle.c Normal file
View File

@@ -0,0 +1,115 @@
#include <ctype.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
/* TODO: sysexits.h */
#define PROGRAM_NAME "wordle"
#define DEFAULT_DICTIONARY_FILENAME "/usr/share/" PROGRAM_NAME "/dictionary.txt"
#define DEFAULT_SOLUTIONS_FILENAME "/usr/share/" PROGRAM_NAME "/solutions.txt"
#define WORD_LENGTH 5
#define GUESSES 6
int
dictionary_has(char *s, int fd){
char buf[WORD_LENGTH + 2];
if(lseek(fd, 0, SEEK_SET) != 0){
fprintf(stderr, "%s: Could not seek to the start of the"
" dictionary (errno %d).\n", PROGRAM_NAME, errno
);
close(fd);
exit(1);
}
/* unused, but just in case */
buf[WORD_LENGTH + 1] = '\0';
if(read(fd, buf, WORD_LENGTH + 1) < WORD_LENGTH)
return 1;
}
int
strisuint(char *s){
while(*s != '\0')
if(!isdigit(*(s++)))
return 0;
return 1;
}
void
usage(char *name){
fprintf(stderr, "Usage: %s [index] (-d [dictionary file])"
" (-s [solutions file])\n", name
);
exit(1);
}
int main(int argc, char *argv[]){
int c;
int dictionary_fd;
size_t i;
size_t index;
size_t j;
FILE *solutions_file;
char word[WORD_LENGTH + 1];
/* arg parse */
if(argc < 2)
usage(argv[0] != NULL ? argv[0] : PROGRAM_NAME);
while((c = getopt(argc, argv, "d:hs:")) != -1)
switch(c){
case 'd':
dictionary_filename = optarg;
break;
case 's':
solutions_filename = optarg;
break;
case 'h':
usage(argv[0] != NULL ? argv[0] : PROGRAM_NAME);
}
if(!strisuint(argv[optind])){
fprintf(stderr, "%s: index must be a number.\n",
argv[0] != NULL ? argv[0] : PROGRAM_NAME
);
exit(1);
}
index = (size_t)atoi(argv[optind]);
/* get word */
if((solutions_file = fopen(solutions_filename, "rb")) == NULL){
fprintf(stderr, "%s: %s: Error opening solutions file.\n",
argv[0] != NULL ? argv[0] : PROGRAM_NAME, solutions_filename
);
exit(1);
}
i = j = 0;
while((c = getc(solutions_file)) != EOF)
if(i == index){
if(j == WORD_LENGTH){
word[WORD_LENGTH] = '\0';
j = 0;
break;
}else
word[j++] = c;
}else
i += c == '\n';
if(j != '\0'){
word[j] = '\0';
fprintf(stderr, "%s: %s: Word is too few characters.\n",
argv[0] != NULL ? argv[0] : PROGRAM_NAME, word
);
exit(1);
}
fclose(solutions_file);
if(dictionary_fd = open(dictionary_filename, O_RDONLY) == NULL){
fprintf(stderr, "%s: %s: Error opening dictionary file.\n",
argv[0] != NULL ? argv[0] : PROGRAM_NAME, dictionary_filename
);
exit(1);
}
close(dictionary_fd);
exit(0);
}