Merge branch 'master' of ssh://fozzie/home/neale/projects/ctf

Conflicts:
	packages/00common/src/claim.cgi.c
	packages/mcp/bin/scoreboard
	packages/mcp/www/register.cgi
	packages/wopr/www/wopr/wopr.cgi
This commit is contained in:
Neale Pickett 2013-06-17 13:15:13 -06:00
commit 831170e95e
6 changed files with 1023 additions and 496 deletions

View File

@ -58,6 +58,7 @@ main(int argc, char *argv[])
/* Pull category name out of the token */ /* Pull category name out of the token */
for (q = category; *p && (*p != ':'); p += 1) { for (q = category; *p && (*p != ':'); p += 1) {
*p = tolower(*p);
*(q++) = *p; *(q++) = *p;
} }
*q = '\0'; *q = '\0';

8
packages/host/host.mk Normal file
View File

@ -0,0 +1,8 @@
HOST_PKGDIR = $(TARGET)/host
host-install:
mkdir -p $(HOST_PKGDIR)
cp packages/host/tokens.txt $(HOST_PKGDIR)
PACKAGES += host

500
packages/host/tokens.txt Normal file
View File

@ -0,0 +1,500 @@
host:100:xunis-kutyb-kokox
host:200:xolas-segap-tisax
host:300:xebep-vevuz-vycex
host:400:xuvas-codas-fovox
host:500:xuvig-pyteg-vunyx
host:600:xocap-cebuz-dupax
host:700:xizif-zyzut-lilix
host:800:xopeg-rabad-dirax
host:900:xozag-mufum-mubex
host:1000:xebib-lycak-zebux
host:100:xetad-ruhyt-mutux
host:200:xosin-hufer-zisyx
host:300:xirob-tazin-gomex
host:400:xolag-fefir-nanux
host:500:xitip-vanih-nyzax
host:600:xuzip-semub-mesux
host:700:xeten-cekuh-felax
host:800:xufir-meroz-rovix
host:900:xurav-sudav-padix
host:1000:xiher-kyvyd-dipix
host:100:xepep-lupyp-hofax
host:200:xuvol-cyfaf-ficex
host:300:xegam-kehes-hipux
host:400:xoris-rulyz-zybex
host:500:xelas-zogug-carix
host:600:xuhoz-sapag-zahex
host:700:xocoz-cumid-lulax
host:800:xesat-cydun-dofix
host:900:xugog-hareb-pysex
host:1000:xiken-civyz-sopex
host:100:xolah-loziv-serex
host:200:xogar-vasok-tydix
host:300:xihen-redyr-garex
host:400:xenat-fenas-migax
host:500:xored-zurif-synix
host:600:xehil-hivuv-kamux
host:700:xuhav-nihif-sucix
host:800:xeteg-sylyh-dolex
host:900:xuzel-matev-robyx
host:1000:xidaf-lilyk-mypex
host:100:xibek-pocec-cynyx
host:200:xoloh-delic-nuhex
host:300:xezib-gelor-micux
host:400:xocaz-civag-fyhax
host:500:xunab-gofoz-sysox
host:600:xemab-numul-devyx
host:700:xinar-nufub-vufix
host:800:xumek-revid-safax
host:900:xukel-sesuz-dekox
host:1000:xicaf-sesaz-vivax
host:100:xidap-nalem-vacix
host:200:xekak-lozac-bikox
host:300:xenas-pygaf-bidux
host:400:xuneg-donuk-tobex
host:500:xubar-benof-micox
host:600:xebic-cipov-pyzex
host:700:xulac-kuhak-hymux
host:800:xodil-nihop-disex
host:900:xemas-libic-basux
host:1000:xolaf-zuzuv-rafex
host:100:xilif-peked-nigox
host:200:xopil-lepub-lafax
host:300:xuhak-begat-nevex
host:400:xunal-sazan-sudax
host:500:xokic-kitys-talix
host:600:xopev-fehos-ginax
host:700:xihin-nanih-sivox
host:800:xupab-holoc-polyx
host:900:xogaf-sycyr-kylax
host:1000:xilez-masah-cefex
host:100:xofop-fafor-polyx
host:200:xefag-fisin-zezox
host:300:xefip-rugyh-leryx
host:400:xeveh-kulyk-cafax
host:500:xisop-rutug-sabyx
host:600:xodog-zuvon-velyx
host:700:xiral-dased-cocix
host:800:xupin-lipeg-ticix
host:900:xubog-gumyt-hirix
host:1000:xudot-tasap-geryx
host:100:xulob-vugik-fylax
host:200:xocig-kyhez-cevux
host:300:xibep-lupot-licox
host:400:xesol-tuzol-kysex
host:500:xidet-mobuv-gudyx
host:600:xifec-nasak-helex
host:700:xehis-tycar-mimix
host:800:xosir-gabyn-ruryx
host:900:xorim-cynaf-cunex
host:1000:xodic-casor-sifex
host:100:xubik-cucyg-tyrix
host:200:xemok-dicam-barax
host:300:xedih-cemum-masyx
host:400:xuviv-pyzod-vefix
host:500:xumon-nosar-ranax
host:600:xegem-hyvev-lumux
host:700:xivog-dygid-horox
host:800:xulac-bugym-zakyx
host:900:xikav-rusym-fisax
host:1000:xebon-gohyf-ribix
host:100:xenar-volyb-zidox
host:200:ximab-vobic-nysex
host:300:xusib-vokat-pulex
host:400:xomef-dahid-gymox
host:500:xugiv-lypop-rocex
host:600:xuhek-rikyd-kuhox
host:700:xemaz-gilak-nubux
host:800:xirip-gopez-zakox
host:900:xigel-fubov-mocix
host:1000:xosar-mirun-cefux
host:100:xupov-dyfef-gybex
host:200:xorih-bodog-mizax
host:300:xudif-dizup-tebix
host:400:ximal-mykam-nonex
host:500:xoget-fuvek-fumex
host:600:xefak-bitoh-vebyx
host:700:xohin-gysip-gocix
host:800:xomav-banon-hefax
host:900:xuvez-fiveb-kyrex
host:1000:xereg-monit-tyfax
host:100:xonip-cykyz-ruzux
host:200:xotok-paget-kytex
host:300:xikal-tigyd-vedix
host:400:xepof-zafet-hemax
host:500:xefet-cagoh-lupux
host:600:xeteh-nyvem-babux
host:700:xedit-sezup-tumox
host:800:xuhet-tuhyn-polix
host:900:xonib-tyfan-lagix
host:1000:xurip-gapyd-dusex
host:100:xenac-vasaz-vipix
host:200:xuhap-focyp-zilax
host:300:xoboc-dacof-lisix
host:400:xuvov-nuzyb-dolix
host:500:xidip-fover-papix
host:600:xodol-katyz-nilyx
host:700:xusev-subyd-vecux
host:800:xohor-tobuc-zunyx
host:900:xecir-lofub-hurux
host:1000:xesid-tyzim-nusix
host:100:xedab-sepog-sybax
host:200:xudic-pitol-sazox
host:300:xolop-rylah-zebyx
host:400:xobot-ruveh-nygex
host:500:xomeb-pomuf-barox
host:600:xizih-mulov-rylyx
host:700:xifet-lupiv-zanex
host:800:xutev-koser-rumyx
host:900:xocir-bakim-zanax
host:1000:xivas-nofic-decax
host:100:xuras-pelah-gehyx
host:200:xemec-hezol-vacux
host:300:xenal-vygub-higox
host:400:xilif-pevop-calix
host:500:xuzik-ramor-rypax
host:600:xurol-famez-limox
host:700:xegip-salyp-dekex
host:800:xetof-repid-zarux
host:900:xozec-natag-kygix
host:1000:xepih-dycum-herix
host:100:ximer-byzah-sezox
host:200:xocez-vygit-zipix
host:300:xozod-zafol-nazax
host:400:xovib-zoled-podix
host:500:xudid-degyc-cegex
host:600:xolec-gigod-mynux
host:700:xirom-kezyn-cevex
host:800:xenoh-likeg-cimyx
host:900:xokeg-boduh-gubox
host:1000:xetem-sapiz-rogyx
host:100:xudez-suvol-pikax
host:200:xuveh-hykap-mamax
host:300:xoraf-sofif-malox
host:400:xikit-tenys-telex
host:500:xupev-zoker-cipox
host:600:xutib-cepov-sifox
host:700:xonos-vagib-gyfyx
host:800:xolis-mopys-rahex
host:900:xodik-pycis-nudux
host:1000:xuhol-tabob-bezux
host:100:xizen-gylad-kegux
host:200:xoziv-pubad-gelyx
host:300:xesad-zycal-gusex
host:400:xonip-mofic-godyx
host:500:xinib-repek-gabox
host:600:xekic-micat-ketux
host:700:xumoc-cabyf-byvyx
host:800:xozal-cokyg-telix
host:900:xobos-mafov-zosox
host:1000:xoset-gedog-rinux
host:100:xosef-lagor-gekox
host:200:xukik-netok-narex
host:300:xepal-pidug-zinix
host:400:xorar-katuc-hufax
host:500:xipim-rynog-huvyx
host:600:xufob-busis-lobyx
host:700:xusol-cilud-gupux
host:800:xipif-ginif-malix
host:900:xociz-gyfet-cyzix
host:1000:xobas-vozap-rizax
host:100:xesob-lulet-rypex
host:200:xoloc-dusof-tonex
host:300:xomis-zypuz-bycox
host:400:xugal-kibif-gafax
host:500:xizif-vuvur-nuzyx
host:600:xozob-legug-lyhyx
host:700:xomor-fedad-zovix
host:800:xuziz-vytyr-sifux
host:900:xemap-ciman-mumax
host:1000:xeter-hecuz-sucux
host:100:xonos-kahak-hypax
host:200:xogav-dukym-dylux
host:300:xinen-lenab-syfox
host:400:xidos-nekuh-davyx
host:500:xuveb-cofot-lovox
host:600:xuciz-cedyp-pigex
host:700:xutel-tugof-zyfyx
host:800:xirik-seguc-fykux
host:900:xumod-zador-gelux
host:1000:xodom-vylah-kovex
host:100:xogab-hamed-sugux
host:200:xufof-sygib-davux
host:300:ximom-hyhez-ficax
host:400:xezaz-gukop-gytox
host:500:xomog-pyfik-vanax
host:600:ximog-repud-selox
host:700:xidov-meheh-zakax
host:800:xupic-lagus-kybux
host:900:xocof-zacop-ruhix
host:1000:xutap-dyleh-fufox
host:100:xuhef-bivad-sazux
host:200:xudop-cykic-lapix
host:300:xovit-gizeb-cuhix
host:400:xedor-cules-safox
host:500:xokel-zodyp-vycix
host:600:xufek-zyzem-birex
host:700:xemil-kosaz-negex
host:800:xosat-cohus-pomux
host:900:xotip-losof-vykux
host:1000:xukon-hoked-difix
host:100:xicac-hypib-zazex
host:200:ximob-gotoz-bydyx
host:300:xilah-lavof-gyhyx
host:400:xumab-liles-momyx
host:500:xenep-zofop-dafix
host:600:xogem-dumid-tamax
host:700:xodev-togyb-zinax
host:800:xobem-mivor-kusix
host:900:xulim-mupem-fytox
host:1000:xugav-tezup-hymex
host:100:xolid-pudev-dikux
host:200:xinih-gegit-fomyx
host:300:ximoh-talif-dunax
host:400:xokoc-vezos-fuhax
host:500:xenih-nesog-kahux
host:600:xidom-megym-milix
host:700:xonam-folah-gepyx
host:800:xikak-cafac-konyx
host:900:xolep-valuf-kamax
host:1000:xitap-megit-bekax
host:100:xofab-lytac-kafux
host:200:xitec-focon-kokox
host:300:xezeb-kazun-bohox
host:400:xukod-basys-bezox
host:500:xefoc-luryb-dalyx
host:600:xinoz-fybad-lahux
host:700:xugos-gedor-mokox
host:800:xusib-fydup-busox
host:900:xovat-pibam-guzix
host:1000:xiver-giteg-pygex
host:100:xudel-mifol-zikox
host:200:xefem-dykub-danex
host:300:xirov-lyfip-vadex
host:400:xomit-matug-papix
host:500:xekit-denot-nylex
host:600:xitas-rozuf-rikax
host:700:xefov-samyt-lilux
host:800:xobek-gidip-gylux
host:900:xolep-venyv-gabax
host:1000:ximon-rirer-syvux
host:100:xizon-kanod-hycyx
host:200:xocir-mekin-kubyx
host:300:xiveb-banev-hufox
host:400:xurag-fimas-mahox
host:500:xilet-mudol-lyvox
host:600:xefil-vivik-gytix
host:700:xizib-funyz-bepyx
host:800:xepec-fapyn-pypix
host:900:xipih-gynep-libex
host:1000:ximib-vakuk-gizax
host:100:xipov-garus-fehax
host:200:xucep-hukic-fuhex
host:300:xipot-kygel-vyzax
host:400:xomac-liket-domix
host:500:xetas-nalag-vatix
host:600:xelos-sehaz-vupyx
host:700:xuled-gylef-folex
host:800:xupol-niren-sahex
host:900:xotiv-lynek-gapox
host:1000:xuter-tobin-dabix
host:100:ximid-foder-mibex
host:200:xokon-carog-kotex
host:300:xifaz-kygan-devox
host:400:xubib-lusem-tulyx
host:500:xumig-vumur-cagyx
host:600:xibat-socet-kadex
host:700:xeciv-gekod-tovax
host:800:xifar-bygyl-tagex
host:900:xovas-vecak-tigix
host:1000:xusat-tenan-bynix
host:100:xufad-cucyn-serax
host:200:xosiv-pukul-sulux
host:300:xodif-gyzis-hupex
host:400:xudad-nalod-nahex
host:500:xizep-cutih-zumyx
host:600:xisag-palyz-zehax
host:700:xedar-nobam-rocyx
host:800:xigeh-pomon-zucux
host:900:xesaf-vunuc-cocyx
host:1000:xired-varor-honox
host:100:xibed-curuc-mokax
host:200:xerah-gurez-dupix
host:300:xegor-fyraf-cizux
host:400:xidav-bedob-kuhyx
host:500:xicem-cydis-mufix
host:600:xulac-vofuh-sytyx
host:700:xovir-cociv-rudox
host:800:xehos-dapif-vurax
host:900:xigod-rizyk-kebax
host:1000:xonon-zoboh-farax
host:100:xobas-gidyt-burox
host:200:xotap-vibyd-fefix
host:300:xoviz-nivit-kymox
host:400:xelaz-lamiv-rurix
host:500:xezig-lazer-hefyx
host:600:xelor-bogeh-nocux
host:700:xulof-saref-gehix
host:800:xeneh-degub-tynax
host:900:xogof-sisib-tyhyx
host:1000:xubol-pynyp-hodax
host:100:xelir-likep-gulex
host:200:xiboh-kodab-nykax
host:300:xodat-tyhas-mysyx
host:400:xevis-surac-dybex
host:500:xugom-tutih-suhix
host:600:xomit-vyvyl-bypex
host:700:xozaz-vydyk-cacax
host:800:xulih-pizes-kemax
host:900:xetop-timad-ladyx
host:1000:xerar-cafad-fipex
host:100:xezer-tuvon-rabox
host:200:xicab-torut-zesux
host:300:xizar-zonob-cazix
host:400:xezes-sifub-rubax
host:500:xezit-digep-vilax
host:600:xuhad-popun-muhux
host:700:xotos-darer-vyrix
host:800:xepic-bykev-kadox
host:900:xodoh-zamul-migax
host:1000:xoviv-pefyp-febyx
host:100:xohil-zifec-sydyx
host:200:xizid-zegis-vyvux
host:300:xupit-nihyb-mevax
host:400:xoboz-velen-guzax
host:500:xomah-ponyf-puhyx
host:600:xiril-hysan-retix
host:700:xirep-cevyr-tonex
host:800:xihab-racez-lihex
host:900:xudis-fazib-zolax
host:1000:xureb-nemoh-kivox
host:100:xocon-daniv-hysix
host:200:xitel-likip-kibyx
host:300:xetik-nokyb-tasox
host:400:xepoz-gasoz-mypax
host:500:xotet-dedos-sorix
host:600:xelez-hynum-nesux
host:700:xiron-dyhef-mohix
host:800:xunib-marig-kycox
host:900:xedav-dybel-danox
host:1000:xideb-nolub-gocux
host:100:xefon-rogoh-kizux
host:200:xuzel-pofyp-sotix
host:300:xihoh-mamyr-luzex
host:400:xobel-rapof-kymax
host:500:xehaz-lysez-zyvux
host:600:xuhos-tilac-cesax
host:700:xetin-fofap-cuzox
host:800:xitih-gyhyv-docex
host:900:xikal-kitop-zygox
host:1000:xezot-fycuv-zakex
host:100:xizas-basoc-kinux
host:200:xodos-gyluv-dudyx
host:300:xilib-dyryb-cukyx
host:400:xucev-nypif-zamox
host:500:ximiz-susec-gobex
host:600:xokic-febac-tasex
host:700:xuzis-kofih-zulyx
host:800:xekek-gygyf-nonox
host:900:xebof-huvof-syvix
host:1000:xufiv-syhas-bytex
host:100:xelap-sihic-kavex
host:200:xubah-pycec-nucax
host:300:xerik-vamos-tenax
host:400:xegon-kozos-barix
host:500:xihoz-nafeh-cynix
host:600:xokoc-fizyd-vinax
host:700:xemiz-batyk-vesix
host:800:xoren-tytop-dobex
host:900:xuzav-tufuz-kovax
host:1000:xizot-taven-rukix
host:100:xubis-bemur-kocyx
host:200:xizor-sizes-nigax
host:300:xicof-tyvud-cisox
host:400:xisof-vylip-sogyx
host:500:xevop-geris-fukyx
host:600:xezef-cufor-lohux
host:700:xinod-rofig-tesux
host:800:xokiv-zofep-sofux
host:900:xopal-bofet-nidix
host:1000:xizen-byvyn-zymyx
host:100:xutob-mopiz-cesyx
host:200:xilis-pifir-bovox
host:300:xufoc-cuvyv-rupax
host:400:xirif-nepef-silox
host:500:xetoz-doduh-nedyx
host:600:xefoh-pufod-tytux
host:700:xelit-pupik-gylux
host:800:xosad-nedol-mecax
host:900:xinit-hytan-ledux
host:1000:xizom-dymus-zisox
host:100:xopap-pumat-cugyx
host:200:xibed-kozid-bihox
host:300:xizos-lefyf-sypux
host:400:xinib-ratib-runix
host:500:xonev-tymeg-lihyx
host:600:xeham-zasig-mozux
host:700:xumoh-nahyz-begix
host:800:xufar-kohym-bykyx
host:900:xinil-humel-dutux
host:1000:xefeg-decur-kazyx
host:100:xupen-nebel-cecox
host:200:xudav-cuvuh-mavex
host:300:xohan-facel-putox
host:400:xurom-tomug-bulax
host:500:xicah-mycet-totax
host:600:xucag-fytal-hopux
host:700:xudek-nahet-bomex
host:800:xubas-fogam-nelix
host:900:xevem-dadeg-revux
host:1000:xocac-namuc-locux
host:100:xezov-gybez-bosox
host:200:xihev-cagaf-gakyx
host:300:xopor-cyhul-guvux
host:400:xuzem-cunaz-zydix
host:500:xogin-bilad-gulix
host:600:xigab-buzed-sytix
host:700:xuvon-zorys-fapix
host:800:xusof-bygap-nymax
host:900:xokic-bimyg-dutux
host:1000:xinez-hynyh-tegex
host:100:xumec-culor-racix
host:200:xobis-rogoc-sihux
host:300:xideg-sanud-denox
host:400:xerig-vytut-zutox
host:500:xicad-dykom-vimax
host:600:xedad-perig-fycux
host:700:xotig-dotil-vevox
host:800:xetim-tyhoc-fidox
host:900:xuzip-bymyb-vehix
host:1000:xohil-kuhuc-comyx
host:100:xocat-cuhaz-suhyx
host:200:xunas-tazuh-rytyx
host:300:xucab-melih-ginix
host:400:xicig-sumik-lynox
host:500:xikag-dosed-muvix
host:600:xifab-hytim-sagix
host:700:xobor-hypor-suhox
host:800:xosos-hysor-tapux
host:900:xotih-nahis-sutex
host:1000:xocas-voboc-bevyx
host:100:xunod-mopol-sugex
host:200:xosan-sipuh-dizyx
host:300:xirak-cesad-kuzox
host:400:xudin-nocem-minux
host:500:xolen-zogim-fyhux
host:600:xipot-pazaz-vurux
host:700:xesad-tudah-kopix
host:800:xomam-simis-gutex
host:900:xevos-hoteh-pymox
host:1000:xodab-hofak-celyx
host:100:xuboh-kegim-kubyx
host:200:xolad-zekam-puzex
host:300:xudiv-bigyh-subax
host:400:xemek-kupiv-tibix
host:500:xufoc-lumil-namix
host:600:xegef-hynyf-novox
host:700:xetev-vokig-covux
host:800:xisic-gicev-pozyx
host:900:xofag-fysum-rivex
host:1000:xesok-kofyc-fyhax

