commit: 68093027341c3b5d7c7d27da27d6e863639fd02d
parent 8f7852ae1c1d37b388c116af70545878c9f21b14
Author: Haelwenn (lanodan) Monnier <contact@hacktivis.me>
Date: Fri, 19 Sep 2025 11:22:57 +0200
cmd/mesg: new
Diffstat:
3 files changed, 135 insertions(+), 1 deletion(-)
diff --git a/cmd/mesg.1 b/cmd/mesg.1
@@ -0,0 +1,46 @@
+.\" utils-std: Collection of commonly available Unix tools
+.\" Copyright 2017 Haelwenn (lanodan) Monnier <contact+utils@hacktivis.me>
+.\" SPDX-License-Identifier: MPL-2.0
+.Dd September 19, 2025
+.Dt MESG 1
+.Os
+.Sh NAME
+.Nm mesg
+.Nd permit or deny messages
+.Sh SYNOPSIS
+.Nm
+.Op Ar y Ns | Ns Ar n
+.Sh DESCRIPTION
+.Nm
+controls whether other users are allowed to send messages
+to the current terminal, determined via searching for a TTY
+on stdin, stdout, stderr.
+If none were found,
+.Nm
+fails.
+.Sh OPERANDS
+.Bl -tag -width _
+.It Ar y
+Allow other users to write to current terminal
+.It Ar n
+Deny other users from writing to current terminal
+.El
+.Sh EXIT STATUS
+.Bl -tag -width __
+.It 0
+Other users can write.
+.It 1
+Other users cannot write.
+.It >1
+An error occurred.
+.El
+.Sh SEE ALSO
+.Xr talk 1 ,
+.Xr write 1
+.Sh STANDARDS
+.Nm
+should be compliant with the
+IEEE Std 1003.1-2024 (“POSIX.1”)
+specification.
+.Sh AUTHORS
+.An Haelwenn (lanodan) Monnier Aq Mt contact+utils@hacktivis.me
diff --git a/cmd/mesg.c b/cmd/mesg.c
@@ -0,0 +1,88 @@
+// utils-std: Collection of commonly available Unix tools
+// SPDX-FileCopyrightText: 2017 Haelwenn (lanodan) Monnier <contact+utils@hacktivis.me>
+// SPDX-License-Identifier: MPL-2.0
+
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/stat.h> // stat, chmod
+#include <unistd.h> // ttyname
+
+int
+main(int argc, char *argv[])
+{
+ argc -= 1;
+ argv += 1;
+
+ if(argc > 1)
+ {
+ fprintf(stderr, "mesg: error: Expected either 0 or 1 argument, got %d\n", argc);
+ return 2;
+ }
+
+ if(argc == 1)
+ {
+ if(argv[0][0] == '\0')
+ {
+ fputs("mesg: error: argument is empty, expected 'y' or 'n'\n", stderr);
+ return 2;
+ }
+ if(argv[0][1] != '\0')
+ {
+ fputs("mesg: error: argument is too long, expected 'y' or 'n'\n", stderr);
+ return 2;
+ }
+ if(argv[0][0] != 'y' && argv[0][0] != 'n')
+ {
+ fprintf(stderr, "mesg: error: unknown argument '%s', expected 'y' or 'n'\n", argv[0]);
+ return 2;
+ }
+ }
+
+ char *tty = ttyname(STDIN_FILENO);
+ if(!tty) ttyname(STDOUT_FILENO);
+ if(!tty) ttyname(STDERR_FILENO);
+ if(!tty)
+ {
+ fputs("mesg: error: Could not determine TTY from stdin/stdout/stderr\n", stderr);
+ return 2;
+ }
+
+ struct stat tty_st;
+ if(stat(tty, &tty_st) < 0)
+ {
+ fprintf(
+ stderr, "mesg: error: Failed getting file status from '%s': %s\n", tty, strerror(errno));
+ return 2;
+ }
+
+ if(argc == 0)
+ {
+ if((tty_st.st_mode & 0022) == 0022)
+ {
+ fputs("messages allowed\n", stdout);
+ return 0;
+ }
+
+ fputs("messages denied\n", stdout);
+ return 1;
+ }
+
+ mode_t new_mode = tty_st.st_mode;
+ if(argv[0][0] == 'y')
+ new_mode |= 0022;
+ else
+ new_mode &= ~0022;
+
+ if(chmod(tty, new_mode) < 0)
+ {
+ fprintf(stderr,
+ "mesg: error: Failed setting new mode (0%03o) on terminal '%s': %s\n",
+ new_mode,
+ tty,
+ strerror(errno));
+ return 2;
+ }
+
+ return 0;
+}
diff --git a/posix_utilities.txt b/posix_utilities.txt
@@ -83,7 +83,7 @@ m4: no, external
mailx: no, external
make: no, devtool POSIX2_SW_DEV
man: no, external (for example with mandoc) POSIX2_UPE
-mesg: no, external (linked to wall and write)
+mesg: done
mkdir: done
mkfifo: done
more: no POSIX2_UPE