wall: access FILE under real user's credentials

While at it, move applet/config/kbuild bits into wall.c.
(This way, it's more visible that applet is suid'ed).

function                                             old     new   delta
wall_main                                             87     138     +51

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
diff --git a/miscutils/wall.c b/miscutils/wall.c
index 762f53b..c74f4f2 100644
--- a/miscutils/wall.c
+++ b/miscutils/wall.c
@@ -6,6 +6,18 @@
  * Licensed under GPLv2 or later, see file LICENSE in this source tree.
  */
 
+//config:config WALL
+//config:	bool "wall"
+//config:	default y
+//config:	depends on FEATURE_UTMP
+//config:	help
+//config:	  Write a message to all users that are logged in.
+
+/* Needs to be run by root or be suid root - needs to write to /dev/TTY: */
+//applet:IF_WALL(APPLET(wall, BB_DIR_USR_BIN, BB_SUID_REQUIRE))
+
+//kbuild:lib-$(CONFIG_WALL) += wall.o
+
 //usage:#define wall_trivial_usage
 //usage:	"[FILE]"
 //usage:#define wall_full_usage "\n\n"
@@ -22,8 +34,19 @@
 {
 	struct utmp *ut;
 	char *msg;
-	int fd = argv[1] ? xopen(argv[1], O_RDONLY) : STDIN_FILENO;
+	int fd;
 
+	fd = STDIN_FILENO;
+	if (argv[1]) {
+		/* The applet is setuid.
+		 * Access to the file must be under user's uid/gid.
+		 */
+		setfsuid(getuid());
+		setfsgid(getgid());
+		fd = xopen(argv[1], O_RDONLY);
+		setfsuid(geteuid());
+		setfsgid(getegid());
+	}
 	msg = xmalloc_read(fd, NULL);
 	if (ENABLE_FEATURE_CLEAN_UP && argv[1])
 		close(fd);