summaryrefslogtreecommitdiff
path: root/socket_linux.go
blob: 0c211867396c84aaa3ea91f87c57d97baba08758 (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
// SPDX-FileCopyrightText: © 2021 Grégoire Duchêne <gduchene@awhk.org>
// SPDX-License-Identifier: ISC

//go:build linux && !nosystemd

package gosdd

// #cgo LDFLAGS: -lsystemd
// #include <stdlib.h>
// #include <string.h>
// #include <systemd/sd-daemon.h>
import "C"

import (
	"os"
	"syscall"
	"unsafe"
)

func sdListenFDs(unsetenv bool) ([]*os.File, error) {
	i := C.int(0)
	if unsetenv {
		i = C.int(1)
	}
	c := C.sd_listen_fds(i)
	if c < 0 {
		return nil, syscall.Errno(-c)
	}
	if c == 0 {
		return nil, nil
	}
	fds := make([]*os.File, 0, c)
	for fd := uintptr(C.SD_LISTEN_FDS_START); fd < uintptr(C.SD_LISTEN_FDS_START+c); fd++ {
		fds = append(fds, os.NewFile(fd, ""))
	}
	return fds, nil
}

func sdListenFDsWithNames(unsetenv bool) (map[string]*os.File, error) {
	i := C.int(0)
	if unsetenv {
		i = C.int(1)
	}
	var arr **C.char
	c := C.sd_listen_fds_with_names(i, &arr)
	if c < 0 {
		return nil, syscall.Errno(-c)
	}
	if c == 0 {
		return nil, nil
	}
	// See https://github.com/golang/go/wiki/cgo#turning-c-arrays-into-go-slices.
	names := (*[1 << 28]*C.char)(unsafe.Pointer(arr))[:c:c]
	fds := make(map[string]*os.File)
	for fd := uintptr(C.SD_LISTEN_FDS_START); fd < uintptr(C.SD_LISTEN_FDS_START+c); fd++ {
		name := C.GoString(names[int(fd-C.SD_LISTEN_FDS_START)])
		fds[name] = os.NewFile(fd, name)
		C.free(unsafe.Pointer(names[int(fd-C.SD_LISTEN_FDS_START)]))
	}
	C.free(unsafe.Pointer(arr))
	return fds, nil
}