/*
* SandboxMain.java
*
* Copyright (C) 2015 Pixelgaffer
*
* This work is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation; either version 2 of the License, or any later
* version.
*
* This work is distributed in the hope that it will be useful, but without
* any warranty; without even the implied warranty of merchantability or
* fitness for a particular purpose. See version 2 and version 3 of the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.pixelgaffer.turnierserver.sandboxmanager;
import static org.pixelgaffer.turnierserver.PropertyUtils.*;
import static java.lang.System.*;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.nio.file.Files;
import static java.nio.file.attribute.PosixFilePermission.*;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import lombok.Getter;
import org.apache.commons.io.FileUtils;
import org.pixelgaffer.turnierserver.Airbrake;
import org.pixelgaffer.turnierserver.Logger;
import org.pixelgaffer.turnierserver.networking.NetworkService;
public class SandboxMain
{
@Getter
private static final Logger logger = new Logger();
@Getter
private static WorkerClient client;
public static final HashMap<String, String> commands = new HashMap<>();
private static void searchExecutable (String execfile, String language) throws IOException
{
String pathes[] = getenv("PATH").split(":");
for (String path : pathes)
{
File file = new File(path, execfile);
while (Files.isSymbolicLink(file.toPath()))
file = file.toPath().toRealPath().toFile();
if (file.exists() && Files.isExecutable(file.toPath()))
{
getLogger().info(language + " gefunden: " + file.getAbsolutePath());
commands.put(language, file.getAbsolutePath());
return;
}
}
}
public static File etc;
public static void main (String args[]) throws IOException
{
Thread.setDefaultUncaughtExceptionHandler(new Airbrake());
// Properties laden
loadProperties(args.length > 0 ? args[0] : "/etc/turnierserver/sandbox.prop");
// den Rechner nach Programmiersprachen durchsuchen
for (int i = 0; i < getIntRequired("languages.size"); i++)
{
String lang = getStringRequired("languages." + i);
String command = getString("languages." + lang, "");
if (command.isEmpty())
{
getLogger().info("Erlaube native Sprache " + lang);
commands.put(lang, "");
}
else
{
getLogger().info("Suche Sprache " + lang + " (Befehl " + command + ")");
searchExecutable(command, lang);
}
}
// isolate-Zeugs schreiben
etc = Files.createTempDirectory("etc").toFile();
Files.setPosixFilePermissions(etc.toPath(), new HashSet<>(Arrays.asList(
OWNER_READ, OWNER_WRITE, OWNER_EXECUTE,
GROUP_READ, GROUP_EXECUTE,
OTHERS_READ, OTHERS_EXECUTE)));
File passwd = new File(etc, "passwd");
PrintWriter pw = new PrintWriter(passwd);
for (int i = 0; i <= 99; i++)
{
int id = 60000 + i;
pw.println("isolate-user-" + i + ":x:" + id + ":" + id + "::/:/usr/sbin/nologin");
}
pw.close();
File etcJavaDir = new File(etc, "java-jdk8/amd64");
etcJavaDir.mkdirs();
File jvmCfg = new File(etcJavaDir, "jvm.cfg");
pw = new PrintWriter(jvmCfg);
pw.println("# GENERATED FILE - DO NOT EDIT");
pw.println("-server KNOWN");
pw.println("-client IGNORE");
pw.close();
// Netzwerkzeugs starten
client = new WorkerClient();
new Thread( () -> NetworkService.mainLoop(), "NetworkService").start();
// beim beenden alle laufenden kis auch beenden
Runtime.getRuntime().addShutdownHook(new Thread( () -> {
getLogger().info("Received shutdown signal");
client.getJobControl().shutdown();
try
{
FileUtils.deleteDirectory(etc);
}
catch (Exception e)
{
e.printStackTrace();
}
}, "SandboxMain-ShutdownHook"));
}
}