-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathvarlib.c
225 lines (196 loc) · 4.85 KB
/
varlib.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
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
/* varlib.c
*
* a simple storage system to store name=value pairs
* with facility to mark items as part of the environment
*
* interface:
* VLstore( name, value ) returns 0 for 0k, 1 for no
* VLlookup( name ) returns string or NULL if not there
* VLlist() prints out current table
*
* environment-related functions
* VLexport( name ) adds name to list of env vars
* VLtable2environ() copy from table to environ
* VLenviron2table() copy from environ to table
*
* details:
* the table is stored as an array of structs that
* contain a flag for `global' and a single string of
* the form name=value. This allows EZ addition to the
* environment. It makes searching pretty easy, as
* long as you search for "name="
*
* hist: 2015-05-14 VLstore now handles NULL cases safely (10q mk)
*/
#include <stdio.h>
#include <stdlib.h>
#include "varlib.h"
#include <string.h>
#define MAXVARS 200 /* a linked list would be nicer */
struct var {
char *str; /* name=val string */
int global; /* a boolean */
};
static struct var tab[MAXVARS]; /* the table */
static char *new_string( char *, char *); /* private methods */
static struct var *find_item(char *, int);
void VLinit()
/*
* initialize variable storage system
*/
{
}
int VLstore( char *name, char *val )
/*
* traverse list, if found, replace it, else add at end
* since there is no delete, a blank one is a free one
* return 1 if trouble, 0 if ok (like a command)
*/
{
struct var *itemp;
char *s;
int rv = 1; /* assume failure */
/* find spot to put it and make new string */
if ((itemp=find_item(name,1))!=NULL && (s=new_string(name,val))!=NULL)
{
if ( itemp->str ) /* has a val? */
free(itemp->str); /* y: remove it */
itemp->str = s;
rv = 0; /* ok! */
}
return rv;
}
char * new_string( char *name, char *val )
/*
* returns new string of form name=value or NULL on error
*/
{
char *retval;
if ( name == NULL )
retval = NULL;
else if ( val == NULL )
retval = malloc(strlen(name)+1);
else
retval = malloc( strlen(name) + strlen(val) + 2 );
if ( retval != NULL )
sprintf(retval, "%s=%s", name, (val==NULL ? "" : val) );
return retval;
}
char * VLlookup( char *name )
/*
* returns value of var or empty string if not there
*/
{
struct var *itemp;
if ( (itemp = find_item(name,0)) != NULL )
return itemp->str + 1 + strlen(name);
return "";
}
int VLexport( char *name )
/*
* marks a var for export, adds it if not there
* returns 1 for no, 0 for ok
*/
{
struct var *itemp;
int rv = 1;
if ( (itemp = find_item(name,0)) != NULL ){
itemp->global = 1;
rv = 0;
}
else if ( VLstore(name, "") == 0 ) /* bug fix 31 mar 08 */
rv = VLexport(name);
return rv;
}
static struct var * find_item( char *name , int first_blank )
/*
* searches table for an item
* returns ptr to struct or NULL if not found
* OR if (first_blank) then ptr to first blank one
*/
{
int i;
int len ;
char *s;
if ( name == NULL )
return NULL;
len = strlen(name);
for( i = 0 ; i<MAXVARS && tab[i].str != NULL ; i++ )
{
s = tab[i].str;
if ( strncmp(s,name,len) == 0 && s[len] == '=' ){
return &tab[i];
}
}
if ( i < MAXVARS && first_blank )
return &tab[i];
return NULL;
}
void VLlist()
/*
* performs the shell's `set' command
* Lists the contents of the variable table, marking each
* exported variable with the symbol '*'
*/
{
int i;
for(i = 0 ; i<MAXVARS && tab[i].str != NULL ; i++ )
{
if ( tab[i].global )
printf(" * %s\n", tab[i].str);
else
printf(" %s\n", tab[i].str);
}
}
int VLenviron2table(char *env[])
/*
* initialize the variable table by loading array of strings
* return 1 for ok, 0 for not ok
*/
{
int i;
char *newstring;
for(i = 0 ; env[i] != NULL ; i++ )
{
if ( i == MAXVARS )
return 0;
newstring = malloc(1+strlen(env[i]));
if ( newstring == NULL )
return 0;
strcpy(newstring, env[i]);
tab[i].str = newstring;
tab[i].global = 1;
}
while( i < MAXVARS ){ /* I know we don't need this */
tab[i].str = NULL ; /* static globals are nulled */
tab[i++].global = 0; /* by default */
}
return 1;
}
char ** VLtable2environ()
/*
* build an array of pointers suitable for making a new environment
* note, you need to free() this when done to avoid memory leaks
*/
{
int i, /* index */
j, /* another index */
n = 0; /* counter */
char **envtab; /* array of pointers */
/*
* first, count the number of global variables
*/
for( i = 0 ; i<MAXVARS && tab[i].str != NULL ; i++ )
if ( tab[i].global == 1 )
n++;
/* then, allocate space for that many variables */
envtab = (char **) malloc( (n+1) * sizeof(char *) );
if ( envtab == NULL )
return NULL;
/* then, load the array with pointers */
for(i = 0, j = 0 ; i<MAXVARS && tab[i].str != NULL ; i++ )
if ( tab[i].global == 1 )
envtab[j++] = tab[i].str;
envtab[j] = NULL;
return envtab;
}