]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/shared/specifier.c
Merge pull request #2080 from chaloulo/split-mode-host-remove-port-from-journal-filename
[thirdparty/systemd.git] / src / shared / specifier.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4 This file is part of systemd.
5
6 Copyright 2010 Lennart Poettering
7
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
12
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
17
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 ***/
21
22 #include <errno.h>
23 #include <stdbool.h>
24 #include <stddef.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <sys/utsname.h>
28
29 #include "sd-id128.h"
30
31 #include "alloc-util.h"
32 #include "hostname-util.h"
33 #include "macro.h"
34 #include "specifier.h"
35 #include "string-util.h"
36
37 /*
38 * Generic infrastructure for replacing %x style specifiers in
39 * strings. Will call a callback for each replacement.
40 *
41 */
42
43 int specifier_printf(const char *text, const Specifier table[], void *userdata, char **_ret) {
44 char *ret, *t;
45 const char *f;
46 bool percent = false;
47 size_t l;
48 int r;
49
50 assert(text);
51 assert(table);
52
53 l = strlen(text);
54 ret = new(char, l+1);
55 if (!ret)
56 return -ENOMEM;
57
58 t = ret;
59
60 for (f = text; *f; f++, l--) {
61
62 if (percent) {
63 if (*f == '%')
64 *(t++) = '%';
65 else {
66 const Specifier *i;
67
68 for (i = table; i->specifier; i++)
69 if (i->specifier == *f)
70 break;
71
72 if (i->lookup) {
73 _cleanup_free_ char *w = NULL;
74 char *n;
75 size_t k, j;
76
77 r = i->lookup(i->specifier, i->data, userdata, &w);
78 if (r < 0) {
79 free(ret);
80 return r;
81 }
82
83 j = t - ret;
84 k = strlen(w);
85
86 n = new(char, j + k + l + 1);
87 if (!n) {
88 free(ret);
89 return -ENOMEM;
90 }
91
92 memcpy(n, ret, j);
93 memcpy(n + j, w, k);
94
95 free(ret);
96
97 ret = n;
98 t = n + j + k;
99 } else {
100 *(t++) = '%';
101 *(t++) = *f;
102 }
103 }
104
105 percent = false;
106 } else if (*f == '%')
107 percent = true;
108 else
109 *(t++) = *f;
110 }
111
112 *t = 0;
113 *_ret = ret;
114 return 0;
115 }
116
117 /* Generic handler for simple string replacements */
118
119 int specifier_string(char specifier, void *data, void *userdata, char **ret) {
120 char *n;
121
122 n = strdup(strempty(data));
123 if (!n)
124 return -ENOMEM;
125
126 *ret = n;
127 return 0;
128 }
129
130 int specifier_machine_id(char specifier, void *data, void *userdata, char **ret) {
131 sd_id128_t id;
132 char *n;
133 int r;
134
135 r = sd_id128_get_machine(&id);
136 if (r < 0)
137 return r;
138
139 n = new(char, 33);
140 if (!n)
141 return -ENOMEM;
142
143 *ret = sd_id128_to_string(id, n);
144 return 0;
145 }
146
147 int specifier_boot_id(char specifier, void *data, void *userdata, char **ret) {
148 sd_id128_t id;
149 char *n;
150 int r;
151
152 r = sd_id128_get_boot(&id);
153 if (r < 0)
154 return r;
155
156 n = new(char, 33);
157 if (!n)
158 return -ENOMEM;
159
160 *ret = sd_id128_to_string(id, n);
161 return 0;
162 }
163
164 int specifier_host_name(char specifier, void *data, void *userdata, char **ret) {
165 char *n;
166
167 n = gethostname_malloc();
168 if (!n)
169 return -ENOMEM;
170
171 *ret = n;
172 return 0;
173 }
174
175 int specifier_kernel_release(char specifier, void *data, void *userdata, char **ret) {
176 struct utsname uts;
177 char *n;
178 int r;
179
180 r = uname(&uts);
181 if (r < 0)
182 return -errno;
183
184 n = strdup(uts.release);
185 if (!n)
186 return -ENOMEM;
187
188 *ret = n;
189 return 0;
190 }