start service tasks separately in-case platforms need to perform additional set-up...
[AROS.git] / compiler / posixc / __env.c
blobf83625035477c58cb9b90f593634a582907d3346
1 /*
2 Copyright © 1995-2013, The AROS Development Team. All rights reserved.
3 $Id$
5 Internal functions for environment variables handling.
6 */
8 #include "__posixc_intbase.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 posixc.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 PosixCIntBase *PosixCBase =
95 (struct PosixCIntBase *)__aros_getbase_PosixCBase();
97 __env_item **curr;
99 for (
100 curr = &PosixCBase->env_list;
101 *curr && strcmp((*curr)->name, name);
102 curr = &((*curr)->next)
105 return curr;
109 Allocates space for a variable with name 'name' returning a pointer to it.
110 If a variable with this name already exists then returns a pointer to that
111 variable.
113 Returns NULL on error.
115 __env_item *__env_getvar(const char *name, int valuesize)
117 register __env_item **curr;
119 curr = internal_findvar(name);
121 if (*curr)
123 if (strlen((*curr)->value) < valuesize)
125 free((*curr)->value);
126 (*curr)->value = malloc(valuesize);
128 if (!(*curr)->value)
130 __env_item *tmp = (*curr)->next;
132 free(*curr);
133 *curr = tmp;
137 else
139 *curr = __env_newvar(name, valuesize);
142 return *curr;
145 void __env_delvar(const char *name)
147 register __env_item **curr;
149 curr = internal_findvar(name);
151 if (*curr)
153 register __env_item *tmp = *curr;
155 *curr = (*curr)->next;
157 free(tmp->name);
158 free(tmp->value);
159 free(tmp);
163 struct EnvData
165 int envcount;
166 int varbufsize;
167 char * varbufptr;
170 /* Hook function counting the number of variables and computing the buffer size
171 needed for name=value character buffer. */
172 LONG get_var_len(struct Hook *hook, APTR userdata, struct ScanVarsMsg *message)
174 struct EnvData *data = (struct EnvData *) userdata;
175 data->envcount++;
176 data->varbufsize +=
177 (ptrdiff_t) strlen((char*)message->sv_Name) +
178 message->sv_VarLen + 2;
179 return 0;
182 /* Hook function storing name=value strings in buffer */
183 LONG get_var(struct Hook *hook, APTR userdata, struct ScanVarsMsg *message)
185 struct EnvData *data = userdata;
186 data->varbufptr[0] = '\0';
187 strcat(data->varbufptr, (char*) message->sv_Name);
188 strcat(data->varbufptr, "=");
189 strncat(data->varbufptr, (char*) message->sv_Var, message->sv_VarLen);
190 data->varbufptr = data->varbufptr + strlen(data->varbufptr) + 1;
191 return 0;
194 /* Function storing name=value strings in given environ buffer. When buffer is
195 null, it returns minimal necessary size of the buffer needed to store all
196 name=value strings. */
197 int __env_get_environ(char **environ, int size)
199 int i;
200 struct Hook hook;
201 struct EnvData u;
202 char *varbuf;
204 u.envcount = 0;
205 u.varbufsize = 0;
207 memset(&hook, 0, sizeof(struct Hook));
208 hook.h_Entry = (HOOKFUNC) get_var_len;
209 ScanVars(&hook, GVF_LOCAL_ONLY, &u);
211 if(environ == NULL)
212 return sizeof(char*) * (u.envcount + 1) + u.varbufsize;
213 else if(size < sizeof(char*) *(u.envcount + 1) + u.varbufsize)
214 return -1;
216 /* store name=value strings after table of pointers */
217 varbuf = (char*) (environ + (u.envcount + 1));
219 /* time to fill in the buffers */
220 u.varbufptr = varbuf;
221 u.varbufptr[0] = '\0';
222 hook.h_Entry = (HOOKFUNC) get_var;
223 ScanVars(&hook, GVF_LOCAL_ONLY, &u);
225 for(i = 0; i < u.envcount; i++)
227 environ[i] = varbuf;
228 varbuf = strchr(varbuf, '\0') + 1;
230 environ[u.envcount] = NULL;
232 return 0;