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