-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathvariables.c
125 lines (101 loc) · 2.33 KB
/
variables.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
/* see LICENSE file for copyright and license details */
/* expand variables into their stored value */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <unistd.h>
#include "region.h"
#include "reporting.h"
#include "stringport.h"
#include "tokenizer.h"
#include "variables.h"
#include "util.h"
char varname[TOK_MAX];
char *varerr;
/* set positional variables before loading file */
void
vars_set(char **argv)
{
int i = 0;
char var[8];
/* char varcat[ARG_MAX_STRLEN]; */
long max = sysconf(_SC_ARG_MAX);
for (argv++; *argv && i < max; argv++, i++) {
snprintf(var, sizeof(var), "%d", i);
setenv(var, *argv, 1);
}
setenv("#", var, 1);
}
/* remove positional variables to prevent leakage */
void
vars_unset(void)
{
int i = 0;
char var[8];
long max = sysconf(_SC_ARG_MAX);
for (; i < max; i++) {
snprintf(var, sizeof(var), "%d", i);
if (!getenv(var)) break;
unsetenv(var);
}
unsetenv("#");
}
static int
variable_character(char c)
{
return c == '_' ||
BETWEEN(c, 'A', 'Z') ||
BETWEEN(c, 'a', 'z') ||
BETWEEN(c, '0', '9');
}
static char *
read_variable_prefix(char *tok)
{
int pos = 0;
int brc = 0;
assert(*tok == '$');
tok++;
/* NOTE: We don't bother to bounds check here */
/* because tok is already <= the size of a token */
/* ...lets see if this ever bites? */
if (*tok == '{') {
brc = 1;
tok++;
}
while (variable_character(*tok) || (!pos && *tok == '#'))
varname[pos++] = *tok++;
if (brc && *tok++ != '}')
reportvar(varerr, "missing '}'");
varname[pos] = '\0';
if (!pos)
reportvar(varerr, "length 0 variable");
return tok;
}
char *
expand_variables(region *r, char *tok, int t)
{
char *stok = tok, *o, *val;
int alloc_len = t+1;
int pos = 0, l;
o = region_malloc(r, alloc_len);
while (*tok)
if (*tok == '$') {
if (!(tok = read_variable_prefix(tok)))
reportret(NULL, "problem parsing variable '%s' at character %d: %s",
stok, pos, varerr);
if (!(val = getenv(varname)))
reportret(NULL, "reference to undefined variable '%s'", stok);
l = strlen(val);
alloc_len += l;
if (alloc_len > TOK_MAX)
reportret(NULL, "variable expansion blew up token size too large");
o = region_realloc(r, o, alloc_len);
memcpy(o + pos, val, l);
pos += l;
} else {
o[pos++] = *tok++;
}
o[pos] = '\0';
return o;
}