Added missing version tags, clean-up
[AROS.git] / compiler / clib / __env.c
blobe0365b3c3cc6e880bd5f77a9a4b1101adb1318bc
1 /*
2 Copyright © 1995-2012, The AROS Development Team. All rights reserved.
3 $Id$
5 Internal functions for environment variables handling.
6 */
8 #include "__arosc_privdata.h"
10 #include <stdlib.h>
11 #include <string.h>
12 #include <proto/exec.h>
13 #include <proto/dos.h>
14 #include <proto/utility.h>
15 #include <dos/var.h>
17 #include "__env.h"
19 #if AROS_AMIGAOS_COMPLIANCE && (AROS_AMIGAOS_COMPLIANCE >= 30)
20 /* ScanVars is a Morphos addition in dos.library v50, so we
21 * have this stub here for arosc.library compatability with
22 * dos.library v30..v39.
24 static LONG v30_ScanVars(struct Hook *hook, ULONG flags, APTR userdata)
26 /* We scan through the process->pr_LocalVars list */
27 struct Process *pr;
28 struct LocalVar *var;
29 struct ScanVarsMsg msg;
30 LONG res = 0;
31 APTR UtilityBase;
33 UtilityBase = OpenLibrary("utility.library", 0);
34 if (UtilityBase == NULL)
35 return 0;
37 msg.sv_SVMSize = sizeof(struct ScanVarsMsg);
38 msg.sv_Flags = flags;
39 pr = (struct Process *)FindTask(NULL);
41 /* We know that the callers of this routine
42 * will be asking for GVF_LOCAL_ONLY
44 var = (struct LocalVar *)pr->pr_LocalVars.mlh_Head;
46 ForeachNode(&pr->pr_LocalVars, var)
48 if (var->lv_Node.ln_Type == LV_VAR)
50 msg.sv_Name = var->lv_Node.ln_Name;
51 msg.sv_Var = var->lv_Value;
52 msg.sv_VarLen = var->lv_Len;
53 msg.sv_GDir = "";
54 res = CallHookPkt(hook, userdata, &msg);
55 if(res != 0)
56 break;
60 CloseLibrary(UtilityBase);
61 return res;
63 #undef ScanVars
64 #define ScanVars(a,b,c) v30_ScanVars(a,b,c)
65 #endif
67 static __env_item *__env_newvar(const char *name, int valuesize)
69 __env_item *item;
71 item = malloc(sizeof(__env_item));
72 if (!item) goto err1;
74 item->name = strdup(name);
75 if (!item->name) goto err2;
77 item->value = malloc(valuesize);
78 if (!item->value) goto err3;
80 item->next = NULL;
82 return item;
84 err3:
85 free(item->name);
86 err2:
87 free(item);
88 err1:
89 return NULL;
92 static __env_item **internal_findvar(register const char *name)
94 struct aroscbase *aroscbase = __aros_getbase_aroscbase();
96 __env_item **curr;
98 for (
99 curr = &aroscbase->acb_env_list;
100 *curr && strcmp((*curr)->name, name);
101 curr = &((*curr)->next)
104 return curr;
108 Allocates space for a variable with name 'name' returning a pointer to it.
109 If a variable with this name already exists then returns a pointer to that
110 variable.
112 Returns NULL on error.
114 __env_item *__env_getvar(const char *name, int valuesize)
116 register __env_item **curr;
118 curr = internal_findvar(name);
120 if (*curr)
122 if (strlen((*curr)->value) < valuesize)
124 free((*curr)->value);
125 (*curr)->value = malloc(valuesize);
127 if (!(*curr)->value)
129 __env_item *tmp = (*curr)->next;
131 free(*curr);
132 *curr = tmp;
136 else
138 *curr = __env_newvar(name, valuesize);
141 return *curr;
144 void __env_delvar(const char *name)
146 register __env_item **curr;
148 curr = internal_findvar(name);
150 if (*curr)
152 register __env_item *tmp = *curr;
154 *curr = (*curr)->next;
156 free(tmp->name);
157 free(tmp->value);
158 free(tmp);
162 struct EnvData
164 int envcount;
165 int varbufsize;
166 char * varbufptr;
169 /* Hook function counting the number of variables and computing the buffer size
170 needed for name=value character buffer. */
171 LONG get_var_len(struct Hook *hook, APTR userdata, struct ScanVarsMsg *message)
173 struct EnvData *data = (struct EnvData *) userdata;
174 data->envcount++;
175 data->varbufsize +=
176 (ptrdiff_t) strlen((char*)message->sv_Name) +
177 message->sv_VarLen + 2;
178 return 0;
181 /* Hook function storing name=value strings in buffer */
182 LONG get_var(struct Hook *hook, APTR userdata, struct ScanVarsMsg *message)
184 struct EnvData *data = userdata;
185 data->varbufptr[0] = '\0';
186 strcat(data->varbufptr, (char*) message->sv_Name);
187 strcat(data->varbufptr, "=");
188 strncat(data->varbufptr, (char*) message->sv_Var, message->sv_VarLen);
189 data->varbufptr = data->varbufptr + strlen(data->varbufptr) + 1;
190 return 0;
193 /* Function storing name=value strings in given environ buffer. When buffer is
194 null, it returns minimal necessary size of the buffer needed to store all
195 name=value strings. */
196 int __env_get_environ(char **environ, int size)
198 int i;
199 struct Hook hook;
200 struct EnvData u;
201 char *varbuf;
203 u.envcount = 0;
204 u.varbufsize = 0;
206 memset(&hook, 0, sizeof(struct Hook));
207 hook.h_Entry = (HOOKFUNC) get_var_len;
208 ScanVars(&hook, GVF_LOCAL_ONLY, &u);
210 if(environ == NULL)
211 return sizeof(char*) * (u.envcount + 1) + u.varbufsize;
212 else if(size < sizeof(char*) *(u.envcount + 1) + u.varbufsize)
213 return -1;
215 /* store name=value strings after table of pointers */
216 varbuf = (char*) (environ + (u.envcount + 1));
218 /* time to fill in the buffers */
219 u.varbufptr = varbuf;
220 u.varbufptr[0] = '\0';
221 hook.h_Entry = (HOOKFUNC) get_var;
222 ScanVars(&hook, GVF_LOCAL_ONLY, &u);
224 for(i = 0; i < u.envcount; i++)
226 environ[i] = varbuf;
227 varbuf = strchr(varbuf, '\0') + 1;
229 environ[u.envcount] = NULL;
231 return 0;