( expect to see: ) ( ) ( header is everything before ">" ) ( header includes "Selected interface 'wlp170s0'\r\n" ) ( ) ( "OK\r\n" in response to command ) ( ) ( "" starts an unpromtped message about network `id` e.g. 3 ) ( ) ( > scan ) ( <3>CTRL-EVENT-SCAN-STARTED ) ( ) ( <3>CTRL-EVENT-SCAN-RESULTS ) ( > scan_results ) ( ) ( <3>WPA: Group rekeying completed with 70:73:cb:b8:ce:b7 [GTK=CCMP] ) ( ) ( <3>CTRL-EVENT-DISCONNECTED bssid=70:73:cb:b8:ce:b7 reason=3 locally_generated=1 ) ( <3>CTRL-EVENT-DSCP-POLICY clear_all ) ( <3>CTRL-EVENT-NETWORK-REMOVED 0 ) ( <3>CTRL-EVENT-SCAN-STARTED ) ( <3>CTRL-EVENT-REGDOM-CHANGE init=DRIVER type=WORLD ) ( ) ( <3>CTRL-REQ-PASSWORD-1:Password needed for SSID foobar ) ( > password 3 mysecretpassword ) ( ) ( > status ) ( bssid=e8:9f:80:d8:f4:04 ) ( freq=5180 ) ( ssid=_VelopSetup402 ) ( id=0 ) ( mode=station ) ( wifi_generation=5 ) ( pairwise_cipher=CCMP ) ( group_cipher=CCMP ) ( key_mgmt=WPA2-PSK ) ( wpa_state=COMPLETED ) ( ip_address=192.168.1.25 ) ( p2p_device_address=74:3a:f4:33:fc:7f ) ( address=74:3a:f4:33:fc:7f ) ( uuid=75819ed3-c224-5b27-92bf-d167dc1ebc85 ) ( ieee80211ac=1 ) |00 @System [ &vect $2 &expansion $2 &title $2 &metadata $2 &r $2 &g $2 &b $2 ] |10 @Console [ &vect $2 &stdin $1 &pad1 $4 &type $1 &stdout $1 &stderr $1 &proc-put $1 &pad2 $1 ¶m $2 &opts $1 &host-put $1 ] |20 @Screen [ &vect $2 &w $2 &h $2 &auto $1 &pad $1 &x $2 &y $2 &addr $2 &px $1 &sprite $1 ] |80 @Controller [ &vect $2 &button $1 &key $1 &fn $1 ] |90 @Mouse [ &vect $2 &x $2 &y $2 &state $1 &pad1 $1 &pad2 $2 &scrollx $2 &scrolly $2 &pad3 $2 ] |c0 @DateTime [ &year $2 &month $1 &day $1 &hour $1 &minute $1 &second $1 &dotw $1 &doty $2 &isdst $1 &pad $5 ] |0000 @ready $1 ( wpa_cli is ready to start ) @cur-x $2 ( mouse: current x position ) @cur-y $2 ( mouse: current y position ) @scan-year $2 ( last scan time: year ) @scan-month $1 ( last scan time: month ) @scan-day $1 ( last scan time: day of month ) @scan-hour $1 ( last scan time: hour ) @scan-minute $1 ( last scan time: minute ) @cur-ap $2 ( address of current wireless AP ) |0100 #17ef .System/r DEO2 #229e .System/g DEO2 #406e .System/b DEO2 ;on-screen .Screen/vect DEO2 ;on-console .Console/vect DEO2 ;on-mouse .Mouse/vect DEO2 ;on-controller .Controller/vect DEO2 ;on-stdin .Console/vect DEO2 ( FIXME ) save-scan-time ( 320x256 resolution ) #0140 .Screen/w DEO2 #0100 .Screen/h DEO2 draw-ui BRK @on-console ( -> BRK ) .Console/type DEI #01 EQU ?on-stdin BRK ( from literal stdin ) .Console/type DEI #20 EQU ?on-stdin BRK ( from child 0 ) BRK @on-stdin ( -> BRK ) .Console/stdin DEI #0a EQU ?on-newline .Console/stdin DEI save-char BRK @on-newline ( -> BRK ) #00 save-char ;buffer readln reset-buffer BRK @readln ( s* -> ) LIT "? .Console/stdout DEO minutes-since-scan LIT "0 ADD .Console/stdout DEO #0a .Console/stdout DEO save-scan-time LIT "< .Console/stdout DEO .Console/stdout !println @sendln ( s* -> ) LIT "> .Console/stdout DEO DUP2 .Console/stdout println .Console/proc-put !println @println ( s* d^ -> ) STH &loop LDAk ?{ POP2 #0a STHr DEO JMP2r } LDAk STHkr DEO INC2 !&loop @save-char ( c^ -> ) ;buffer/ptr LDA2 STA ;buffer/ptr LDA2k INC2 SWP2 STA2 JMP2r @reset-buffer ( -> ) ;buffer ;buffer/ptr STA2 JMP2r ( formula: ) ( ) ( if signal >= -40 then percentage = 100 ) ( if signal <= -100 then percentage = 0 ) ( else percentage = 166 + 5/3 * signal ) @parse-scan JMP2r @parse-scan-line ( -> ) ( bssid - first 17 bytes: "1a:85:f9:85:1f:5e" ) ( skip one tab: "\t" ) ( frequency: 1+ digits: "2412" ) ( skip 1+ spaces: " " ) ( signal: 1+ signed digit: "-76" ) ( skip 1+ spaces: " " ) ( read 1+ non-space bytes: "[WPA2-PSK-CCMP][WPS][ESS]" ) ( skip 1+ spaces: " " ) ( read until CRLF: "NZTW802" ) JMP2r @draw-space ( -> ) ;tiles/space #81 !draw-tile @draw-cursor ( tile* -> ) .Screen/addr DEO2 .cur-x LDZ2 .Screen/x DEO2 .cur-y LDZ2 .Screen/y DEO2 #c3 .Screen/sprite DEO JMP2r @draw-str ( s* attr^ -> ) STH &loop LDAk DUP ?{ POPr POP POP2 JMP2r } #00 SWP #40 SFT2 ;tiles ADD2 .Screen/addr DEO2 STHkr .Screen/sprite DEO INC2 !&loop @draw-ui ( -> ) draw-frame draw-ap draw-listings draw-scrollbar JMP2r @draw-frame ( -> ) #0000 #0000 goto ;tiles/nw ;tiles/ne draw-horiz #0008 #0002 draw-vert ;tiles/nes ;tiles/nsw draw-horiz #0020 #0008 draw-vert ;tiles/nes ;tiles/nsw draw-horiz #0068 #0001 draw-vert ;tiles/sw ;tiles/se draw-horiz JMP2r ( draw h tiles of vertical side bars, starting at y ) @draw-vert ( y* h* -> ) STH2 ( y* [h*] ) #02 .Screen/auto DEO ;tiles/vert load #0108 OVR2 goto STH2kr #81 draw-n #0000 SWP2 goto STH2r #81 draw-n JMP2r ( draw horizontal bar, tile w on left, e on right ) @draw-horiz ( w* e* -> ) STH2 #01 .Screen/auto DEO load #81 .Screen/sprite DEO ;tiles/horiz load #0020 #81 draw-n STH2r load #81 .Screen/sprite DEO ( draw currently connected ap, if any ) @draw-ap ( -> ) #0008 #0008 goto ;tiles/str3 ;tiles/lit-lock ;demo/Paradiso draw-listing #00e8 #0008 goto ;demo/percentage #82 draw-str #0008 #0010 goto ;demo/bssid #81 draw-str #00d8 #0010 goto ;demo/signal #81 draw-str JMP2r ( draw scan results, if any ) @draw-listings ( -> ) #01 .Screen/auto DEO #0008 #0020 goto ;tiles/str2 ;tiles/lit-lock ;demo/RadioX draw-listing #0008 #0028 goto ;tiles/str2 ;tiles/lit-lock ;demo/interzone draw-listing #0008 #0030 goto ;tiles/str1 ;tiles/dark-lock ;demo/bee_happy_ draw-listing #0008 #0038 goto ;tiles/str1 ;tiles/lit-lock ;demo/DuckHunt draw-listing #0008 #0040 goto ;tiles/str1 ;tiles/lit-lock ;demo/LINKSYS6672 draw-listing #0008 #0048 goto ;tiles/str0 ;tiles/space ;demo/Public draw-listing #0008 #0050 goto ;tiles/str0 ;tiles/space ;demo/Q-bert draw-listing #0008 #0058 goto ;tiles/str0 ;tiles/dark-lock ;demo/xyzzy draw-listing JMP2r ( draw individual scan listing ) @draw-listing ( str* lock* name* -> ) STH2 STH2 #81 draw-tile STH2r #81 draw-tile STH2r #82 !draw-str ( draw scrollbar, if necessary ) @draw-scrollbar ( -> ) #02 .Screen/auto DEO #0100 #0020 goto ;tiles/bar-top load #81 .Screen/sprite DEO ;tiles/bar-fg load #0004 #81 draw-n ;tiles/bar-bg load #0002 #81 draw-n ;tiles/bar-bot load #81 .Screen/sprite DEO JMP2r @constants &connected-to "Connected 20 "To: 00 &interactive-mode "Interactive 20 "mode 00 @demo &bssid "70:73:cb:b8:ce:b7 00 &frequency "2437 20 "Mhz 00 &signal "-53 20 "dB 00 &percentage 20 "86% 00 &Paradiso "Paradiso 00 &RadioX "RadioX 00 &interzone "interzone 00 &bee_happy_ "bee_happy_ 00 &DuckHunt "DuckHunt 00 &LINKSYS6672 "LINKSYS6672 00 &Public "Public 00 &Q-bert "Q-bert 00 &xyzzy "xyzzy 00 @load ( tile* -> ) .Screen/addr DEO2 JMP2r @goto ( x* y* -> ) .Screen/y DEO2 .Screen/x DEO2 JMP2r @draw-tile ( tile* attr^ -> ) STH .Screen/addr DEO2 STHr .Screen/sprite DEO JMP2r ( TODO: redraw parts of the screen ) @on-screen ( -> BRK ) BRK ( TODO: supports clicks and interaction ) @on-mouse ( -> BRK ) ;tiles/space draw-cursor .Mouse/x DEI2 .cur-x STZ2 .Mouse/y DEI2 .cur-y STZ2 ;tiles/cursor draw-cursor BRK ( TODO: keyboard input ) @on-controller ( -> BRK ) BRK @draw-n ( n* attr^ -> ) STH #0000 SWP2 SUB2 &loop STHkr .Screen/sprite DEO INC2 ORAk ?&loop POPr POP2 JMP2r @str-eq ( s* t* -> ok^ ) STH2 &l LDAk ?{ &d LDA LDAr STHr EQU JMP2r } LDAk LDAkr STHr NEQ ?&d INC2 INC2r !&l @read-bssid ( addr* -> addr+18* ) ;buffer LIT2r =networks/ptr LDA2r ( buf* [dst*] ) &do LDA2k hexdigit #40 SFT SWP hexdigit ORA ( buf* byte^ [dst*] ) STH2kr STA INC2 INC2 INC2r ( buf+2* [dst+1*] ; dst<-byte ) LDAk #20 EQU ?{ INC2 !&do } POP2 STH2r JMP2r ( buf+k* [dst+1*] ) ( last scan: "yyyy-mm-dd hh:mm" 16 chars ) @save-scan-time ( -> ) .DateTime/year DEI2 .scan-year STZ2 .DateTime/month DEI .scan-month STZ .DateTime/day DEI .scan-day STZ .DateTime/hour DEI .scan-hour STZ .DateTime/minute DEI .scan-minute STZ JMP2r ( lower bound on time since last scan; ignores hours/days/etc. ) @minutes-since-scan ( -> min^ ) .DateTime/minute DEI .scan-minute LDZ LTHk ?&wrap SUB JMP2r &wrap SUB #c4 SUB JMP2r @hexdigit ( c^ -> h^ ) LIT "0 SUB DUP #0a LTH ?{ #27 SUB } JMP2r ( > scan_results ) ( bssid / frequency / signal level / flags / ssid ) ( 70:73:cb:b8:ce:b7 2437 -60 [WPA2-PSK-CCMP][ESS] timecrimes ) ( dBm to percentage mapping ) ( see https://www.intuitibits.com/2016/03/23/dbm-to-percent-conversion/ ) @table 64 ( -0: 100% ) 64 64 64 64 64 64 64 64 64 64 ( -1 to -10 dBm: 100% ) 64 64 64 64 64 64 64 64 64 64 ( -11 to -20 dBm: 100% ) 63 63 63 62 62 62 61 61 60 60 ( -21 to -30 dBm: 99 to 96% ) 5f 5f 5e 5d 5d 5c 5b 5a 5a 59 ( -31 to -40 dBm: 95 to 89% ) 58 57 56 55 54 53 52 51 50 4f ( -41 to -50 dBm: 88 to 79% ) 4e 4c 4b 4a 49 47 46 45 43 42 ( -51 to -60 dBm: 78 to 66% ) 40 3f 3d 3c 3a 38 37 35 33 32 ( -61 to -70 dBm: 64 to 50% ) 30 2e 2c 2a 28 26 24 22 20 1e ( -71 to -80 dBm: 48 to 30% ) 1c 1a 18 16 14 11 0f 0d 0a 08 ( -81 to -90 dBm: 28 to 8% ) 06 03 01 01 01 01 01 01 01 01 ( -91 to -100 dBm: 6 to 1% ) @tiles ~tiles.tal ( buffer one line of input, until "\n"; up to 512 bytes ) @buffer [ $200 &ptr =buffer ] ( scan-line [43 bytes]: ) ( - bssid, 6 bytes ) ( - frequency, 2 bytes ) ( - signal, 1 signed byte ) ( - flags, 1 byte ) ( + 0x00 no encryption ) ( + 0x01 weaker: wep, wpa ) ( + 0x02 stronger: wpa2 ) ( + 0x03 other ) ( - ssid, 33 bytes ) ( store results, 43 bytes per entry; 11008 bytes means 256 entries ) ( @networks [ $2b00 &ptr =networks ] ) $2100 @networks 1122 3344 5566 ff 30 02 "RadioX $1b 3e42 9f11 6733 ee 35 02 "interzone $18 3e42 9f11 6733 ee 40 02 "bee_happy_ $17 3e42 9f11 6733 ee 33 02 "DuckHunt $19 3e42 9f11 6733 ee 45 02 "LINKSYS6672 $16 3e42 9f11 6733 ee 50 02 "Public $1b 3e42 9f11 6733 ee 55 02 "Q-bert $1b 3e42 9f11 6733 ee 70 02 "xyzzy $1c &ptr =networks ( FIXME )