]> CyberLeo.Net >> Repos - CDN/flag.git/blob - flag
Eliminate scary eval and sed invocation
[CDN/flag.git] / flag
1 #!/bin/sh
2
3 #set -x
4
5 # Places for flags:
6 # $HOME/.flag-cache <- Autogenerated flag (refreshed when hostname changes)
7 # /etc/flag <- Site admin's flag
8 # $HOME/.flag <- Local user's flag
9 # Check them in that order.
10
11 # Name available algos as algo_something() and left-align for autodetection
12 # Order the algos by priority: the first one that is correct will be used
13 algo_cksum_linux() { printf '%08x\n' $(cksum) | head -n 1; }
14 algo_cksum_freebsd() { printf '%08x\n' $(cksum -o 3) | head -n 1; }
15 algo_crc32() { crc32 /dev/stdin; }
16 algo_crc32sum() { crc32sum; }
17 algo_crc32sum_linux() { crc32sum-linux; }
18 algo_crc32sum_freebsd() { crc32sum-freebsd; }
19 algo_ruby() { ruby -e 'require "zlib"; printf "%08x\n", Zlib.crc32(STDIN.readlines.join)'; }
20 algo_php() { php -r 'printf("%08x\n", crc32(file_get_contents("/dev/stdin")));'; }
21 algo_perl() { perl -e 'use String::CRC32; printf("%08x\n", crc32(*STDIN));'; }
22
23 find_crc32_algo() {
24   sed -e '/^algo_[^(]*()/!d; s/().*$//' "${0}" | while read algo
25   do
26     if [ "$(printf "meow" | "${algo}" 2>/dev/null)" = "8a106afe" ]
27     then
28       echo "${algo}"
29       break
30     fi
31   done
32 }
33
34 hash_string() {
35   # Hash the passed string into 8 hex characters
36   [ "${crc32_algo}" ] || crc32_algo="$(find_crc32_algo)"
37   if [ -z "${crc32_algo}" ]
38   then
39     echo "No crc32 algo found!" >&2
40     echo "deadbeef"
41     return 1
42   else
43     echo -n "${*}" | "${crc32_algo}" 2>/dev/null | awk '{print $1}'
44     return 0
45   fi
46 }
47
48 flagcache(){
49   myhost="$(/bin/hostname -f)"
50   cache="${HOME}/.flag-cache"
51   if [ -f "${cache}" ]
52   then
53     flag_hex="$(awk '/^'${myhost}'/{print $2}' "${cache}")"
54   fi
55   if [ -z "${flag_hex}" ]
56   then
57     flag_hex="$(hash_string "${myhost}")" && echo -e "${myhost}\t${flag_hex}" >> "${cache}"
58   fi
59   echo "${flag_hex}"
60 }
61
62 if [ -f "${HOME}/.flag" ]
63 then
64   flag_hex="$(cat "${HOME}/.flag")"
65 fi
66
67 if [ -z "${flag_hex}" -a -f "/etc/flag" ]
68 then
69   flag_hex="$(cat "/etc/flag")"
70 fi
71
72 if [ -z "${flag_hex}" ]
73 then
74   flag_hex="$(flagcache)"
75 fi
76
77 # Now we definitely have flag_hex
78 firstchar() {
79   char="$(printf '%c' "${data}")"
80   data="${data##${char}}"
81 }
82
83 hexdec() {
84   if [ -z "${1}" ]
85   then
86     echo "0"
87     return
88   fi
89   echo $(( 0x${1} + 0 ))
90 }
91
92 flag() {
93   if [ -z "${1}" ]
94   then
95     echo "Usage: flag 'hexcode' [symbol] [shellmode]" >&2
96     echo "Generates an ANSI color flag using the specified hex codes" >&2
97     echo "Uses the optional symbol (or ' ') to draw the flag" >&2
98     echo "shellmode encapsulates all nonprintable codes in \[\] to" >&2
99     echo " give the shell hints on how long the string is, for proper" >&2
100     echo " wrapping of command prompts." >&2
101     return
102   fi
103   data="${1}"
104   sym="${2}"
105   shm="${3}"
106   [ -n "${shm}" ] && open='\\[' shut='\\]'
107   while [ -n "${data}" ]
108   do
109     firstchar
110     ord=$(hexdec "${char}")
111     bright="0"
112     [ "$(( ${ord} & 8 ))" -gt 0 ] && bright="1;7"
113     colour="$(( ${ord} & 7 ))"
114     printf "${open}\033[%s;3%s;4%sm${shut}%s" "${bright}" "${colour}" "${colour}" "${sym:-${char}}"
115   done
116   printf "${open}\033[0m${shut}"
117 }
118
119 pebkac() {
120    echo "Usage: $(basename "${0}") [-s #] [-e]" >&2
121    echo "Produces a neat little ansi colour 'flag' based off" >&2
122    echo " a hash of the machine's hostname (or settable via" >&2
123    echo " ~/.flag or /etc/flag) which can uniquely visually" >&2
124    echo " identify a machine, at a glance. Useful for placing" >&2
125    echo " into /etc/issue or your bash prompt, so that you" >&2
126    echo " don't send stupid commands to the wrong machine." >&2
127    echo " " >&2
128    echo " -s #   Specify which character should be used to" >&2
129    echo "         render the flag. If empty, use the hex code." >&2
130    echo " -e     Turn on bash encapsulation mode, to provide" >&2
131    echo "         hints to Bash on what is or is not printable" >&2
132    echo "         so it can wrap your commands appropriately" >&2
133    echo "         when used in your prompt" >&2
134    echo " " >&2
135    echo "This machine's flag is as such: ($(flag "${flag_hex}"))" >&2
136    exit 1
137 }
138
139 symbol=""
140 shellmode=""
141
142 while [ -n "${1}" ]
143 do
144   case "${1}" in
145   -s)  shift; symbol="${1}" ;;
146   -e)  shellmode="yes" ;;
147   *)   pebkac ;;
148   esac
149   shift
150 done
151 flag "${flag_hex}" "${symbol}" "${shellmode}"
152