chiark / gitweb /
unit-name: fix escaping logic in unit_name_mangle_with_suffix()
[elogind.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 <string.h>
23 #include <sys/utsname.h>
24
25 #include "macro.h"
26 #include "util.h"
27 #include "specifier.h"
28
29 /*
30  * Generic infrastructure for replacing %x style specifiers in
31  * strings. Will call a callback for each replacement.
32  *
33  */
34
35 int specifier_printf(const char *text, const Specifier table[], void *userdata, char **_ret) {
36         char *ret, *t;
37         const char *f;
38         bool percent = false;
39         size_t l;
40         int r;
41
42         assert(text);
43         assert(table);
44
45         l = strlen(text);
46         ret = new(char, l+1);
47         if (!ret)
48                 return -ENOMEM;
49
50         t = ret;
51
52         for (f = text; *f; f++, l--) {
53
54                 if (percent) {
55                         if (*f == '%')
56                                 *(t++) = '%';
57                         else {
58                                 const Specifier *i;
59
60                                 for (i = table; i->specifier; i++)
61                                         if (i->specifier == *f)
62                                                 break;
63
64                                 if (i->lookup) {
65                                         _cleanup_free_ char *w = NULL;
66                                         char *n;
67                                         size_t k, j;
68
69                                         r = i->lookup(i->specifier, i->data, userdata, &w);
70                                         if (r < 0) {
71                                                 free(ret);
72                                                 return r;
73                                         }
74
75                                         j = t - ret;
76                                         k = strlen(w);
77
78                                         n = new(char, j + k + l + 1);
79                                         if (!n) {
80                                                 free(ret);
81                                                 return -ENOMEM;
82                                         }
83
84                                         memcpy(n, ret, j);
85                                         memcpy(n + j, w, k);
86
87                                         free(ret);
88
89                                         ret = n;
90                                         t = n + j + k;
91                                 } else {
92                                         *(t++) = '%';
93                                         *(t++) = *f;
94                                 }
95                         }
96
97                         percent = false;
98                 } else if (*f == '%')
99                         percent = true;
100                 else
101                         *(t++) = *f;
102         }
103
104         *t = 0;
105         *_ret = ret;
106         return 0;
107 }
108
109 /* Generic handler for simple string replacements */
110
111 int specifier_string(char specifier, void *data, void *userdata, char **ret) {
112         char *n;
113
114         n = strdup(strempty(data));
115         if (!n)
116                 return -ENOMEM;
117
118         *ret = n;
119         return 0;
120 }
121
122 int specifier_machine_id(char specifier, void *data, void *userdata, char **ret) {
123         sd_id128_t id;
124         char *n;
125         int r;
126
127         r = sd_id128_get_machine(&id);
128         if (r < 0)
129                 return r;
130
131         n = new(char, 33);
132         if (!n)
133                 return -ENOMEM;
134
135         *ret = sd_id128_to_string(id, n);
136         return 0;
137 }
138
139 int specifier_boot_id(char specifier, void *data, void *userdata, char **ret) {
140         sd_id128_t id;
141         char *n;
142         int r;
143
144         r = sd_id128_get_boot(&id);
145         if (r < 0)
146                 return r;
147
148         n = new(char, 33);
149         if (!n)
150                 return -ENOMEM;
151
152         *ret = sd_id128_to_string(id, n);
153         return 0;
154 }
155
156 int specifier_host_name(char specifier, void *data, void *userdata, char **ret) {
157         char *n;
158
159         n = gethostname_malloc();
160         if (!n)
161                 return -ENOMEM;
162
163         *ret = n;
164         return 0;
165 }
166
167 int specifier_kernel_release(char specifier, void *data, void *userdata, char **ret) {
168         struct utsname uts;
169         char *n;
170         int r;
171
172         r = uname(&uts);
173         if (r < 0)
174                 return -errno;
175
176         n = strdup(uts.release);
177         if (!n)
178                 return -ENOMEM;
179
180         *ret = n;
181         return 0;
182 }