// Copyright 2015 CoreOS, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Package activation implements primitives for systemd socket activation. package activation import ( "os" "strconv" "strings" "syscall" ) const ( // listenFdsStart corresponds to `SD_LISTEN_FDS_START`. listenFdsStart = 3 ) // Files returns a slice containing a `os.File` object for each // file descriptor passed to this process via systemd fd-passing protocol. // // The order of the file descriptors is preserved in the returned slice. // `unsetEnv` is typically set to `true` in order to avoid clashes in // fd usage and to avoid leaking environment flags to child processes. func Files(unsetEnv bool) []*os.File { if unsetEnv { defer os.Unsetenv("LISTEN_PID") defer os.Unsetenv("LISTEN_FDS") defer os.Unsetenv("LISTEN_FDNAMES") } pid, err := strconv.Atoi(os.Getenv("LISTEN_PID")) if err != nil || pid != os.Getpid() { return nil } nfds, err := strconv.Atoi(os.Getenv("LISTEN_FDS")) if err != nil || nfds == 0 { return nil } names := strings.Split(os.Getenv("LISTEN_FDNAMES"), ":") files := make([]*os.File, 0, nfds) for fd := listenFdsStart; fd < listenFdsStart+nfds; fd++ { syscall.CloseOnExec(fd) name := "LISTEN_FD_" + strconv.Itoa(fd) offset := fd - listenFdsStart if offset < len(names) && len(names[offset]) > 0 { name = names[offset] } files = append(files, os.NewFile(uintptr(fd), name)) } return files }