aboutsummaryrefslogtreecommitdiffhomepage
path: root/internal/outcome/spaccount.go
diff options
context:
space:
mode:
authorOphestra <cat@gensokyo.uk>2025-10-29 04:32:43 +0900
committerOphestra <cat@gensokyo.uk>2025-10-29 04:33:13 +0900
commita0b4e47acc228e48165966d8e139277b8f6f450e (patch)
treed363a6781536ce946aa445271ca1d3df587e6031 /internal/outcome/spaccount.go
parenta52f7038e5a607dd0901244abb791c96deaf9c2d (diff)
internal/outcome: rename from app
This is less ambiguous, and more accurately describes the purpose of the package. Signed-off-by: Ophestra <cat@gensokyo.uk>
Diffstat (limited to 'internal/outcome/spaccount.go')
-rw-r--r--internal/outcome/spaccount.go56
1 files changed, 56 insertions, 0 deletions
diff --git a/internal/outcome/spaccount.go b/internal/outcome/spaccount.go
new file mode 100644
index 00000000..0e9c602a
--- /dev/null
+++ b/internal/outcome/spaccount.go
@@ -0,0 +1,56 @@
+package outcome
+
+import (
+ "encoding/gob"
+ "fmt"
+ "syscall"
+
+ "hakurei.app/container/fhs"
+ "hakurei.app/internal/validate"
+)
+
+func init() { gob.Register(spAccountOp{}) }
+
+// spAccountOp sets up user account emulation inside the container.
+type spAccountOp struct{}
+
+func (s spAccountOp) toSystem(state *outcomeStateSys) error {
+ // do checks here to fail before fork/exec
+ if state.Container == nil || state.Container.Home == nil || state.Container.Shell == nil {
+ // unreachable
+ return syscall.ENOTRECOVERABLE
+ }
+
+ // default is applied in toContainer
+ if state.Container.Username != "" && !validate.IsValidUsername(state.Container.Username) {
+ return newWithMessage(fmt.Sprintf("invalid user name %q", state.Container.Username))
+ }
+ return nil
+}
+
+func (s spAccountOp) toContainer(state *outcomeStateParams) error {
+ const fallbackUsername = "chronos"
+
+ username := state.Container.Username
+ if username == "" {
+ username = fallbackUsername
+ }
+
+ state.params.Dir = state.Container.Home
+ state.env["HOME"] = state.Container.Home.String()
+ state.env["USER"] = username
+ state.env["SHELL"] = state.Container.Shell.String()
+
+ state.params.
+ Place(fhs.AbsEtc.Append("passwd"),
+ []byte(username+":x:"+
+ state.mapuid.String()+":"+
+ state.mapgid.String()+
+ ":Hakurei:"+
+ state.Container.Home.String()+":"+
+ state.Container.Shell.String()+"\n")).
+ Place(fhs.AbsEtc.Append("group"),
+ []byte("hakurei:x:"+state.mapgid.String()+":\n"))
+
+ return nil
+}