blob: 9cb0dd2720b3f41a7c036656cf8fd2ad60897df4 [file] [log] [blame]
robert.swiecki3bb518c2010-10-14 00:48:24 +00001/*
robert.swiecki3bb518c2010-10-14 00:48:24 +00002
Robert Swieckic8c32db2015-10-09 18:06:22 +02003 nsjail - logging
4 -----------------------------------------
5
6 Copyright 2014 Google Inc. All Rights Reserved.
7
8 Licensed under the Apache License, Version 2.0 (the "License");
9 you may not use this file except in compliance with the License.
10 You may obtain a copy of the License at
11
12 http://www.apache.org/licenses/LICENSE-2.0
13
14 Unless required by applicable law or agreed to in writing, software
15 distributed under the License is distributed on an "AS IS" BASIS,
16 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 See the License for the specific language governing permissions and
18 limitations under the License.
19
20*/
Jagger03267342016-03-11 02:40:47 +010021
22#include "common.h"
robert.swiecki@gmail.comba85c3e2015-02-02 14:55:16 +000023#include "log.h"
24
robert.swiecki@gmail.comba85c3e2015-02-02 14:55:16 +000025#include <errno.h>
Robert Swieckic8c32db2015-10-09 18:06:22 +020026#include <fcntl.h>
27#include <getopt.h>
28#include <limits.h>
Jagger94021372015-10-11 17:01:53 +020029#include <pthread.h>
robert.swiecki@gmail.comba85c3e2015-02-02 14:55:16 +000030#include <stdarg.h>
31#include <stdio.h>
32#include <stdlib.h>
robert.swiecki3bb518c2010-10-14 00:48:24 +000033#include <string.h>
Robert Swieckic8c32db2015-10-09 18:06:22 +020034#include <sys/stat.h>
robert.swiecki@gmail.comdfde1c72015-02-18 13:22:55 +000035#include <sys/types.h>
robert.swiecki3bb518c2010-10-14 00:48:24 +000036#include <time.h>
robert.swiecki@gmail.comebc1cac2011-07-02 03:15:51 +000037#include <unistd.h>
robert.swiecki3bb518c2010-10-14 00:48:24 +000038
Robert Swiecki98b10562017-02-09 23:58:13 +010039#include "display.h"
Robert Swiecki94d54ff2016-09-06 14:38:21 +020040#include "util.h"
Robert Swiecki0212d692016-08-30 16:45:33 +020041
Anestis Bechtsoudisc9473322015-10-09 12:59:17 -070042#if defined(_HF_ARCH_LINUX)
43#include <sys/syscall.h>
44#define __hf_pid() (pid_t) syscall(__NR_gettid)
45#else /* defined(_HF_ARCH_LINUX) */
46#define __hf_pid() getpid()
47#endif /* defined(_HF_ARCH_LINUX) */
48
Robert Swiecki1c040032016-02-16 18:51:23 +010049static int log_fd;
50static bool log_fd_isatty;
51enum llevel_t log_level;
Robert Swiecki0212d692016-08-30 16:45:33 +020052static pthread_mutex_t log_mutex = PTHREAD_MUTEX_INITIALIZER;
robert.swiecki@gmail.com6f319912015-02-28 05:01:37 +000053
Robert Swiecki1c040032016-02-16 18:51:23 +010054__attribute__ ((constructor))
55static void log_init(void)
56{
57 log_level = INFO;
Robert Swiecki54a195d2016-03-16 16:34:32 +010058 log_fd = fcntl(STDERR_FILENO, F_DUPFD_CLOEXEC, 0);
59 if (log_fd == -1) {
60 log_fd = STDERR_FILENO;
61 }
Robert Swiecki1c040032016-02-16 18:51:23 +010062 log_fd_isatty = isatty(log_fd);
63}
64
Robert Swieckic8c32db2015-10-09 18:06:22 +020065/*
66 * Log to stderr by default. Use a dup()d fd, because in the future we'll associate the
67 * connection socket with fd (0, 1, 2).
68 */
69bool logInitLogFile(const char *logfile, enum llevel_t ll)
robert.swiecki3bb518c2010-10-14 00:48:24 +000070{
Robert Swieckic8c32db2015-10-09 18:06:22 +020071 log_level = ll;
Jagger94021372015-10-11 17:01:53 +020072
Robert Swieckic8c32db2015-10-09 18:06:22 +020073 if (logfile == NULL) {
Robert Swieckic8c32db2015-10-09 18:06:22 +020074 return true;
75 }
Jagger94021372015-10-11 17:01:53 +020076
Robert Swieckic8c32db2015-10-09 18:06:22 +020077 log_fd = open(logfile, O_CREAT | O_RDWR | O_APPEND, 0640);
78 if (log_fd == -1) {
79 log_fd = STDERR_FILENO;
80 PLOG_E("Couldn't open logfile open('%s')", logfile);
81 return false;
82 }
83 log_fd_isatty = (isatty(log_fd) == 1 ? true : false);
84 return true;
robert.swiecki3bb518c2010-10-14 00:48:24 +000085}
86
Robert Swieckic8c32db2015-10-09 18:06:22 +020087void logLog(enum llevel_t ll, const char *fn, int ln, bool perr, const char *fmt, ...)
Robert Swiecki30254b82015-10-08 16:36:08 +020088{
robert.swiecki3bb518c2010-10-14 00:48:24 +000089 char strerr[512];
Robert Swieckic8c32db2015-10-09 18:06:22 +020090 if (perr == true) {
robert.swiecki@gmail.com528fa202011-06-22 17:25:07 +000091 snprintf(strerr, sizeof(strerr), "%s", strerror(errno));
robert.swiecki3bb518c2010-10-14 00:48:24 +000092 }
Robert Swieckic8c32db2015-10-09 18:06:22 +020093 struct ll_t {
Jaggerc62c2a92016-09-19 03:29:53 +020094 const char *descr;
95 const char *prefix;
96 const bool print_funcline;
Robert Swieckib2b89b02016-10-20 18:09:49 +020097 const bool print_time;
Robert Swieckic8c32db2015-10-09 18:06:22 +020098 };
Jagger18f680f2016-09-19 03:30:30 +020099 static const struct ll_t logLevels[] = {
Robert Swieckib2b89b02016-10-20 18:09:49 +0200100 {"F", "\033[7;35m", true, true},
101 {"E", "\033[1;31m", true, true},
102 {"W", "\033[0;33m", true, true},
Robert Swiecki84793cc2017-01-26 19:51:23 +0100103 {"I", "\033[1m", false, false},
Robert Swieckib2b89b02016-10-20 18:09:49 +0200104 {"D", "\033[0;4m", true, true},
105 {"HR", "\033[0m", false, false},
106 {"HB", "\033[1m", false, false},
Robert Swieckic8c32db2015-10-09 18:06:22 +0200107 };
robert.swiecki3bb518c2010-10-14 00:48:24 +0000108
Robert Swieckic8c32db2015-10-09 18:06:22 +0200109 time_t ltstamp = time(NULL);
110 struct tm utctime;
111 localtime_r(&ltstamp, &utctime);
112 char timestr[32];
113 if (strftime(timestr, sizeof(timestr) - 1, "%FT%T%z", &utctime) == 0) {
114 timestr[0] = '\0';
robert.swiecki@gmail.comebc1cac2011-07-02 03:15:51 +0000115 }
robert.swiecki@gmail.comdfde1c72015-02-18 13:22:55 +0000116
Robert Swieckic8c32db2015-10-09 18:06:22 +0200117 /* Start printing logs */
Robert Swieckia9db9dd2016-03-09 16:29:37 +0100118 {
Robert Swiecki0212d692016-08-30 16:45:33 +0200119 MX_SCOPED_LOCK(&log_mutex);
robert.swiecki3bb518c2010-10-14 00:48:24 +0000120
Robert Swieckia9db9dd2016-03-09 16:29:37 +0100121 if (log_fd_isatty) {
122 dprintf(log_fd, "%s", logLevels[ll].prefix);
123 }
Robert Swieckib2b89b02016-10-20 18:09:49 +0200124 if (logLevels[ll].print_time) {
125 dprintf(log_fd, "[%s][%s][%d] ", timestr, logLevels[ll].descr, __hf_pid());
Robert Swiecki9c900942016-10-20 18:10:14 +0200126 }
Robert Swieckia9db9dd2016-03-09 16:29:37 +0100127 if (logLevels[ll].print_funcline) {
Robert Swieckib2b89b02016-10-20 18:09:49 +0200128 dprintf(log_fd, "%s():%d ", fn, ln);
Robert Swieckia9db9dd2016-03-09 16:29:37 +0100129 }
Jagger94021372015-10-11 17:01:53 +0200130
Robert Swieckia9db9dd2016-03-09 16:29:37 +0100131 va_list args;
132 va_start(args, fmt);
133 vdprintf(log_fd, fmt, args);
134 va_end(args);
135
136 if (perr == true) {
137 dprintf(log_fd, ": %s", strerr);
138 }
139 if (log_fd_isatty) {
140 dprintf(log_fd, "\033[0m");
141 }
142 dprintf(log_fd, "\n");
robert.swiecki3bb518c2010-10-14 00:48:24 +0000143 }
Robert Swieckic8c32db2015-10-09 18:06:22 +0200144 /* End printing logs */
robert.swiecki@gmail.comebc1cac2011-07-02 03:15:51 +0000145
Robert Swieckic8c32db2015-10-09 18:06:22 +0200146 if (ll == FATAL) {
Robert Swiecki1f1ce172017-02-10 03:43:00 +0100147 display_fini();
Robert Swieckic8c32db2015-10-09 18:06:22 +0200148 exit(1);
robert.swiecki@gmail.com6f319912015-02-28 05:01:37 +0000149 }
Robert Swieckic8c32db2015-10-09 18:06:22 +0200150}
robert.swiecki@gmail.come7190b92015-02-14 23:05:42 +0000151
Robert Swieckic8c32db2015-10-09 18:06:22 +0200152void logStop(int sig)
153{
154 LOG_I("Server stops due to fatal signal (%d) caught. Exiting", sig);
155}
156
157void logRedirectLogFD(int fd)
158{
159 log_fd = fd;
160}
161
162void logDirectlyToFD(const char *msg)
163{
164 dprintf(log_fd, "%s", msg);
robert.swiecki3bb518c2010-10-14 00:48:24 +0000165}
Robert Swiecki0212d692016-08-30 16:45:33 +0200166
167pthread_mutex_t *logMutexGet(void)
168{
169 return &log_mutex;
170}
Robert Swiecki4d45c3e2017-02-02 22:54:46 +0100171
172bool logIsTTY(void)
173{
174 return log_fd_isatty;
175}
176
177int logFd(void)
178{
179 return log_fd;
180}