2 * Copyright (c) 2016 The DragonFly Project
3 * Copyright (c) 2014 The FreeBSD Foundation
6 * This software was developed by Edward Tomasz Napierala under sponsorship
7 * from the FreeBSD Foundation.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * All the "defined" stuff is for handling variables,
34 * such as ${OSNAME}, in maps.
37 #include <sys/types.h>
38 #include <sys/utsname.h>
48 static TAILQ_HEAD(, defined_value
) defined_values
;
51 defined_find(const char *name
)
53 struct defined_value
*d
;
55 TAILQ_FOREACH(d
, &defined_values
, d_next
) {
56 if (strcmp(d
->d_name
, name
) == 0)
64 defined_expand(const char *string
)
67 char c
, *expanded
, *name
;
68 int i
, ret
, before_len
= 0, name_off
= 0, name_len
= 0, after_off
= 0;
69 bool backslashed
= false, bracketed
= false;
71 expanded
= checked_strdup(string
);
73 for (i
= 0; string
[i
] != '\0'; i
++) {
75 if (c
== '\\' && backslashed
== false) {
88 * The 'before_len' variable contains the number
89 * of characters before the '$'.
92 assert(i
+ 1 < (int)strlen(string
));
93 if (string
[i
+ 1] == '{')
96 if (string
[i
+ 1] == '\0') {
97 log_warnx("truncated variable");
107 if (string
[i
+ 1] == '\0') {
108 log_warnx("truncated variable");
119 * The 'name_off' variable contains the number
120 * of characters before the variable name,
121 * including the "$" or "${".
125 for (; string
[i
] != '\0'; i
++) {
128 * XXX: Decide on the set of characters that can be
129 * used in a variable name.
131 if (isalnum(c
) || c
== '_')
135 * End of variable name.
142 * The 'after_off' variable contains the number
143 * of characters before the rest of the string,
144 * i.e. after the variable name.
148 assert(i
- 1 > name_off
);
149 name_len
= i
- name_off
;
155 assert(i
> name_off
);
156 name_len
= i
- name_off
;
160 name
= strndup(string
+ name_off
, name_len
);
162 log_err(1, "strndup");
163 value
= defined_find(name
);
165 log_warnx("undefined variable ${%s}", name
);
170 * Concatenate it back.
172 ret
= asprintf(&expanded
, "%.*s%s%s",
173 before_len
, string
, value
, string
+ after_off
);
175 log_err(1, "asprintf");
177 //log_debugx("\"%s\" expanded to \"%s\"", string, expanded);
181 * Figure out where to start searching for next variable.
184 i
= before_len
+ strlen(value
);
185 backslashed
= bracketed
= false;
186 before_len
= name_off
= name_len
= after_off
= 0;
187 assert(i
<= (int)strlen(string
));
190 if (before_len
!= 0 || name_off
!= 0 || name_len
!= 0 || after_off
!= 0) {
191 log_warnx("truncated variable");
199 defined_add(const char *name
, const char *value
)
201 struct defined_value
*d
;
204 found
= defined_find(name
);
206 log_errx(1, "variable %s already defined", name
);
208 log_debugx("defining variable %s=%s", name
, value
);
210 d
= calloc(1, sizeof(*d
));
212 log_err(1, "calloc");
213 d
->d_name
= checked_strdup(name
);
214 d
->d_value
= checked_strdup(value
);
216 TAILQ_INSERT_TAIL(&defined_values
, d
, d_next
);
220 defined_parse_and_add(char *def
)
225 name
= strsep(&value
, "=");
227 if (value
== NULL
|| value
[0] == '\0')
228 log_errx(1, "missing variable value");
229 if (name
== NULL
|| name
[0] == '\0')
230 log_errx(1, "missing variable name");
232 defined_add(name
, value
);
241 TAILQ_INIT(&defined_values
);
243 error
= uname(&name
);
247 defined_add("ARCH", name
.machine
);
248 defined_add("CPU", name
.machine
);
249 defined_add("HOST", name
.nodename
);
250 defined_add("OSNAME", name
.sysname
);
251 defined_add("OSREL", name
.release
);
252 defined_add("OSVERS", name
.version
);