mirror of
https://github.com/opnsense/src.git
synced 2026-06-11 09:41:03 -04:00
tee: try opening as a UNIX socket if open(2) fails
If we get EOPNOTSUPP from open() failing, then it may just be that we're looking at a unix(4) socket instead of a normal file/device or whatnot. Fallback to trying to open it as a unix(4) socket, which is a useful feature that doesn't add much complexity. Reviewed by: des, emaste, markj Differential Revision: https://reviews.freebsd.org/D48197
This commit is contained in:
parent
414c2b8d1e
commit
1b3748977f
3 changed files with 83 additions and 3 deletions
|
|
@ -28,7 +28,7 @@
|
|||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.Dd October 30, 2022
|
||||
.Dd December 25, 2024
|
||||
.Dt TEE 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
|
|
@ -69,6 +69,12 @@ utility takes the default action for all signals,
|
|||
except in the event of the
|
||||
.Fl i
|
||||
option.
|
||||
.Pp
|
||||
This implementation of the
|
||||
.Nm
|
||||
utility may also write to
|
||||
.Xr unix 4
|
||||
sockets.
|
||||
.Sh EXIT STATUS
|
||||
.Ex -std
|
||||
.Sh EXAMPLES
|
||||
|
|
|
|||
|
|
@ -29,10 +29,12 @@
|
|||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/capsicum.h>
|
||||
#include <sys/queue.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/un.h>
|
||||
|
||||
#include <capsicum_helpers.h>
|
||||
#include <err.h>
|
||||
|
|
@ -52,6 +54,7 @@ struct entry {
|
|||
static STAILQ_HEAD(, entry) head = STAILQ_HEAD_INITIALIZER(head);
|
||||
|
||||
static void add(int, const char *);
|
||||
static int tee_open(const char *, int);
|
||||
static void usage(void) __dead2;
|
||||
|
||||
int
|
||||
|
|
@ -93,7 +96,7 @@ main(int argc, char *argv[])
|
|||
oflags |= O_TRUNC;
|
||||
|
||||
for (exitval = 0; *argv; ++argv) {
|
||||
if ((fd = open(*argv, oflags, DEFFILEMODE)) < 0) {
|
||||
if ((fd = tee_open(*argv, oflags)) < 0) {
|
||||
warn("%s", *argv);
|
||||
exitval = 1;
|
||||
} else {
|
||||
|
|
@ -149,3 +152,42 @@ add(int fd, const char *name)
|
|||
p->name = name;
|
||||
STAILQ_INSERT_HEAD(&head, p, entries);
|
||||
}
|
||||
|
||||
static int
|
||||
tee_open(const char *path, int oflags)
|
||||
{
|
||||
struct sockaddr_un sun = { .sun_family = AF_UNIX };
|
||||
size_t pathlen;
|
||||
int fd;
|
||||
|
||||
if ((fd = open(path, oflags, DEFFILEMODE)) >= 0)
|
||||
return (fd);
|
||||
|
||||
if (errno != EOPNOTSUPP)
|
||||
return (-1);
|
||||
|
||||
pathlen = strnlen(path, sizeof(sun.sun_path));
|
||||
if (pathlen >= sizeof(sun.sun_path))
|
||||
goto failed;
|
||||
|
||||
/*
|
||||
* For EOPNOTSUPP, we'll try again as a unix(4) socket. Any errors here
|
||||
* we'll just surface as the original EOPNOTSUPP since they may not have
|
||||
* intended for this.
|
||||
*/
|
||||
fd = socket(PF_UNIX, SOCK_STREAM, 0);
|
||||
if (fd < 0)
|
||||
goto failed;
|
||||
|
||||
(void)strlcpy(&sun.sun_path[0], path, sizeof(sun.sun_path));
|
||||
sun.sun_len = SUN_LEN(&sun);
|
||||
|
||||
if (connect(fd, (const struct sockaddr *)&sun, sun.sun_len) == 0)
|
||||
return (fd);
|
||||
|
||||
failed:
|
||||
if (fd >= 0)
|
||||
close(fd);
|
||||
errno = EOPNOTSUPP;
|
||||
return (-1);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -64,6 +64,37 @@ sigint_ignored_body()
|
|||
atf_check -o inline:"text\ntext\n" cat file
|
||||
}
|
||||
|
||||
atf_test_case unixsock "cleanup"
|
||||
unixsock_pidfile="nc.pid"
|
||||
|
||||
unixsock_body()
|
||||
{
|
||||
outfile=out.log
|
||||
|
||||
nc -lU logger.sock > "$outfile" &
|
||||
npid=$!
|
||||
|
||||
atf_check -o save:"$unixsock_pidfile" echo "$npid"
|
||||
|
||||
# Wait for the socket to come online, just in case.
|
||||
while [ ! -S logger.sock ]; do
|
||||
sleep 0.1
|
||||
done
|
||||
|
||||
atf_check -o inline:"text over socket\n" -x \
|
||||
'echo "text over socket" | tee logger.sock'
|
||||
|
||||
atf_check rm "$unixsock_pidfile"
|
||||
atf_check -o inline:"text over socket\n" cat "$outfile"
|
||||
}
|
||||
unixsock_cleanup()
|
||||
{
|
||||
if [ -s "$unixsock_pidfile" ]; then
|
||||
read npid < "$unixsock_pidfile"
|
||||
kill "$npid"
|
||||
fi
|
||||
}
|
||||
|
||||
atf_init_test_cases()
|
||||
{
|
||||
atf_add_test_case single_file
|
||||
|
|
@ -71,4 +102,5 @@ atf_init_test_cases()
|
|||
atf_add_test_case multiple_file
|
||||
atf_add_test_case append
|
||||
atf_add_test_case sigint_ignored
|
||||
atf_add_test_case unixsock
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue