summaryrefslogtreecommitdiffstats
path: root/debian/patches/75_27_Fix-logging-with-empty-element-in-log_file_path-Bug-.patch
blob: 58da37cd163ba4927b424537613f58bfb02c259d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
From e19790f7707cc901435849e78d20f249056c16b5 Mon Sep 17 00:00:00 2001
From: Jeremy Harris <jgh146exb@wizmail.org>
Date: Sat, 15 May 2021 13:37:04 +0200
Subject: [PATCH 3/4] Fix logging with empty element in log_file_path (Bug
 2733)

---
 src/log.c | 84 +++++++++++++++++++++++++++++++++------------------
 1 file changed, 55 insertions(+), 29 deletions(-)

diff --git a/src/log.c b/src/log.c
index 2108ed46f..716bec553 100644
--- a/src/log.c
+++ b/src/log.c
@@ -283,16 +283,19 @@ problem. */
 
 if (fd < 0 && errno == ENOENT)
   {
   BOOL created;
   uschar *lastslash = Ustrrchr(name, '/');
   *lastslash = 0;
   created = directory_make(NULL, name, LOG_DIRECTORY_MODE, FALSE);
-  DEBUG(D_any) debug_printf("%s log directory %s\n",
-    created ? "created" : "failed to create", name);
+  DEBUG(D_any)
+    if (created)
+      debug_printf("created log directory %s\n", name);
+    else
+      debug_printf("failed to create log directory %s: %s\n", name, strerror(errno));
   *lastslash = '/';
   if (created) fd = Uopen(name, flags, LOG_MODE);
   }
 
 return fd;
 }
 
