blob: 398765cea854ca52ac5ad54ce99259941853e26f [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
Anestis Bechtsoudisc9473322015-10-09 12:59:17 -070039#if defined(_HF_ARCH_LINUX)
40#include <sys/syscall.h>
41#define __hf_pid() (pid_t) syscall(__NR_gettid)
42#else /* defined(_HF_ARCH_LINUX) */
43#define __hf_pid() getpid()
44#endif /* defined(_HF_ARCH_LINUX) */
45
Robert Swiecki1c040032016-02-16 18:51:23 +010046static int log_fd;
47static bool log_fd_isatty;
48enum llevel_t log_level;
Jagger94021372015-10-11 17:01:53 +020049pthread_mutex_t log_mutex = PTHREAD_MUTEX_INITIALIZER;
robert.swiecki@gmail.com6f319912015-02-28 05:01:37 +000050
Robert Swiecki1c040032016-02-16 18:51:23 +010051__attribute__ ((constructor))
52static void log_init(void)
53{
54 log_level = INFO;
Robert Swiecki54a195d2016-03-16 16:34:32 +010055 log_fd = fcntl(STDERR_FILENO, F_DUPFD_CLOEXEC, 0);
56 if (log_fd == -1) {
57 log_fd = STDERR_FILENO;
58 }
Robert Swiecki1c040032016-02-16 18:51:23 +010059 log_fd_isatty = isatty(log_fd);
60}
61
Robert Swieckic8c32db2015-10-09 18:06:22 +020062/*
63 * Log to stderr by default. Use a dup()d fd, because in the future we'll associate the
64 * connection socket with fd (0, 1, 2).
65 */
66bool logInitLogFile(const char *logfile, enum llevel_t ll)
robert.swiecki3bb518c2010-10-14 00:48:24 +000067{
Robert Swieckic8c32db2015-10-09 18:06:22 +020068 log_level = ll;
Jagger94021372015-10-11 17:01:53 +020069
Robert Swieckic8c32db2015-10-09 18:06:22 +020070 if (logfile == NULL) {
Robert Swieckic8c32db2015-10-09 18:06:22 +020071 return true;
72 }
Jagger94021372015-10-11 17:01:53 +020073
Robert Swieckic8c32db2015-10-09 18:06:22 +020074 log_fd = open(logfile, O_CREAT | O_RDWR | O_APPEND, 0640);
75 if (log_fd == -1) {
76 log_fd = STDERR_FILENO;
77 PLOG_E("Couldn't open logfile open('%s')", logfile);
78 return false;
79 }
80 log_fd_isatty = (isatty(log_fd) == 1 ? true : false);
81 return true;
robert.swiecki3bb518c2010-10-14 00:48:24 +000082}
83
Robert Swieckic8c32db2015-10-09 18:06:22 +020084void logLog(enum llevel_t ll, const char *fn, int ln, bool perr, const char *fmt, ...)
Robert Swiecki30254b82015-10-08 16:36:08 +020085{
robert.swiecki3bb518c2010-10-14 00:48:24 +000086 char strerr[512];
Robert Swieckic8c32db2015-10-09 18:06:22 +020087 if (perr == true) {
robert.swiecki@gmail.com528fa202011-06-22 17:25:07 +000088 snprintf(strerr, sizeof(strerr), "%s", strerror(errno));
robert.swiecki3bb518c2010-10-14 00:48:24 +000089 }
Robert Swieckic8c32db2015-10-09 18:06:22 +020090 struct ll_t {
91 char *descr;
92 char *prefix;
93 bool print_funcline;
94 };
95 struct ll_t logLevels[] = {
Robert Swieckia88f96f2015-10-09 16:47:39 +020096 {"F", "\033[7;35m", true},
97 {"E", "\033[1;31m", true},
98 {"W", "\033[0;33m", true},
99 {"I", "\033[1m", true},
100 {"D", "\033[0;4m", true},
Robert Swieckic8c32db2015-10-09 18:06:22 +0200101 {"HR", "\033[0m", false},
102 {"HB", "\033[1m", false},
Robert Swieckic8c32db2015-10-09 18:06:22 +0200103 };
robert.swiecki3bb518c2010-10-14 00:48:24 +0000104
Robert Swieckic8c32db2015-10-09 18:06:22 +0200105 time_t ltstamp = time(NULL);
106 struct tm utctime;
107 localtime_r(&ltstamp, &utctime);
108 char timestr[32];
109 if (strftime(timestr, sizeof(timestr) - 1, "%FT%T%z", &utctime) == 0) {
110 timestr[0] = '\0';
robert.swiecki@gmail.comebc1cac2011-07-02 03:15:51 +0000111 }
robert.swiecki@gmail.comdfde1c72015-02-18 13:22:55 +0000112
Robert Swieckic8c32db2015-10-09 18:06:22 +0200113 /* Start printing logs */
Robert Swieckia9db9dd2016-03-09 16:29:37 +0100114 {
115 pthread_mutex_lock(&log_mutex);
Jagger4fe18692016-04-22 23:15:07 +0200116 defer {
117 pthread_mutex_unlock(&log_mutex);
118 };
robert.swiecki3bb518c2010-10-14 00:48:24 +0000119
Robert Swieckia9db9dd2016-03-09 16:29:37 +0100120 if (log_fd_isatty) {
121 dprintf(log_fd, "%s", logLevels[ll].prefix);
122 }
123 if (logLevels[ll].print_funcline) {
124 dprintf(log_fd, "[%s][%s][%d] %s():%d ", timestr, logLevels[ll].descr, __hf_pid(), fn,
125 ln);
126 }
Jagger94021372015-10-11 17:01:53 +0200127
Robert Swieckia9db9dd2016-03-09 16:29:37 +0100128 va_list args;
129 va_start(args, fmt);
130 vdprintf(log_fd, fmt, args);
131 va_end(args);
132
133 if (perr == true) {
134 dprintf(log_fd, ": %s", strerr);
135 }
136 if (log_fd_isatty) {
137 dprintf(log_fd, "\033[0m");
138 }
139 dprintf(log_fd, "\n");
robert.swiecki3bb518c2010-10-14 00:48:24 +0000140 }
Robert Swieckic8c32db2015-10-09 18:06:22 +0200141 /* End printing logs */
robert.swiecki@gmail.comebc1cac2011-07-02 03:15:51 +0000142
Robert Swieckic8c32db2015-10-09 18:06:22 +0200143 if (ll == FATAL) {
144 exit(1);
robert.swiecki@gmail.com6f319912015-02-28 05:01:37 +0000145 }
Robert Swieckic8c32db2015-10-09 18:06:22 +0200146}
robert.swiecki@gmail.come7190b92015-02-14 23:05:42 +0000147
Robert Swieckic8c32db2015-10-09 18:06:22 +0200148void logStop(int sig)
149{
150 LOG_I("Server stops due to fatal signal (%d) caught. Exiting", sig);
151}
152
153void logRedirectLogFD(int fd)
154{
155 log_fd = fd;
156}
157
158void logDirectlyToFD(const char *msg)
159{
160 dprintf(log_fd, "%s", msg);
robert.swiecki3bb518c2010-10-14 00:48:24 +0000161}