arch/m68k-amiga: Define the gcc symbol 'start' instead of using .bss
[AROS.git] / compiler / clib / __env.c
blob1b7e37fe5ee86988e4a44d1db7dbbdd78c3d6ec6
1 /*
2 Copyright © 1995-2003, 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 <strings.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)
95 __env_item **curr;
97 for (
98 curr = &__env_list;
99 *curr && strcmp((*curr)->name, name);
100 curr = &((*curr)->next)
103 return curr;
107 Allocates space for a variable with name 'name' returning a pointer to it.
108 If a variable with this name already exists then returns a pointer to that
109 variable.
111 Returns NULL on error.
113 __env_item *__env_getvar(const char *name, int valuesize)
115 register __env_item **curr;
117 curr = internal_findvar(name);
119 if (*curr)
121 if (strlen((*curr)->value) < valuesize)
123 free((*curr)->value);
124 (*curr)->value = malloc(valuesize);
126 if (!(*curr)->value)
128 __env_item *tmp = (*curr)->next;
130 free(*curr);
131 *curr = tmp;
135 else
137 *curr = __env_newvar(name, valuesize);
140 return *curr;
143 void __env_delvar(const char *name)
145 register __env_item **curr;
147 curr = internal_findvar(name);
149 if (*curr)
151 register __env_item *tmp = *curr;
153 *curr = (*curr)->next;
155 free(tmp->name);
156 free(tmp->value);
157 free(tmp);
161 struct EnvData
163 int envcount;
164 int varbufsize;
165 char * varbufptr;
168 /* Hook function counting the number of variables and computing the buffer size
169 needed for name=value character buffer. */
170 LONG get_var_len(struct Hook *hook, APTR userdata, struct ScanVarsMsg *message)
172 struct EnvData *data = (struct EnvData *) userdata;
173 data->envcount++;
174 data->varbufsize +=
175 (ptrdiff_t) strlen((char*)message->sv_Name) +
176 message->sv_VarLen + 2;
177 return 0;
180 /* Hook function storing name=value strings in buffer */
181 LONG get_var(struct Hook *hook, APTR userdata, struct ScanVarsMsg *message)
183 struct EnvData *data = userdata;
184 data->varbufptr[0] = '\0';
185 strcat(data->varbufptr, (char*) message->sv_Name);
186 strcat(data->varbufptr, "=");
187 strncat(data->varbufptr, (char*) message->sv_Var, message->sv_VarLen);
188 data->varbufptr = data->varbufptr + strlen(data->varbufptr) + 1;
189 return 0;
192 /* Function storing name=value strings in given environ buffer. When buffer is
193 null, it returns minimal necessary size of the buffer needed to store all
194 name=value strings. */
195 int __env_get_environ(char **environ, int size)
197 int i;
198 struct Hook hook;
199 struct EnvData u;
200 char *varbuf;
202 u.envcount = 0;
203 u.varbufsize = 0;
205 memset(&hook, 0, sizeof(struct Hook));
206 hook.h_Entry = (HOOKFUNC) get_var_len;
207 ScanVars(&hook, GVF_LOCAL_ONLY, &u);
209 if(environ == NULL)
210 return sizeof(char*) * (u.envcount + 1) + u.varbufsize;
211 else if(size < sizeof(char*) *(u.envcount + 1) + u.varbufsize)
212 return -1;
214 /* store name=value strings after table of pointers */
215 varbuf = (char*) (environ + (u.envcount + 1));
217 /* time to fill in the buffers */
218 u.varbufptr = varbuf;
219 u.varbufptr[0] = '\0';
220 hook.h_Entry = (HOOKFUNC) get_var;
221 ScanVars(&hook, GVF_LOCAL_ONLY, &u);
223 for(i = 0; i < u.envcount; i++)
225 environ[i] = varbuf;
226 varbuf = strchr(varbuf, '\0') + 1;
228 environ[u.envcount] = NULL;
230 return 0;