13ad8ecb64e9dd5614169232b84a93eb3b8aa32d7Elliott Hughes/*
23ad8ecb64e9dd5614169232b84a93eb3b8aa32d7Elliott Hughes * Copyright (C) 2014 The Android Open Source Project
33ad8ecb64e9dd5614169232b84a93eb3b8aa32d7Elliott Hughes *
43ad8ecb64e9dd5614169232b84a93eb3b8aa32d7Elliott Hughes * Licensed under the Apache License, Version 2.0 (the "License");
53ad8ecb64e9dd5614169232b84a93eb3b8aa32d7Elliott Hughes * you may not use this file except in compliance with the License.
63ad8ecb64e9dd5614169232b84a93eb3b8aa32d7Elliott Hughes * You may obtain a copy of the License at
73ad8ecb64e9dd5614169232b84a93eb3b8aa32d7Elliott Hughes *
83ad8ecb64e9dd5614169232b84a93eb3b8aa32d7Elliott Hughes *      http://www.apache.org/licenses/LICENSE-2.0
93ad8ecb64e9dd5614169232b84a93eb3b8aa32d7Elliott Hughes *
103ad8ecb64e9dd5614169232b84a93eb3b8aa32d7Elliott Hughes * Unless required by applicable law or agreed to in writing, software
113ad8ecb64e9dd5614169232b84a93eb3b8aa32d7Elliott Hughes * distributed under the License is distributed on an "AS IS" BASIS,
123ad8ecb64e9dd5614169232b84a93eb3b8aa32d7Elliott Hughes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
133ad8ecb64e9dd5614169232b84a93eb3b8aa32d7Elliott Hughes * See the License for the specific language governing permissions and
143ad8ecb64e9dd5614169232b84a93eb3b8aa32d7Elliott Hughes * limitations under the License.
153ad8ecb64e9dd5614169232b84a93eb3b8aa32d7Elliott Hughes */
163ad8ecb64e9dd5614169232b84a93eb3b8aa32d7Elliott Hughes
17f1e83cc34a58761fc7bc5178c6f283db85d6057aElliott Hughes#include <errno.h>
183ad8ecb64e9dd5614169232b84a93eb3b8aa32d7Elliott Hughes#include <stdlib.h>
1976f8916b904db14facf811ae44e1265261349702Elliott Hughes#include <string.h>
20afe6360627ef3f0e9bc8f45535fbfae3354f3ae0Elliott Hughes#include <syslog.h>
213ad8ecb64e9dd5614169232b84a93eb3b8aa32d7Elliott Hughes
227a3681e5b6c39bc2b3b62031ca5941dbf7bc4e63Christopher Ferris#include <async_safe/log.h>
233ad8ecb64e9dd5614169232b84a93eb3b8aa32d7Elliott Hughes
243ad8ecb64e9dd5614169232b84a93eb3b8aa32d7Elliott Hughesstatic const char* syslog_log_tag = NULL;
253ad8ecb64e9dd5614169232b84a93eb3b8aa32d7Elliott Hughesstatic int syslog_priority_mask = 0xff;
263ad8ecb64e9dd5614169232b84a93eb3b8aa32d7Elliott Hughes
273ad8ecb64e9dd5614169232b84a93eb3b8aa32d7Elliott Hughesvoid closelog() {
28afe6360627ef3f0e9bc8f45535fbfae3354f3ae0Elliott Hughes  syslog_log_tag = NULL;
293ad8ecb64e9dd5614169232b84a93eb3b8aa32d7Elliott Hughes}
303ad8ecb64e9dd5614169232b84a93eb3b8aa32d7Elliott Hughes
313ad8ecb64e9dd5614169232b84a93eb3b8aa32d7Elliott Hughesvoid openlog(const char* log_tag, int /*options*/, int /*facility*/) {
323ad8ecb64e9dd5614169232b84a93eb3b8aa32d7Elliott Hughes  syslog_log_tag = log_tag;
333ad8ecb64e9dd5614169232b84a93eb3b8aa32d7Elliott Hughes}
343ad8ecb64e9dd5614169232b84a93eb3b8aa32d7Elliott Hughes
353ad8ecb64e9dd5614169232b84a93eb3b8aa32d7Elliott Hughesint setlogmask(int new_mask) {
363ad8ecb64e9dd5614169232b84a93eb3b8aa32d7Elliott Hughes  int old_mask = syslog_priority_mask;
373ad8ecb64e9dd5614169232b84a93eb3b8aa32d7Elliott Hughes  // 0 is used to query the current mask.
383ad8ecb64e9dd5614169232b84a93eb3b8aa32d7Elliott Hughes  if (new_mask != 0) {
393ad8ecb64e9dd5614169232b84a93eb3b8aa32d7Elliott Hughes    syslog_priority_mask = new_mask;
403ad8ecb64e9dd5614169232b84a93eb3b8aa32d7Elliott Hughes  }
413ad8ecb64e9dd5614169232b84a93eb3b8aa32d7Elliott Hughes  return old_mask;
423ad8ecb64e9dd5614169232b84a93eb3b8aa32d7Elliott Hughes}
433ad8ecb64e9dd5614169232b84a93eb3b8aa32d7Elliott Hughes
443ad8ecb64e9dd5614169232b84a93eb3b8aa32d7Elliott Hughesvoid syslog(int priority, const char* fmt, ...) {
453ad8ecb64e9dd5614169232b84a93eb3b8aa32d7Elliott Hughes  va_list args;
463ad8ecb64e9dd5614169232b84a93eb3b8aa32d7Elliott Hughes  va_start(args, fmt);
473ad8ecb64e9dd5614169232b84a93eb3b8aa32d7Elliott Hughes  vsyslog(priority, fmt, args);
483ad8ecb64e9dd5614169232b84a93eb3b8aa32d7Elliott Hughes  va_end(args);
493ad8ecb64e9dd5614169232b84a93eb3b8aa32d7Elliott Hughes}
503ad8ecb64e9dd5614169232b84a93eb3b8aa32d7Elliott Hughes
513ad8ecb64e9dd5614169232b84a93eb3b8aa32d7Elliott Hughesvoid vsyslog(int priority, const char* fmt, va_list args) {
52f1e83cc34a58761fc7bc5178c6f283db85d6057aElliott Hughes  int caller_errno = errno;
53f1e83cc34a58761fc7bc5178c6f283db85d6057aElliott Hughes
543ad8ecb64e9dd5614169232b84a93eb3b8aa32d7Elliott Hughes  // Check whether we're supposed to be logging messages of this priority.
553ad8ecb64e9dd5614169232b84a93eb3b8aa32d7Elliott Hughes  if ((syslog_priority_mask & LOG_MASK(LOG_PRI(priority))) == 0) {
563ad8ecb64e9dd5614169232b84a93eb3b8aa32d7Elliott Hughes    return;
573ad8ecb64e9dd5614169232b84a93eb3b8aa32d7Elliott Hughes  }
583ad8ecb64e9dd5614169232b84a93eb3b8aa32d7Elliott Hughes
593ad8ecb64e9dd5614169232b84a93eb3b8aa32d7Elliott Hughes  // What's our log tag?
603ad8ecb64e9dd5614169232b84a93eb3b8aa32d7Elliott Hughes  const char* log_tag = syslog_log_tag;
613ad8ecb64e9dd5614169232b84a93eb3b8aa32d7Elliott Hughes  if (log_tag == NULL) {
623ad8ecb64e9dd5614169232b84a93eb3b8aa32d7Elliott Hughes    log_tag = getprogname();
633ad8ecb64e9dd5614169232b84a93eb3b8aa32d7Elliott Hughes  }
643ad8ecb64e9dd5614169232b84a93eb3b8aa32d7Elliott Hughes
653ad8ecb64e9dd5614169232b84a93eb3b8aa32d7Elliott Hughes  // What's our Android log priority?
663ad8ecb64e9dd5614169232b84a93eb3b8aa32d7Elliott Hughes  priority &= LOG_PRIMASK;
673ad8ecb64e9dd5614169232b84a93eb3b8aa32d7Elliott Hughes  int android_log_priority;
68afe6360627ef3f0e9bc8f45535fbfae3354f3ae0Elliott Hughes  if (priority <= LOG_ERR) {
693ad8ecb64e9dd5614169232b84a93eb3b8aa32d7Elliott Hughes    android_log_priority = ANDROID_LOG_ERROR;
703ad8ecb64e9dd5614169232b84a93eb3b8aa32d7Elliott Hughes  } else if (priority == LOG_WARNING) {
713ad8ecb64e9dd5614169232b84a93eb3b8aa32d7Elliott Hughes    android_log_priority = ANDROID_LOG_WARN;
723ad8ecb64e9dd5614169232b84a93eb3b8aa32d7Elliott Hughes  } else if (priority <= LOG_INFO) {
733ad8ecb64e9dd5614169232b84a93eb3b8aa32d7Elliott Hughes    android_log_priority = ANDROID_LOG_INFO;
743ad8ecb64e9dd5614169232b84a93eb3b8aa32d7Elliott Hughes  } else {
753ad8ecb64e9dd5614169232b84a93eb3b8aa32d7Elliott Hughes    android_log_priority = ANDROID_LOG_DEBUG;
763ad8ecb64e9dd5614169232b84a93eb3b8aa32d7Elliott Hughes  }
773ad8ecb64e9dd5614169232b84a93eb3b8aa32d7Elliott Hughes
78f1e83cc34a58761fc7bc5178c6f283db85d6057aElliott Hughes  // glibc's printf family support %m directly, but our BSD-based one doesn't.
79f1e83cc34a58761fc7bc5178c6f283db85d6057aElliott Hughes  // If the format string seems to contain "%m", rewrite it.
80f1e83cc34a58761fc7bc5178c6f283db85d6057aElliott Hughes  const char* log_fmt = fmt;
81f1e83cc34a58761fc7bc5178c6f283db85d6057aElliott Hughes  if (strstr(fmt, "%m") != NULL) {
82f1e83cc34a58761fc7bc5178c6f283db85d6057aElliott Hughes    size_t dst_len = 1024;
83f1e83cc34a58761fc7bc5178c6f283db85d6057aElliott Hughes    char* dst = reinterpret_cast<char*>(malloc(dst_len));
84f1e83cc34a58761fc7bc5178c6f283db85d6057aElliott Hughes    log_fmt = dst;
85f1e83cc34a58761fc7bc5178c6f283db85d6057aElliott Hughes
86f1e83cc34a58761fc7bc5178c6f283db85d6057aElliott Hughes    const char* src = fmt;
87f1e83cc34a58761fc7bc5178c6f283db85d6057aElliott Hughes    for (; dst_len > 0 && *src != '\0'; ++src) {
88f1e83cc34a58761fc7bc5178c6f283db85d6057aElliott Hughes      if (*src == '%' && *(src + 1) == 'm') {
89f1e83cc34a58761fc7bc5178c6f283db85d6057aElliott Hughes        // Expand %m.
90f1e83cc34a58761fc7bc5178c6f283db85d6057aElliott Hughes        size_t n = strlcpy(dst, strerror(caller_errno), dst_len);
91f1e83cc34a58761fc7bc5178c6f283db85d6057aElliott Hughes        if (n >= dst_len) {
92f1e83cc34a58761fc7bc5178c6f283db85d6057aElliott Hughes          n = dst_len;
93f1e83cc34a58761fc7bc5178c6f283db85d6057aElliott Hughes        }
94f1e83cc34a58761fc7bc5178c6f283db85d6057aElliott Hughes        dst += n;
95f1e83cc34a58761fc7bc5178c6f283db85d6057aElliott Hughes        dst_len -= n;
96f1e83cc34a58761fc7bc5178c6f283db85d6057aElliott Hughes        ++src;
97f1e83cc34a58761fc7bc5178c6f283db85d6057aElliott Hughes      } else if (*src == '%' && *(src + 1) == '%') {
98f1e83cc34a58761fc7bc5178c6f283db85d6057aElliott Hughes        // We need to copy pairs of '%'s so the %m test works.
99f1e83cc34a58761fc7bc5178c6f283db85d6057aElliott Hughes        if (dst_len <= 2) {
100f1e83cc34a58761fc7bc5178c6f283db85d6057aElliott Hughes          break;
101f1e83cc34a58761fc7bc5178c6f283db85d6057aElliott Hughes        }
102f1e83cc34a58761fc7bc5178c6f283db85d6057aElliott Hughes        *dst++ = '%'; --dst_len;
103f1e83cc34a58761fc7bc5178c6f283db85d6057aElliott Hughes        *dst++ = '%'; --dst_len;
104f1e83cc34a58761fc7bc5178c6f283db85d6057aElliott Hughes        ++src;
105f1e83cc34a58761fc7bc5178c6f283db85d6057aElliott Hughes      } else {
106f1e83cc34a58761fc7bc5178c6f283db85d6057aElliott Hughes        *dst++ = *src; --dst_len;
107f1e83cc34a58761fc7bc5178c6f283db85d6057aElliott Hughes      }
108f1e83cc34a58761fc7bc5178c6f283db85d6057aElliott Hughes    }
109f1e83cc34a58761fc7bc5178c6f283db85d6057aElliott Hughes    *dst = '\0';
110f1e83cc34a58761fc7bc5178c6f283db85d6057aElliott Hughes  }
111f1e83cc34a58761fc7bc5178c6f283db85d6057aElliott Hughes
1127a3681e5b6c39bc2b3b62031ca5941dbf7bc4e63Christopher Ferris  // We can't let async_safe_format_log do the formatting because it doesn't support
113f1e83cc34a58761fc7bc5178c6f283db85d6057aElliott Hughes  // all the printf functionality.
114f1e83cc34a58761fc7bc5178c6f283db85d6057aElliott Hughes  char log_line[1024];
115f1e83cc34a58761fc7bc5178c6f283db85d6057aElliott Hughes  vsnprintf(log_line, sizeof(log_line), log_fmt, args);
116f1e83cc34a58761fc7bc5178c6f283db85d6057aElliott Hughes
117f1e83cc34a58761fc7bc5178c6f283db85d6057aElliott Hughes  if (log_fmt != fmt) {
118f1e83cc34a58761fc7bc5178c6f283db85d6057aElliott Hughes    free(const_cast<char*>(log_fmt));
119f1e83cc34a58761fc7bc5178c6f283db85d6057aElliott Hughes  }
120f1e83cc34a58761fc7bc5178c6f283db85d6057aElliott Hughes
1217a3681e5b6c39bc2b3b62031ca5941dbf7bc4e63Christopher Ferris  async_safe_format_log(android_log_priority, log_tag, "%s", log_line);
1223ad8ecb64e9dd5614169232b84a93eb3b8aa32d7Elliott Hughes}
123