Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sudo-project
GitHub Repository: sudo-project/sudo
Path: blob/main/lib/iolog/iolog_path.c
1532 views
1
/*
2
* SPDX-License-Identifier: ISC
3
*
4
* Copyright (c) 2011-2015 Todd C. Miller <[email protected]>
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 USE, DATA OR PROFITS, WHETHER IN AN
15
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17
*/
18
19
#include <config.h>
20
21
#include <stdio.h>
22
#include <stdlib.h>
23
#ifdef HAVE_STDBOOL_H
24
# include <stdbool.h>
25
#else
26
# include <compat/stdbool.h>
27
#endif /* HAVE_STDBOOL_H */
28
#include <string.h>
29
#include <limits.h>
30
#include <time.h>
31
#include <unistd.h>
32
33
#include <sudo_compat.h>
34
#include <sudo_debug.h>
35
#include <sudo_fatal.h>
36
#include <sudo_gettext.h>
37
#include <sudo_iolog.h>
38
#include <sudo_util.h>
39
40
/*
41
* Expand any escape sequences in inpath, returning the expanded path.
42
*/
43
bool
44
expand_iolog_path(const char *inpath, char *path, size_t pathlen,
45
const struct iolog_path_escape *escapes, void *closure)
46
{
47
char *dst, *pathend, tmpbuf[PATH_MAX];
48
const char *endbrace, *src;
49
bool strfit = false;
50
size_t len;
51
debug_decl(expand_iolog_path, SUDO_DEBUG_UTIL);
52
53
/* Collapse multiple leading slashes. */
54
while (inpath[0] == '/' && inpath[1] == '/')
55
inpath++;
56
57
pathend = path + pathlen;
58
for (src = inpath, dst = path; *src != '\0'; src++) {
59
if (src[0] == '%') {
60
if (src[1] == '{') {
61
endbrace = strchr(src + 2, '}');
62
if (endbrace != NULL) {
63
const struct iolog_path_escape *esc;
64
len = (size_t)(endbrace - src - 2);
65
for (esc = escapes; esc->name != NULL; esc++) {
66
if (strncmp(src + 2, esc->name, len) == 0 &&
67
esc->name[len] == '\0')
68
break;
69
}
70
if (esc->name != NULL) {
71
len = esc->copy_fn(dst, (size_t)(pathend - dst),
72
closure);
73
if (len >= (size_t)(pathend - dst))
74
goto bad;
75
dst += len;
76
src = endbrace;
77
continue;
78
}
79
}
80
} else if (src[1] == '%') {
81
/* Collapse %% -> % */
82
src++;
83
} else {
84
/* May need strftime() */
85
strfit = true;
86
}
87
}
88
/* Need at least 2 chars, including the NUL terminator. */
89
if (dst + 1 >= pathend)
90
goto bad;
91
*dst++ = *src;
92
}
93
94
/* Trim trailing slashes and NUL terminate. */
95
while (dst > path && dst[-1] == '/')
96
dst--;
97
*dst = '\0';
98
99
/* Expand strftime escapes as needed. */
100
if (strfit) {
101
struct tm tm;
102
time_t now;
103
104
time(&now);
105
if (localtime_r(&now, &tm) == NULL)
106
goto bad;
107
108
/* We only call strftime() on the current part of the buffer. */
109
tmpbuf[sizeof(tmpbuf) - 1] = '\0';
110
len = strftime(tmpbuf, sizeof(tmpbuf), path, &tm);
111
112
if (len == 0 || tmpbuf[sizeof(tmpbuf) - 1] != '\0')
113
goto bad; /* strftime() failed, buf too small? */
114
115
if (len >= (size_t)(pathend - path))
116
goto bad; /* expanded buffer too big to fit. */
117
memcpy(path, tmpbuf, len);
118
dst = path + len;
119
*dst = '\0';
120
}
121
122
debug_return_bool(true);
123
bad:
124
debug_return_bool(false);
125
}
126
127
/*
128
* Like strlcpy(3) but replaces '/' with '_'.
129
*/
130
size_t
131
strlcpy_no_slash(char * restrict dst, const char * restrict src, size_t size)
132
{
133
size_t len = 0;
134
char ch;
135
debug_decl(strlcpy_no_slash, SUDO_DEBUG_UTIL);
136
137
while ((ch = *src++) != '\0') {
138
if (size > 1) {
139
/* Replace '/' with '_' */
140
if (ch == '/')
141
ch = '_';
142
*dst++ = ch;
143
size--;
144
}
145
len++;
146
}
147
if (size > 0)
148
*dst = '\0';
149
150
debug_return_size_t(len);
151
}
152
153