Readme 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. # TimekeeperEnforcement
  2. Local enforcement for the Timekeeper e107 plugin. Once a minute it looks for each
  3. monitored student's games, asks the server how many play minutes are left
  4. (`timer.php`), warns, and closes the game when there are none.
  5. Needs Java 11 or newer. Run it as root (it stops other users' processes and shows
  6. popups as them).
  7. ## Build
  8. ```bash
  9. javac -d out src/au/pfip/*.java
  10. jar --create --file TimekeeperEnforcement.jar --main-class au.pfip.Main -C out .
  11. ```
  12. ## Settings
  13. The first of these that exists is used. Use `/etc/timekeeper.inf`, owned by root and
  14. not writable by the students: a settings file they can edit defeats the monitoring.
  15. 1. `/etc/timekeeper.inf`
  16. 2. `~/timekeeper.inf`
  17. 3. `~/.config/timekeeper/timekeeper.inf`
  18. 4. `./timekeeper.inf`
  19. If none exists, a new one is written to `~/.config/timekeeper/timekeeper.inf` with the
  20. defaults below. It is Java XML properties format.
  21. | Key | Default | Meaning |
  22. |---|---|---|
  23. | `UsersToMonitor` | *(empty, must be set)* | Comma separated accounts to watch, e.g. `alice,bob` |
  24. | `TimekeeperActive` | `true` | `false` makes the program wait 10 minutes and exit |
  25. | `ExemptNetwork` | *(empty = none)* | Network name where enforcement is off (checked at start-up only; anyone can name a hotspot after a network) |
  26. | `OfflineChecksBeforeKill` | `5` | Failed server checks in a row before a game is closed (`1` = close at once) |
  27. | `GamesRefreshMinutes` | `60` | How often the games list is fetched again |
  28. | `GamesURL`, `PlaytimeURL` | the overlord URLs | Server endpoints |
  29. | `LogFilePath` | home folder | Where `timekeeper<day>.log` is written |
  30. | `MatchWholeWords` | `true` | A game name must not run on into more letters or digits in the command line (`technic` no longer matches `technical-report.odt`). `false` = plain "contains" |
  31. | `IgnoreCommandLines` | *(empty)* | Comma separated command line fragments that exempt a process, e.g. `--kiosk,-contentproc`. Anyone can add such a fragment to a command they start themselves |
  32. ## games.json
  33. A JSON array of strings, or an object whose values are the names (keys are ignored).
  34. Each name is looked for in the full command line (`ps -eo user,args`) of every process
  35. the student owns, case-sensitively. Check what a game really looks like first:
  36. ```bash
  37. ps -eo user,args | grep -i <name>
  38. ```
  39. - Use a name that appears in the command line, and is specific: `technic` also matched
  40. `technical-report.odt` before whole-word matching.
  41. - Wine/Proton games show up as their `.exe` name (`bf2.exe`). Native Steam games show up
  42. as the binary (`hl2_linux`).
  43. - Browsers listed here are closed like any other game, including a browser used for
  44. Timekeeper's own questions. Use `IgnoreCommandLines` or a separate browser for those.
  45. - It is a deny-list: a browser, launcher or game that isn't listed isn't enforced.
  46. The games list is cached in `games.cache` next to the settings file and used when the
  47. server can't be reached.
  48. ## systemd
  49. ```ini
  50. [Unit]
  51. Description=Timekeeper enforcement
  52. After=network-online.target
  53. Wants=network-online.target
  54. [Service]
  55. ExecStart=/usr/bin/java -jar /opt/timekeeper/TimekeeperEnforcement.jar
  56. Restart=always
  57. RestartSec=30
  58. User=root
  59. [Install]
  60. WantedBy=multi-user.target
  61. ```
  62. ## Tests
  63. `test/au/pfip/Harness.java` and `Harness2.java` run against a fake local server and
  64. start and stop throwaway `sleep` processes owned by the current user:
  65. ```bash
  66. javac -d out src/au/pfip/*.java test/au/pfip/*.java
  67. java -cp out au.pfip.Harness
  68. java -cp out au.pfip.Harness2
  69. ```