#!/usr/bin/env bash

dir="$( cd "$( dirname "$0" )" && pwd )"

touch $dir/lockfile

if [ -z "$1" ]; then
    echo "invalid args"
    exit
fi
if [ -z "$2" ]; then
    echo "invalid args"
    exit
fi

lang=$1
epoch=$(date +%s%N)
basepath="/var/lib/lxc/piston/rootfs"
filepath="/tmp/$epoch/code.code"
argpath="/tmp/$epoch/args.args"
arg=$(basename $argpath)

# write arg file
mkdir -p $basepath/tmp/$epoch
chmod 777 $basepath/tmp/$epoch
cat $2 > $basepath$filepath
echo "${@:3}" > $basepath$argpath

# process incrementor
exec 200>$dir/lockfile
flock -x 200
oldinc=$(cat $dir/i | awk '{$1=$1};1')
newinc=$(expr $oldinc + 1)

if (( newinc >= 151 )); then
    newinc=1
    echo 1 > $dir/i
else
    echo $newinc > $dir/i
fi
exec 200>&-

bin=
case "$lang" in
"awk")
    bin=awk
    ;;
"bash")
    bin=bash
    ;;
"c")
    bin=c
    ;;
"cpp" | "c++")
    bin=cpp
    ;;
"csharp" | "cs" | "c#")
    bin=csharp
    ;;
"go")
    bin=go
    ;;
"java")
    bin=java
    ;;
"julia" | "jl")
    bin=julia
    ;;
"kotlin")
    bin=kotlin
    ;;
"nasm" | "asm")
    bin=nasm
    ;;
"node" | "js" | "javascript")
    bin=node
    ;;
"php")
    bin=php
    ;;
"python2")
    bin=python2
    ;;
"python3" | "python")
    bin=python3
    ;;
"ruby")
    bin=ruby
    ;;
"rust")
    bin=rust
    ;;
"swift")
    bin=swift
    ;;
"typescript" | "ts")
    bin=typescript
    ;;
*)
    echo "invalid language"
    exit
esac

# runner
timeout -s KILL 10 \
    lxc-attach --clear-env -n piston -- \
        /bin/bash -l -c "bash /exec/$bin $newinc $epoch 2>&1 | head -c 65536"

# process janitor
lxc-attach --clear-env -n piston -- \
    /bin/bash -l -c "\
        for i in {1..100}; do pkill -u runner$newinc --signal SIGKILL; done ;\
        find /tmp -user runner$newinc -exec /bin/rm -rf {} \;\
        " > /dev/null 2>&1 &

rm -rf $basepath/tmp/$epoch