Coverage Report

Created: 2023-06-07 06:04

/src/tmux/log.c
Line
Count
Source (jump to first uncovered line)
1
/* $OpenBSD$ */
2
3
/*
4
 * Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
5
 *
6
 * Permission to use, copy, modify, and distribute this software for any
7
 * purpose with or without fee is hereby granted, provided that the above
8
 * copyright notice and this permission notice appear in all copies.
9
 *
10
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14
 * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
15
 * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
16
 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17
 */
18
19
#include <sys/types.h>
20
21
#include <errno.h>
22
#include <stdio.h>
23
#include <stdlib.h>
24
#include <string.h>
25
#include <unistd.h>
26
27
#include "tmux.h"
28
29
static FILE *log_file;
30
static int   log_level;
31
32
/* Log callback for libevent. */
33
static void
34
log_event_cb(__unused int severity, const char *msg)
35
0
{
36
0
  log_debug("%s", msg);
37
0
}
38
39
/* Increment log level. */
40
void
41
log_add_level(void)
42
0
{
43
0
  log_level++;
44
0
}
45
46
/* Get log level. */
47
int
48
log_get_level(void)
49
20.2k
{
50
20.2k
  return (log_level);
51
20.2k
}
52
53
/* Open logging to file. */
54
void
55
log_open(const char *name)
56
0
{
57
0
  char  *path;
58
59
0
  if (log_level == 0)
60
0
    return;
61
0
  log_close();
62
63
0
  xasprintf(&path, "tmux-%s-%ld.log", name, (long)getpid());
64
0
  log_file = fopen(path, "a");
65
0
  free(path);
66
0
  if (log_file == NULL)
67
0
    return;
68
69
0
  setvbuf(log_file, NULL, _IOLBF, 0);
70
0
  event_set_log_callback(log_event_cb);
71
0
}
72
73
/* Toggle logging. */
74
void
75
log_toggle(const char *name)
76
0
{
77
0
  if (log_level == 0) {
78
0
    log_level = 1;
79
0
    log_open(name);
80
0
    log_debug("log opened");
81
0
  } else {
82
0
    log_debug("log closed");
83
0
    log_level = 0;
84
0
    log_close();
85
0
  }
86
0
}
87
88
/* Close logging. */
89
void
90
log_close(void)
91
0
{
92
0
  if (log_file != NULL)
93
0
    fclose(log_file);
94
0
  log_file = NULL;
95
96
0
  event_set_log_callback(NULL);
97
0
}
98
99
/* Write a log message. */
100
static void printflike(1, 0)
101
log_vwrite(const char *msg, va_list ap, const char *prefix)
102
0
{
103
0
  char    *s, *out;
104
0
  struct timeval   tv;
105
106
0
  if (log_file == NULL)
107
0
    return;
108
109
0
  if (vasprintf(&s, msg, ap) == -1)
110
0
    return;
111
0
  if (stravis(&out, s, VIS_OCTAL|VIS_CSTYLE|VIS_TAB|VIS_NL) == -1) {
112
0
    free(s);
113
0
    return;
114
0
  }
115
0
  free(s);
116
117
0
  gettimeofday(&tv, NULL);
118
0
  if (fprintf(log_file, "%lld.%06d %s%s\n", (long long)tv.tv_sec,
119
0
      (int)tv.tv_usec, prefix, out) != -1)
120
0
    fflush(log_file);
121
0
  free(out);
122
0
}
123
124
/* Log a debug message. */
125
void
126
log_debug(const char *msg, ...)
127
1.32M
{
128
1.32M
  va_list ap;
129
130
1.32M
  if (log_file == NULL)
131
1.32M
    return;
132
133
0
  va_start(ap, msg);
134
0
  log_vwrite(msg, ap, "");
135
0
  va_end(ap);
136
0
}
137
138
/* Log a critical error with error string and die. */
139
__dead void
140
fatal(const char *msg, ...)
141
0
{
142
0
  char   tmp[256];
143
0
  va_list  ap;
144
145
0
  if (snprintf(tmp, sizeof tmp, "fatal: %s: ", strerror(errno)) < 0)
146
0
    exit(1);
147
148
0
  va_start(ap, msg);
149
0
  log_vwrite(msg, ap, tmp);
150
0
  va_end(ap);
151
152
0
  exit(1);
153
0
}
154
155
/* Log a critical error and die. */
156
__dead void
157
fatalx(const char *msg, ...)
158
0
{
159
0
  va_list  ap;
160
161
0
  va_start(ap, msg);
162
0
  log_vwrite(msg, ap, "fatal: ");
163
0
  va_end(ap);
164
165
0
  exit(1);
166
0
}