git: 09e0a909fb07 - stable/14 - tee: try opening as a UNIX socket if open(2) fails
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Sun, 27 Apr 2025 18:59:50 UTC
The branch stable/14 has been updated by kevans:
URL: https://cgit.FreeBSD.org/src/commit/?id=09e0a909fb07615ed97c8648a24b541840bc1fa7
commit 09e0a909fb07615ed97c8648a24b541840bc1fa7
Author: Kyle Evans <kevans@FreeBSD.org>
AuthorDate: 2025-04-20 16:34:52 +0000
Commit: Kyle Evans <kevans@FreeBSD.org>
CommitDate: 2025-04-27 18:59:34 +0000
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
(cherry picked from commit 1b3748977f28c70e0b161fb476bf4e075bcc5940)
---
usr.bin/tee/tee.1 | 8 +++++++-
usr.bin/tee/tee.c | 46 +++++++++++++++++++++++++++++++++++++++++--
usr.bin/tee/tests/tee_test.sh | 32 ++++++++++++++++++++++++++++++
3 files changed, 83 insertions(+), 3 deletions(-)
diff --git a/usr.bin/tee/tee.1 b/usr.bin/tee/tee.1
index b7673ea0ce61..b4d38fbb5b24 100644
--- a/usr.bin/tee/tee.1
+++ b/usr.bin/tee/tee.1
@@ -30,7 +30,7 @@
.\"
.\" @(#)tee.1 8.1 (Berkeley) 6/6/93
.\"
-.Dd October 30, 2022
+.Dd December 25, 2024
.Dt TEE 1
.Os
.Sh NAME
@@ -71,6 +71,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
diff --git a/usr.bin/tee/tee.c b/usr.bin/tee/tee.c
index aeda9c34ac45..92c8913210aa 100644
--- a/usr.bin/tee/tee.c
+++ b/usr.bin/tee/tee.c
@@ -41,10 +41,12 @@ static char sccsid[] = "@(#)tee.c 8.1 (Berkeley) 6/6/93";
#endif
#endif /* not lint */
+#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>
@@ -64,6 +66,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
@@ -105,7 +108,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 {
@@ -161,3 +164,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);
+}
diff --git a/usr.bin/tee/tests/tee_test.sh b/usr.bin/tee/tests/tee_test.sh
index 6ac733f2e58f..cf8e74dd47e7 100644
--- a/usr.bin/tee/tests/tee_test.sh
+++ b/usr.bin/tee/tests/tee_test.sh
@@ -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
}