: wizard? ( d -- i ) dup "C" flag? swap "Q" flag? not and ; : full_idle ( i -- s ) conidle dup 86400 / dup if swap pop dup 1 = if " day " else " days " then swap intostr swap strcat "Idle Time" strcat exit then pop dup 3600 / dup if dup 9 > if swap pop intostr " hours Idle Time" strcat exit else swap over 3600 * - swap dup 1 = if " hour " else " hours " then swap intostr swap strcat swap 60 / dup 1 = if " minute " else " minutes " then swap intostr swap strcat strcat "Idle Time" strcat exit then then pop dup 60 / dup if dup 1 = if " minute " else " minutes " then swap intostr swap strcat "Idle Time" strcat swap pop exit then pop dup 1 = if " second " else " seconds " then swap intostr swap strcat "Idle Time" strcat ; : get_plan ( d -- ) dup ".plan" swap intostr strcat 3 pick swap getpropstr dup not if pop exit then me @ swap notify 1 + get_plan ; : find_descriptor ( d -- i ) dup not if pop exit then over condbref over 3 + pick dbcmp if dup 3 + rotate pop over over 3 + 0 swap - rotate then swap pop 1 - find_descriptor ; : resolve_tty ( i -- s ) 4 - dup 16 % swap 16 / "pqrstuvwx" swap strcut 1 strcut pop swap pop swap "0123456789abcdef" swap strcut 1 strcut pop swap pop strcat ; : idle_time ( i -- s ) dup 86400 / dup if swap pop intostr "d" strcat exit then pop dup 3600 / dup not if pop 60 / dup not if pop "" exit else intostr exit then then dup 9 > if swap pop intostr "h" strcat exit then swap dup 3600 / 3600 * - 60 / intostr dup strlen 1 = if "0" swap strcat then ":" swap strcat swap intostr swap strcat ; : get_blank_string ( -- s ) " " ; : reverse_pad ( s -- s ) over strlen over > if strcut pop else get_blank_string swap strcut pop over strlen strcut swap pop swap strcat then ; : pad ( s -- s ) over strlen over > if strcut pop else get_blank_string swap strcut pop over strlen strcut swap pop strcat then ; : finger_all_loop ( i1 ... iX X -- ) dup not if pop exit then over condbref #-1 dbcmp if swap pop 1 - finger_all_loop exit then over condbref "D" flag? me @ wizard? not and if swap pop 1 - finger_all_loop exit then over condbref name tolower 8 pad " " strcat 3 pick condbref "*realname" getpropstr dup "" stringcmp not if pop 3 pick condbref name then 20 pad strcat " " strcat 3 pick resolve_tty 4 pick condbref "H" flag? if "*" swap strcat then dup strlen 2 = if " " swap strcat then strcat " " strcat 3 pick conidle idle_time dup "0" stringcmp not if pop "" then 4 reverse_pad strcat " " strcat 3 pick condbref time_used ctime dup strlen 8 - strcut pop 4 strcut dup strlen 5 - strcut swap pop strcat strcat " " strcat 3 pick condbref "*office" getpropstr 28 pad strcat me @ swap notify swap pop 1 - finger_all_loop ; : finger_all ( -- ) "Login Name TTY Idle When Office" me @ swap notify connections finger_all_loop ; : wth? ( d -- ) "Login name: " over strcat dup strlen 40 > if 40 strcut pop else " " dup strcat dup strcat over strlen strcut swap pop strcat then "In real life: ???" strcat me @ swap notify ; : find_shell ( d -- s ) over #0 dbcmp if swap pop dup "" strcmp not if pop "/" then exit then over "_shell" getpropstr dup "" stringcmp if "/" swap strcat swap strcat else pop then swap location swap find_shell ; : main ( s -- ) .sstrip dup not if pop finger_all exit then dup .pmatch+ dup #-1 dbcmp if pop wth? pop exit then swap pop "Login name: " over name tolower 8 pad strcat " " dup strcat dup strcat over strlen strcut swap pop strcat over "H" flag? if dup strlen 16 - strcut pop "(messages off) " strcat then "In real life: " strcat over "*realname" getpropstr dup "" stringcmp not if pop over name then 20 pad strcat me @ swap notify "/P/newbie/" over "B" flag? if pop "/P/builder/" then over "M" flag? if pop "/P/mucker/" then over "R" flag? if pop "/P/royal/" then over "C" flag? if pop "/P/wiz/" then over "G" flag? if pop "/P/sysadmin/" then over name tolower 8 pad strcat "Directory: " swap strcat 40 pad "Shell: " strcat over location "" find_shell strcat me @ swap notify dup awake? over "D" flag? not me @ wizard? or and if "On since " over time_used ctime 4 strcut swap pop dup strlen 5 - strcut pop strcat me @ wizard? if " on " strcat over 0 swap connections find_descriptor pop swap over dup conhost dup "localhost" stringcmp not swap "127.0.0.1" stringcmp not or if pop "console" strcat strcat swap pop else resolve_tty "tty" swap strcat strcat " from " strcat swap conhost strcat then then me @ swap notify else dup "*connect" getpropstr "" stringcmp if "Last login " over "*connect" getpropstr atoi ctime dup strlen 5 - strcut pop strcat me @ wizard? if " on " strcat over "*tty" getpropstr atoi not if "console" strcat else over "*tty" getpropstr atoi resolve_tty "tty" swap strcat strcat " from " strcat over "*host" getpropstr strcat then then else "Never logged in." then me @ swap notify then dup awake? if dup 0 swap connections find_descriptor pop dup conidle if full_idle me @ swap notify else pop then then dup ".project" getpropstr dup "" stringcmp not if pop else "Project: " swap strcat 75 strcut pop me @ swap notify then dup ".plan1" getpropstr "" stringcmp not if "No Plan." me @ swap notify else me @ "Plan:" notify 1 get_plan pop then pop ;