diff --git a/api/.gitignore b/api/.gitignore new file mode 100644 index 0000000..3c3629e --- /dev/null +++ b/api/.gitignore @@ -0,0 +1 @@ +node_modules diff --git a/api/main.go b/api/main.go deleted file mode 100644 index d883445..0000000 --- a/api/main.go +++ /dev/null @@ -1,263 +0,0 @@ -package main - -import ( - "bytes" - "encoding/json" - "fmt" - "io/ioutil" - "net/http" - "os/exec" - "regexp" - "strings" - "time" -) - -type Inbound struct { - Language string `json:"language"` - Source string `json:"source"` - Args []string `json:"args"` -} - -type Problem struct { - Code string `json:"code"` - Message string `json:"message"` -} - -type Outbound struct { - Ran bool `json:"ran"` - Language string `json:"language"` - Version string `json:"version"` - Output string `json:"output"` -} - -type Language struct { - Name string `json:"name,omitempty"` - Version string `json:"version,omitempty"` -} - -var instance int -var languages []Language - -func main() { - port := "2000" - - var err error - languages, err = UpdateVersions() - - if err != nil { - fmt.Println("could not get version info and therefore couldn't start") - fmt.Println(err) - return - } - - fmt.Println("starting api on port", port) - http.HandleFunc("/execute", Execute) - http.HandleFunc("/versions", Versions) - http.ListenAndServe(":"+port, nil) -} - -func Execute(res http.ResponseWriter, req *http.Request) { - res.Header().Set("Content-Type", "application/json") - - // get json - inbound := Inbound{} - message := json.NewDecoder(req.Body) - message.Decode(&inbound) - - whitelist := []string{ - "awk", - "bash", - "brainfuck", "bf", - "c", - "cpp", "c++", - "csharp", "cs", "c#", - "d", - "deno", "denojs", "denots", - "elixir", "exs", - "emacs", "elisp", "el", - "go", - "haskell", "hs", - "java", - "jelly", - "julia", "jl", - "kotlin", - "lua", - "nasm", "asm", - "nasm64", "asm64", - "nim", - "node", "javascript", "js", - "perl", "pl", - "php", - "python2", - "python3", "python", - "paradoc", - "ruby", - "rust", - "swift", - "typescript", "ts", - } - - // check if the supplied language is supported - // now calls function and returns - for _, lang := range whitelist { - if lang == inbound.Language { - launch(inbound, res) - return - } - } - - // now only called when the language is not supported - problem := Problem{ - Code: "unsupported_language", - Message: inbound.Language + " is not supported by Piston", - } - - pres, _ := json.Marshal(problem) - - res.Write(pres) -} - -func Versions(res http.ResponseWriter, req *http.Request) { - res.Header().Set("Content-Type", "application/json") - - data, _ := json.Marshal(languages) - - res.Write(data) -} - -func launch(request Inbound, res http.ResponseWriter) { - stamp := time.Now().UnixNano() - - // write the code to temp dir - srcfile := fmt.Sprintf("/tmp/%d.code", stamp) - - ioutil.WriteFile(srcfile, []byte(request.Source), 0644) - - // set up the arguments to send to the execute command - cmd := exec.Command("../lxc/execute", request.Language, srcfile, strings.Join(request.Args, "\n")) - - // capture out/err - var stdout, stderr bytes.Buffer - cmd.Stdout = &stdout - cmd.Stderr = &stderr - - err := cmd.Run() - - // get the executing version of the language - execlang := request.Language - - switch execlang { - case "bf": - execlang = "brainfuck" - case "c++": - execlang = "cpp" - case "cs", "c#": - execlang = "csharp" - case "denojs", "denots": - execlang = "deno" - case "el", "elisp": - execlang = "emacs" - case "exs": - execlang = "elixir" - case "hs": - execlang = "haskell" - case "asm": - execlang = "nasm" - case "asm64": - execlang = "nasm64" - case "js", "javascript": - execlang = "node" - case "jl": - execlang = "julia" - case "python": - execlang = "python3" - case "ts": - execlang = "typescript" - } - - // prepare response - outbound := Outbound{ - Ran: err == nil, - Language: request.Language, - Version: "", - Output: strings.TrimSpace(stdout.String()), - } - - // retrieve the language version - for _, lang := range languages { - if lang.Name == execlang { - outbound.Version = lang.Version - break - } - } - - response, _ := json.Marshal(outbound) - - res.Write(response) -} - -func UpdateVersions() ([]Language, error) { - langs, err := GetVersions() - - if err != nil { - return nil, err - } - - return langs, nil -} - -// get all the language and their current version -func GetVersions() ([]Language, error) { - var languages []Language - - res, err := ExecVersionScript() - - if err != nil { - return nil, err - } - - info := strings.Split(res, "---") - - for _, v := range info { - if len(v) < 2 { - continue - } - name, version := GetVersion(v) - languages = append(languages, Language{ - Name: name, - Version: version, - }) - } - - return languages, nil -} - -// run the script that retrieves all the language versions -func ExecVersionScript() (string, error) { - cmd := exec.Command("../lxc/versions") - - var stdout bytes.Buffer - cmd.Stdout = &stdout - cmd.Stderr = &stdout - - err := cmd.Run() - - return strings.ToLower(stdout.String()), err -} - -// return the language and its version -// most of the time it is easy to get the name and version -// but for some languages helper functions are used -func GetVersion(s string) (string, string) { - lines := strings.Split(s, "\n") - - if lines[1] == "java" { - return "java", regexp.MustCompile("([0-9]+)").FindString(lines[2]) - } - - if lines[1] == "emacs" { - return "emacs", regexp.MustCompile("([0-9]+\\.[0-9]+)").FindString(lines[2]) - } - - return lines[1], regexp.MustCompile("([0-9]+\\.[0-9]+\\.[0-9]+)").FindString(s) -} diff --git a/api/package-lock.json b/api/package-lock.json new file mode 100644 index 0000000..4757c95 --- /dev/null +++ b/api/package-lock.json @@ -0,0 +1,903 @@ +{ + "name": "api", + "version": "1.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "express": "^4.17.1", + "express-validator": "^6.9.2" + } + }, + "node_modules/accepts": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", + "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", + "dependencies": { + "mime-types": "~2.1.24", + "negotiator": "0.6.2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" + }, + "node_modules/body-parser": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", + "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", + "dependencies": { + "bytes": "3.1.0", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "~1.1.2", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "on-finished": "~2.3.0", + "qs": "6.7.0", + "raw-body": "2.4.0", + "type-is": "~1.6.17" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/bytes": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", + "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/content-disposition": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", + "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", + "dependencies": { + "safe-buffer": "5.1.2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", + "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", + "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" + }, + "node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/destroy": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", + "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" + }, + "node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/express": { + "version": "4.17.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", + "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", + "dependencies": { + "accepts": "~1.3.7", + "array-flatten": "1.1.1", + "body-parser": "1.19.0", + "content-disposition": "0.5.3", + "content-type": "~1.0.4", + "cookie": "0.4.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "~1.1.2", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "~1.1.2", + "fresh": "0.5.2", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.5", + "qs": "6.7.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.1.2", + "send": "0.17.1", + "serve-static": "1.14.1", + "setprototypeof": "1.1.1", + "statuses": "~1.5.0", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/express-validator": { + "version": "6.9.2", + "resolved": "https://registry.npmjs.org/express-validator/-/express-validator-6.9.2.tgz", + "integrity": "sha512-Yqlsw2/uBobtBVkP+gnds8OMmVAEb3uTI4uXC93l0Ym5JGHgr8Vd4ws7oSo7GGYpWn5YCq4UePMEppKchURXrw==", + "dependencies": { + "lodash": "^4.17.20", + "validator": "^13.5.2" + }, + "engines": { + "node": ">= 8.0.0" + } + }, + "node_modules/finalhandler": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", + "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "statuses": "~1.5.0", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/forwarded": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", + "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/http-errors": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", + "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", + "dependencies": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.1", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/lodash": { + "version": "4.17.20", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", + "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==" + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/mime-db": { + "version": "1.45.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.45.0.tgz", + "integrity": "sha512-CkqLUxUk15hofLoLyljJSrukZi8mAtgd+yE5uO4tqRZsdsAJKv0O+rFMhVDRJgozy+yG6md5KwuXhD4ocIoP+w==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.28", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.28.tgz", + "integrity": "sha512-0TO2yJ5YHYr7M2zzT7gDU1tbwHxEUWBCLt0lscSNpcdAfFyJOVEpRYNS7EXVcTLNj/25QO8gulHC5JtTzSE2UQ==", + "dependencies": { + "mime-db": "1.45.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "node_modules/negotiator": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", + "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" + }, + "node_modules/proxy-addr": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz", + "integrity": "sha512-dh/frvCBVmSsDYzw6n926jv974gddhkFPfiN8hPOi30Wax25QZyZEGveluCgliBnqmuM+UJmBErbAUFIoDbjOw==", + "dependencies": { + "forwarded": "~0.1.2", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/qs": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", + "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", + "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", + "dependencies": { + "bytes": "3.1.0", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "node_modules/send": { + "version": "0.17.1", + "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", + "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", + "dependencies": { + "debug": "2.6.9", + "depd": "~1.1.2", + "destroy": "~1.0.4", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "~1.7.2", + "mime": "1.6.0", + "ms": "2.1.1", + "on-finished": "~2.3.0", + "range-parser": "~1.2.1", + "statuses": "~1.5.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" + }, + "node_modules/serve-static": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", + "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", + "dependencies": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.17.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/setprototypeof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", + "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" + }, + "node_modules/statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/toidentifier": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", + "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/validator": { + "version": "13.5.2", + "resolved": "https://registry.npmjs.org/validator/-/validator-13.5.2.tgz", + "integrity": "sha512-mD45p0rvHVBlY2Zuy3F3ESIe1h5X58GPfAtslBjY7EtTqGquZTj+VX/J4RnHWN8FKq0C9WRVt1oWAcytWRuYLQ==", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", + "engines": { + "node": ">= 0.8" + } + } + }, + "dependencies": { + "accepts": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", + "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", + "requires": { + "mime-types": "~2.1.24", + "negotiator": "0.6.2" + } + }, + "array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" + }, + "body-parser": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", + "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", + "requires": { + "bytes": "3.1.0", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "~1.1.2", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "on-finished": "~2.3.0", + "qs": "6.7.0", + "raw-body": "2.4.0", + "type-is": "~1.6.17" + } + }, + "bytes": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", + "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==" + }, + "content-disposition": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", + "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", + "requires": { + "safe-buffer": "5.1.2" + } + }, + "content-type": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", + "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" + }, + "cookie": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", + "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==" + }, + "cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" + }, + "destroy": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", + "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" + }, + "ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" + }, + "encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" + }, + "escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" + }, + "etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" + }, + "express": { + "version": "4.17.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", + "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", + "requires": { + "accepts": "~1.3.7", + "array-flatten": "1.1.1", + "body-parser": "1.19.0", + "content-disposition": "0.5.3", + "content-type": "~1.0.4", + "cookie": "0.4.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "~1.1.2", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "~1.1.2", + "fresh": "0.5.2", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.5", + "qs": "6.7.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.1.2", + "send": "0.17.1", + "serve-static": "1.14.1", + "setprototypeof": "1.1.1", + "statuses": "~1.5.0", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + } + }, + "express-validator": { + "version": "6.9.2", + "resolved": "https://registry.npmjs.org/express-validator/-/express-validator-6.9.2.tgz", + "integrity": "sha512-Yqlsw2/uBobtBVkP+gnds8OMmVAEb3uTI4uXC93l0Ym5JGHgr8Vd4ws7oSo7GGYpWn5YCq4UePMEppKchURXrw==", + "requires": { + "lodash": "^4.17.20", + "validator": "^13.5.2" + } + }, + "finalhandler": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", + "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", + "requires": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "statuses": "~1.5.0", + "unpipe": "~1.0.0" + } + }, + "forwarded": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", + "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=" + }, + "fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" + }, + "http-errors": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", + "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.1", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.0" + } + }, + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + }, + "ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==" + }, + "lodash": { + "version": "4.17.20", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", + "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==" + }, + "media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" + }, + "merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" + }, + "methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" + }, + "mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" + }, + "mime-db": { + "version": "1.45.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.45.0.tgz", + "integrity": "sha512-CkqLUxUk15hofLoLyljJSrukZi8mAtgd+yE5uO4tqRZsdsAJKv0O+rFMhVDRJgozy+yG6md5KwuXhD4ocIoP+w==" + }, + "mime-types": { + "version": "2.1.28", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.28.tgz", + "integrity": "sha512-0TO2yJ5YHYr7M2zzT7gDU1tbwHxEUWBCLt0lscSNpcdAfFyJOVEpRYNS7EXVcTLNj/25QO8gulHC5JtTzSE2UQ==", + "requires": { + "mime-db": "1.45.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "negotiator": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", + "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==" + }, + "on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "requires": { + "ee-first": "1.1.1" + } + }, + "parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" + }, + "path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" + }, + "proxy-addr": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz", + "integrity": "sha512-dh/frvCBVmSsDYzw6n926jv974gddhkFPfiN8hPOi30Wax25QZyZEGveluCgliBnqmuM+UJmBErbAUFIoDbjOw==", + "requires": { + "forwarded": "~0.1.2", + "ipaddr.js": "1.9.1" + } + }, + "qs": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", + "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==" + }, + "range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" + }, + "raw-body": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", + "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", + "requires": { + "bytes": "3.1.0", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "send": { + "version": "0.17.1", + "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", + "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", + "requires": { + "debug": "2.6.9", + "depd": "~1.1.2", + "destroy": "~1.0.4", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "~1.7.2", + "mime": "1.6.0", + "ms": "2.1.1", + "on-finished": "~2.3.0", + "range-parser": "~1.2.1", + "statuses": "~1.5.0" + }, + "dependencies": { + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" + } + } + }, + "serve-static": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", + "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", + "requires": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.17.1" + } + }, + "setprototypeof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", + "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" + }, + "statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" + }, + "toidentifier": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", + "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==" + }, + "type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "requires": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + } + }, + "unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" + }, + "utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" + }, + "validator": { + "version": "13.5.2", + "resolved": "https://registry.npmjs.org/validator/-/validator-13.5.2.tgz", + "integrity": "sha512-mD45p0rvHVBlY2Zuy3F3ESIe1h5X58GPfAtslBjY7EtTqGquZTj+VX/J4RnHWN8FKq0C9WRVt1oWAcytWRuYLQ==" + }, + "vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" + } + } +} diff --git a/api/package.json b/api/package.json new file mode 100644 index 0000000..cf6bf15 --- /dev/null +++ b/api/package.json @@ -0,0 +1,16 @@ +{ + "name": "api", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "keywords": [], + "author": "", + "license": "ISC", + "dependencies": { + "express": "^4.17.1", + "express-validator": "^6.9.2" + } +} diff --git a/api/src/index.js b/api/src/index.js new file mode 100644 index 0000000..a2b5265 --- /dev/null +++ b/api/src/index.js @@ -0,0 +1,79 @@ +const express = require('express'); +const { execute } = require('../../shared/execute'); +const { languages } = require('./languages'); +const { checkSchema, validationResult } = require('express-validator'); + +const PORT = 2000; + +const app = express(); +app.use(express.json()); + +app.post( + '/execute', + checkSchema({ + language: { + in: 'body', + notEmpty: { + errorMessage: 'No language supplied', + }, + isString: { + errorMessage: 'Supplied language is not a string', + }, + custom: { + options: value => value && languages.find(language => language.aliases.includes(value.toLowerCase())), + errorMessage: 'Supplied language is not supported by Piston', + }, + }, + source: { + in: 'body', + notEmpty: { + errorMessage: 'No source supplied', + }, + isString: { + errorMessage: 'Supplied source is not a string', + }, + }, + args: { + in: 'body', + optional: true, + isArray: { + errorMessage: 'Supplied args is not an array', + }, + }, + stdin: { + in: 'body', + optional: true, + isString: { + errorMessage: 'Supplied stdin is not a string', + }, + } + }), + async (req, res) => { + const errors = validationResult(req).array(); + + if (errors.length === 0) { + const language = languages.find(language => + language.aliases.includes(req.body.language.toLowerCase()) + ); + + const { stdout, stderr, output, ran } = await execute(language, req.body.source, req.body.stdin, req.body.args); + + res.status(200).json({ + ran, + language: language.name, + version: language.version, + stdout, + stderr, + output, + }); + } else { + res.status(400).json({ + message: errors[0].msg, + }); + } + }, +); + +app.get('/versions', (_, res) => res.json(languages)); + +app.listen(PORT, () => console.log(`Listening on port ${PORT}`)); diff --git a/api/src/languages.js b/api/src/languages.js new file mode 100644 index 0000000..23e352a --- /dev/null +++ b/api/src/languages.js @@ -0,0 +1,39 @@ +const { spawn } = require('child_process'); +const languages = require('../../shared/languages.json'); + +{ + const process = spawn(__dirname + '/../../lxc/versions'); + + let output = ''; + process.stderr.on('data', chunk => output += chunk); + process.stdout.on('data', chunk => output += chunk); + + process.on('exit', () => { + const sections = output.toLowerCase().split('---'); + const versions = {}; + + for (const section of sections) { + const lines = section.trim().split('\n'); + + if (lines.length >= 2) { + const language = lines[0]; + + if (language === 'java') { + versions[language] = /\d+/.exec(lines[1])?.[0]; + } else if (language === 'emacs') { + versions[language] = /\d+\.\d+/.exec(lines[1])?.[0]; + } else { + versions[language] = /\d+\.\d+\.\d+/.exec(section)?.[0]; + } + } + } + + for (const language of languages) { + language.version = versions[language.name]; + } + }); +} + +module.exports = { + languages, +}; diff --git a/api/start b/api/start index 9cf6e69..fe2024e 100755 --- a/api/start +++ b/api/start @@ -1,3 +1,3 @@ #!/usr/bin/env bash -go run main.go $* +node src diff --git a/cli/execute b/cli/execute new file mode 100755 index 0000000..a8dc72c --- /dev/null +++ b/cli/execute @@ -0,0 +1,32 @@ +#!/usr/bin/env node + +const { execute } = require('../shared/execute'); +const { readFileSync } = require('fs'); +const languages = require('../shared/languages.json'); + +const [languageName, sourceFile, ...args] = process.argv.slice(2); + +(async () => { + if (!languageName) { + console.error('Provide a language name'); + return; + } + + if (!sourceFile) { + console.error('Provide a source file'); + return; + } + + const source = readFileSync(sourceFile).toString(); + + const language = languages.find(language => language.aliases.includes(languageName.toLowerCase())); + + if (!language) { + console.error(`${languageName} is not supported by Piston`); + return; + } + + const { output } = await execute(language, source, '', args); + + console.log(output); +})(); diff --git a/lxc/execute b/lxc/execute index 6a8c4ee..824b578 100755 --- a/lxc/execute +++ b/lxc/execute @@ -4,11 +4,7 @@ dir="$( cd "$( dirname "$0" )" && pwd )" touch $dir/lockfile -if [ -z "$1" ]; then - echo "invalid args" - exit -fi -if [ -z "$2" ]; then +if [ -z "$1" ] || [ -z "$2" ]; then echo "invalid args" exit fi @@ -18,13 +14,15 @@ epoch=$(date +%s%N) basepath="/var/lib/lxc/piston/rootfs" filepath="/tmp/$epoch/code.code" argpath="/tmp/$epoch/args.args" +stdinpath="/tmp/$epoch/stdin.stdin" arg=$(basename $argpath) # write arg file mkdir -p $basepath/tmp/$epoch chmod 777 $basepath/tmp/$epoch cat $2 > $basepath$filepath -echo "${@:3}" > $basepath$argpath +echo $3 > $basepath$stdinpath +echo -n "${@:4}" > $basepath$argpath # process incrementor exec 200>$dir/lockfile @@ -40,116 +38,24 @@ else fi exec 200>&- -bin= -case "$lang" in -"awk") - bin=awk - ;; -"bash") - bin=bash - ;; -"brainfuck" | "bf") - bin=brainfuck - ;; -"c") - bin=c - ;; -"cpp" | "c++") - bin=cpp - ;; -"csharp" | "cs" | "c#") - bin=csharp - ;; -"d") - bin=d - ;; -"elixir" | "exs") - bin=elixir - ;; -"go") - bin=go - ;; -"haskell" | "hs") - bin=haskell - ;; -"java") - bin=java - ;; -"jelly") - bin=jelly - ;; -"julia" | "jl") - bin=julia - ;; -"kotlin") - bin=kotlin - ;; -"lua") - bin=lua - ;; -"nasm" | "asm") - bin=nasm - ;; -"nasm64" | "asm64") - bin=nasm64 - ;; -"nim") - bin=nim - ;; -"node" | "js" | "javascript") - bin=node - ;; -"deno" | "denojs" | "denots") - bin=deno - ;; -"paradoc") - bin=paradoc - ;; -"perl") - bin=perl - ;; -"php") - bin=php - ;; -"python2") - bin=python2 - ;; -"python3" | "python") - bin=python3 - ;; -"ruby") - bin=ruby - ;; -"rust") - bin=rust - ;; -"swift") - bin=swift - ;; -"emacs" | "elisp" | "el") - bin=emacs - ;; -"bash") - bin=bash - ;; -"typescript" | "ts") - bin=typescript - ;; -*) - echo "invalid language" - exit -esac - # runner -timeout -s KILL 10 \ +timeout -s KILL 20 \ lxc-attach --clear-env -n piston -- \ - /bin/bash -l -c "bash /exec/$bin $newinc $epoch 2>&1 | head -c 65536" + /bin/bash -l -c "runuser runner$newinc /exec/$lang $newinc $epoch" # 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 & + /bin/bash -l -c " + for i in {1..100} + do + pkill -u runner$newinc --signal SIGKILL + done + + find /tmp -user runner$newinc -delete + find /var/tmp -user runner$newinc -delete + find /var/lock -user runner$newinc -delete + find /dev/shm -user runner$newinc -delete + find /run/lock -user runner$newinc -delete + " > /dev/null 2>&1 & rm -rf $basepath/tmp/$epoch diff --git a/lxc/executors/awk b/lxc/executors/awk index 26723b3..395424f 100755 --- a/lxc/executors/awk +++ b/lxc/executors/awk @@ -1,4 +1,4 @@ +#!/bin/bash + cd /tmp/$2 -timeout -s KILL 2 sed "/___code___/Q" code.code > code.stdin -timeout -s KILL 2 sed "1,/___code___/d" code.code > code.awk -runuser runner$1 -c "cd /tmp/$2 ; timeout -s KILL 3 awk -f code.awk < code.stdin" +timeout -s KILL 3 xargs -a args.args -d '\n' awk -f code.code < stdin.stdin diff --git a/lxc/executors/bash b/lxc/executors/bash index c13ad07..6aeb899 100755 --- a/lxc/executors/bash +++ b/lxc/executors/bash @@ -1,2 +1,4 @@ +#!/bin/bash + cd /tmp/$2 -runuser runner$1 -c "cd /tmp/$2 ; cat args.args | xargs -d '\n' timeout -s KILL 3 bash code.code" +xargs -a args.args -d '\n' timeout -s KILL 3 bash code.code < stdin.stdin diff --git a/lxc/executors/brainfuck b/lxc/executors/brainfuck index b4458a0..7ec1bfe 100755 --- a/lxc/executors/brainfuck +++ b/lxc/executors/brainfuck @@ -1,2 +1,4 @@ +#!/bin/bash + cd /tmp/$2 -runuser runner$1 -c "cd /tmp/$2 ; cat args.args | xargs -d '\n' timeout -s KILL 3 brainfuck code.code" +timeout -s KILL 3 xargs -a args.args -d '\n' brainfuck code.code < stdin.stdin diff --git a/lxc/executors/c b/lxc/executors/c index 5b3d84c..096b1d9 100755 --- a/lxc/executors/c +++ b/lxc/executors/c @@ -1,3 +1,5 @@ +#!/usr/bin/bash + cd /tmp/$2 -timeout -s KILL 10 gcc -std=c11 -o binary -x c code.code -runuser runner$1 -c "cd /tmp/$2 ; cat args.args | xargs -d '\n' timeout -s KILL 3 ./binary" +gcc -std=c11 -o binary -x c code.code +timeout -s KILL 3 xargs -a args.args ./binary < stdin.stdin diff --git a/lxc/executors/cpp b/lxc/executors/cpp index c4f6471..5f7008b 100755 --- a/lxc/executors/cpp +++ b/lxc/executors/cpp @@ -1,3 +1,5 @@ +#!/bin/bash + cd /tmp/$2 -timeout -s KILL 10 g++ -std=c++17 -o binary -x c++ code.code -runuser runner$1 -c "cd /tmp/$2 ; cat args.args | xargs -d '\n' timeout -s KILL 3 ./binary" +g++ -std=c++17 -o binary -x c++ code.code +timeout -s KILL 3 xargs -a args.args -d '\n' ./binary < stdin.stdin diff --git a/lxc/executors/csharp b/lxc/executors/csharp index 76b3338..f35c876 100755 --- a/lxc/executors/csharp +++ b/lxc/executors/csharp @@ -1,3 +1,5 @@ +#!/bin/bash + cd /tmp/$2 -timeout -s KILL 10 mcs $(echo code.code | sed 's/\///') -nowarn:0219 -out:binary -runuser runner$1 -c "cd /tmp/$2 ; cat args.args | xargs -d '\n' timeout -s KILL 3 mono binary" +mcs $(echo code.code | sed 's/\///') -nowarn:0219 -out:binary +timeout -s KILL 3 xargs -a args.args -d '\n' mono binary < stdin.stdin diff --git a/lxc/executors/d b/lxc/executors/d index bfceccb..60b3225 100644 --- a/lxc/executors/d +++ b/lxc/executors/d @@ -1,4 +1,6 @@ +#!/bin/bash + cd /tmp/$2 cp code.code code.d timeout -s KILL 10 dmd code.d -runuser runner$1 -c "cd /tmp/$2 ; cat args.args | xargs -d '\n' timeout -s KILL 3 ./code" +xtimeout -s KILL 3 args -a args.args -d '\n' ./code diff --git a/lxc/executors/deno b/lxc/executors/deno index b466288..31132fa 100755 --- a/lxc/executors/deno +++ b/lxc/executors/deno @@ -1,7 +1,4 @@ -cd /tmp/$2 +#!/bin/bash -if [[ -z $(grep '[^[:space:]]' args.args) ]]; then - runuser runner$1 -c "cd /tmp/$2 ; timeout -s KILL 3 deno run code.code" -else - runuser runner$1 -c "cd /tmp/$2 ; cat args.args | xargs -d '\n' timeout -s KILL 3 deno run code.code" -fi +cd /tmp/$2 +timeout -s KILL 3 xargs -a args.args -d '\n' deno run code.code < stdin.stdin diff --git a/lxc/executors/elixir b/lxc/executors/elixir index 49f9679..1a8e23f 100755 --- a/lxc/executors/elixir +++ b/lxc/executors/elixir @@ -1,7 +1,6 @@ -cd /tmp/$2 +#!/bin/bash -if [[ -z $(grep '[^[:space:]]' args.args) ]]; then - runuser runner$1 -c "cd /tmp/$2 ; timeout -s KILL 3 elixir code.code" -else - runuser runner$1 -c "cd /tmp/$2 ; cat args.args ; xargs -d '\n' timeout -s KILL 3 elixir code.code" -fi +export LC_ALL="en_US.UTF-8" + +cd /tmp/$2 +timeout -s KILL 3 xargs -a args.args -d '\n' elixir code.code < stdin.stdin diff --git a/lxc/executors/emacs b/lxc/executors/emacs index 156723e..ab41624 100755 --- a/lxc/executors/emacs +++ b/lxc/executors/emacs @@ -1,7 +1,4 @@ -cd /tmp/$2 +#!/bin/bash -if [[ -z $(grep '[^[:space:]]' args.args) ]]; then - runuser -l runner$1 -c "cd /tmp/$2 ; timeout -s KILL 3 emacs -Q --script code.code" -else - runuser -l runner$1 -c "cd /tmp/$2 ; cat args.args | xargs -d '\n' timeout -s KILL 3 emacs -Q --script code.code" -fi +cd /tmp/$2 +timeout -s KILL 3 xargs -a args.args -d '\n' emacs -Q --script code.code < stdin.stdin diff --git a/lxc/executors/go b/lxc/executors/go index e7903d1..09c1e68 100755 --- a/lxc/executors/go +++ b/lxc/executors/go @@ -1,6 +1,6 @@ +#!/bin/bash + cd /tmp/$2 cp code.code interim.go -file="interim.go" -timeout -s KILL 10 go build $file -file=${file%%.*} -runuser runner$1 -c "cd /tmp/$2 ; cat args.args | xargs -d '\n' timeout -s KILL 3 ./$file" +go build interim.go +timeout -s KILL 3 xargs -a args.args -d '\n' ./interim < stdin.stdin diff --git a/lxc/executors/haskell b/lxc/executors/haskell index edde524..df517d9 100755 --- a/lxc/executors/haskell +++ b/lxc/executors/haskell @@ -1,4 +1,6 @@ +#!/bin/bash + cd /tmp/$2 -mv code.code code.hs -timeout -s KILL 10 ghc -dynamic -o binary code.hs > /dev/null 2>&1 -runuser runner$1 -c "cd /tmp/$2 ; cat args.args | xargs -d '\n' timeout -s KILL 3 ./binary" +cp code.code code.hs +ghc -dynamic -o binary code.hs > /dev/null 2>&1 +timeout -s KILL 3 xargs -a args.args -d '\n' ./binary < stdin.stdin diff --git a/lxc/executors/java b/lxc/executors/java index 66261bb..5539c4a 100755 --- a/lxc/executors/java +++ b/lxc/executors/java @@ -1,6 +1,7 @@ +#!/bin/bash + cd /tmp/$2 -cp code.code interim.java -name=$(grep -Po "(?<=\n|\A)\s*(public\s+)?(class|interface)\s+\K([^\n\s{]+)" interim.java) -mv interim.java $name.java -timeout -s KILL 10 javac $name.java -runuser runner$1 -c "cd /tmp/$2 ; cat args.args | xargs -d '\n' timeout -s KILL 3 java $name" +name=$(grep -Po "(?<=\n|\A)\s*(public\s+)?(class|interface)\s+\K([^\/\\\\\n\s{]+)" code.code) +cp code.code $name.java +javac $name.java +timeout -s KILL 3 xargs -a args.args -d '\n' java $name < stdin.stdin diff --git a/lxc/executors/jelly b/lxc/executors/jelly index 4107b6b..945444e 100755 --- a/lxc/executors/jelly +++ b/lxc/executors/jelly @@ -1,2 +1,4 @@ +#!/bin/bash + cd /tmp/$2 -runuser runner$1 -c "cd /tmp/$2 ; cat args.args | xargs -d '\n' timeout -s KILL 3 jelly fu code.code" +timeout -s KILL 3 xargs -a args.args -d '\n' jelly fu code.code < stdin.stdin diff --git a/lxc/executors/julia b/lxc/executors/julia index 7dddb24..e8b4ea5 100755 --- a/lxc/executors/julia +++ b/lxc/executors/julia @@ -1,2 +1,4 @@ +#!/bin/bash + cd /tmp/$2 -runuser runner$1 -c "cd /tmp/$2 ; cat args.args | xargs -d '\n' timeout -s KILL 3 julia code.code" +timeout -s KILL 3 xargs -a args.args -d '\n' julia code.code < stdin.stdin diff --git a/lxc/executors/kotlin b/lxc/executors/kotlin index dcd5eff..c304575 100755 --- a/lxc/executors/kotlin +++ b/lxc/executors/kotlin @@ -1,4 +1,6 @@ +#!/bin/bash + cd /tmp/$2 cp code.code code.kt -timeout -s KILL 10 kotlinc code.kt -include-runtime -d code.jar -runuser runner$1 -c "cd /tmp/$2 ; cat args.args | xargs -d '\n' timeout -s KILL 3 java -jar code.jar" +kotlinc code.kt -include-runtime -d code.jar +timeout -s KILL 3 xargs -a args.args -d '\n' java -jar code.jar < stdin.stdin diff --git a/lxc/executors/lua b/lxc/executors/lua index b412013..4caa4b6 100755 --- a/lxc/executors/lua +++ b/lxc/executors/lua @@ -1,2 +1,4 @@ +#!/bin/bash + cd /tmp/$2 -runuser runner$1 -c "cd /tmp/$2 ; cat args.args | xargs -d '\n' timeout -s KILL 3 lua code.code" +timeout -s KILL 3 xargs -a args.args -d '\n' lua code.code < stdin.stdin diff --git a/lxc/executors/nasm b/lxc/executors/nasm index 60c4963..ffe8fd0 100755 --- a/lxc/executors/nasm +++ b/lxc/executors/nasm @@ -1,4 +1,6 @@ +#!/bin/bash + cd /tmp/$2 -timeout -s KILL 10 nasm -f elf32 -o binary.o code.code -timeout -s KILL 10 ld -m elf_i386 binary.o -o binary -runuser runner$1 -c "cd /tmp/$2 ; cat args.args | xargs -d '\n' timeout -s KILL 3 ./binary" +nasm -f elf32 -o binary.o code.code +ld -m elf_i386 binary.o -o binary +timeout -s KILL 3 xargs -a args.args -d '\n' ./binary < stdin.stdin diff --git a/lxc/executors/nasm64 b/lxc/executors/nasm64 index 8723995..98c2aab 100755 --- a/lxc/executors/nasm64 +++ b/lxc/executors/nasm64 @@ -1,4 +1,6 @@ +#!/bin/bash + cd /tmp/$2 -timeout -s KILL 10 nasm -f elf64 -o binary.o code.code -timeout -s KILL 10 ld -m elf_x86_64 binary.o -o binary -runuser runner$1 -c "cd /tmp/$2 ; cat args.args | xargs -d '\n' timeout -s KILL 3 ./binary" +nasm -f elf64 -o binary.o code.code +ld -m elf_x86_64 binary.o -o binary +timeout -s KILL 3 xargs -a args.args -d '\n' ./binary < stdin.stdin diff --git a/lxc/executors/nim b/lxc/executors/nim deleted file mode 100755 index c6e6caf..0000000 --- a/lxc/executors/nim +++ /dev/null @@ -1,4 +0,0 @@ -cd /tmp/$2 -timeout -s KILL 10 nim --hints:off c code.code -runuser runner$1 -c "cd /tmp/$2 ; cat args.args | xargs -d '\n' timeout -s KILL 3 ./code" - diff --git a/lxc/executors/node b/lxc/executors/node index 5fd7d26..3262b53 100755 --- a/lxc/executors/node +++ b/lxc/executors/node @@ -1,7 +1,4 @@ -cd /tmp/$2 +#!/bin/bash -if [[ -z $(grep '[^[:space:]]' args.args) ]]; then - runuser runner$1 -c "cd /tmp/$2 ; timeout -s KILL 3 node code.code" -else - runuser runner$1 -c "cd /tmp/$2 ; cat args.args | xargs -d '\n' timeout -s KILL 3 node code.code" -fi +cd /tmp/$2 +timeout -s KILL 3 xargs -a args.args -d '\n' node code.code < stdin.stdin diff --git a/lxc/executors/paradoc b/lxc/executors/paradoc index 33fe880..f82630a 100755 --- a/lxc/executors/paradoc +++ b/lxc/executors/paradoc @@ -1,2 +1,5 @@ +#!/bin/bash + cd /tmp/$2 -runuser runner$1 -c "cd /tmp/$2 ; timeout -s KILL 3 python3 -m paradoc code.code <<< args.args" +export PYTHONPATH=$PYTHONPATH:/opt/paradoc +timeout -s KILL 3 python3.8 -m paradoc code.code < args.args diff --git a/lxc/executors/perl b/lxc/executors/perl index afb8ad5..8b65855 100755 --- a/lxc/executors/perl +++ b/lxc/executors/perl @@ -1,2 +1,4 @@ +#!/bin/bash + cd /tmp/$2 -runuser runner$1 -c "cd /tmp/$2 ; cat args.args | xargs -d '\n' timeout -s KILL 3 perl code.code" +timeout -s KILL 3 xargs -a args.args -d '\n' perl code.code < stdin.stdin diff --git a/lxc/executors/php b/lxc/executors/php index d88a8d2..9f21f7b 100755 --- a/lxc/executors/php +++ b/lxc/executors/php @@ -1,2 +1,4 @@ +#!/bin/bash + cd /tmp/$2 -runuser runner$1 -c "cd /tmp/$2 ; cat args.args | xargs -d '\n' timeout -s KILL 3 php code.code" +timeout -s KILL 3 xargs -a args.args -d '\n' php code.code < stdin.stdin diff --git a/lxc/executors/python2 b/lxc/executors/python2 index d172f18..5fa1c3e 100755 --- a/lxc/executors/python2 +++ b/lxc/executors/python2 @@ -1,2 +1,4 @@ +#!/bin/bash + cd /tmp/$2 -runuser runner$1 -c "cd /tmp/$2 ; cat args.args | xargs -d '\n' timeout -s KILL 3 python code.code" +timeout -s KILL 3 xargs -a args.args -d '\n' python code.code < stdin.stdin diff --git a/lxc/executors/python3 b/lxc/executors/python3 index 0749d88..6cb93f8 100755 --- a/lxc/executors/python3 +++ b/lxc/executors/python3 @@ -1,2 +1,4 @@ +#!/bin/bash + cd /tmp/$2 -runuser runner$1 -c "cd /tmp/$2 ; cat args.args | xargs -d '\n' timeout -s KILL 3 python3.8 code.code" +timeout -s KILL 3 xargs -a args.args -d '\n' python3.8 code.code < stdin.stdin diff --git a/lxc/executors/ruby b/lxc/executors/ruby index 9de7477..ebb9b06 100755 --- a/lxc/executors/ruby +++ b/lxc/executors/ruby @@ -1,2 +1,4 @@ +#!/bin/bash + cd /tmp/$2 -runuser runner$1 -c "cd /tmp/$2 ; cat args.args | xargs -d '\n' timeout -s KILL 3 ruby code.code" +timeout -s KILL 3 xargs -a args.args -d '\n' ruby code.code < stdin.stdin diff --git a/lxc/executors/rust b/lxc/executors/rust index aef4af3..137dffa 100755 --- a/lxc/executors/rust +++ b/lxc/executors/rust @@ -1,3 +1,5 @@ +#!/bin/bash + cd /tmp/$2 -timeout -s KILL 10 rustc -o binary code.code -runuser runner$1 -c "cd /tmp/$2 ; cat args.args | xargs -d '\n' timeout -s KILL 3 ./binary" +rustc -o binary code.code +timeout -s KILL 3 xargs -a args.args -d '\n' ./binary < stdin.stdin diff --git a/lxc/executors/swift b/lxc/executors/swift index 4b5d8a1..a8327f7 100755 --- a/lxc/executors/swift +++ b/lxc/executors/swift @@ -1,2 +1,4 @@ +#!/bin/bash + cd /tmp/$2 -runuser runner$1 -c "cd /tmp/$2 ; cat args.args | xargs -d '\n' timeout -s KILL 3 swift code.code" +timeout -s KILL 3 xargs -a args.args -d '\n' swift code.code < stdin.stdin diff --git a/lxc/executors/typescript b/lxc/executors/typescript index 5ed50c5..8c1873d 100755 --- a/lxc/executors/typescript +++ b/lxc/executors/typescript @@ -1,6 +1,8 @@ +#!/bin/bash + cd /tmp/$2 mv code.code interim.ts -timeout -s KILL 10 tsc interim.ts -rm interim.ts +tsc interim.ts +rm -f interim.ts mv interim.js code.code -runuser runner$1 -c "cd /tmp/$2 ; cat args.args | xargs -d '\n' timeout -s KILL 3 node code.code" +timeout -s KILL 3 xargs -a args.args -d '\n' node code.code < stdin.stdin diff --git a/lxc/start b/lxc/start index 6c13c98..fec7aef 100755 --- a/lxc/start +++ b/lxc/start @@ -3,7 +3,7 @@ mkdir -p /var/lib/lxc/piston/rootfs/exec rm -f /var/lib/lxc/piston/rootfs/exec/* cp -f executors/* /var/lib/lxc/piston/rootfs/exec -chmod 700 /var/lib/lxc/piston/rootfs/exec/* +chmod 555 /var/lib/lxc/piston/rootfs/exec/* chown -R root:root /var/lib/lxc/piston/rootfs/exec lxc-start -n piston -d diff --git a/lxc/test_all_lxc b/lxc/test_all_lxc index 070b4b8..31f236f 100755 --- a/lxc/test_all_lxc +++ b/lxc/test_all_lxc @@ -1,57 +1,57 @@ #!/usr/bin/env bash cd tests -echo 'testing awk' -../execute awk test.awk -echo 'testing c' -../execute c test.c -echo 'testing cpp' -../execute cpp test.cpp -echo 'testing cs' -../execute cs test.cs -echo 'testing d' -../execute d test.d -echo 'testing deno ts' -../execute deno testdeno.ts -echo 'testing elisp' -../execute elisp test.el -echo 'testing elixir' -../execute exs test.exs -echo 'testing go' -../execute go test.go -echo 'testing haskell' -../execute haskell test.hs -echo 'testing java' -../execute java test.java -echo 'testing jl' -../execute jl test.jl -echo 'testing js' -../execute js test.js -echo 'testing kotlin' -../execute kotlin test.kt -echo 'testing asm 32 bit' -../execute asm test.nasm -echo 'testing asm 64 bit' -../execute asm64 test64.nasm -echo 'testing nim' -../execute nim test.nim -echo 'testing php' -../execute php test.php -echo 'testing perl' -../execute perl test.pl -echo 'testing ruby' -../execute ruby test.rb -echo 'testing rust' -../execute rust test.rs -echo 'testing bash' -../execute bash test.sh -echo 'testing swift' -../execute swift test.swift -echo 'testing typescript' -../execute typescript test.ts -echo 'testing python2' -../execute python2 test2.py -echo 'testing python3' -../execute python3 test3.py -echo 'testing paradoc' -../execute python3 test_paradoc.py +echo -n 'testing awk = ' +../../cli/execute awk awk.awk +echo -n 'testing bash = ' +../../cli/execute bash bash.sh +echo -n 'testing c = ' +../../cli/execute c c.c +echo -n 'testing cpp = ' +../../cli/execute cpp cpp.cpp +echo -n 'testing csharp = ' +../../cli/execute csharp csharp.cs +echo -n 'testing d = ' +../../cli/execute d test.d +echo -n 'testing deno = ' +../../cli/execute deno deno.ts +echo -n 'testing elixir = ' +../../cli/execute elixir elixir.exs +echo -n 'testing emacs = ' +../../cli/execute emacs emacs.el +echo -n 'testing go = ' +../../cli/execute go go.go +echo -n 'testing haskell = ' +../../cli/execute haskell haskell.hs +echo -n 'testing java = ' +../../cli/execute java java.java +echo -n 'testing jelly = ' +../../cli/execute jelly jelly.jelly good +echo -n 'testing julia = ' +../../cli/execute julia julia.jl +echo -n 'testing kotlin = ' +../../cli/execute kotlin kotlin.kt +echo -n 'testing nasm 32 bit = ' +../../cli/execute nasm nasm.nasm +echo -n 'testing nasm 64 bit = ' +../../cli/execute nasm64 nasm64.nasm +echo -n 'testing node = ' +../../cli/execute node node.js +echo -n 'testing paradoc = ' +../../cli/execute bash paradoc.sh +echo -n 'testing perl = ' +../../cli/execute perl perl.pl +echo -n 'testing php = ' +../../cli/execute php php.php +echo -n 'testing python2 = ' +../../cli/execute python2 python2.py +echo -n 'testing python3 = ' +../../cli/execute python3 python3.py +echo -n 'testing ruby = ' +../../cli/execute ruby ruby.rb +echo -n 'testing rust = ' +../../cli/execute rust rust.rs +echo -n 'testing swift = ' +../../cli/execute swift swift.swift +echo -n 'testing typescript = ' +../../cli/execute typescript typescript.ts diff --git a/lxc/tests/awk.awk b/lxc/tests/awk.awk new file mode 100644 index 0000000..c5ba5ad --- /dev/null +++ b/lxc/tests/awk.awk @@ -0,0 +1 @@ +{ print "good" } diff --git a/lxc/tests/test.sh b/lxc/tests/bash.sh similarity index 100% rename from lxc/tests/test.sh rename to lxc/tests/bash.sh diff --git a/lxc/tests/test.c b/lxc/tests/c.c similarity index 100% rename from lxc/tests/test.c rename to lxc/tests/c.c diff --git a/lxc/tests/test.cpp b/lxc/tests/cpp.cpp similarity index 100% rename from lxc/tests/test.cpp rename to lxc/tests/cpp.cpp diff --git a/lxc/tests/test.cs b/lxc/tests/csharp.cs similarity index 100% rename from lxc/tests/test.cs rename to lxc/tests/csharp.cs diff --git a/lxc/tests/testdeno.ts b/lxc/tests/deno.ts similarity index 100% rename from lxc/tests/testdeno.ts rename to lxc/tests/deno.ts diff --git a/lxc/tests/test.exs b/lxc/tests/elixir.exs similarity index 100% rename from lxc/tests/test.exs rename to lxc/tests/elixir.exs diff --git a/lxc/tests/test.el b/lxc/tests/emacs.el similarity index 100% rename from lxc/tests/test.el rename to lxc/tests/emacs.el diff --git a/lxc/tests/test.go b/lxc/tests/go.go similarity index 100% rename from lxc/tests/test.go rename to lxc/tests/go.go diff --git a/lxc/tests/test.hs b/lxc/tests/haskell.hs similarity index 100% rename from lxc/tests/test.hs rename to lxc/tests/haskell.hs diff --git a/lxc/tests/test.java b/lxc/tests/java.java similarity index 100% rename from lxc/tests/test.java rename to lxc/tests/java.java diff --git a/lxc/tests/jelly.jelly b/lxc/tests/jelly.jelly new file mode 100644 index 0000000..77a1774 --- /dev/null +++ b/lxc/tests/jelly.jelly @@ -0,0 +1 @@ +³ diff --git a/lxc/tests/test.jl b/lxc/tests/julia.jl similarity index 100% rename from lxc/tests/test.jl rename to lxc/tests/julia.jl diff --git a/lxc/tests/kotlin.kt b/lxc/tests/kotlin.kt new file mode 100644 index 0000000..1e0df2c --- /dev/null +++ b/lxc/tests/kotlin.kt @@ -0,0 +1,3 @@ +fun main() { + println("good") +} diff --git a/lxc/tests/test.nasm b/lxc/tests/nasm.nasm similarity index 100% rename from lxc/tests/test.nasm rename to lxc/tests/nasm.nasm diff --git a/lxc/tests/nasm64.nasm b/lxc/tests/nasm64.nasm new file mode 100644 index 0000000..fbc5aef --- /dev/null +++ b/lxc/tests/nasm64.nasm @@ -0,0 +1,18 @@ +SECTION .data + good: db "good", 0x0 + txtlen: equ $ - good + +SECTION .text +GLOBAL _start + +_start: + ;sys_write + mov rax, 1 + mov rdi, 1 + mov rsi, good + mov rdx, txtlen + syscall + ;sys_exit + mov rax, 60 + mov rdi, 0 + syscall diff --git a/lxc/tests/test.nim b/lxc/tests/nim.nim similarity index 100% rename from lxc/tests/test.nim rename to lxc/tests/nim.nim diff --git a/lxc/tests/test.js b/lxc/tests/node.js similarity index 100% rename from lxc/tests/test.js rename to lxc/tests/node.js diff --git a/lxc/tests/paradoc.sh b/lxc/tests/paradoc.sh new file mode 100644 index 0000000..5f70e1c --- /dev/null +++ b/lxc/tests/paradoc.sh @@ -0,0 +1,11 @@ +#!/usr/bin/env bash +# add paradoc module to python python +export PYTHONPATH=$PYTHONPATH:/opt/paradoc +# file for test code +test_code=/tmp/paradoc.test +# save test code to file +echo -n iP>$test_code +# pass param to paradoc module and have it print it +echo good | python3.8 -m paradoc $test_code +# clean test code +rm -f $test_code diff --git a/lxc/tests/test.pl b/lxc/tests/perl.pl similarity index 100% rename from lxc/tests/test.pl rename to lxc/tests/perl.pl diff --git a/lxc/tests/test.php b/lxc/tests/php.php similarity index 100% rename from lxc/tests/test.php rename to lxc/tests/php.php diff --git a/lxc/tests/test2.py b/lxc/tests/python2.py similarity index 100% rename from lxc/tests/test2.py rename to lxc/tests/python2.py diff --git a/lxc/tests/test3.py b/lxc/tests/python3.py similarity index 100% rename from lxc/tests/test3.py rename to lxc/tests/python3.py diff --git a/lxc/tests/test.rb b/lxc/tests/ruby.rb similarity index 100% rename from lxc/tests/test.rb rename to lxc/tests/ruby.rb diff --git a/lxc/tests/test.rs b/lxc/tests/rust.rs similarity index 100% rename from lxc/tests/test.rs rename to lxc/tests/rust.rs diff --git a/lxc/tests/test.swift b/lxc/tests/swift.swift similarity index 100% rename from lxc/tests/test.swift rename to lxc/tests/swift.swift diff --git a/lxc/tests/test.awk b/lxc/tests/test.awk deleted file mode 100644 index de48d9a..0000000 --- a/lxc/tests/test.awk +++ /dev/null @@ -1,3 +0,0 @@ -good -___code___ -{ print } diff --git a/lxc/tests/test.kt b/lxc/tests/test.kt deleted file mode 100644 index a6f9758..0000000 --- a/lxc/tests/test.kt +++ /dev/null @@ -1,3 +0,0 @@ -fun main(args: Array) { - println("good") -} diff --git a/lxc/tests/test64.nasm b/lxc/tests/test64.nasm deleted file mode 100644 index 191b8d3..0000000 --- a/lxc/tests/test64.nasm +++ /dev/null @@ -1,18 +0,0 @@ -SECTION .data - good: db "good", 0x0a, 0x0 - txtlen: equ $ - good - -SECTION .text -GLOBAL _start - -_start: - ;sys_write - mov rax, 1 - mov rdi, 1 - mov rsi, good - mov rdx, txtlen - syscall - ;sys_exit - mov rax, 60 - mov rdi, 0 - syscall diff --git a/lxc/tests/test_paradoc.py b/lxc/tests/test_paradoc.py deleted file mode 100644 index 3acba15..0000000 --- a/lxc/tests/test_paradoc.py +++ /dev/null @@ -1,5 +0,0 @@ -try: - import paradoc - print('good') -except: - pass diff --git a/lxc/tests/test.ts b/lxc/tests/typescript.ts similarity index 100% rename from lxc/tests/test.ts rename to lxc/tests/typescript.ts diff --git a/lxc/versions b/lxc/versions index a946e07..83edee9 100755 --- a/lxc/versions +++ b/lxc/versions @@ -14,11 +14,11 @@ echo '1.0.0' echo '---' echo 'c' -lxc-attach --clear-env -n piston -- /bin/bash -l -c "gcc -v" +lxc-attach --clear-env -n piston -- /bin/bash -l -c "gcc --version" echo '---' echo 'cpp' -lxc-attach --clear-env -n piston -- /bin/bash -l -c "g++ -v" +lxc-attach --clear-env -n piston -- /bin/bash -l -c "g++ --version" echo '---' echo 'csharp' @@ -73,8 +73,8 @@ echo 'nasm' lxc-attach --clear-env -n piston -- /bin/bash -l -c "nasm -version" echo '---' -echo 'nim' -lxc-attach --clear-env -n piston -- /bin/bash -l -c "nim -v | head -n1" +echo 'nasm64' +lxc-attach --clear-env -n piston -- /bin/bash -l -c "nasm -version" echo '---' echo 'node' @@ -94,11 +94,11 @@ lxc-attach --clear-env -n piston -- /bin/bash -l -c "python -V" echo '---' echo 'python3' -lxc-attach --clear-env -n piston -- /bin/bash -l -c "python3 -V" +lxc-attach --clear-env -n piston -- /bin/bash -l -c "python3.8 -V" echo '---' echo 'paradoc' -lxc-attach --clear-env -n piston -- /bin/bash -l -c "python3 -m paradoc --version" +lxc-attach --clear-env -n piston -- /bin/bash -l -c "python3.8 -m paradoc --version" echo '---' echo 'ruby' diff --git a/readme.md b/readme.md index 1abee11..07d1abe 100644 --- a/readme.md +++ b/readme.md @@ -1,348 +1,220 @@ -## Piston -Piston is the underlying engine for running untrusted and possibly malicious -code that originates from EMKC contests and challenges. It's also used in the -Engineer Man Discord server via [I Run Code](https://github.com/engineer-man/piston-bot) bot as well as 1000+ other servers. +

+ engineer-man piston + Piston +

+ +

A high performance general purpose code execution engine.

+
+ +

+ + GitHub last commit + + GitHub issues + + GitHub pull requests +

+ +--- + +

+ About • + Public API • + Getting Started • + Usage • + Supported Languages • + Principles • + Security • + License +

+ +--- +
+ +# About + +

+Piston is a high performance general purpose code execution engine. It excels at running untrusted and +possibly malicious code without fear from any harmful effects. +

+
+ +It's used in numerous places including: +* [EMKC Challenges](https://emkc.org/challenges), +* [EMKC Weekly Contests](https://emkc.org/contests), +* [Engineer Man Discord Server](https://discord.gg/engineerman), +* [I Run Code (Discord Bot)](https://github.com/engineer-man/piston-bot) bot as well as 1300+ other servers +and 100+ direct integrations. + To get it in your own server, go here: https://emkc.org/run. -#### Use Public API (new) -Requires no installation and you can use it immediately. Reference the API Usage section below to learn -about the request format but rather than using the local URLs, use the following URLs: -- `GET` `https://emkc.org/api/v1/piston/versions` -- `POST` `https://emkc.org/api/v1/piston/execute` +
-Important Note: The Piston API is rate limited to 5 requests per second +# Public API + +- Requires no installation and you can use it immediately. +- Reference the Versions/Execute sections below to learn about the request and response formats. + +
+ +When using the public Piston API, use the base URL: -#### Installation ``` -# clone and enter repo -git clone https://github.com/engineer-man/piston -cd piston/lxc +https://emkc.org/api/v1/piston +``` -# install dependencies +#### GET +``` +https://emkc.org/api/v1/piston/versions +``` +#### POST +``` +https://emkc.org/api/v1/piston/execute +``` + +> Important Note: The Piston API is rate limited to 5 requests per second. If you have a need for more requests than that +and it's for a good cause, please reach out to me (EngineerMan#0001) on [Discord](https://discord.gg/engineerman) +so we can discuss potentially getting you an unlimited key. + +
+ +# Getting Started + +### Host System Package Dependencies + +* NodeJS +* lxc +* libvirt + +
+ +If your OS is not documented below, please open pull requests with the correct commands for your OS. + +
+CentOS / RHEL + +```sh +curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.37.2/install.sh | bash +nvm install --lts +nvm use --lts -# centos: yum install -y epel-release yum install -y lxc lxc-templates debootstrap libvirt systemctl start libvirtd +``` +
-# ubuntu server 18.04: -apt install lxc lxc-templates debootstrap libvirt0 +
+Ubuntu (18.04) -# arch: -sudo pacman -S lxc libvirt unzip +```sh +curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.37.2/install.sh | bash +nvm install --lts +nvm use --lts -# everything else: -# not documented, please open pull requests with commands for debian/arch/macos +apt install -y lxc lxc-templates debootstrap libvirt0 +``` +
-# create and start container -lxc-create -t download -n piston -- --dist ubuntu --release bionic --arch amd64 -./start +
+Arch Linux -# open a shell to the container -./shell +```sh +curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.37.2/install.sh | bash +nvm install --lts +nvm use --lts -# install all necessary piston dependencies -echo 'source /opt/.profile' >> /opt/.bashrc -echo 'export HOME=/opt' >> /opt/.profile -echo 'export TERM=linux' >> /opt/.profile -echo 'export PATH=$PATH:/opt/.local/bin' >> /opt/.profile -export HOME=/opt -export TERM=linux -sed -i 's/\/root/\/opt/' /etc/passwd -sed -i \ - 's/http:\/\/archive.ubuntu.com\/ubuntu/http:\/\/mirror.math.princeton.edu\/pub\/ubuntu/' \ - /etc/apt/sources.list -apt-get update -apt-get install -y \ - nano wget build-essential pkg-config libxml2-dev \ - libsqlite3-dev mono-complete curl cmake libpython2.7-dev \ - ruby libtinfo-dev unzip +pacman -S lxc libvirt unzip +``` +
-# install python2 -# final binary: /opt/python2/Python-2.7.17/python -# get version: /opt/python2/Python-2.7.17/python -V -cd /opt && mkdir python2 && cd python2 -wget https://www.python.org/ftp/python/2.7.17/Python-2.7.17.tar.xz -unxz Python-2.7.17.tar.xz -tar -xf Python-2.7.17.tar -cd Python-2.7.17 -./configure -# open Modules/Setup and uncomment zlib line -make -echo 'export PATH=$PATH:/opt/python2/Python-2.7.17' >> /opt/.profile -source /opt/.profile +#### After system dependencies are installed, clone this repository: -# install python3 -# final binary: /opt/python3/Python-3.8.2/python -# get version: /opt/python3/Python-3.8.2/python -V -cd /opt && mkdir python3 && cd python3 -wget https://www.python.org/ftp/python/3.8.2/Python-3.8.2.tar.xz -unxz Python-3.8.2.tar.xz -tar -xf Python-3.8.2.tar -cd Python-3.8.2 -./configure -make -ln -s python python3.8 -echo 'export PATH=$PATH:/opt/python3/Python-3.8.2' >> /opt/.profile -source /opt/.profile - -# install paradoc -# this is not a binary, it is a python module -# therefore it cannot be run directly as it requires python3 to be installed -cd /opt && mkdir paradoc && cd paradoc -git clone https://github.com/betaveros/paradoc.git -echo 'export PYTHONPATH=$PYTHONPATH:/opt/paradoc/paradoc' >> /opt/.profile -source /opt/.profile - -# install node.js -# final binary: /opt/nodejs/node-v12.16.1-linux-x64/bin/node -# get version: /opt/nodejs/node-v12.16.1-linux-x64/bin/node -v -cd /opt && mkdir nodejs && cd nodejs -wget https://nodejs.org/dist/v12.16.1/node-v12.16.1-linux-x64.tar.xz -unxz node-v12.16.1-linux-x64.tar.xz -tar -xf node-v12.16.1-linux-x64.tar -echo 'export PATH=$PATH:/opt/nodejs/node-v12.16.1-linux-x64/bin' >> /opt/.profile -source /opt/.profile - -# install typescript -# final binary: /opt/nodejs/node-v12.16.1-linux-x64/bin/tsc -# get version: /opt/nodejs/node-v12.16.1-linux-x64/bin/tsc -v -/opt/nodejs/node-v12.16.1-linux-x64/bin/npm i -g typescript - -# install golang -# final binary: /opt/go/go/bin/go -# get version: /opt/go/go/bin/go version -cd /opt && mkdir go && cd go -wget https://dl.google.com/go/go1.14.1.linux-amd64.tar.gz -tar -xzf go1.14.1.linux-amd64.tar.gz -echo 'export PATH=$PATH:/opt/go/go/bin' >> /opt/.profile -echo 'export GOROOT=/opt/go/go' >> /opt/.profile -echo 'export GOCACHE=/tmp' >> /opt/.profile -source /opt/.profile - -# install php -# final binary: /usr/local/bin/php -# get version: /usr/local/bin/php -v -cd /opt && mkdir php && cd php -wget https://www.php.net/distributions/php-7.4.4.tar.gz -tar -xzf php-7.4.4.tar.gz -cd php-7.4.4 -./configure -make -make install - -# install rust -# final binary: /opt/.cargo/bin/rustc -# get version: /opt/.cargo/bin/rustc --version -curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -echo 'export PATH=$PATH:/opt/.cargo/bin' >> /opt/.profile -source /opt/.profile - -# install swift -# final binary: /opt/swift/swift-5.1.5-RELEASE-ubuntu18.04/usr/bin/swift -# get version: /opt/swift/swift-5.1.5-RELEASE-ubuntu18.04/usr/bin/swift --version -cd /opt && mkdir swift && cd swift -wget https://swift.org/builds/swift-5.1.5-release/ubuntu1804/swift-5.1.5-RELEASE/swift-5.1.5-RELEASE-ubuntu18.04.tar.gz -tar -xzf swift-5.1.5-RELEASE-ubuntu18.04.tar.gz -echo 'export PATH=$PATH:/opt/swift/swift-5.1.5-RELEASE-ubuntu18.04/usr/bin' >> /opt/.profile -source /opt/.profile - -# install nasm -# final binary: /opt/nasm/nasm-2.14.02/nasm -# get version: /opt/nasm/nasm-2.14.02/nasm -v -cd /opt && mkdir nasm && cd nasm -wget https://www.nasm.us/pub/nasm/releasebuilds/2.14.02/nasm-2.14.02.tar.gz -tar -xzf nasm-2.14.02.tar.gz -cd nasm-2.14.02 -./configure -make -echo 'export PATH=$PATH:/opt/nasm/nasm-2.14.02' >> /opt/.profile -source /opt/.profile - -# install java -# final binary: /opt/java/jdk-14/bin/java -# get version: /opt/java/jdk-14/bin/java -version -cd /opt && mkdir java && cd java -wget https://download.java.net/java/GA/jdk14/076bab302c7b4508975440c56f6cc26a/36/GPL/openjdk-14_linux-x64_bin.tar.gz -tar -xzf openjdk-14_linux-x64_bin.tar.gz -echo 'export PATH=$PATH:/opt/java/jdk-14/bin' >> /opt/.profile -source /opt/.profile - -# install jelly -cd /opt && mkdir jelly && cd jelly -wget https://github.com/DennisMitchell/jellylanguage/archive/master.zip -unzip master.zip -cd jellylanguage-master -pip3.8 install . - -# install julia -# final binary: /opt/julia/julia-1.5.0/bin/julia -# get version: /opt/julia/julia-1.5.0/bin/julia --version -cd /opt && mkdir julia && cd julia -wget https://julialang-s3.julialang.org/bin/linux/x64/1.5/julia-1.5.0-linux-x86_64.tar.gz -tar -xzf julia-1.5.0-linux-x86_64.tar.gz -echo 'export PATH=$PATH:/opt/julia/julia-1.5.0/bin' >> /opt/.profile -source /opt/.profile - -# install kotlin -# final binary: /opt/kotlinc/bin/kotlinc -# get version: /opt/kotlinc/bin/kotlinc -version -cd /opt -wget https://github.com/JetBrains/kotlin/releases/download/v1.4.10/kotlin-compiler-1.4.10.zip -unzip kotlin-compiler-1.4.10.zip -rm kotlin-compiler-1.4.10.zip -echo 'export PATH=$PATH:/opt/kotlinc/bin' >> /opt/.profile -source /opt/.profile - -# install elixir and erlang -# final binary: /opt/elixir/bin/elixir -# get version: /opt/elixir/bin/elixir --version -# erlang -cd /opt && mkdir erlang && cd erlang -wget http://erlang.org/download/otp_src_23.0.tar.gz -gunzip -c otp_src_23.0.tar.gz | tar xf - -cd otp_src_23.0 && ./configure -make -echo 'export PATH=$PATH:/opt/erlang/otp_src_23.0/bin' >> /opt/.profile -source /opt/.profile -# elixir -cd /opt && mkdir elixir && cd elixir -wget https://github.com/elixir-lang/elixir/releases/download/v1.10.3/Precompiled.zip -mkdir elixir-1.10.3 && unzip Precompiled.zip -d elixir-1.10.3/ -echo 'export PATH=$PATH:/opt/elixir/elixir-1.10.3/bin' >> /opt/.profile -source /opt/.profile - -# install emacs -# final binary: /opt/emacs/emacs-26.3/src/emacs -# get version: /opt/emacs/emacs-26.3/src/emacs --version -cd /opt && mkdir emacs && cd emacs -wget https://mirrors.ocf.berkeley.edu/gnu/emacs/emacs-26.3.tar.xz -tar -xf emacs-26.3.tar.xz -cd emacs-26.3 -./configure --with-gnutls=no -make -echo 'export PATH=$PATH:/opt/emacs/emacs-26.3/src' >> /opt/.profile -source /opt/.profile - -# install lua -# final binary: /opt/lua/lua54/src/lua -# get version: /opt/lua/lua54/src/lua -v -cd /opt && mkdir lua && cd lua -wget https://sourceforge.net/projects/luabinaries/files/5.4.0/Docs%20and%20Sources/lua-5.4.0_Sources.tar.gz/download -tar -xzf download -cd lua54 -make -echo 'export PATH=$PATH:/opt/lua/lua54/src' >> /opt/.profile -source /opt/.profile - -# install haskell -# final binary: /usr/bin/ghc -# get version: /usr/bin/ghc --version -apt install -y ghc - -# install deno -# final binary: /opt/.deno/bin/deno -# get version: /opt/.deno/bin/deno --version -cd /opt && mkdir deno && cd deno -curl -fsSL https://deno.land/x/install/install.sh | sh -echo 'export DENO_INSTALL="/opt/.deno"' >> /opt/.profile -echo 'export PATH="$DENO_INSTALL/bin:$PATH"' >> /opt/.profile -source /opt/.profile - -# install nim -# final binary: /opt/nim/bin/nim -# get version: /opt/nim/bin/nim -v -cd /opt && mkdir nim && cd nim -wget https://nim-lang.org/download/nim-1.4.0-linux_x64.tar.xz -unxz nim-1.4.0-linux_x64.tar.xz -tar -xf nim-1.4.0-linux_x64.tar -cd nim-1.4.0 -./install.sh /opt -echo 'export PATH=$PATH:/opt/nim/bin' >> /opt/.profile -source /opt/.profile - -# install d -# final binary: /opt/d/dmd2/linux/bin64/dmd -# get version: /opt/d/dmd2/linux/bin64/dmd --version -cd /opt && mkdir d && cd d -wget http://downloads.dlang.org/releases/2.x/2.095.0/dmd.2.095.0.linux.tar.xz -unxz dmd.2.095.0.linux.tar.xz -tar -xf dmd.2.095.0.linux.tar -echo 'export PATH=$PATH:/opt/d/dmd2/linux/bin64' >> /opt/.profile -source /opt/.profile - -# create runnable users and apply limits -for i in {1..150}; do - useradd -M runner$i - usermod -d /tmp runner$i - echo "runner$i soft nproc 64" >> /etc/security/limits.conf - echo "runner$i hard nproc 64" >> /etc/security/limits.conf - echo "runner$i soft nofile 2048" >> /etc/security/limits.conf - echo "runner$i hard nofile 2048" >> /etc/security/limits.conf -done - -# cleanup -rm -rf /home/ubuntu -chmod 777 /tmp - -# leave container -exit - -# optionally run tests -cd ../tests -./test_all_lxc +```sh +# clone and enter repo +git clone https://github.com/engineer-man/piston +cd piston/lxc ``` -#### CLI Usage -- `lxc/execute [language] [file path] [arg]...` +#### Installation (simple) + +- Coming soon. + +#### Installation (advanced) + +- See `var/install.txt` for how to create a new LXC container and install all of the required +software. + +#### CLI Usage +- `cli/execute [language] [file path] [args]` +
+ +# Usage + +### CLI + +```sh +lxc/execute [language] [file path] [args] +``` + +### API +To use the API, it must first be started. Please note that if root is required to access +LXC then the API must also be running as root. To start the API, run the following: -#### API Usage -To use the API, it must first be started. To start the API, run the following: ``` cd api ./start ``` -#### Base URLs -For your own local installation, use: +For your own local installation, the API is available at: + ``` http://127.0.0.1:2000 ``` -When using the public Piston API, use: -``` -https://emkc.org/api/v1/piston -``` #### Versions Endpoint `GET /versions` -This endpoint takes no input and returns a JSON array of the currently installed languages. - -Truncated response sample: +This endpoint will return the supported languages along with the current version and aliases. To execute +code for a particular language using the `/execute` endpoint, either the name or one of the aliases must +be provided. ```json +HTTP/1.1 200 OK +Content-Type: application/json + [ { "name": "awk", + "aliases": ["awk"], "version": "1.3.3" }, { "name": "bash", + "aliases": ["bash"], "version": "4.4.20" }, { "name": "c", + "aliases": ["c"], "version": "7.5.0" } ] ``` -#### Execution Endpoint +#### Execute Endpoint `POST /execute` -This endpoint takes the following JSON payload and expects at least the language and source. If -source is not provided, a blank file is passed as the source. +This endpoint requests execution of some arbitrary code. +- `language` (**required**) The language to use for execution, must be a string and supported by Piston (see list below). +- `source` (**required**) The source code to execute, must be a string. +- `stdin` (*optional*) The text to pass as stdin to the program. Must be a string or left out of the request. +- `args` (*optional*) The arguments to pass to the program. Must be an array or left out of the request. ```json { "language": "js", "source": "console.log(process.argv)", + "stdin": "", "args": [ "1", "2", @@ -350,58 +222,76 @@ source is not provided, a blank file is passed as the source. ] } ``` -A typical response when everything succeeds will be similar to the following: +A typical response upon successful execution will contain the `language`, `version`, `output` which +is a combination of both `stdout` and `stderr` but in chronological order according to program output, +as well as separate `stdout` and `stderr`. ```json +HTTP/1.1 200 OK +Content-Type: application/json + { "ran": true, "language": "js", "version": "12.13.0", - "output": "[ '/usr/bin/node',\n '/tmp/code.code',\n '1',\n '2',\n '3' ]" + "output": "[ '/usr/bin/node',\n '/tmp/code.code',\n '1',\n '2',\n '3' ]", + "stdout": "[ '/usr/bin/node',\n '/tmp/code.code',\n '1',\n '2',\n '3' ]", + "stderr": "" } ``` -If an invalid language is supplied, a typical response will look like the following: +If a problem exists with the request, a `400` status code is returned and the reason in the `message` key. ```json +HTTP/1.1 400 Bad Request +Content-Type: application/json + { - "code": "unsupported_language", - "message": "whatever is not supported by Piston" + "message": "Supplied language is not supported by Piston" } ``` -#### Supported Languages -- awk -- bash -- c -- cpp -- csharp -- d -- deno -- elixir -- emacs -- go -- haskell -- java -- jelly -- julia -- kotlin -- nasm -- node -- perl -- php -- python2 -- python3 -- paradoc -- ruby -- rust -- swift -- typescript +
-#### Principle of Operation -Piston utilizes LXC as the primary mechanism for sandboxing. There is a small API written in Go which takes +# Supported Languages +`awk`, +`bash`, +`brainfuck`, +`c`, +`cpp`, +`csharp`, +`d`, +`deno`, +`elixir`, +`emacs`, +`elisp`, +`go`, +`haskell`, +`java`, +`jelly`, +`julia`, +`kotlin`, +`lua`, +`nasm`, +`node`, +`paradoc`, +`perl`, +`php`, +`python2`, +`python3`, +`ruby`, +`rust`, +`swift`, +`typescript`, + +
+ +# Principle of Operation +Piston utilizes LXC as the primary mechanism for sandboxing. There is a small API written in Node which takes in execution requests and executes them in the container. High level, the API writes a temporary source and args file to `/tmp` and that gets mounted read-only along with the execution scripts into the container. The source file is either ran or compiled and ran (in the case of languages like c, c++, c#, go, etc.). -#### Security +
+ +# Security LXC provides a great deal of security out of the box in that it's separate from the system. Piston takes additional steps to make it resistant to various privilege escalation, denial-of-service, and resource saturation threats. These steps include: @@ -409,10 +299,13 @@ various privilege escalation, denial-of-service, and resource saturation threats - Capping max processes at 64 (resists `:(){ :|: &}:;`, `while True: os.fork()`, etc.) - Capping max files at 2048 (resists various file based attacks) - Mounting all resources read-only (resists `sudo rm -rf --no-preserve-root /`) +- Cleaning up all temp space after each execution (resists out of drive space attacks) - Running as a variety of unprivileged users - Capping runtime execution at 3 seconds - Capping stdout to 65536 characters (resists yes/no bombs and runaway output) - SIGKILLing misbehaving code -#### License +
+ +# License Piston is licensed under the MIT license. diff --git a/shared/execute.js b/shared/execute.js new file mode 100644 index 0000000..526efdd --- /dev/null +++ b/shared/execute.js @@ -0,0 +1,57 @@ +const { writeFileSync, unlinkSync } = require('fs'); +const { spawn } = require('child_process'); + +const OUTPUT_LIMIT = 65535; + +function execute(language, source, stdin = '', args = []) { + return new Promise(resolve => { + const stamp = new Date().getTime(); + const sourceFile = `/tmp/${stamp}.code`; + + writeFileSync(sourceFile, source); + + const process = spawn(__dirname + '/../lxc/execute', [ + language.name, + sourceFile, + stdin, + args.join('\n'), + ]); + + let stdout = ''; + let stderr = ''; + let output = ''; + + process.stderr.on('data', chunk => { + if (stderr.length >= OUTPUT_LIMIT) return; + + stderr += chunk; + output += chunk; + }); + + process.stdout.on('data', chunk => { + if (stdout.length >= OUTPUT_LIMIT) return; + + stdout += chunk; + output += chunk; + }); + + process.on('exit', code => { + unlinkSync(sourceFile); + + stderr = stderr.trim().substring(0, OUTPUT_LIMIT); + stdout = stdout.trim().substring(0, OUTPUT_LIMIT); + output = output.trim().substring(0, OUTPUT_LIMIT); + + resolve({ + stdout, + stderr, + output, + ran: code === 0, + }); + }); + }); +} + +module.exports = { + execute, +}; diff --git a/shared/languages.json b/shared/languages.json new file mode 100644 index 0000000..aa21914 --- /dev/null +++ b/shared/languages.json @@ -0,0 +1,209 @@ +[ + { + "name": "nasm", + "aliases": [ + "asm", + "nasm" + ] + }, + { + "name": "nasm64", + "aliases": [ + "asm64", + "nasm64" + ] + }, + { + "name": "awk", + "aliases": [ + "awk" + ] + }, + { + "name": "bash", + "aliases": [ + "bash" + ] + }, + { + "name": "brainfuck", + "aliases": [ + "bf", + "brainfuck" + ] + }, + { + "name": "c", + "aliases": [ + "c" + ] + }, + { + "name": "csharp", + "aliases": [ + "c#", + "cs", + "csharp" + ] + }, + { + "name": "cpp", + "aliases": [ + "c++", + "cpp", + "cc", + "cxx" + ] + }, + { + "name": "d", + "aliases": [ + "dlang", + "d" + ] + }, + { + "name": "deno", + "aliases": [ + "deno", + "denojs", + "denots" + ] + }, + { + "name": "ruby", + "aliases": [ + "duby", + "rb", + "ruby" + ] + }, + { + "name": "emacs", + "aliases": [ + "el", + "elisp", + "emacs" + ] + }, + { + "name": "elixir", + "aliases": [ + "elixir", + "exs" + ] + }, + { + "name": "haskell", + "aliases": [ + "haskell", + "hs" + ] + }, + { + "name": "go", + "aliases": [ + "go", + "golang" + ] + }, + { + "name": "java", + "aliases": [ + "java" + ] + }, + { + "name": "node", + "aliases": [ + "javascript", + "js", + "node", + "node.js" + ] + }, + { + "name": "jelly", + "aliases": [ + "jelly" + ] + }, + { + "name": "julia", + "aliases": [ + "jl", + "julia" + ] + }, + { + "name": "kotlin", + "aliases": [ + "kotlin", + "kt" + ] + }, + { + "name": "lua", + "aliases": [ + "lua" + ] + }, + { + "name": "paradoc", + "aliases": [ + "paradoc" + ] + }, + { + "name": "perl", + "aliases": [ + "perl", + "pl" + ] + }, + { + "name": "php", + "aliases": [ + "php", + "php3", + "php4", + "php5" + ] + }, + { + "name": "python3", + "aliases": [ + "py", + "py3", + "python", + "python3" + ] + }, + { + "name": "python2", + "aliases": [ + "python2", + "py2" + ] + }, + { + "name": "rust", + "aliases": [ + "rs", + "rust" + ] + }, + { + "name": "swift", + "aliases": [ + "swift" + ] + }, + { + "name": "typescript", + "aliases": [ + "ts", + "typescript" + ] + } +] diff --git a/var/install.txt b/var/install.txt new file mode 100644 index 0000000..046f937 --- /dev/null +++ b/var/install.txt @@ -0,0 +1,262 @@ +# create and start container +lxc-create -t download -n piston -- --dist ubuntu --release bionic --arch amd64 +./start + +# open a shell to the container +./shell + +# install all necessary piston dependencies +echo 'source /opt/.profile' >> /opt/.bashrc +echo 'export HOME=/opt' >> /opt/.profile +echo 'export TERM=linux' >> /opt/.profile +echo 'export PATH=$PATH:/opt/.local/bin' >> /opt/.profile +export HOME=/opt +export TERM=linux +sed -i 's/\/root/\/opt/' /etc/passwd +sed -i \ + 's/http:\/\/archive.ubuntu.com\/ubuntu/http:\/\/mirror.math.princeton.edu\/pub\/ubuntu/' \ + /etc/apt/sources.list +apt-get update +apt-get install -y \ + nano wget build-essential pkg-config libxml2-dev \ + libsqlite3-dev mono-complete curl cmake libpython2.7-dev \ + ruby libtinfo-dev unzip git openssl libssl-dev + +# install python2 +# final binary: /opt/python2/Python-2.7.17/python +# get version: /opt/python2/Python-2.7.17/python -V +cd /opt && mkdir python2 && cd python2 +wget https://www.python.org/ftp/python/2.7.17/Python-2.7.17.tar.xz +unxz Python-2.7.17.tar.xz +tar -xf Python-2.7.17.tar +cd Python-2.7.17 +./configure +# open Modules/Setup and uncomment zlib line +make +echo 'export PATH=$PATH:/opt/python2/Python-2.7.17' >> /opt/.profile +source /opt/.profile + +# install python3 +# final binary: /opt/python3/Python-3.8.2/python +# get version: /opt/python3/Python-3.8.2/python -V +cd /opt && mkdir python3 && cd python3 +wget https://www.python.org/ftp/python/3.8.2/Python-3.8.2.tar.xz +unxz Python-3.8.2.tar.xz +tar -xf Python-3.8.2.tar +cd Python-3.8.2 +./configure +make +ln -s python python3.8 +echo 'export PATH=$PATH:/opt/python3/Python-3.8.2' >> /opt/.profile +source /opt/.profile + +# install paradoc +# this is not a binary, it is a python module +# therefore it cannot be run directly as it requires python3 to be installed +cd /opt && mkdir paradoc && cd paradoc +git clone https://github.com/betaveros/paradoc.git + +# install node.js +# final binary: /opt/nodejs/node-v12.16.1-linux-x64/bin/node +# get version: /opt/nodejs/node-v12.16.1-linux-x64/bin/node -v +cd /opt && mkdir nodejs && cd nodejs +wget https://nodejs.org/dist/v12.16.1/node-v12.16.1-linux-x64.tar.xz +unxz node-v12.16.1-linux-x64.tar.xz +tar -xf node-v12.16.1-linux-x64.tar +echo 'export PATH=$PATH:/opt/nodejs/node-v12.16.1-linux-x64/bin' >> /opt/.profile +source /opt/.profile + +# install typescript +# final binary: /opt/nodejs/node-v12.16.1-linux-x64/bin/tsc +# get version: /opt/nodejs/node-v12.16.1-linux-x64/bin/tsc -v +/opt/nodejs/node-v12.16.1-linux-x64/bin/npm i -g typescript + +# install golang +# final binary: /opt/go/go/bin/go +# get version: /opt/go/go/bin/go version +cd /opt && mkdir go && cd go +wget https://dl.google.com/go/go1.14.1.linux-amd64.tar.gz +tar -xzf go1.14.1.linux-amd64.tar.gz +echo 'export PATH=$PATH:/opt/go/go/bin' >> /opt/.profile +echo 'export GOROOT=/opt/go/go' >> /opt/.profile +echo 'export GOCACHE=/tmp' >> /opt/.profile +source /opt/.profile + +# install php +# final binary: /usr/local/bin/php +# get version: /usr/local/bin/php -v +cd /opt && mkdir php && cd php +wget https://www.php.net/distributions/php-7.4.4.tar.gz +tar -xzf php-7.4.4.tar.gz +cd php-7.4.4 +./configure +make +make install + +# install rust +# final binary: /usr/local/bin/rustc +# get version: /usr/local/bin/rustc --version +cd /opt && mkdir rust && cd rust +wget https://static.rust-lang.org/dist/rust-1.49.0-x86_64-unknown-linux-gnu.tar.gz +tar -xzf rust-1.49.0-x86_64-unknown-linux-gnu.tar.gz +cd rust-1.49.0-x86_64-unknown-linux-gnu +./install.sh + +# install swift +# final binary: /opt/swift/swift-5.1.5-RELEASE-ubuntu18.04/usr/bin/swift +# get version: /opt/swift/swift-5.1.5-RELEASE-ubuntu18.04/usr/bin/swift --version +cd /opt && mkdir swift && cd swift +wget https://swift.org/builds/swift-5.1.5-release/ubuntu1804/swift-5.1.5-RELEASE/swift-5.1.5-RELEASE-ubuntu18.04.tar.gz +tar -xzf swift-5.1.5-RELEASE-ubuntu18.04.tar.gz +echo 'export PATH=$PATH:/opt/swift/swift-5.1.5-RELEASE-ubuntu18.04/usr/bin' >> /opt/.profile +source /opt/.profile + +# install nasm +# final binary: /opt/nasm/nasm-2.14.02/nasm +# get version: /opt/nasm/nasm-2.14.02/nasm -v +cd /opt && mkdir nasm && cd nasm +wget https://www.nasm.us/pub/nasm/releasebuilds/2.14.02/nasm-2.14.02.tar.gz +tar -xzf nasm-2.14.02.tar.gz +cd nasm-2.14.02 +./configure +make +echo 'export PATH=$PATH:/opt/nasm/nasm-2.14.02' >> /opt/.profile +source /opt/.profile + +# install java +# final binary: /opt/java/jdk-14/bin/java +# get version: /opt/java/jdk-14/bin/java -version +cd /opt && mkdir java && cd java +wget https://download.java.net/java/GA/jdk14/076bab302c7b4508975440c56f6cc26a/36/GPL/openjdk-14_linux-x64_bin.tar.gz +tar -xzf openjdk-14_linux-x64_bin.tar.gz +echo 'export PATH=$PATH:/opt/java/jdk-14/bin' >> /opt/.profile +source /opt/.profile + +# install jelly +cd /opt && mkdir jelly && cd jelly +wget https://github.com/DennisMitchell/jellylanguage/archive/master.zip +unzip master.zip +cd jellylanguage-master +python3.8 -m pip install . +sed -i 's/\/usr\/local\/bin\/python3.8/\/opt\/python3\/Python-3.8.2\/python3.8/' /usr/local/bin/jelly + +# install julia +# final binary: /opt/julia/julia-1.5.0/bin/julia +# get version: /opt/julia/julia-1.5.0/bin/julia --version +cd /opt && mkdir julia && cd julia +wget https://julialang-s3.julialang.org/bin/linux/x64/1.5/julia-1.5.0-linux-x86_64.tar.gz +tar -xzf julia-1.5.0-linux-x86_64.tar.gz +echo 'export PATH=$PATH:/opt/julia/julia-1.5.0/bin' >> /opt/.profile +source /opt/.profile + +# install kotlin +# final binary: /opt/kotlinc/bin/kotlinc +# get version: /opt/kotlinc/bin/kotlinc -version +cd /opt +wget https://github.com/JetBrains/kotlin/releases/download/v1.4.10/kotlin-compiler-1.4.10.zip +unzip kotlin-compiler-1.4.10.zip +rm kotlin-compiler-1.4.10.zip +echo 'export PATH=$PATH:/opt/kotlinc/bin' >> /opt/.profile +source /opt/.profile + +# install elixir and erlang +# final binary: /opt/elixir/bin/elixir +# get version: /opt/elixir/bin/elixir --version +# erlang +cd /opt && mkdir erlang && cd erlang +wget http://erlang.org/download/otp_src_23.0.tar.gz +gunzip -c otp_src_23.0.tar.gz | tar xf - +cd otp_src_23.0 && ./configure +make +echo 'export PATH=$PATH:/opt/erlang/otp_src_23.0/bin' >> /opt/.profile +source /opt/.profile +# elixir +cd /opt && mkdir elixir && cd elixir +wget https://github.com/elixir-lang/elixir/releases/download/v1.10.3/Precompiled.zip +mkdir elixir-1.10.3 && unzip Precompiled.zip -d elixir-1.10.3/ +echo 'export PATH=$PATH:/opt/elixir/elixir-1.10.3/bin' >> /opt/.profile +source /opt/.profile + +# install emacs +# final binary: /opt/emacs/emacs-26.3/src/emacs +# get version: /opt/emacs/emacs-26.3/src/emacs --version +cd /opt && mkdir emacs && cd emacs +wget https://mirrors.ocf.berkeley.edu/gnu/emacs/emacs-26.3.tar.xz +tar -xf emacs-26.3.tar.xz +rm emacs-26.3.tar.xz +cd emacs-26.3 +./configure --with-gnutls=no +make +echo 'export PATH=$PATH:/opt/emacs/emacs-26.3/src' >> /opt/.profile +source /opt/.profile + +# install lua +# final binary: /opt/lua/lua54/src/lua +# get version: /opt/lua/lua54/src/lua -v +cd /opt && mkdir lua && cd lua +wget https://sourceforge.net/projects/luabinaries/files/5.4.0/Docs%20and%20Sources/lua-5.4.0_Sources.tar.gz/download +tar -xzf download +cd lua54 +make +echo 'export PATH=$PATH:/opt/lua/lua54/src' >> /opt/.profile +source /opt/.profile + +# install haskell +# final binary: /usr/bin/ghc +# get version: /usr/bin/ghc --version +apt install -y ghc + +# install deno +# final binary: /opt/.deno/bin/deno +# get version: /opt/.deno/bin/deno --version +cd /opt && mkdir deno && cd deno +curl -fsSL https://deno.land/x/install/install.sh | sh +echo 'export DENO_INSTALL="/opt/.deno"' >> /opt/.profile +echo 'export PATH="$DENO_INSTALL/bin:$PATH"' >> /opt/.profile +source /opt/.profile + +# install brainfuck +cd /opt && mkdir bf && cd bf +git clone https://github.com/texus/Brainfuck-interpreter +cd Brainfuck-interpreter +echo 'export PATH=$PATH:/opt/bf/Brainfuck-interpreter' >> /opt/.profile +source /opt/.profile + +# install d +# final binary: /opt/d/dmd2/linux/bin64/dmd +# get version: /opt/d/dmd2/linux/bin64/dmd --version +cd /opt && mkdir d && cd d +wget http://downloads.dlang.org/releases/2.x/2.095.0/dmd.2.095.0.linux.tar.xz +unxz dmd.2.095.0.linux.tar.xz +tar -xf dmd.2.095.0.linux.tar +echo 'export PATH=$PATH:/opt/d/dmd2/linux/bin64' >> /opt/.profile +source /opt/.profile + +# create runnable users and apply limits +for i in {1..150}; do + useradd -M runner$i + usermod -d /tmp runner$i + echo "runner$i soft nproc 64" >> /etc/security/limits.conf + echo "runner$i hard nproc 64" >> /etc/security/limits.conf + echo "runner$i soft nofile 2048" >> /etc/security/limits.conf + echo "runner$i hard nofile 2048" >> /etc/security/limits.conf +done + +# remove any lingering write access to others +cd /opt +chown -R root: * +chmod -R o-w * + +# cleanup +rm -rf /home/ubuntu +chmod 777 /tmp + +# disable cron +systemctl stop cron +systemctl disable cron + +# leave container +exit + +# optionally run tests +./test_all_lxc diff --git a/var/notes.txt b/var/notes.txt new file mode 100644 index 0000000..7767b8b --- /dev/null +++ b/var/notes.txt @@ -0,0 +1,24 @@ +# make piston image +lxc-clone -KMP /mnt/piston_image piston piston +sed -i 's/\/mnt\/piston_image/\/var\/lib\/lxc/' piston/config +tar -czf piston.tar.gz piston/ + +# restore piston image +cd /var/lib/lxc +tar -xzf piston.tar.gz + + + + + +``` +# get piston image +cd /var/lib/lxc +wget whatever url +tar -xzf piston.tar.gz +sed -i "s/virtbr0/$(ip a | grep br0: | cut -d' ' -f2 | sed 's/://gi')/" piston/config + +# start piston +cd /path/to/piston/lxc +./start +```