// Copyright (c) 2026 Storm Dragon // Authors: Storm Dragon, Angus Kola // SPDX-License-Identifier: GPL-3.0-or-later package remoteinput import ( "os" "syscall" ) // AdoptPipe transfers an inherited pipe to an owned nonblocking duplicate so // Go's poller can interrupt blocked I/O on Close. Terminals/regular files and // wrong-direction descriptors are rejected; a helper must have private control // pipes. Failure leaves the original file owned by its caller. func AdoptPipe(file *os.File, write bool) (*os.File, error) { if file == nil { return nil, ErrProtocol } info, err := file.Stat() if err != nil || info.Mode()&os.ModeNamedPipe == 0 { return nil, ErrProtocol } flags, _, failure := syscall.Syscall(syscall.SYS_FCNTL, file.Fd(), syscall.F_GETFL, 0) want := syscall.O_RDONLY if write { want = syscall.O_WRONLY } if failure != 0 || int(flags)&syscall.O_ACCMODE != want { return nil, ErrProtocol } fd, err := syscall.Dup(int(file.Fd())) if err != nil { return nil, ErrProtocol } syscall.CloseOnExec(fd) if err := syscall.SetNonblock(fd, true); err != nil { syscall.Close(fd) return nil, ErrProtocol } owned := os.NewFile(uintptr(fd), "remote-input-pipe") file.Close() return owned, nil }