え?もう本番ですか…?

Welcome to ようこそ evalpark !

パークレンジャーの弾です。ここ404 Blog Not Foundではご無沙汰しております。

年度末のドッタンバッタン大騒ぎも落ち着いてきたので、 evalpark を開園します。

要はllevalの後継サービスなのですが、

  • 64bit化しました
  • SSL対応しました
  • けもののpermalink化に対応しました
  • ptrace()監視社会やめました
  • もはや時代遅れのJSONPやめました
  • パークにはFreeBSD 11の全ユーザーランド+pkgで入ったけものがいます

CodePadからideoneまで、もはやWeb REPLはいくらでもあるのですが、さすがに最後の条項まで満たしたものは当園以外は見当たらないようです。

遊び方は、簡単。

  • http://eval.dan.co.jp/park.cgi?s=source
  • https://eval.dan.co.jp/park.cgi?s=source

で、sourceContent-Type: application/jsonかつAccess-Control-Allow-Origin: *でかえってきます。ここでsourceは任意のshell scriptです。その中にpathというフィールドがありますが、そこにsourceのコピーがあるので、

  • http://eval.dan.co.jp/path
  • https://eval.dan.co.jp/path

で内容を、

  • http://eval.dan.co.jp/park.cgi/path
  • https://eval.dan.co.jp/park.cgi/path

で実行結果をお取り寄せできます。

jQuery pluginも用意しています。以下のような感じでお使いになれます。

<script src="//ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script src="//eval.dan.co.jp/jquery-runpark.js"></script>
<div>
<textarea id="src" rows="4">
#!/bin/sh -v
pkg info | awk '{print $1}'
</textarea>
  <div>
    <input type="submit" value="run" onclick="$('#src').runPark('#dst')">
    <input type="submit" value="rerun" onclick="$('#dst').rerunPark('/friends/sample/pkg.sh')">
    <input type="submit" value="clear" onclick="$('#dst').html('')">
  </div>
  <div id="dst"></div>
</div>

けものはいても

上でさらっと言いましたが、evalparkがevalのはshell scriptです。llevalの頃のl=による言語指定は廃止されました。その代わりに#!でけものを指定します。

🦏とか

#!/usr/local/bin/node
for (var i = 1; i <= 30; i++) console.log(
  (i % 3 == 0 ? 'Fizz' : '') + (i % 5 == 0 ? 'Buzz' : '') || i
);

🐪とか

#!/usr/local/bin/perl -l
print(((Fizz)[$_%3].(Buzz)[$_%5])||$_)for 1..30

🐍とか(2か3かは要明示)

