|
@@ -4,8 +4,11 @@ import java.nio.charset.StandardCharsets;
|
|
|
import java.nio.file.Files;
|
|
import java.nio.file.Files;
|
|
|
import java.nio.file.Path;
|
|
import java.nio.file.Path;
|
|
|
import java.util.ArrayList;
|
|
import java.util.ArrayList;
|
|
|
|
|
+import java.util.HashMap;
|
|
|
import java.util.List;
|
|
import java.util.List;
|
|
|
|
|
+import java.util.Map;
|
|
|
import java.util.Optional;
|
|
import java.util.Optional;
|
|
|
|
|
+import java.util.regex.Pattern;
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
* Finds and stops a student's game processes without a shell.
|
|
* Finds and stops a student's game processes without a shell.
|
|
@@ -34,6 +37,7 @@ public class Processes {
|
|
|
public static List<Proc> snapshot(String user) {
|
|
public static List<Proc> snapshot(String user) {
|
|
|
List<Proc> result = new ArrayList<>();
|
|
List<Proc> result = new ArrayList<>();
|
|
|
long self = ProcessHandle.current().pid();
|
|
long self = ProcessHandle.current().pid();
|
|
|
|
|
+ List<String> ignoredCommandLines = ignoredCommandLines();
|
|
|
|
|
|
|
|
ProcessHandle.allProcesses().forEach(handle -> {
|
|
ProcessHandle.allProcesses().forEach(handle -> {
|
|
|
try {
|
|
try {
|
|
@@ -48,6 +52,11 @@ public class Processes {
|
|
|
if (commandLine.isEmpty() || commandLine.contains("notify-send")) {
|
|
if (commandLine.isEmpty() || commandLine.contains("notify-send")) {
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
|
|
+ for (String ignored : ignoredCommandLines) {
|
|
|
|
|
+ if (commandLine.contains(ignored)) {
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
result.add(new Proc(handle, commandLine));
|
|
result.add(new Proc(handle, commandLine));
|
|
|
} catch (RuntimeException e) {
|
|
} catch (RuntimeException e) {
|
|
|
// The process ended while we were looking at it.
|
|
// The process ended while we were looking at it.
|
|
@@ -58,17 +67,51 @@ public class Processes {
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
* The processes in the list whose command line contains the game name.
|
|
* The processes in the list whose command line contains the game name.
|
|
|
|
|
+ *
|
|
|
|
|
+ * By default the name must not run on into more letters or digits:
|
|
|
|
|
+ * "technic" matches "/home/x/.technic/launcher" but not
|
|
|
|
|
+ * "technical-report.odt", and "opera" does not match "operate" or
|
|
|
|
|
+ * "cooperative". Anything else after the name (. - _ / space \ end of
|
|
|
|
|
+ * line) is fine. Nothing is required before the name, so "-Dminecraft"
|
|
|
|
|
+ * (a Java property) still matches. Set MatchWholeWords to false for the
|
|
|
|
|
+ * old plain "contains" matching.
|
|
|
*/
|
|
*/
|
|
|
public static List<Proc> matching(List<Proc> processes, String game) {
|
|
public static List<Proc> matching(List<Proc> processes, String game) {
|
|
|
|
|
+ boolean wholeWords = !"false".equalsIgnoreCase(settings.getSetting("MatchWholeWords"));
|
|
|
|
|
+ Pattern pattern = wholeWords ? wholeWordPattern(game) : null;
|
|
|
|
|
+
|
|
|
List<Proc> result = new ArrayList<>();
|
|
List<Proc> result = new ArrayList<>();
|
|
|
for (Proc proc : processes) {
|
|
for (Proc proc : processes) {
|
|
|
- if (proc.commandLine.contains(game)) {
|
|
|
|
|
|
|
+ boolean found = (pattern == null) ? proc.commandLine.contains(game) : pattern.matcher(proc.commandLine).find();
|
|
|
|
|
+ if (found) {
|
|
|
result.add(proc);
|
|
result.add(proc);
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
return result;
|
|
return result;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ private static final Map<String, Pattern> patterns = new HashMap<>();
|
|
|
|
|
+
|
|
|
|
|
+ private static Pattern wholeWordPattern(String game) {
|
|
|
|
|
+ return patterns.computeIfAbsent(game, g -> Pattern.compile(Pattern.quote(g) + "(?![A-Za-z0-9])"));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Command line fragments (IgnoreCommandLines, comma separated) that take a
|
|
|
|
|
+ * process out of consideration, e.g. "--kiosk". Note that anyone can add
|
|
|
|
|
+ * such a fragment to a command they start themselves.
|
|
|
|
|
+ */
|
|
|
|
|
+ private static List<String> ignoredCommandLines() {
|
|
|
|
|
+ List<String> ignored = new ArrayList<>();
|
|
|
|
|
+ for (String part : settings.getSetting("IgnoreCommandLines").split(",")) {
|
|
|
|
|
+ part = part.trim();
|
|
|
|
|
+ if (!part.isEmpty()) {
|
|
|
|
|
+ ignored.add(part);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ return ignored;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
/**
|
|
/**
|
|
|
* Stop the user's processes for the game: politely first, then by force.
|
|
* Stop the user's processes for the game: politely first, then by force.
|
|
|
*
|
|
*
|