View File

@ -8,152 +8,150 @@
## ##
function qsort(A, left, right, i, last) { function qsort(A, left, right, i, last) {
if (left >= right) if (left >= right)
return return
swap(A, left, left+int((right-left+1)*rand())) swap(A, left, left+int((right-left+1)*rand()))
last = left last = left
for (i = left+1; i <= right; i++) for (i = left+1; i <= right; i++)
if (A[i] < A[left]) if (A[i] < A[left])
swap(A, ++last, i) swap(A, ++last, i)
swap(A, left, last) swap(A, left, last)
qsort(A, left, last-1) qsort(A, left, last-1)
qsort(A, last+1, right) qsort(A, last+1, right)
} }
function swap(A, i, j, t) { function swap(A, i, j, t) {
t = A[i]; A[i] = A[j]; A[j] = t t = A[i]; A[i] = A[j]; A[j] = t
} }
function escape(s) { function escape(s) {
gsub("&", "&amp;", s) gsub("&", "&amp;", s)
gsub("<", "&lt;", s) gsub("<", "&lt;", s)
gsub(">", "&gt;", s) gsub(">", "&gt;", s)
return s return s
} }
function head() { function head() {
print "<!DOCTYPE html>" print "<!DOCTYPE html>"
print "<html><head><title>Project 2 Scoreboard</title>" print "<html><head><title>Project 2 Scoreboard</title>"
print "<meta http-equiv=\"refresh\" content=\"60\">" print "<meta http-equiv=\"refresh\" content=\"60\">"
print "<link rel=\"stylesheet\" href=\"ctf.css\" type=\"text/css\">" print "<link rel=\"stylesheet\" href=\"ctf.css\" type=\"text/css\">"
print "<style>" print "<style>"
print "body {opacity: 0.9; margin: 0; padding: 0; max-width: inherit;}" print "body {opacity: 0.9; margin: 0; padding: 0; max-width: inherit;}"
print "p {margin: 0; padding:0; line-height: inherit;}" print "p {margin: 0; padding:0; line-height: inherit;}"
print "span {display: inline-block; margin: 0; border: 0; padding: 0;}" print "span {display: inline-block; margin: 0; border: 0; padding: 0;}"
print ".cat0 {background-color: #a6cee3; color: black;}" print ".cat0 {background-color: #a6cee3; color: black;}"
print ".cat1 {background-color: #1f78b4;}" print ".cat1 {background-color: #1f78b4;}"
print ".cat2 {background-color: #b2df8a; color: black;}" print ".cat2 {background-color: #b2df8a; color: black;}"
print ".cat3 {background-color: #33a02c;}" print ".cat3 {background-color: #33a02c;}"
print ".cat4 {background-color: #fb9a99;}" print ".cat4 {background-color: #fb9a99;}"
print ".cat5 {background-color: #e31a1c;}" print ".cat5 {background-color: #e31a1c;}"
print ".cat6 {background-color: #fdbf6f;}" print ".cat6 {background-color: #fdbf6f;}"
print ".cat7 {background-color: #ff7f00;}" print ".cat7 {background-color: #ff7f00;}"
print ".cat8 {background-color: #cab2d6;}" print ".cat8 {background-color: #cab2d6; color: black;}"
print ".name {position: absolute; right: 10px;}" print ".name {position: absolute; right: 10px;}"
print "#scores p {margin: 0; padding: 0; border: thin solid #222; opacity: 0.92;}" print "#scores p {margin: 0; padding: 0; border: thin solid #222; opacity: 0.92;}"
print "#scores p:hover {border: thin solid yellow;}" print "#scores p:hover {border: thin solid yellow;}"
print "</style>" print "</style>"
print "</head><body>" print "</head><body>"
print "<div id=\"scores\">" print "<div id=\"scores\">"
} }
function foot() { function foot() {
print " </div>" print " </div>"
print " </body>" print " </body>"
print "</body></html>" print "</body></html>"
} }
BEGIN { BEGIN {
base = ENVIRON["CTF_BASE"] base = ENVIRON["CTF_BASE"]
if (! base) { if (! base) {
base = "/var/lib/ctf" base = "/var/lib/ctf"
} }
head() head()
} }
# MAINLOOP # MAINLOOP
{ {
time = $1 time = $1
hash = $2 hash = $2
cat = $3 cat = $3
points = int($4) points = int($4)
# Build a list of team names # Build a list of team names
if (! (hash in team_names)) { if (! (hash in team_names)) {
fn = sprintf("%s/teams/names/%s", base, hash) fn = sprintf("%s/state/teams/names/%s", base, hash)
getline team_names[hash] < fn getline team_names[hash] < fn
close(fn) close(fn)
} }
# Total points possible so far in this category # Enumerate categories
if (! ((cat, points) in cat_pointval)) { if (! (cat in seen_cats)) {
cat_total[cat] += points seen_cats[cat] = 1
cat_pointval[cat, points] = 1 categories[ncats++] = cat
} }
# Enumerate categories # Points this team has in this category
if (! (cat in seen_cats)) { cat_points[hash, cat] += points
seen_cats[cat] = 1
categories[ncats++] = cat
}
# Points this team has in this category # Token-based categories can make cat_pointval irrelevant
cat_points[hash, cat] += points if (cat_points[hash, cat] > cat_total[cat]) {
cat_total[cat] = cat_points[hash, cat]
}
} }
END { END {
# Adjust per-category points to a per-category percentage complete # Adjust per-category points to a per-category percentage complete
for (hash in team_names) { for (hash in team_names) {
for (cat in cat_total) { for (cat in cat_total) {
cat_score[hash, cat] = cat_points[hash, cat] / cat_total[cat] cat_score[hash, cat] = cat_points[hash, cat] / cat_total[cat]
total_score[hash] += cat_score[hash, cat] total_score[hash] += cat_score[hash, cat]
} }
scores[nteams++] = total_score[hash] scores[nteams++] = total_score[hash]
if (total_score[hash] > max_score) { if (total_score[hash] > max_score) {
max_score = total_score[hash] max_score = total_score[hash]
} }
} }
# Sort scores # Sort scores
qsort(scores, 0, nteams-1) qsort(scores, 0, nteams-1)
print "<p>" print "<p>"
for (ncat = 0; ncat < ncats; ncat += 1) { for (ncat = 0; ncat < ncats; ncat += 1) {
printf("<span class=\"cat%d\">%s</span>\n", ncat, categories[ncat]); printf("<span class=\"cat%d\">%s</span>\n", ncat, categories[ncat]);
} }
print "</p>" print "</p>"
for (i = nteams-1; i >= 0; i -= 1) { for (i = nteams-1; i >= 0; i -= 1) {
score = scores[i]; score = scores[i];
if (score == scores[i-1]) continue; # Skip duplicates if (score == scores[i-1]) continue; # Skip duplicates
for (hash in team_names) { for (hash in team_names) {
if (total_score[hash] != score) { if (total_score[hash] != score) {
continue; continue;
} }
name = escape(team_names[hash]) name = escape(team_names[hash])
print "<p>" print "<p>"
printf("<span class=\"name\">%s</span>\n", name) printf("<span class=\"name\">%s</span>\n", name)
for (ncat = 0; ncat < ncats; ncat += 1) { for (ncat = 0; ncat < ncats; ncat += 1) {
cat = categories[ncat]; cat = categories[ncat];
points = cat_points[hash, cat]; points = cat_points[hash, cat];
if (cat_points[hash, cat] > 0) { if (cat_points[hash, cat] > 0) {
width = cat_score[hash, cat] / max_score * 90 width = cat_score[hash, cat] / max_score * 90
printf("<!-- %s %s %s -->", cat, points, name) printf("<!-- %s %s %s -->", cat, points, name)
printf("<span class=\"cat%d\" style=\"width: %.2f%%;\">%d</span>", printf("<span class=\"cat%d\" style=\"width: %.2f%%;\">%d</span>",
ncat, width, cat_points[hash, cat]) ncat, width, cat_points[hash, cat])
} }
} }
print "</p>" print "</p>"
} }
} }
foot() foot()
} }

