--- /dev/null
+#!/bin/sh
+
+error() { echo "$@" 1>&2; }
+fail() { [ $# -eq 0 ] || error "$@"; exit 1; }
+
+Usage() {
+ cat <<EOF
+Usage: ${0##*/} [ options ] key
+
+ add the key to .ssh/authorized_keys
+ give '-' to read keys from stdin
+
+ options:
+ -p | --prefix STRING prefix key with STRING
+ -r | --replace replace any existing entries
+EOF
+}
+
+removekey() {
+ local file="$1" keyline="$2"
+ shift;
+ set -- $keyline
+ sed -i "\\|$2|d" "$file" || return
+}
+
+bad_Usage() { Usage 1>&2; [ $# -eq 0 ] || error "$@"; exit 1; }
+
+short_opts="hpru"
+long_opts="help,prefix:,replace,user:"
+getopt_out=$(getopt --name "${0##*/}" \
+ --options "${short_opts}" --long "${long_opts}" -- "$@") &&
+ eval set -- "${getopt_out}" ||
+ bad_Usage
+
+user=""
+prefix=""
+key=""
+replace=false
+
+while [ $# -ne 0 ]; do
+ cur=${1}; next=${2};
+ case "$cur" in
+ -h|--help) Usage ; exit 0;;
+ -p|--prefix) prefix="$next"; shift;;
+ -r|--replace) replace=true;;
+ --) shift; break;;
+ esac
+ shift;
+done
+
+[ $# -ge 1 ] || bad_Usage "must provide keys"
+
+cd ~/ || fail "failed to cd ~"
+mkdir -p -m 0755 .ssh || fail "failed to make .ssh"
+umask 066
+: >> .ssh/authorized_keys ||
+ fail "can't write to ~/.ssh/authorized_keys"
+
+if [ "$1" = "-" ]; then
+ keys=""
+ key=""
+ # we check for success or non empty string.
+ # on final line with no EOF, it returns 1, but sets key
+ while read key || [ -n "$key" ]; do
+ keys="${keys}|${key}"
+ done
+ keys=${keys#|};
+ oifs="$IFS"
+ IFS="|"
+ set -- $keys
+ IFS="$oifs"
+fi
+
+if $replace; then
+ for key in "$@"; do
+ removekey ".ssh/authorized_keys" "$key" || fail "failed to remove: $key"
+ done
+fi
+
+{
+ for key in "$@"; do
+ echo "${prefix:+${prefix} }$key"
+ done
+} >> .ssh/authorized_keys
+chmod 600 .ssh/authorized_keys
+
+# vi: ts=4 noexpandtab