#! /usr/bin/env oksh # shellcheck shell=ksh # Copyright (c) 2021, 2024 Stefan Kreutz # # 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. set -o errexit set -o nounset set -o pipefail alphabet=23456789abcdefghijmopqrstwxyzABCDEFGHJKLMNPQRSTUVWXYZ groups=12 width=4 separator=- verbosity=0 while getopts :va:g:w:s: option; do case "$option" in v) verbosity=$((verbosity+1)) ;; a) alphabet="$OPTARG" ;; g) groups="$OPTARG" ;; w) width="$OPTARG" ;; s) separator="$OPTARG" ;; :) print -u2 -- "missing argument for option -$OPTARG"; exit 1 ;; ?) print -u2 -- "illegal option: -$OPTARG"; exit 1 ;; esac done shift $((OPTIND-1)) # shellcheck disable=SC2046 set -A symbol -- $( echo "$alphabet" | fold -w 1 | sort -u | tr -d '\n' | sed 's/./& /g' ) # shellcheck disable=SC2154 symbols=${#symbol[*]} jot -r $((groups*width)) 0 $((symbols-1)) | while IFS= read -r i; do echo "${symbol[$i]}"; done | tr -d '\n' | fold -w "$width" | paste -s -d "$separator" - if [ "$( uname )" == "FreeBSD" ] ; then # FreeBSD's paste(1) swallows the final newline. printf '\n' fi if [ $verbosity -gt 0 ]; then entropy="$( printf 'e = (%d * %d * l(%d))/l(2); scale = 0; e/1\n' "$groups" "$width" "$symbols" | bc -l )" print -u2 -- "The generated password has an entropy of ${entropy} bits." fi