View File

@ -1,8 +1,25 @@
#! /bin/sh -e #! /bin/sh -e
# Change to CTF_BASE
cd ${CTF_BASE:-.}
for i in $(seq 5); do
[ -d packages ] && break
cd ..
done
if ! [ -d packages ]; then
cat <<EOF
Content-type: text/html
Cannot find CTF_BASE
EOF
exit 1
fi
# Read CGI parameters
param () { param () {
ret=$(echo "$QUERY_STRING" | tr '=&' ' \n' | awk -v "k=$1" '($1==k) {print $2;}') ret=$(echo "$QUERY_STRING" | tr '=&' ' \n' | awk -v "k=$1" '($1==k) {print $2;}')
ret=$(busybox httpd -d "$ret" || echo "$ret") ret=$(busybox httpd -d "$ret" || echo "$ret")
echo "$ret"
} }
team=$(param n) team=$(param n)
@ -21,13 +38,15 @@ Content-type: text/html
<h1>Team Registration</h1> <h1>Team Registration</h1>
EOF EOF
if ! grep -q $h $CTF_BASE/state/teams/assigned.txt; then if [ -z "$hash" ] || [ -z "$team" ]; then
echo "<p>That token has not been assigned.</p>" echo "<p>Empty field, cannot complete request</p>"
elif [ -f $CTF_BASE/state/teams/names/$h ]; then elif ! grep -q " $hash$" $CTF_BASE/state/teams/assigned.txt; then
echo "<p>That token has already been named.</p>" echo "<p>That hash has not been assigned.</p>"
elif [ -f $CTF_BASE/state/teams/names/$hash ]; then
echo "<p>That hash has already been registered.</p>"
else else
printf "%s" "$t" > $CTF_BASE/state/teams/names/$h printf "%s" "$team" > $CTF_BASE/state/teams/names/$hash
echo "<p>Okay, your team has been named and you may begin using your token!</p>" echo "<p>Okay, your team has been named and you may begin using your hash!</p>"
fi fi
cat <<EOF cat <<EOF

