aboutsummaryrefslogtreecommitdiff
path: root/daemonize.go
blob: 7d002883740c8b94802c7bbbc5c558d30135bd30 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
package main

import (
	"fmt"
	"log"
	"log/syslog"
	"os"
	"os/exec"
	"os/signal"
	"syscall"

	"github.com/rfjakob/gocryptfs/cryptfs"
)

// The child sends us USR1 if the mount was successful
func exitOnUsr1() {
	c := make(chan os.Signal, 1)
	signal.Notify(c, syscall.SIGUSR1)
	<-c
	os.Exit(0)
}

// forkChild - execute ourselves once again, this time with the "-f" flag, and
// wait for SIGUSR1 or child exit.
// This is a workaround for the missing true fork function in Go.
func forkChild() {
	go exitOnUsr1()
	name := os.Args[0]
	newArgs := []string{"-f", fmt.Sprintf("-notifypid=%d", os.Getpid())}
	newArgs = append(newArgs, os.Args[1:]...)
	c := exec.Command(name, newArgs...)
	c.Stdout = os.Stdout
	c.Stderr = os.Stderr
	c.Stdin = os.Stdin
	err := c.Start()
	if err != nil {
		fmt.Printf("forkChild: starting %s failed: %v\n", name, err)
		os.Exit(1)
	}
	err = c.Wait()
	if err != nil {
		if exiterr, ok := err.(*exec.ExitError); ok {
			if waitstat, ok := exiterr.Sys().(syscall.WaitStatus); ok {
				os.Exit(waitstat.ExitStatus())
			}
		}
		fmt.Printf("forkChild: wait returned an unknown error: %v\n", err)
		os.Exit(1)
	}
	// The child exited with 0 - let's do the same.
	os.Exit(0)
}

// Switch one Logger to syslog
func switchToSyslog(l *log.Logger, p syslog.Priority) {
	w, err := syslog.New(p, PROGRAM_NAME)
	if err != nil {
		cryptfs.Warn.Printf("Cannot switch 0x%02x to syslog: %v", p, err)
	} else {
		l.SetOutput(w)
	}
}