From 027a73a903af306449710ce12bc09e0e3550c6c9 Mon Sep 17 00:00:00 2001
From: Rob Landley <rob@landley.net>
Date: Thu, 4 Aug 2016 10:16:59 -0500
Subject: Make xopen() skip stdin/stdout/stderr, add xopen_stdio() if you want
 stdout, add xopenro() that takes one argument and understands "-" means
 stdin, and switch over lots of users.

---
 lib/lib.c      |  2 +-
 lib/lib.h      |  3 +++
 lib/password.c |  2 +-
 lib/xwrap.c    | 42 +++++++++++++++++++++++++++++++++++++++---
 4 files changed, 44 insertions(+), 5 deletions(-)

(limited to 'lib')

diff --git a/lib/lib.c b/lib/lib.c
index 5c7696d0..718ea3ac 100644
--- a/lib/lib.c
+++ b/lib/lib.c
@@ -1008,7 +1008,7 @@ int qstrcmp(const void *a, const void *b)
 void create_uuid(char *uuid)
 {
   // Read 128 random bits
-  int fd = xopen("/dev/urandom", O_RDONLY);
+  int fd = xopenro("/dev/urandom");
   xreadall(fd, uuid, 16);
   close(fd);
 
diff --git a/lib/lib.h b/lib/lib.h
index c3aa7e72..520a5ed6 100644
--- a/lib/lib.h
+++ b/lib/lib.h
@@ -130,6 +130,9 @@ void xaccess(char *path, int flags);
 void xunlink(char *path);
 int xcreate(char *path, int flags, int mode);
 int xopen(char *path, int flags);
+int xcreate_stdio(char *path, int flags, int mode);
+int xopen_stdio(char *path, int flags);
+int xopenro(char *path);
 void xpipe(int *pp);
 void xclose(int fd);
 int xdup(int fd);
diff --git a/lib/password.c b/lib/password.c
index bf13c441..eab2d669 100644
--- a/lib/password.c
+++ b/lib/password.c
@@ -24,7 +24,7 @@ int get_salt(char *salt, char *algo)
       if (al[i].id) s += sprintf(s, "$%c$", '0'+al[i].id);
 
       // Read appropriate number of random bytes for salt
-      i = xopen("/dev/urandom", O_RDONLY);
+      i = xopenro("/dev/urandom");
       xreadall(i, libbuf, ((len*6)+7)/8);
       close(i);
 
diff --git a/lib/xwrap.c b/lib/xwrap.c
index 7176aae1..a7b7bfcb 100644
--- a/lib/xwrap.c
+++ b/lib/xwrap.c
@@ -318,17 +318,18 @@ void xunlink(char *path)
 }
 
 // Die unless we can open/create a file, returning file descriptor.
-int xcreate(char *path, int flags, int mode)
+int xcreate_stdio(char *path, int flags, int mode)
 {
   int fd = open(path, flags^O_CLOEXEC, mode);
+
   if (fd == -1) perror_exit_raw(path);
   return fd;
 }
 
 // Die unless we can open a file, returning file descriptor.
-int xopen(char *path, int flags)
+int xopen_stdio(char *path, int flags)
 {
-  return xcreate(path, flags, 0);
+  return xcreate_stdio(path, flags, 0);
 }
 
 void xpipe(int *pp)
@@ -350,6 +351,41 @@ int xdup(int fd)
   return fd;
 }
 
+// Move file descriptor above stdin/stdout/stderr, using /dev/null to consume
+// old one. (We should never be called with stdin/stdout/stderr closed, but...)
+int notstdio(int fd)
+{
+  while (fd<3) {
+    int fd2 = xdup(fd);
+
+    close(fd);
+    xopen_stdio("/dev/null", O_RDWR);
+    fd = fd2;
+  }
+
+  return fd;
+}
+
+// Create a file but don't return stdin/stdout/stderr
+int xcreate(char *path, int flags, int mode)
+{
+  return notstdio(xcreate_stdio(path, flags, mode));
+}
+
+// Open a file descriptor NOT in stdin/stdout/stderr
+int xopen(char *path, int flags)
+{
+  return notstdio(xopen_stdio(path, flags));
+}
+
+// Open read only, treating "-" as a synonym for stdin.
+int xopenro(char *path)
+{
+  if (!strcmp(path, "-")) return 0;
+
+  return xopen(path, O_RDONLY);
+}
+
 FILE *xfdopen(int fd, char *mode)
 {
   FILE *f = fdopen(fd, mode);
-- 
cgit v1.2.3