misc

Misc scripts and tools
git clone git://git.alexwennerberg.com/misc
Log | Files | Refs | README | LICENSE

commit 8333ef17b277fdaf50e4e8114b69a76b69b5b1c3
Author: alex wennerberg <alex@alexwennerberg.com>
Date:   Mon, 19 Jul 2021 08:33:54 -0700

Initial commit

Diffstat:
ALICENSE | 19+++++++++++++++++++
AREADME.md | 3+++
Aarg.rs | 70++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aavatar.go | 88+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Afinger.rs | 64++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aout.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.