summaryrefslogtreecommitdiff
path: root/src/util.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/util.c')
-rw-r--r--src/util.c294
1 files changed, 294 insertions, 0 deletions
diff --git a/src/util.c b/src/util.c
new file mode 100644
index 0000000..fea4b32
--- /dev/null
+++ b/src/util.c
@@ -0,0 +1,294 @@
+/*--------------------------------------------------------------------
+ * Copyright © 2016 James Hunt <jamesodhunt@ubuntu.com>.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *--------------------------------------------------------------------
+ */
+
+#include "util.h"
+#if __GLIBC__
+#include <sys/sysmacros.h>
+#endif
+
+// FIXME
+extern struct procenv_user user;
+extern struct procenv_misc misc;
+
+struct baud_speed
+{
+ speed_t speed;
+ char *name;
+};
+
+/**
+ * fd_valid:
+ * @fd: file descriptor.
+ *
+ * Return 1 if @fd is valid, else 0.
+ **/
+int
+fd_valid (int fd)
+{
+ int flags = 0;
+
+ if (fd < 0)
+ return 0;
+
+ errno = 0;
+ flags = fcntl (fd, F_GETFL);
+
+ if (flags < 0)
+ return 0;
+
+ /* redundant really */
+ if (errno == EBADF)
+ return 0;
+
+ return 1;
+}
+
+#if !defined (PROCENV_PLATFORM_HURD) && \
+ !defined (PROCENV_PLATFORM_MINIX) && \
+ !defined (PROCENV_PLATFORM_DARWIN)
+
+/**
+ * is_console:
+ * @fd: open file descriptor.
+ *
+ * Check if specified file descriptor is attached to a _console_
+ * device (physical or virtual).
+ *
+ * Notes:
+ * - ptys are NOT consoles :)
+ * - running inside screen/tmux will report not running on console.
+ *
+ * Returns: true if @fd is attached to a console, else false.
+ **/
+int
+is_console (int fd)
+{
+ struct vt_mode vt;
+ int ret;
+
+ ret = ioctl (fd, VT_GETMODE, &vt);
+
+ return !ret;
+}
+#endif
+
+/**
+ * is_big_endian:
+ *
+ * Returns: true if system is big-endian, else false.
+ **/
+bool
+is_big_endian (void)
+{
+ int x = 1;
+
+ if (*(char *)&x == 1)
+ return false;
+
+ return true;
+}
+
+bool
+has_ctty (void)
+{
+ int fd;
+ fd = open ("/dev/tty", O_RDONLY | O_NOCTTY);
+
+ if (fd < 0)
+ return false;
+
+ close (fd);
+
+ return true;
+}
+
+bool
+uid_match (uid_t uid)
+{
+ return uid == getuid ();
+}
+
+/**
+ * in_container:
+ *
+ * Determine if running inside a container.
+ *
+ * Returns: Name of container type, or NO_STR.
+ **/
+const char *
+container_type (void)
+{
+ struct stat statbuf;
+ char buffer[1024];
+ FILE *f;
+#if defined (PROCENV_PLATFORM_LINUX)
+ dev_t expected;
+
+ expected = makedev (5, 1);
+#endif
+
+ if (stat ("/dev/console", &statbuf) < 0)
+ goto out;
+
+#if defined (PROCENV_PLATFORM_FREEBSD)
+ if (misc.in_jail)
+ return "jail";
+#endif
+
+ /* LXC's /dev/console is actually a pty */
+#if defined (PROCENV_PLATFORM_LINUX)
+ if (major (statbuf.st_rdev) != major (expected)
+ || (minor (statbuf.st_rdev)) != minor (expected))
+ return "lxc";
+#endif
+
+ if (! stat ("/proc/vz", &statbuf) && stat ("/proc/bc", &statbuf) < 0)
+ return "openvz";
+
+ f = fopen ("/proc/self/status", "r");
+ if (! f)
+ goto out;
+
+ while (fgets (buffer, sizeof (buffer), f)) {
+ size_t len = strlen (buffer);
+ buffer[len-1] = '\0';
+
+ if (strstr (buffer, "VxID") == buffer) {
+ fclose (f);
+ return "vserver";
+ }
+ }
+
+ fclose (f);
+
+out:
+ return NO_STR;
+}
+
+/**
+ * in_chroot:
+ *
+ * Determine if running inside a chroot environment.
+ *
+ * Failures are fatal.
+ *
+ * Returns true if within a chroot, else false.
+ **/
+// FIXME: add different implementations?
+bool
+in_chroot (void)
+{
+ struct stat st;
+ int i;
+ int root_inode, self_inode;
+ char root[] = "/";
+ char self[] = "/proc/self/root";
+ char bsd_self[] = "/proc/curproc";
+ char *dir = NULL;
+
+ i = stat (root, &st);
+ if (i != 0) {
+ dir = root;
+ goto error;
+ }
+
+ root_inode = st.st_ino;
+
+ /*
+ * Inode 2 is the root inode for most filesystems. However, XFS
+ * uses 128 for root.
+ */
+ if (root_inode != 2 && root_inode != 128)
+ return true;
+
+ i = stat (bsd_self, &st);
+ if (i == 0) {
+ /* Give up here if running on BSD */
+ return false;
+ }
+
+ i = stat (self, &st);
+ if (i != 0)
+ return false;
+
+ self_inode = st.st_ino;
+
+ if (root_inode == self_inode)
+ return false;
+
+ return true;
+
+error:
+ die ("cannot stat '%s'", dir);
+
+ /* compiler appeasement */
+ return false;
+}
+
+/* detect if setsid(2) has been called */
+bool
+is_session_leader (void)
+{
+ return user.sid == user.pid;
+}
+
+/* detect if setpgrp(2)/setpgid(2) (or setsid(2)) has been called */
+bool
+is_process_group_leader (void)
+{
+ return user.pgroup == user.pid;
+}
+
+static struct baud_speed baud_speeds[] = {
+ SPEED (B0),
+ SPEED (B50),
+ SPEED (B75),
+ SPEED (B110),
+ SPEED (B134),
+ SPEED (B150),
+ SPEED (B200),
+ SPEED (B300),
+ SPEED (B600),
+ SPEED (B1200),
+ SPEED (B1800),
+ SPEED (B2400),
+ SPEED (B4800),
+ SPEED (B9600),
+ SPEED (B19200),
+ SPEED (B38400),
+ SPEED (B57600),
+ SPEED (B115200),
+ SPEED (B230400),
+
+ /* terminator */
+ { 0, NULL }
+};
+
+const char *
+get_speed (speed_t speed)
+{
+ struct baud_speed *s;
+
+ for (s = baud_speeds; s && s->name; s++) {
+ if (speed == s->speed)
+ return s->name;
+ }
+
+ return NULL;
+}
+