commit 8333ef17b277fdaf50e4e8114b69a76b69b5b1c3
Author: alex wennerberg <alex@alexwennerberg.com>
Date: Mon, 19 Jul 2021 08:33:54 -0700
Initial commit
Diffstat:
A | LICENSE | | | 19 | +++++++++++++++++++ |
A | README.md | | | 3 | +++ |
A | arg.rs | | | 70 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
A | avatar.go | | | 88 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
A | finger.rs | | | 64 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
A | out.png | | | 0 | |
6 files changed, 244 insertions(+), 0 deletions(-)
diff --git a/LICENSE b/LICENSE
@@ -0,0 +1,19 @@
+Copyright 2021 Alex Wennerberg
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+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 OR COPYRIGHT HOLDERS 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.
diff --git a/README.md b/README.md
@@ -0,0 +1,3 @@
+# Misc one-off scripts
+
+A collection of misc single-file scripts and code.
diff --git a/arg.rs b/arg.rs
@@ -0,0 +1,70 @@
+// Extremely minimalist command line interface, inspired by
+// [sbase](https://git.suckless.org/sbase/)'s
+// [arg.h](https://git.suckless.org/sbase/file/arg.h.html)
+// Copy/paste this code and you have a CLI! No library needed!
+
+use std::env;
+use std::process::exit;
+
+fn usage() {
+ eprintln!(r#"./main [-ab] [-c var] [positional]
+
+-a enables a flag
+-b enables b flag
+-c NUM sets var c to NUM
+ "#);
+ exit(1);
+}
+fn main() {
+ // Initialize your variables here;
+ let mut a_enabled = false;
+ let mut b_enabled = false;
+ let mut positional: Option<&str> = None;
+ let mut var: Option<i32> = None;
+
+ let args: Vec<String> = env::args().collect();
+ for mut n in 1..args.len() {
+ let arg: Vec<char> = args[n].chars().collect();
+ if arg.len() > 1 && arg[0] == '-' {
+ let mut iter = arg.iter();
+ iter.next();
+ for m in iter {
+ // Match your variables here (only supports single-char vars)
+ match m {
+ 'c' => {
+ if n+1 != args.len() {
+ var = Some(args[n+1].parse().unwrap());
+ n += 1;
+ }
+ },
+ 'a' => {
+ a_enabled = true;
+ },
+ 'b' =>{
+ b_enabled = true;
+ }
+ _ => {
+ usage();
+ }
+ }
+ }
+ arg[0];
+ } else {
+ positional = Some(&args[n]);
+ }
+ }
+
+ // Check values of variables, use to direct behavior
+ if a_enabled {
+ println!("a enabled");
+ }
+ if b_enabled {
+ println!("b enabled");
+ }
+ if let Some(v) = var {
+ println!("var: {}", v);
+ }
+ if let Some(p) = positional {
+ println!("positional: {}", p);
+ }
+}
diff --git a/avatar.go b/avatar.go
@@ -0,0 +1,88 @@
+// Generate a simple avatar based on a hash of your name
+//
+// Derived from Ted Unangst's Honk
+// https://humungus.tedunangst.com/r/honk/v/tip/f/avatar.go
+//
+// Copyright (c) 2019 Alex Wennerberg, Ted Unangst <tedu@tedunangst.com>
+//
+// Permission to use, copy, modify, and distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+package main
+
+import (
+ "bytes"
+ "fmt"
+ "crypto/sha512"
+ "image"
+ "image/png"
+ "os"
+ "io/ioutil"
+
+)
+
+// Modify the four colors used
+var avatarcolors = [4][4]byte{
+ {0, 0, 0, 255},
+ {255, 255, 255, 255},
+ {172, 172, 172, 255},
+ {96, 96, 96, 255},
+}
+
+func genAvatar(name string) []byte {
+ h := sha512.New()
+ h.Write([]byte(name))
+ s := h.Sum(nil)
+ // Mess with these numbers to change the size
+ img := image.NewNRGBA(image.Rect(0, 0, 64, 64))
+ for i := 0; i < 64; i++ {
+ for j := 0; j < 64; j++ {
+ p := i*img.Stride + j*4
+ xx := i/16*16 + j/16
+ x := s[xx]
+ if x < 64 {
+ img.Pix[p+0] = avatarcolors[0][0]
+ img.Pix[p+1] = avatarcolors[0][1]
+ img.Pix[p+2] = avatarcolors[0][2]
+ img.Pix[p+3] = avatarcolors[0][3]
+ } else if x < 128 {
+ img.Pix[p+0] = avatarcolors[1][0]
+ img.Pix[p+1] = avatarcolors[1][1]
+ img.Pix[p+2] = avatarcolors[1][2]
+ img.Pix[p+3] = avatarcolors[1][3]
+ } else if x < 192 {
+ img.Pix[p+0] = avatarcolors[2][0]
+ img.Pix[p+1] = avatarcolors[2][1]
+ img.Pix[p+2] = avatarcolors[2][2]
+ img.Pix[p+3] = avatarcolors[2][3]
+ } else {
+ img.Pix[p+0] = avatarcolors[3][0]
+ img.Pix[p+1] = avatarcolors[3][1]
+ img.Pix[p+2] = avatarcolors[3][2]
+ img.Pix[p+3] = avatarcolors[3][3]
+ }
+ }
+ }
+ var buf bytes.Buffer
+ png.Encode(&buf, img)
+ return buf.Bytes()
+}
+
+func main() {
+ if len(os.Args) > 2 {
+ avatar := genAvatar(os.Args[1])
+ ioutil.WriteFile(os.Args[2], avatar, 0644)
+ } else {
+ fmt.Println("Usage: [script] name output_file.png")
+ os.Exit(1)
+ }
+}
diff --git a/finger.rs b/finger.rs
@@ -0,0 +1,64 @@
+// A simple finger client written in Rust implementing rfc1288. Zero dependencies outside std. Compiles with rustc:
+// rustc finger.rs -o finger
+// Usage:
+// finger user@domain
+// e.g.
+
+// finger aw@happynetbox.com
+
+// You could also just use netcat:
+
+// printf 'aw\r\n' | nc happnetbox.com 79
+
+// The finger protocol is featured heavily in Elif Batuman's Pulitizer Prize nominated novel The Idiot.
+// FINGER > FACEBOOK
+
+use std::io::prelude::*;
+use std::net::TcpStream;
+use std::env;
+use std::process;
+use std::io;
+
+fn main() -> std::io::Result<()> {
+ let args: Vec<String> = env::args().collect();
+ if args.len() < 2 {
+ println!("Usage: finger [user]@host");
+ process::exit(1);
+ }
+ let params: Vec<&str> = args[1].split("@").collect();
+ let user: &str;
+ let host: &str;
+ if params.len() == 1 {
+ host = params[0];
+ user = "";
+ } else {
+ user = params[0];
+ if params.len() > 2 || !user.chars().all(|c| c.is_ascii()) {
+ println!("Username must be ascii and not include @");
+ process::exit(1);
+ }
+ host = params[1];
+ }
+ let mut stream = TcpStream::connect(format!("{}:79", host)).expect("Couldn't connect to the server.");
+
+ // Only supports queries of type Q1
+ // https://datatracker.ietf.org/doc/html/rfc1288#section-2.3
+ // Doesn't support long mode (/W) -- most servers online don't
+ stream.write(user.as_bytes())?;
+ stream.write(&[13, 10])?; // CLRF
+ let mut line: Vec<u8> = vec![];
+ // TODO -- filter out nonprintable
+ stream.read_to_end(&mut line)?;
+
+ let mut stdout = io::stdout();
+ for byte in line.iter() {
+ // RFC 1288: "this program
+ // SHOULD filter any unprintable data, leaving only printable 7-bit
+ // characters (ASCII 32 through ASCII 126), tabs (ASCII 9), and CRLFs."
+ if (*byte >= 32 && *byte <= 126) || *byte == 9 || *byte == 10 || *byte == 13 {
+ // probably a more efficient way of doing this
+ stdout.write_all(&[*byte])?;
+ }
+ }
+ Ok(())
+}
diff --git a/out.png b/out.png
Binary files differ.