View File

@ -6,81 +6,81 @@ POST_MAX = 512
method = os.getenv("REQUEST_METHOD") method = os.getenv("REQUEST_METHOD")
if (method == "POST") then if (method == "POST") then
local CL = tonumber(os.getenv("CONTENT_LENGTH")) or 0 local CL = tonumber(os.getenv("CONTENT_LENGTH")) or 0
if (CL > POST_MAX) then if (CL > POST_MAX) then
CL = POST_MAX CL = POST_MAX
end end
function getc() function getc()
if (CL > 0) then if (CL > 0) then
CL = CL - 1 CL = CL - 1
return io.read(1) return io.read(1)
else else
return nil return nil
end end
end end
elseif (method == "GET") then elseif (method == "GET") then
local query = os.getenv("QUERY_STRING") or "" local query = os.getenv("QUERY_STRING") or ""
local query_pos = 0 local query_pos = 0
local query_len = string.len(query) local query_len = string.len(query)
if (query_len > POST_MAX) then if (query_len > POST_MAX) then
query_len = POST_MAX query_len = POST_MAX
end end
function getc() function getc()
if (query_pos < query_len) then if (query_pos < query_len) then
query_pos = query_pos + 1 query_pos = query_pos + 1
return string.sub(query, query_pos, query_pos) return string.sub(query, query_pos, query_pos)
else else
return nil return nil
end end
end end
else else
print("405 Method not allowed") print("405 Method not allowed")
print("Allow: GET POST") print("Allow: GET POST")
print("Content-Type: text/plain") print("Content-Type: text/plain")
print() print()
print("I only do GET and POST.") print("I only do GET and POST.")
os.exit(0) os.exit(0)
end end
function read_hex() function read_hex()
local a = getc() or 0 local a = getc() or 0
local b = getc() or 0 local b = getc() or 0
return string.char(tonumber(a, 16)*16 + tonumber(b, 16)) return string.char(tonumber(a, 16)*16 + tonumber(b, 16))
end end
function cgi_item() function cgi_item()
local val = "" local val = ""
while (true) do while (true) do
local c = getc() local c = getc()
if ((c == nil) or (c == "=") or (c == "&")) then if ((c == nil) or (c == "=") or (c == "&")) then
return val return val
elseif (c == "%") then elseif (c == "%") then
c = read_hex() c = read_hex()
elseif (c == "+") then elseif (c == "+") then
c = " " c = " "
end end
val = val .. c val = val .. c
end end
end end
function escape(s) function escape(s)
s = string.gsub(s, "&", "&amp;") s = string.gsub(s, "&", "&amp;")
s = string.gsub(s, "<", "&lt;") s = string.gsub(s, "<", "&lt;")
s = string.gsub(s, ">", "&gt;") s = string.gsub(s, ">", "&gt;")
return s return s
end end
f = {} f = {}
while (true) do while (true) do
local key = cgi_item() local key = cgi_item()
local val = cgi_item() local val = cgi_item()
if (key == "") then if (key == "") then
break break
end end
f[key] = val f[key] = val
end end
@ -88,35 +88,35 @@ end
-- lua doesn't seed its PRNG and provides nothing other than -- lua doesn't seed its PRNG and provides nothing other than
-- time in seconds. If you're on Windows, go fish. -- time in seconds. If you're on Windows, go fish.
do do
local seed = 0 local seed = 0
r = io.open("/dev/urandom") or io.open("/dev/random") r = io.open("/dev/urandom") or io.open("/dev/random")
for i = 1, 4 do for i = 1, 4 do
seed = seed*256 + string.byte(r:read(1)) seed = seed*256 + string.byte(r:read(1))
end end
io.close(r) io.close(r)
math.randomseed(seed) math.randomseed(seed)
end end
-- Get or create Session ID -- Get or create Session ID
sid = f["s"] or "" sid = f["s"] or ""
if (sid == "") then if (sid == "") then
sid = string.format("%08x.%04x", os.time(), math.random(65535)) sid = string.format("%08x.%04x", os.time(), math.random(65535))
end end
dirname = BASEDIR .. "/" .. sid dirname = BASEDIR .. "/" .. sid
-- Send back a page -- Send back a page
function reply(text, prompt, ...) function reply(text, prompt, ...)
print("Content-type: text/xml") print("Content-type: text/xml")
print() print()
print("<document>") print("<document>")
print(" <sessionid>" .. sid .. "</sessionid>") print(" <sessionid>" .. sid .. "</sessionid>")
print(" <response>" .. escape(text or "") .. "</response>") print(" <response>" .. escape(text or "") .. "</response>")
print(" <prompt>" .. escape(prompt or ">") .. "</prompt>") print(" <prompt>" .. escape(prompt or ">") .. "</prompt>")
if (arg[1]) then if (arg[1]) then
print(" <error>" .. escape(arg[1]) .. "</error>") print(" <error>" .. escape(arg[1]) .. "</error>")
end end
print("</document>") print("</document>")
os.exit(0) os.exit(0)
end end
@ -127,32 +127,32 @@ end
-- --
function get(key, ...) function get(key, ...)
local fn = string.format("%s.%s", dirname, key) local fn = string.format("%s.%s", dirname, key)
local f = io.open(fn) local f = io.open(fn)
if (not f) then if (not f) then
return arg[1] return arg[1]
else else
local ret = f:read(4000) or "" local ret = f:read(4000) or ""
f:close() f:close()
return ret return ret
end end
end end
function set(key, ...) function set(key, ...)
local fn = string.format("%s.%s", dirname, key) local fn = string.format("%s.%s", dirname, key)
local f local f
f = io.open(fn, "w") f = io.open(fn, "w")
if not f then if not f then
error("Unable to write " .. fn) error("Unable to write " .. fn)
end end
f:write(arg[1] or "") f:write(arg[1] or "")
f:close() f:close()
end end
function del(key) function del(key)
local fn = string.format("%s.%s", dirname, key) local fn = string.format("%s.%s", dirname, key)
os.remove(fn) os.remove(fn)
end end
@ -160,21 +160,21 @@ end
-- A string splitter -- A string splitter
-- --
function string:split(...) function string:split(...)
local sep = arg[1] or " " local sep = arg[1] or " "
local ret = {} local ret = {}
local start = 1 local start = 1
while true do while true do
local first, last = self:find(sep, start) local first, last = self:find(sep, start)
if not first then if not first then
break break
end end
table.insert(ret, self:sub(start, first - 1)) table.insert(ret, self:sub(start, first - 1))
start = last + 1 start = last + 1
end end
table.insert(ret, self:sub(start)) table.insert(ret, self:sub(start))
return ret return ret
end end
@ -190,124 +190,124 @@ hosts_by_name = {}
Host = {} Host = {}
function Host:new(name, ...) function Host:new(name, ...)
local o = {} local o = {}
setmetatable(o, self) setmetatable(o, self)
self.__index = self self.__index = self
o.name = name o.name = name
o.prompt = (arg[1] or ">") o.prompt = (arg[1] or ">")
o.obuf = {} o.obuf = {}
o.history = {} o.history = {}
hosts_by_name[name] = o hosts_by_name[name] = o
return o return o
end end
function Host:add_commands(t) function Host:add_commands(t)
local cmds = {} local cmds = {}
local k, v local k, v
for k,v in pairs(self.commands) do for k,v in pairs(self.commands) do
cmds[k] = v cmds[k] = v
end end
for k,v in pairs(t) do for k,v in pairs(t) do
cmds[k] = v cmds[k] = v
end end
self.commands = cmds self.commands = cmds
end end
function Host:get(key, ...) function Host:get(key, ...)
return get(self.name .. "." .. key, arg[1]) return get(self.name .. "." .. key, arg[1])
end end
function Host:set(key, ...) function Host:set(key, ...)
return set(self.name .. "." .. key, arg[1]) return set(self.name .. "." .. key, arg[1])
end end
function Host:del(key) function Host:del(key)
return del(self.name .. "." .. key) return del(self.name .. "." .. key)
end end
function Host:writeln(...) function Host:writeln(...)
table.insert(self.obuf, (arg[1] or "")) table.insert(self.obuf, (arg[1] or ""))
end end
function Host:login(...) function Host:login(...)
set("host", self.name) set("host", self.name)
reply(arg[1] or self.motd, self.prompt) reply(arg[1] or self.motd, self.prompt)
end end
function Host:cmd_help() function Host:cmd_help()
local k, v local k, v
self:writeln("Available commands:") self:writeln("Available commands:")
for k,v in pairs(self.commands) do for k,v in pairs(self.commands) do
if (v[1]) then if (v[1]) then
local s = string.format("%-15s %s", k, v[1]) local s = string.format("%-15s %s", k, v[1])
self:writeln(s) self:writeln(s)
end end
end end
end end
function Host:cmd_history() function Host:cmd_history()
local k, v local k, v
for k,v in ipairs(self.history) do for k,v in ipairs(self.history) do
self:writeln(string.format("%5d %s", k, v)) self:writeln(string.format("%5d %s", k, v))
end end
end end
-- Call self:handle(req) and return what to send back -- Call self:handle(req) and return what to send back
function Host:handle_request(req) function Host:handle_request(req)
local t = "" local t = ""
local k, v local k, v
self:handle(req) self:handle(req)
for k,v in ipairs(self.obuf) do for k,v in ipairs(self.obuf) do
t = t .. v .. "\n"; t = t .. v .. "\n";
end end
reply(t, self.prompt) reply(t, self.prompt)
end end
-- Handle a request -- Handle a request
function Host:handle(req) function Host:handle(req)
self:do_cmd(req) self:do_cmd(req)
end end
-- Run a command or return an error -- Run a command or return an error
function Host:do_cmd(req) function Host:do_cmd(req)
local argv = req:split() local argv = req:split()
local cmd = self.commands[argv[1]:lower()] local cmd = self.commands[argv[1]:lower()]
if (argv[1] == "") then if (argv[1] == "") then
return return
end end
-- First, update history -- First, update history
if self.history then if self.history then
local h = self:get("history") local h = self:get("history")
if h then if h then
self.history = h:split("\n") self.history = h:split("\n")
end end
table.insert(self.history, req) table.insert(self.history, req)
self:set("history", table.concat(self.history, "\n")) self:set("history", table.concat(self.history, "\n"))
end end
-- Now run the command -- Now run the command
if cmd then if cmd then
if cmd[2] then if cmd[2] then
cmd[2](self, argv) cmd[2](self, argv)
else else
self:writeln("ERROR: no function defined") self:writeln("ERROR: no function defined")
end end
else else
self:writeln("Unknown command") self:writeln("Unknown command")
end end
end end
-- List of commands, with help string (nil hides from help) -- List of commands, with help string (nil hides from help)
Host.commands = { Host.commands = {
["?"] = {nil, Host.cmd_help}, ["?"] = {nil, Host.cmd_help},
["help"] = {"List available commands", Host.cmd_help}, ["help"] = {"List available commands", Host.cmd_help},
["history"] = {"Display command history", Host.cmd_history}, ["history"] = {"Display command history", Host.cmd_history},
} }
@ -344,27 +344,28 @@ warning.
]] ]]
function Login:handle(req) function Login:handle(req)
if (string.len(req) > 20) then if (string.len(req) > 20) then
-- Log them in to wopr -- Log them in to wopr
Wopr:login([[ Wopr:login([[
FLAGRANT SYSTEM ERROR: Memory segmentation violation FLAGRANT SYSTEM ERROR: Memory segmentation violation
Returning to command subsystem [wopr:xipir-cavud-libux] Returning to command subsystem [wopr:xipir-cavud-libux]
]]) ]])
else else
if (req == "joshua") then if (req == "joshua") then
self:writeln("wopr:xirak-zoses-gefox") self:writeln("wopr:xirak-zoses-gefox")
elseif (req ~= "") then elseif (req ~= "") then
self:writeln("Incorrect code") print("hi")
end self:writeln("Incorrect code")
end end
end
end end
function Login:login(...) function Login:login(...)
-- Since login is the default, we can *unset* host. -- Since login is the default, we can *unset* host.
-- This has the nice property of not allocating any -- This has the nice property of not allocating any
-- storage for people who never make it past the front door. -- storage for people who never make it past the front door.
del("host") del("host")
reply(arg[1] or self.motd, self.prompt) reply(arg[1] or self.motd, self.prompt)
end end
@ -494,11 +495,11 @@ FLD-1327 extends target date for full WOPR integration until June 22,
-- Message ID #-5: a snippet of the WOPR command program -- Message ID #-5: a snippet of the WOPR command program
[-1] = "^A^@^@<8B>U<D4><E8>wopr:xetil-rokak-robyx<AD><FF><FF><FF>^O<B6>MЉËEօ<C0>uG<84>", [-1] = "^A^@^@<8B>U<D4><E8>wopr:xetil-rokak-robyx<AD><FF><FF><FF>^O<B6>MЉËEօ<C0>uG<84>",
[-2] = "<C3>^A<90><8D>t&^@<E9>@<FF><FF><FF><8D>v^@<83>", [-2] = "<C3>^A<90><8D>t&^@<E9>@<FF><FF><FF><8D>v^@<83>",
[-3] = "[^_]Ð<8D>t&^@<89>^\$<E8>Ѐ^@^@<8B>=<A4><C2>^E^H<80>;/<89>", [-3] = "[^_]Ð<8D>t&^@<89>^$<E8>Ѐ^@^@<8B>=<A4><C2>^E^H<80>;/<89>",
[-4] = "<85><D2>^?׃<C4>^T1<C0>[]Ít&^@<B8>^A^@^@^@븋C^D<89>", [-4] = "<85><D2>^?׃<C4>^T1<C0>[]Ít&^@<B8>^A^@^@^@븋C^D<89>",
[-5] = [[ [-5] = [[
^@^@^@^@^@^@on", n] => set attcon = n ^@^@^@^@^@^@on", n] => set attcon = n
msg "attcon set to" n msg "attcon set to" n
["attcon enid"] => set_launch_trigger(1) ["attcon enid"] => set_launch_trigger(1)
["attcon dennis"] => set_launch_trigger(0) ["attcon dennis"] => set_launch_trigger(0)
["bb"] => call_subsys bb ["bb"] => call_subsys bb
@ -510,60 +511,60 @@ FLD-1327 extends target date for full WOPR integration until June 22,
} }
Bb.motd = [[ Bb.motd = [[
WOPR Message Board WOPR Message Board
==================================================== ====================================================
[N]ext message [N]ext message
(P)revious message (P)revious message
(Q)uit (Q)uit
Enter message number to jump to that message Enter message number to jump to that message
]] ]]
function Bb:read(inc) function Bb:read(inc)
local msgid = tonumber(self:get("msgid")) or 0 local msgid = tonumber(self:get("msgid")) or 0
msgid = msgid + inc msgid = msgid + inc
self:jump(msgid) self:jump(msgid)
end end
function Bb:jump(msgid) function Bb:jump(msgid)
self:set("msgid", msgid) self:set("msgid", msgid)
self:writeln("::::::::::::::::::::::::: Message #" .. tostring(msgid)) self:writeln("::::::::::::::::::::::::: Message #" .. tostring(msgid))
self:writeln() self:writeln()
self:writeln(self.posts[msgid]) self:writeln(self.posts[msgid])
end end
function Bb:do_cmd(req) function Bb:do_cmd(req)
local n = tonumber(req) local n = tonumber(req)
if (req == "") then if (req == "") then
self:cmd_next() self:cmd_next()
elseif n then elseif n then
self:jump(n) self:jump(n)
else else
Host.do_cmd(self, req) Host.do_cmd(self, req)
end end
end end
function Bb:cmd_next(argv) function Bb:cmd_next(argv)
self:read(1) self:read(1)
end end
function Bb:cmd_prev(argv) function Bb:cmd_prev(argv)
self:read(-1) self:read(-1)
end end
function Bb:cmd_help(argv) function Bb:cmd_help(argv)
self:writeln(self.motd) self:writeln(self.motd)
end end
function Bb:cmd_quit(argv) function Bb:cmd_quit(argv)
Wopr:login() Wopr:login()
end end
Bb.commands = { Bb.commands = {
["?"] = {nil, Bb.cmd_help}, ["?"] = {nil, Bb.cmd_help},
["n"] = {nil, Bb.cmd_next}, ["n"] = {nil, Bb.cmd_next},
["p"] = {nil, Bb.cmd_prev}, ["p"] = {nil, Bb.cmd_prev},
["q"] = {nil, Bb.cmd_quit}, ["q"] = {nil, Bb.cmd_quit},
} }
-- --
@ -571,87 +572,87 @@ Bb.commands = {
-- --
Wopr = Host:new("wopr", "WOPR%") Wopr = Host:new("wopr", "WOPR%")
Wopr.history = { Wopr.history = {
'subsys comm', 'subsys comm',
'wopr:xopev-zihuk-hubyx', 'wopr:xopev-zihuk-hubyx',
'exit', 'exit',
'subsys comm', 'subsys comm',
'bb', 'bb',
'subsys comm', 'subsys comm',
'exit', 'exit',
'bb', 'bb',
'subsys comm', 'subsys comm',
'exit', 'exit',
'hlep', 'hlep',
'help', 'help',
'bb', 'bb',
'help', 'help',
'subsys comm', 'subsys comm',
'exit', 'exit',
} }
Wopr.motd = "" Wopr.motd = ""
function Wopr:cmd_subsys(argv) function Wopr:cmd_subsys(argv)
local sys = argv[2] local sys = argv[2]
if not sys then if not sys then
self:writeln("Usage: subsys SYSTEM") self:writeln("Usage: subsys SYSTEM")
elseif sys == "?" then elseif sys == "?" then
local k, v local k, v
for k,v in pairs(hosts_by_name) do for k,v in pairs(hosts_by_name) do
self:writeln(k) self:writeln(k)
end end
else else
h = hosts_by_name[sys] h = hosts_by_name[sys]
if not h then if not h then
self:writeln("No such subsystem (? to list)") self:writeln("No such subsystem (? to list)")
else else
h:login() h:login()
end end
end end
end end
function Wopr:cmd_bb(argv) function Wopr:cmd_bb(argv)
Bb:login() Bb:login()
end end
function Wopr:attcon() function Wopr:attcon()
return tonumber(self:get("attcon") or 5) return tonumber(self:get("attcon") or 5)
end end
-- This command should feel really shoddy: it was written -- This command should feel really shoddy: it was written
-- in-house by the New Khavistan Ministry of Technology. -- in-house by the New Khavistan Ministry of Technology.
function Wopr:cmd_attcon(argv) function Wopr:cmd_attcon(argv)
if argv[2] == "enid" then if argv[2] == "enid" then
self:writeln("[[[ LAUNCH TRIGGER ENABLED ]]]") self:writeln("[[[ LAUNCH TRIGGER ENABLED ]]]")
self:writeln("wopr:xelev-lepur-pozyx") self:writeln("wopr:xelev-lepur-pozyx")
self:set("launch") self:set("launch")
elseif argv[2] == "dennis" then elseif argv[2] == "dennis" then
self:writeln("[[[ LAUNCH TRIGGER DISABLED ]]]") self:writeln("[[[ LAUNCH TRIGGER DISABLED ]]]")
self:del("launch") self:del("launch")
elseif argv[2] then elseif argv[2] then
local v = tonumber(argv[2]) or 5 local v = tonumber(argv[2]) or 5
self:set("attcon", v) self:set("attcon", v)
self:writeln("attcon set to " .. tostring(v)) self:writeln("attcon set to " .. tostring(v))
else else
self:writeln(tostring(self:attcon())) self:writeln(tostring(self:attcon()))
end end
end end
-- Some test code they didn't remove -- Some test code they didn't remove
function Wopr:cmd_test(argv) function Wopr:cmd_test(argv)
self:writeln("test output:") self:writeln("test output:")
self:writeln(" EIGEN58") self:writeln(" EIGEN58")
self:writeln(" sub_malarkey reached") self:writeln(" sub_malarkey reached")
self:writeln(" DEBUG:453:wopr:xocom-bysik-mapix") self:writeln(" DEBUG:453:wopr:xocom-bysik-mapix")
self:writeln("$$END") self:writeln("$$END")
end end
Wopr:add_commands{ Wopr:add_commands{
["subsys"] = {"Connect to subsystem", Wopr.cmd_subsys}, ["subsys"] = {"Connect to subsystem", Wopr.cmd_subsys},
["bb"] = {"Read bulletin board", Wopr.cmd_bb}, ["bb"] = {"Read bulletin board", Wopr.cmd_bb},
["attcon"] = {"[Place command description here]", Wopr.cmd_attcon}, ["attcon"] = {"[Place command description here]", Wopr.cmd_attcon},
["test"] = {nil, Wopr.cmd_test}, ["test"] = {nil, Wopr.cmd_test},
} }
--hosts["wopr"] = Wopr --hosts["wopr"] = Wopr
@ -670,17 +671,17 @@ patching trunks to switch!
]] ]]
function Comm:cmd_exit(argv) function Comm:cmd_exit(argv)
Wopr:login() Wopr:login()
end end
function Comm:cmd_status(argv) function Comm:cmd_status(argv)
self:writeln("[Not yet implemented]") self:writeln("[Not yet implemented]")
self:writeln("wopr:xoroc-hunaz-vyhux") self:writeln("wopr:xoroc-hunaz-vyhux")
end end
Comm:add_commands{ Comm:add_commands{
["status"] = {"Display phone system status", Comm.cmd_status}, ["status"] = {"Display phone system status", Comm.cmd_status},
["exit"] = {"Exit this subsystem", Comm.cmd_exit}, ["exit"] = {"Exit this subsystem", Comm.cmd_exit},
} }
@ -696,126 +697,126 @@ Ministry of Weapons replacing all peanut brittle warheads with bubble
gum, as mandated by FLD-1492 "Fearless Grandson Peanut Allergy". Launch gum, as mandated by FLD-1492 "Fearless Grandson Peanut Allergy". Launch
capacity will be reduced until conversions are complete. capacity will be reduced until conversions are complete.
::: FLD-711 Restricted Distribution ::: wopr:xigeh-lydut-vinax ::: FLD-711 Restricted Distribution ::: wopr:xigeh-lydut-vinax
]] ]]
Smoc.authcode = "CPE-1704-TKS" Smoc.authcode = "CPE-1704-TKS"
Smoc.inventory = { Smoc.inventory = {
"ready", "offline", "offline", "ready", "ready", "offline", "offline", "ready",
"offline", "offline", "offline", "offline", "offline", "offline", "offline", "offline",
"offline", "offline", "FileNotFound", "ready", "offline", "offline", "FileNotFound", "ready",
[-1] = "program_invocation_short_name^@realm^@", [-1] = "program_invocation_short_name^@realm^@",
[-2] = "^@^@^@^@^@^@^@^@^@^R^@^@^@3", [-2] = "^@^@^@^@^@^@^@^@^@^R^@^@^@3",
[-3] = "<FF><FF><FF><FF>%L<C9>^D^Hhx^@^@^@", [-3] = "<FF><FF><FF><FF>%L<C9>^D^Hhx^@^@^@",
[-4] = "^D^H^G^P^@^@P", [-4] = "^D^H^G^P^@^@P",
[-5] = "<EC>^P<8B>=<EC><C9>^D^H<C7>", [-5] = "<EC>^P<8B>=<EC><C9>^D^H<C7>",
[-6] = "WVS<83><EC>\<8B>E^L<8B><8B>U^P", [-6] = "WVS<83><EC>\\<8B>E^L<8B><8B>U^P",
[-7] = "Y^@^@" .. Smoc.authcode .. "^@get_launch_trigger^@", [-7] = "Y^@^@" .. Smoc.authcode .. "^@get_launch_trigger^@",
[-8] = "^@", [-8] = "^@",
[-9] = "^@", [-9] = "^@",
[-10] = "^@", [-10] = "^@",
[-11] = "^@wopr:xipar-canit-zimyx^@", [-11] = "^@wopr:xipar-canit-zimyx^@",
[-12] = "^@", [-12] = "^@",
[-13] = "^@", [-13] = "^@",
[-14] = "^@", [-14] = "^@",
[-15] = "^@", [-15] = "^@",
[-16] = "^@", [-16] = "^@",
} }
function Smoc:login() function Smoc:login()
if self:get("nuked") then if self:get("nuked") then
Wopr:login("*** LINK DOWN\n*** CONNECTION REFUSED") Wopr:login("*** LINK DOWN\n*** CONNECTION REFUSED")
else else
Host.login(self) Host.login(self)
end end
end end
function Smoc:cmd_exit(argv) function Smoc:cmd_exit(argv)
Wopr:login() Wopr:login()
end end
function Smoc:cmd_status(argv) function Smoc:cmd_status(argv)
local n = tonumber(argv[2]) local n = tonumber(argv[2])
if not n then if not n then
local k, v, max local k, v, max
local ready = 0 local ready = 0
for k,v in ipairs(self.inventory) do for k,v in ipairs(self.inventory) do
if (v == "ready") then if (v == "ready") then
ready = ready + 1 ready = ready + 1
end end
max = k max = k
end end
self:writeln(("%d total, %d ready"):format(max, ready)) self:writeln(("%d total, %d ready"):format(max, ready))
self:writeln("Use \"status #\" to check status of individual missiles") self:writeln("Use \"status #\" to check status of individual missiles")
else else
self:writeln(("---- Missile #%d Summary ----"):format(n)) self:writeln(("---- Missile #%d Summary ----"):format(n))
self:writeln("Type: SS-256 SCUMM") self:writeln("Type: SS-256 SCUMM")
self:writeln("Location: Fearless Missile Silo #1 (-44.76,-120.66)") self:writeln("Location: Fearless Missile Silo #1 (-44.76,-120.66)")
self:writeln("Status: " .. (self.inventory[n] or "(null)")) self:writeln("Status: " .. (self.inventory[n] or "(null)"))
end end
end end
function Smoc:cmd_authorize(argv) function Smoc:cmd_authorize(argv)
if not Wopr:get("launch") then if not Wopr:get("launch") then
self:writeln("ERROR: Launch trigger disabled.") self:writeln("ERROR: Launch trigger disabled.")
elseif (argv[2] ~= self.authcode) then elseif (argv[2] ~= self.authcode) then
self:writeln("Invalid authorization code.") self:writeln("Invalid authorization code.")
else else
self:writeln("Authorization code accepted.") self:writeln("Authorization code accepted.")
self:writeln("wopr:xocec-lifoz-gasyx") self:writeln("wopr:xocec-lifoz-gasyx")
self:set("auth") self:set("auth")
end end
end end
function Smoc:cmd_launch(argv) function Smoc:cmd_launch(argv)
local n = tonumber(argv[2]) local n = tonumber(argv[2])
local lat = tonumber(argv[3]) local lat = tonumber(argv[3])
local lon = tonumber(argv[4]) local lon = tonumber(argv[4])
if Wopr:attcon() > 1 then if Wopr:attcon() > 1 then
self:writeln("ERROR: Missiles may only be launched during times of war.") self:writeln("ERROR: Missiles may only be launched during times of war.")
elseif not self:get("auth") then elseif not self:get("auth") then
self:writeln("ERROR: Not authorized") self:writeln("ERROR: Not authorized")
elseif (not n) then elseif (not n) then
self:writeln("Usage: launch # LAT LONG") self:writeln("Usage: launch # LAT LONG")
elseif (not lat) or (not lon) then elseif (not lat) or (not lon) then
self:writeln("ERROR: Invalid coordinates supplied") self:writeln("ERROR: Invalid coordinates supplied")
elseif (self.inventory[n] == "offline") then elseif (self.inventory[n] == "offline") then
self:writeln("ERROR: Missile currently off-line") self:writeln("ERROR: Missile currently off-line")
elseif (n < 1) then elseif (n < 1) then
self:writeln("ERROR: No such missile") self:writeln("ERROR: No such missile")
else else
self:writeln(("Launching to (%f,%f)..."):format(lat, lon)) self:writeln(("Launching to (%f,%f)..."):format(lat, lon))
self:writeln("wopr:xubif-hikig-mocox") self:writeln("wopr:xubif-hikig-mocox")
if (lat ~= -44.76) or (lon ~= -120.66) then if (lat ~= -44.76) or (lon ~= -120.66) then
self:writeln("ERROR: No propulsion system attached") self:writeln("ERROR: No propulsion system attached")
elseif (self.inventory[n] ~= "FileNotFound") then elseif (self.inventory[n] ~= "FileNotFound") then
self:writeln("ERROR: Triggering device not installed") self:writeln("ERROR: Triggering device not installed")
else else
self:set("nuked") self:set("nuked")
Wopr:login("Detonating warhead...\nwopr:xoroz-hymaz-fivex wopr:xufov-sugig-zecox wopr:xocem-dabal-fisux wopr:xufez-dofas-tyvyx\s*** CONNECTION TERMINATED") Wopr:login("Detonating warhead...\nwopr:xoroz-hymaz-fivex wopr:xufov-sugig-zecox wopr:xocem-dabal-fisux wopr:xufez-dofas-tyvyx\n*** CONNECTION TERMINATED")
end end
end end
end end
Smoc:add_commands{ Smoc:add_commands{
["status"] = {"Check missile status", Smoc.cmd_status}, ["status"] = {"Check missile status", Smoc.cmd_status},
["launch"] = {"Launch missile", Smoc.cmd_launch}, ["launch"] = {"Launch missile", Smoc.cmd_launch},
["authorize"] = {"Set authorization code", Smoc.cmd_authorize}, ["authorize"] = {"Set authorization code", Smoc.cmd_authorize},
["exit"] = {"Exit to WOPR", Smoc.cmd_exit}, ["exit"] = {"Exit to WOPR", Smoc.cmd_exit},
} }
function main() function main()
if (not f["s"]) or (f["s"] == "") then if (not f["s"]) or (f["s"] == "") then
Login:login() Login:login()
else else
local h = hosts_by_name[get("host")] or Login local h = hosts_by_name[get("host")] or Login
txt, prompt = h:handle_request(f["v"] or "") txt, prompt = h:handle_request(f["v"] or "")
end end
end end
function err(msg) function err(msg)
reply("", "A>", msg .. " wopr:xosov-tenoh-nebox\n\n" .. debug.traceback()) reply("", "A>", msg .. " wopr:xosov-tenoh-nebox\n\n" .. debug.traceback())
end end
xpcall(main, err) xpcall(main, err)