@@ -390,17 +393,15 @@ Returns:       a file descriptor, or < 0 on failure (errno set)
 int
 log_open_as_exim(uschar * const name)
 {
 int fd = -1;
 const uid_t euid = geteuid();
 
 if (euid == exim_uid)
-  {
   fd = log_open_already_exim(name);
-  }
 else if (euid == root_uid)
   {
   int sock[2];
   if (socketpair(AF_UNIX, SOCK_STREAM, 0, sock) == 0)
     {
     const pid_t pid = exim_fork(US"logfile-open");
     if (pid == 0)
@@ -495,38 +496,48 @@ ok = string_format(buffer, sizeof(buffer), CS file_path, log_names[type]);
 switch (type)
   {
   case lt_main:
     /* Save the name of the mainlog for rollover processing. Without a datestamp,
     it gets statted to see if it has been cycled. With a datestamp, the datestamp
     will be compared. The static slot for saving it is the same size as buffer,
     and the text has been checked above to fit, so this use of strcpy() is OK. */
+
     Ustrcpy(mainlog_name, buffer);
     if (string_datestamp_offset > 0)
       mainlog_datestamp = mainlog_name + string_datestamp_offset;
+    break;
+
   case lt_reject:
     /* Ditto for the reject log */
+
     Ustrcpy(rejectlog_name, buffer);
     if (string_datestamp_offset > 0)
       rejectlog_datestamp = rejectlog_name + string_datestamp_offset;
+    break;
+
   case lt_debug:
     /* and deal with the debug log (which keeps the datestamp, but does not
     update it) */
+
     Ustrcpy(debuglog_name, buffer);
     if (tag)
       {
       /* this won't change the offset of the datestamp */
       ok2 = string_format(buffer, sizeof(buffer), "%s%s",
         debuglog_name, tag);
       if (ok2)
         Ustrcpy(debuglog_name, buffer);
       }
+    break;
+
   default:
     /* Remove any datestamp if this is the panic log. This is rare, so there's no
   need to optimize getting the datestamp length. We remove one non-alphanumeric
   char afterwards if at the start, otherwise one before. */
+
     if (string_datestamp_offset >= 0)
       {
       uschar * from = buffer + string_datestamp_offset;
       uschar * to = from + string_datestamp_length;
 
       if (from == buffer || from[-1] == '/')
         {
@@ -535,30 +546,29 @@ switch (type)
       else
         if (!isalnum(from[-1])) from--;
 
       /* This copy is ok, because we know that to is a substring of from. But
       due to overlap we must use memmove() not Ustrcpy(). */
       memmove(from, to, Ustrlen(to)+1);
       }
+    break;
   }
 
 /* If the file name is too long, it is an unrecoverable disaster */
 
 if (!ok)
   die(US"exim: log file path too long: aborting",
       US"Logging failure; please try later");
 
 /* We now have the file name. After a successful open, return. */
 
 *fd = log_open_as_exim(buffer);
 
 if (*fd >= 0)
-  {
   return;
-  }
 
 euid = geteuid();
 
 /* Creation failed. There are some circumstances in which we get here when
 the effective uid is not root or exim, which is the problem. (For example, a
 non-setuid binary with log_arguments set, called in certain ways.) Rather than
 just bombing out, force the log to stderr and carry on if stderr is available.
@@ -702,45 +712,61 @@ while (1)
     left -= wrote;
     }
   }
 return total_written;
 }
 
 
+/* Pull the file out of the configured or the compiled-in list.
+Called for an empty log_file_path element, for debug logging activation
+when file_path has not previously been set, and from the appenfile transport setup. */
+
 void
 set_file_path(BOOL *multiple)
 {
 uschar *s;
 int sep = ':';              /* Fixed separator - outside use */
 const uschar *ss = *log_file_path ? log_file_path : US LOG_FILE_PATH;
 
-logging_mode = 0;
-while ((s = string_nextinlist(&ss, &sep, log_buffer, LOG_BUFFER_SIZE)))
-  {
-  if (Ustrcmp(s, "syslog") == 0)
-    logging_mode |= LOG_MODE_SYSLOG;
-  else if (logging_mode & LOG_MODE_FILE)  /* we know a file already */
+if (*ss)
+  for (logging_mode = 0;
+       s = string_nextinlist(&ss, &sep, log_buffer, LOG_BUFFER_SIZE); )
     {
-    if (multiple) *multiple = TRUE;
-    }
-  else
-    {
-    logging_mode |= LOG_MODE_FILE;
+    if (Ustrcmp(s, "syslog") == 0)
+      logging_mode |= LOG_MODE_SYSLOG;
+    else if (!(logging_mode & LOG_MODE_FILE))  /* no file yet */
+      {
+      /* If a non-empty path is given, use it */
 
-    /* If a non-empty path is given, use it */
+      if (*s)
+	file_path = string_copy(s);
 
-    if (*s)
-      file_path = string_copy(s);
+      /* If handling the config option, and the element is empty, we want to use
+      the first non-empty, non-syslog item in LOG_FILE_PATH, if there is one,
+      since the value of log_file_path may have been set at runtime. If there is
+      no such item, use the ultimate default in the spool directory. */
 
-    /* If the path is empty, we want to use the first non-empty, non-
-    syslog item in LOG_FILE_PATH, if there is one, since the value of
-    log_file_path may have been set at runtime. If there is no such item,
-    use the ultimate default in the spool directory. */
+      else if (*log_file_path && LOG_FILE_PATH[0])
+	{
+	ss = US LOG_FILE_PATH;
+	continue;
+	}
+
+      logging_mode |= LOG_MODE_FILE;
+      }
+    else
+      if (multiple) *multiple = TRUE;
     }
-  }
+  else
+    logging_mode = LOG_MODE_FILE;
+
+/* Set up the ultimate default if necessary. */
+
+if (logging_mode & LOG_MODE_FILE  &&  !*file_path)
+  file_path = string_sprintf("%s/log/%%slog", spool_directory);
 }
 
 
 void
 mainlog_close(void)
 {
 /* avoid closing it if it is closed already or if we do not see a chance
@@ -866,19 +892,16 @@ if (!path_inspected)
 
   /* If no modes have been selected, it is a major disaster */
 
   if (logging_mode == 0)
     die(US"Neither syslog nor file logging set in log_file_path",
         US"Unexpected logging failure");
 
-  /* Set up the ultimate default if necessary. Then revert to the old store
-  pool, and record that we've sorted out the path. */
+  /* Revert to the old store pool, and record that we've sorted out the path. */
 
-  if (logging_mode & LOG_MODE_FILE  &&  !file_path[0])
-    file_path = string_sprintf("%s/log/%%slog", spool_directory);
   store_pool = old_pool;
   path_inspected = TRUE;
 
   /* If more than one file path was given, log a complaint. This recursive call
   should work since we have now set up the routing. */
 
   if (multiple)
@@ -1224,14 +1247,15 @@ if (flags & LOG_PANIC)
     write_syslog(LOG_ALERT, log_buffer);
 
   /* If this panic logging was caused by a failure to open the main log,
   the original log line is in panic_save_buffer. Make an attempt to write it. */
 
   if (logging_mode & LOG_MODE_FILE)
     {
+    if (!*file_path) set_file_path(NULL);
     panic_recurseflag = TRUE;
     open_log(&paniclogfd, lt_panic, NULL);  /* Won't return on failure */
     panic_recurseflag = FALSE;
 
     if (panic_save_buffer)
       {
       int i = write(paniclogfd, panic_save_buffer, Ustrlen(panic_save_buffer));
@@ -1501,16 +1525,18 @@ if (!debug_file || !debuglog_name[0]) return;
 
 debug_selector = 0;
 fclose(debug_file);
 debug_file = NULL;
 unlink_log(lt_debug);
 }
 
+/* Called from the appendfile transport setup. */
 void
 open_logs(void)
 {
 set_file_path(NULL);
+if (!(logging_mode & LOG_MODE_FILE)) return;
 open_log(&mainlogfd, lt_main, 0);
 open_log(&rejectlogfd, lt_reject, 0);
 }
 
 /* End of log.c */
-- 
2.30.2