#!/usr/local/bin/python3
print('\n'.join(n%3//2*'Fizz'+n%5//4*'Buzz'or str(n+1)for n in range(30)))

💎とか。え?けものかって?イワークがポケモンでポケモンがけものならけものでしょJK。

#!/usr/local/bin/ruby
1.upto(30){|i|i%3<1&&x=:Fizz;puts i%5<1?"#{x}Buzz":x||i}

そうそう🦋もいますよ。

#!/usr/bin/env /friends/.rakudobrew/bin/perl6
my subset Fizz of Int where * %% 3;
my subset Buzz of Int where * %% 5;
my subset FizzBuzz of Int where Fizz&Buzz;
my subset Number of Int where none Fizz|Buzz;

proto sub fizzbuzz ($) { * }
multi sub fizzbuzz (FizzBuzz) { "FuzzBuzz" }
multi sub fizzbuzz (Fizz) { "Fizz" }
multi sub fizzbuzz (Buzz) { "Buzz" }
multi sub fizzbuzz (Number $number) { $number }

fizzbuzz($_).say for 1..30;

まだまだ開園したてですが、どんなけものがいるかは以下でヒントを得られるでしょう。

のけものはいない

shell script化によって、本来scriptとしては実行できないはずのけものも実行できるようになりました。え?何を言ってるかわからない?こういうことです。

モグラとか

#!/usr/bin/env /friends/bin/goscript
package main
import "fmt"
func main() {  
    for out := range FizzBuzz(30) {
        fmt.Println(out)
    }
}
func FizzBuzz(amount int) <-chan string {
    out := make(chan string, amount)
    go func() {
        for i := 1; i <= amount; i++ {
            res := ""
            if i%3 == 0 { res += "Fizz" }
            if i%5 == 0 { res += "Buzz" }
            if res == "" { res = fmt.Sprintf("%v", i) }
            out <- res
        }
        close(out)
    }()
    return out
}

⚙️とか

#!/usr/bin/env /friends/bin/rustscript
fn main() {
    for i in 1..31 {
        let word = match (i % 3, i % 5) {
            (0, 0) => "FizzBuzz".to_owned(),
            (0, _) => "Fizz".to_owned(),
            (_, 0) => "Buzz".to_owned(),
            _ => i.to_string().to_owned(),
        };
        println!("{}", word);
    }
}

C++とか

#!/usr/bin/env /friends/bin/cxxscript
#include <iostream>
using namespace std;
int main (){
  for (int i = 1; i <= 30; i++) {
    if ((i % 15) == 0)     cout << "FizzBuzz" << endl;
    else if ((i % 3) == 0) cout << "Fizz"     << endl;
    else if ((i % 5) == 0) cout <<     "Buzz" << endl ;
    else                   cout <<          i << endl;
  }
  return 0;
}

☕️まで

#!/usr/bin/env /friends/bin/notjavascript
public class FizzBuzz {
    public static void main(String[] args){
        for(int i= 1; i <= 30; i++){
            if(i % 15 == 0){
                System.out.println("FizzBuzz");
            }else if(i % 3 == 0){
                System.out.println("Fizz");
            }else if(i % 5 == 0){
                System.out.println("Buzz");
            }else{
                System.out.println(i);
            }
        }
    }
}

しくみは例えばrustscriptなどを見れば。

ほんとうの🐚がここにある

要はそういうことなのです。

|``も当然使えます。

ほら君も手を繋いで大冒険(1, 2, Fizz)

#!/bin/sh -v
seq 1 30 \
| sed 's/$/ /' \
| perl -aple '$_.="Fizz" unless $F[0] % 3' \
| ruby -aple '$_+="Buzz" if $F[0].to_i % 5 == 0' \
| awk 'NF==2{print $2}NF==1{print $1}'

ふりむけばあちらこちらでトラブル

開園にあたっては、当然園内の安全性も確保する必要がありました。けものにはなるべく自由に生きて欲しい一方、その結果がウェストワールドでは目もあてられません。当園では以下の対策を施しています。

  • 実行時間は1秒。例外はなし。それを過ぎると世界は消滅し再生します。
    perl -E 'say "pid:", fork() while 1'
    余談ですが、scalaはこの制限のおかげでお見せできません。園内にはいるのですが。☕️はぎりぎり。この1秒にはコンパイル時間も含まれるので、コンパイル型のけものは不利ではあります。
  • けものはnobody。書き込めるのは/tmp/var/tmpだけ。糞を始末し忘れても自動で片付けられます。が、残した糞の目録がdroppingsとして返されます。

    perl -E 'open W,">/tmp/$_.txt" and say W for 1..30' && cat /tmp/*.txt
  • 園内はNATの内側です。よってサーバーを立てても無駄ですし、前述の通り時間制限を過ぎたら世界ごと消滅します。クライエントは時間制限内で完結するのであれば問題なく使えます。が、園内再入場は禁止です。
  • fetch -o - https://www.example.com/
    fetch -o - https://eval.dan.co.jp/park.cgi/bin/sh
    
  • その他にも園内での行動はRACCTなどによる制限がかかっています。まんじゅうは食い放題ではないのでご留意を。

Acknowledgements

  • DATAHOTEL様にはホスティングを。会社は変わっても引き続きお世話になっております。
  • The FreeBSD Projectがなければ造園は不可能でした。jailRACCTZFSのおかげで、造園に必要なIQは劇的に下がりました。園内の安全はデーモンさんにお任せなのだ!
  • けものフレンズロゴジェネレータにはfaviconを。絵心がないフレンズ大助かり。
  • そしてけものフレンズ。今回のアップデートの構想はRACCTがFreeBSD 11で標準サポートされてからずっとあったのですが、重い腰が上がったのは同作のおかげ。

さいごに

ようこそevalpark#!

Dan the Park Ranger Thereof