diff --git a/packages/00common/src/claim.cgi.c b/packages/00common/src/claim.cgi.c index 082962f..14ef6cb 100644 --- a/packages/00common/src/claim.cgi.c +++ b/packages/00common/src/claim.cgi.c @@ -58,6 +58,7 @@ main(int argc, char *argv[]) /* Pull category name out of the token */ for (q = category; *p && (*p != ':'); p += 1) { + *p = tolower(*p); *(q++) = *p; } *q = '\0'; diff --git a/packages/host/host.mk b/packages/host/host.mk new file mode 100644 index 0000000..753c336 --- /dev/null +++ b/packages/host/host.mk @@ -0,0 +1,8 @@ +HOST_PKGDIR = $(TARGET)/host + +host-install: + mkdir -p $(HOST_PKGDIR) + cp packages/host/tokens.txt $(HOST_PKGDIR) + +PACKAGES += host + diff --git a/packages/host/tokens.txt b/packages/host/tokens.txt new file mode 100644 index 0000000..f8313cd --- /dev/null +++ b/packages/host/tokens.txt @@ -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 diff --git a/packages/mcp/bin/scoreboard b/packages/mcp/bin/scoreboard index 74f171b..93e46fc 100755 --- a/packages/mcp/bin/scoreboard +++ b/packages/mcp/bin/scoreboard @@ -8,152 +8,150 @@ ## function qsort(A, left, right, i, last) { - if (left >= right) - return - swap(A, left, left+int((right-left+1)*rand())) - last = left - for (i = left+1; i <= right; i++) - if (A[i] < A[left]) - swap(A, ++last, i) - swap(A, left, last) - qsort(A, left, last-1) - qsort(A, last+1, right) + if (left >= right) + return + swap(A, left, left+int((right-left+1)*rand())) + last = left + for (i = left+1; i <= right; i++) + if (A[i] < A[left]) + swap(A, ++last, i) + swap(A, left, last) + qsort(A, left, last-1) + qsort(A, last+1, right) } 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) { - gsub("&", "&", s) - gsub("<", "<", s) - gsub(">", ">", s) - return s + gsub("&", "&", s) + gsub("<", "<", s) + gsub(">", ">", s) + return s } function head() { - print "" - print "Project 2 Scoreboard" - print "" - print "" - print "" - print "" - print "
" + print ".name {position: absolute; right: 10px;}" + print "#scores p {margin: 0; padding: 0; border: thin solid #222; opacity: 0.92;}" + print "#scores p:hover {border: thin solid yellow;}" + print "" + print "" + print "
" } function foot() { - print "
" - print " " - print "" + print "
" + print " " + print "" } BEGIN { - base = ENVIRON["CTF_BASE"] - if (! base) { - base = "/var/lib/ctf" - } + base = ENVIRON["CTF_BASE"] + if (! base) { + base = "/var/lib/ctf" + } - head() + head() } # MAINLOOP { - time = $1 - hash = $2 - cat = $3 - points = int($4) + time = $1 + hash = $2 + cat = $3 + points = int($4) - # Build a list of team names - if (! (hash in team_names)) { - fn = sprintf("%s/teams/names/%s", base, hash) - getline team_names[hash] < fn - close(fn) - } + # Build a list of team names + if (! (hash in team_names)) { + fn = sprintf("%s/state/teams/names/%s", base, hash) + getline team_names[hash] < fn + close(fn) + } - # Total points possible so far in this category - if (! ((cat, points) in cat_pointval)) { - cat_total[cat] += points - cat_pointval[cat, points] = 1 - } + # Enumerate categories + if (! (cat in seen_cats)) { + seen_cats[cat] = 1 + categories[ncats++] = cat + } - # Enumerate categories - if (! (cat in seen_cats)) { - seen_cats[cat] = 1 - categories[ncats++] = cat - } - - # Points this team has in this category - cat_points[hash, cat] += points + # Points this team has in this category + cat_points[hash, cat] += points + + # Token-based categories can make cat_pointval irrelevant + if (cat_points[hash, cat] > cat_total[cat]) { + cat_total[cat] = cat_points[hash, cat] + } } END { - # Adjust per-category points to a per-category percentage complete - for (hash in team_names) { - for (cat in cat_total) { - cat_score[hash, cat] = cat_points[hash, cat] / cat_total[cat] - total_score[hash] += cat_score[hash, cat] - } - scores[nteams++] = total_score[hash] - if (total_score[hash] > max_score) { - max_score = total_score[hash] - } - } + # Adjust per-category points to a per-category percentage complete + for (hash in team_names) { + for (cat in cat_total) { + cat_score[hash, cat] = cat_points[hash, cat] / cat_total[cat] + total_score[hash] += cat_score[hash, cat] + } + scores[nteams++] = total_score[hash] + if (total_score[hash] > max_score) { + max_score = total_score[hash] + } + } - # Sort scores - qsort(scores, 0, nteams-1) + # Sort scores + qsort(scores, 0, nteams-1) - print "

