Add POSIX <utmpx.h>.

Now <utmpx.h> isn't any more useful on Android than <utmp.h> is, but it
is POSIX, and -- importantly -- we can implement it with just a header
file, so code can use it on every existing API level.

macOS does indeed only have the <utmpx.h> functions (although it does
still have the <utmp.h> header!), so potentially portable code might
want <utmpx.h> on Android. (glibc/musl both have both headers.)

Bug: https://github.com/landley/toybox/pull/213
Test: treehugger
Change-Id: Iaa88167708182009a63e2e1a15f11186b251ed02
diff --git a/tests/Android.bp b/tests/Android.bp
index 6d2a8d4..1949079 100644
--- a/tests/Android.bp
+++ b/tests/Android.bp
@@ -514,6 +514,7 @@
         "unistd_test.cpp",
         "utils.cpp",
         "utmp_test.cpp",
+        "utmpx_test.cpp",
         "wchar_test.cpp",
         "wctype_test.cpp",
     ],
diff --git a/tests/NOTICE b/tests/NOTICE
index 167f90b..cc99d20 100644
--- a/tests/NOTICE
+++ b/tests/NOTICE
@@ -426,3 +426,31 @@
 
 -------------------------------------------------------------------
 
+Copyright (C) 2023 The Android Open Source Project
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+ * Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in
+   the documentation and/or other materials provided with the
+   distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGE.
+
+-------------------------------------------------------------------
+
diff --git a/tests/headers/posix/utmpx_h.c b/tests/headers/posix/utmpx_h.c
new file mode 100644
index 0000000..44dfac9
--- /dev/null
+++ b/tests/headers/posix/utmpx_h.c
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <utmpx.h>
+
+#include "header_checks.h"
+
+static void utmpx_h() {
+  TYPE(struct utmpx);
+  STRUCT_MEMBER_ARRAY(struct utmpx, char/*[]*/, ut_user);
+  STRUCT_MEMBER_ARRAY(struct utmpx, char/*[]*/, ut_id);
+  STRUCT_MEMBER_ARRAY(struct utmpx, char/*[]*/, ut_line);
+  STRUCT_MEMBER(struct utmpx, pid_t, ut_pid);
+  STRUCT_MEMBER(struct utmpx, short, ut_type);
+#if !defined(__GLIBC__)
+  // POSIX says struct timeval, but glibc has an anonymous struct.
+  STRUCT_MEMBER(struct utmpx, struct timeval, ut_tv);
+#endif
+
+  TYPE(pid_t);
+  TYPE(struct timeval);
+
+  MACRO(EMPTY);
+  MACRO(BOOT_TIME);
+  MACRO(OLD_TIME);
+  MACRO(NEW_TIME);
+  MACRO(USER_PROCESS);
+  MACRO(INIT_PROCESS);
+  MACRO(LOGIN_PROCESS);
+  MACRO(DEAD_PROCESS);
+
+  FUNCTION(endutxent, void (*f)(void));
+  FUNCTION(getutxent, struct utmpx* (*f)(void));
+  FUNCTION(getutxid, struct utmpx* (*f)(const struct utmpx*));
+  FUNCTION(getutxline, struct utmpx* (*f)(const struct utmpx*));
+  FUNCTION(pututxline, struct utmpx* (*f)(const struct utmpx*));
+  FUNCTION(setutxent, void (*f)(void));
+}
diff --git a/tests/utmp_test.cpp b/tests/utmp_test.cpp
index b024818..459f9c3 100644
--- a/tests/utmp_test.cpp
+++ b/tests/utmp_test.cpp
@@ -25,6 +25,7 @@
 }
 
 TEST(utmp, smoke) {
+  // The rest of <utmp.h> is just no-op implementations, so testing is trivial.
   ASSERT_EQ(-1, utmpname("hello"));
   setutent();
   ASSERT_EQ(NULL, getutent());
diff --git a/tests/utmpx_test.cpp b/tests/utmpx_test.cpp
new file mode 100644
index 0000000..55427a6
--- /dev/null
+++ b/tests/utmpx_test.cpp
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <gtest/gtest.h>
+
+#include <utmpx.h>
+
+TEST(utmpx, smoke) {
+  // Our utmpx "implementation" just calls the utmp no-op functions.
+  setutxent();
+  utmpx empty = {.ut_type = EMPTY};
+  ASSERT_EQ(NULL, getutxent());
+  ASSERT_EQ(NULL, getutxid(&empty));
+  ASSERT_EQ(NULL, getutxline(&empty));
+  endutxent();
+  ASSERT_EQ(NULL, pututxline(&empty));
+}