<syslog.h>: add facilitynames[] and prioritynames[].

Test: treehugger
Change-Id: I2a65b3088fe5a28b66e7d1c2a8caa10cb4467202
diff --git a/libc/NOTICE b/libc/NOTICE
index ef64e0c..d464e1d 100644
--- a/libc/NOTICE
+++ b/libc/NOTICE
@@ -942,6 +942,35 @@
 
 -------------------------------------------------------------------
 
+Copyright (c) 1982, 1986, 1988, 1993
+   The Regents of the University of California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+1. Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+2. 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.
+3. Neither the name of the University nor the names of its contributors
+   may be used to endorse or promote products derived from this software
+   without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+
+-------------------------------------------------------------------
+
 Copyright (c) 1982, 1986, 1993
    The Regents of the University of California.  All rights reserved.
 
diff --git a/libc/include/syslog.h b/libc/include/syslog.h
index 90ea76e..1e2fcc4 100644
--- a/libc/include/syslog.h
+++ b/libc/include/syslog.h
@@ -25,6 +25,34 @@
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  */
+/*
+ * Copyright (c) 1982, 1986, 1988, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ */
 
 #pragma once
 
@@ -129,6 +157,60 @@
  */
 #define LOG_PERROR 0x20
 
+#if defined(SYSLOG_NAMES)
+/** A mapping from name to value, used by `facilitynames` and `prioritynames`. */
+typedef struct _code {
+  char* c_name;
+  int c_val;
+} CODE;
+/* A bogus facility value for "mark". */
+#define INTERNAL_MARK LOG_MAKEPRI((LOG_NFACILITIES<<3), 0)
+/** A table mapping facility names to values. */
+static const CODE facilitynames[] = {
+  { "auth", LOG_AUTH, },
+  { "authpriv", LOG_AUTHPRIV, },
+  { "cron", LOG_CRON, },
+  { "daemon", LOG_DAEMON, },
+  { "ftp", LOG_FTP, },
+  { "kern", LOG_KERN, },
+  { "lpr", LOG_LPR, },
+  { "mail", LOG_MAIL, },
+  { "mark", INTERNAL_MARK, },
+  { "news", LOG_NEWS, },
+  { "security", LOG_AUTH, },
+  { "syslog", LOG_SYSLOG, },
+  { "user", LOG_USER, },
+  { "uucp", LOG_UUCP, },
+  { "local0", LOG_LOCAL0, },
+  { "local1", LOG_LOCAL1, },
+  { "local2", LOG_LOCAL2, },
+  { "local3", LOG_LOCAL3, },
+  { "local4", LOG_LOCAL4, },
+  { "local5", LOG_LOCAL5, },
+  { "local6", LOG_LOCAL6, },
+  { "local7", LOG_LOCAL7, },
+  { NULL, -1, },
+};
+/* A bogus priority value for "none". */
+#define INTERNAL_NOPRI 8
+/** A table mapping priority names to values. */
+static const CODE prioritynames[] = {
+  { "alert", LOG_ALERT, },
+  { "crit", LOG_CRIT, },
+  { "debug", LOG_DEBUG, },
+  { "emerg", LOG_EMERG, },
+  { "err", LOG_ERR, },
+  { "error", LOG_ERR, },
+  { "info", LOG_INFO, },
+  { "none", INTERNAL_NOPRI, },
+  { "notice", LOG_NOTICE, },
+  { "panic", LOG_EMERG, },
+  { "warn", LOG_WARNING, },
+  { "warning", LOG_WARNING, },
+  { NULL, -1, },
+};
+#endif
+
 /**
  * [closelog(3)](http://man7.org/linux/man-pages/man3/closelog.3.html) does
  * nothing on Android.
diff --git a/tests/syslog_test.cpp b/tests/syslog_test.cpp
index 3ec3337..623d8a3 100644
--- a/tests/syslog_test.cpp
+++ b/tests/syslog_test.cpp
@@ -26,6 +26,9 @@
  * SUCH DAMAGE.
  */
 
+#include <stddef.h>  // glibc's <syslog.h> breaks without this; musl seems fine.
+
+#define SYSLOG_NAMES
 #include <syslog.h>
 
 #include <errno.h>
@@ -72,3 +75,34 @@
       },
       0, "bar: x{1023}\n");
 }
+
+static int by_name(const CODE* array, const char* name) {
+  for (auto c = array; c->c_name != nullptr; c++) {
+    if (!strcmp(c->c_name, name)) return c->c_val;
+  }
+  return -1;
+}
+
+static const char* by_value(const CODE* array, int value) {
+  for (auto c = array; c->c_name != nullptr; c++) {
+    if (c->c_val == value) return c->c_name;
+  }
+  return nullptr;
+}
+
+TEST(syslog, facilitynames) {
+  ASSERT_STREQ("auth", by_value(facilitynames, LOG_AUTH));
+  ASSERT_STREQ("local7", by_value(facilitynames, LOG_LOCAL7));
+  ASSERT_EQ(LOG_AUTH, by_name(facilitynames, "auth"));
+  ASSERT_EQ(LOG_LOCAL7, by_name(facilitynames, "local7"));
+}
+
+TEST(syslog, prioritynames) {
+  ASSERT_STREQ("alert", by_value(prioritynames, LOG_ALERT));
+  ASSERT_STREQ("err", by_value(prioritynames, LOG_ERR));
+  ASSERT_STREQ("warn", by_value(prioritynames, LOG_WARNING));
+  ASSERT_EQ(LOG_ALERT, by_name(prioritynames, "alert"));
+  ASSERT_EQ(LOG_ERR, by_name(prioritynames, "err"));
+  ASSERT_EQ(LOG_WARNING, by_name(prioritynames, "warn"));
+  ASSERT_EQ(LOG_WARNING, by_name(prioritynames, "warning"));
+}