" - for (ncat = 0; ncat < ncats; ncat += 1) { - printf("%s\n", ncat, categories[ncat]); - } - print "

" + print "

" + for (ncat = 0; ncat < ncats; ncat += 1) { + printf("%s\n", ncat, categories[ncat]); + } + print "

" - for (i = nteams-1; i >= 0; i -= 1) { - score = scores[i]; - if (score == scores[i-1]) continue; # Skip duplicates + for (i = nteams-1; i >= 0; i -= 1) { + score = scores[i]; + if (score == scores[i-1]) continue; # Skip duplicates - for (hash in team_names) { - if (total_score[hash] != score) { - continue; - } + for (hash in team_names) { + if (total_score[hash] != score) { + continue; + } - name = escape(team_names[hash]) - print "

" - printf("%s\n", name) + name = escape(team_names[hash]) + print "

" + printf("%s\n", name) - for (ncat = 0; ncat < ncats; ncat += 1) { - cat = categories[ncat]; - points = cat_points[hash, cat]; + for (ncat = 0; ncat < ncats; ncat += 1) { + cat = categories[ncat]; + points = cat_points[hash, cat]; - if (cat_points[hash, cat] > 0) { - width = cat_score[hash, cat] / max_score * 90 - printf("", cat, points, name) - printf("%d", - ncat, width, cat_points[hash, cat]) - } - } - print "

" - } - } + if (cat_points[hash, cat] > 0) { + width = cat_score[hash, cat] / max_score * 90 + printf("", cat, points, name) + printf("%d", + ncat, width, cat_points[hash, cat]) + } + } + print "

" + } + } - foot() + foot() } - diff --git a/packages/mcp/www/register.cgi b/packages/mcp/www/register.cgi index 3737158..6d84dda 100755 --- a/packages/mcp/www/register.cgi +++ b/packages/mcp/www/register.cgi @@ -1,8 +1,25 @@ #! /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 <Team Registration EOF -if ! grep -q $h $CTF_BASE/state/teams/assigned.txt; then - echo "

That token has not been assigned.

" -elif [ -f $CTF_BASE/state/teams/names/$h ]; then - echo "

That token has already been named.

" +if [ -z "$hash" ] || [ -z "$team" ]; then + echo "

Empty field, cannot complete request

" +elif ! grep -q " $hash$" $CTF_BASE/state/teams/assigned.txt; then + echo "

That hash has not been assigned.

" +elif [ -f $CTF_BASE/state/teams/names/$hash ]; then + echo "

That hash has already been registered.

" else - printf "%s" "$t" > $CTF_BASE/state/teams/names/$h - echo "

Okay, your team has been named and you may begin using your token!

" + printf "%s" "$team" > $CTF_BASE/state/teams/names/$hash + echo "

Okay, your team has been named and you may begin using your hash!

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