purge remaining gpl code from clib, and make clib build again
[tangerine.git] / compiler / clib / __arosc_nixmain.c
blob67ed4eba636ba8dd89aad5abcc76721c41d30853
1 /*
2 Copyright © 1995-2003, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: special main function for code which has to use special *nix features.
6 This function gets called from a function with a similar name statically
7 linked with the program. This is so to make the program not depend on a
8 particular libc version.
10 Lang: english
13 #include "__arosc_privdata.h"
15 #include <proto/exec.h>
16 #include <proto/dos.h>
17 #include <exec/lists.h>
18 #include <dos/dos.h>
19 #include <aros/startup.h>
21 #include <aros/debug.h>
23 #include <setjmp.h>
24 #include <string.h>
25 #include <stdlib.h>
26 #include <sys/param.h>
28 #include "__upath.h"
30 static BOOL clone_vars(struct MinList *old_vars);
31 static void restore_vars(struct MinList *old_vars);
32 static void free_vars(struct MinList *vars);
33 static void update_PATH(void);
35 int __arosc_nixmain(int (*main)(int argc, char *argv[]), int argc, char *argv[])
37 char *old_argv0 = NULL;
38 struct MinList old_vars;
40 /* Trigger *nix path handling on. */
41 __doupath = 1;
43 /* argv[0] usually contains the name of the program, possibly with the full
44 path to it. Here we translate that path, which is an AmigaDOS-style path,
45 into an unix-style one. */
46 if (argv && argv[0] && !__get_arosc_privdata()->acpd_parent_does_upath)
48 char *new_argv0;
50 new_argv0 = strdup(__path_a2u(argv[0]));
51 if (new_argv0 == NULL)
52 return RETURN_FAIL;
54 old_argv0 = argv[0];
55 argv[0] = new_argv0;
58 /* Here we clone environment variables. We do this because
59 if we've been invoked as a coroutine via dos.library/RunCommand()
60 rather than as a newly created process, then we share our env variables
61 with the caller, but we do not want that. It's kind of wasteful to do
62 it even if we've been started as a fresh process, though, so if we can
63 we avoid it. */
64 if (!__get_arosc_privdata()->acpd_spawned)
66 if (!clone_vars(&old_vars))
68 __aros_startup_error = RETURN_FAIL;
69 goto err_vars;
73 /* If the PATH variable is not defined, then define it to be what CLI's path list
74 points to. */
75 if (!getenv("PATH"))
76 update_PATH();
78 /* Call the real main. */
79 if (setjmp(__aros_startup_jmp_buf) == 0)
81 __aros_startup_error = (*main)(argc, argv);
85 if (!__get_arosc_privdata()->acpd_spawned)
86 restore_vars(&old_vars);
88 err_vars:
90 /* Restore the old argv[0]. */
91 if (old_argv0 != NULL)
93 free(argv[0]);
94 argv[0] = (char *)old_argv0;
97 return __aros_startup_error;
100 /* Clone the process' environment variables list. Once this function returns,
101 the _cloned_ vars are used in place of the old ones.
103 Returns the old list's content in the old_vars argument. Use this list only as
104 argument to restore_vars() and for _nothing_ else.
106 If this function fails, then FALSE is returned, otherwise TRUE is returned.
108 One might argue that the whole affair is solved the wrong way around, that is
109 clone_vars() should return the _cloned_ list and restore_vars() should be really
110 named replace_vars() and take the cloned list as argument and replace the current
111 one with that one, but doing it this way means breaking any programs which saved
112 vars list's internals before invoking this program, although that is not even guaranteed
113 to work normally, as the called program could change the env list anytime... Well,
114 in either case it doesn't do much of a difference, since the same amount of operations
115 would be performed, only the order would change. */
117 BOOL clone_vars(struct MinList *old_vars)
119 struct MinList l;
120 struct LocalVar *lv, *newVar;
121 struct Process *me;
123 NEWLIST(&l);
125 me = (struct Process *)FindTask(NULL);
126 /* Copied and adapted from rom/dos/createnewproc.c. Perhaps there should
127 be a public function for this? */
128 ForeachNode(&me->pr_LocalVars, lv)
130 size_t copyLength;
132 if (lv->lv_Len == 0)
133 continue;
135 copyLength = strlen(lv->lv_Node.ln_Name) + 1 + sizeof(struct LocalVar);
137 newVar = (struct LocalVar *)AllocVec(copyLength, MEMF_PUBLIC);
138 if (newVar == NULL)
140 free_vars(&l);
141 return FALSE;
144 memcpy(newVar, lv, copyLength);
145 newVar->lv_Node.ln_Name = (char *)newVar + sizeof(struct LocalVar);
146 newVar->lv_Value = AllocMem(lv->lv_Len, MEMF_PUBLIC);
148 if (newVar->lv_Value == NULL)
150 FreeVec(newVar);
151 free_vars(&l);
152 return FALSE;
155 memcpy(newVar->lv_Value, lv->lv_Value, lv->lv_Len);
157 ADDTAIL(&l, newVar);
160 *old_vars = me->pr_LocalVars;
161 me->pr_LocalVars = l;
163 l.mlh_Head->mln_Pred = (struct MinNode *)&me->pr_LocalVars.mlh_Head;
164 l.mlh_TailPred->mln_Succ = (struct MinNode *)&me->pr_LocalVars.mlh_Tail;
166 return TRUE;
169 /* Restores the old env var's list content */
170 static void restore_vars(struct MinList *old_vars)
172 struct Process *me = (struct Process *)FindTask(NULL);
174 free_vars(&me->pr_LocalVars);
175 me->pr_LocalVars = *old_vars;
178 /* taken from rom/dos/createnewproc.c. */
179 static void free_vars(struct MinList *vars)
181 struct LocalVar *varNode;
182 struct Node *tempNode;
184 ForeachNodeSafe(vars, varNode, tempNode)
186 FreeMem(varNode->lv_Value, varNode->lv_Len);
187 Remove((struct Node *)varNode);
188 FreeVec(varNode);
192 /* setenv("PATH", current_cli_path, 1) */
193 static void update_PATH(void)
195 typedef struct
197 BPTR next;
198 BPTR lock;
199 } PathEntry;
201 #define PE(x) ((PathEntry *)(BADDR(x)))
203 UBYTE aname[PATH_MAX]; /* PATH_MAX Ought to enough, it would be too complicated
204 handling aname dynamically (thanks to our sucky dos.library). */
205 char *PATH = NULL;
206 size_t PATH_len = 0;
207 PathEntry *cur;
208 struct CommandLineInterface *cli = Cli();
210 /* No cli, no luck. */
211 if (cli == NULL)
212 return;
216 cur = PE(cli->cli_CommandDir);
217 cur != NULL;
218 cur = PE(cur->next)
221 char *new_PATH;
222 const char *uname;
223 size_t uname_len;
225 if (NameFromLock(cur->lock, aname, sizeof(aname)) == DOSFALSE)
226 continue;
228 D(bug("aname = %s\n", aname));
230 uname = __path_a2u(aname);
231 if (!uname)
232 continue;
233 uname_len = strlen(uname);
235 D(bug("uname = %s\n", uname));
237 new_PATH = realloc(PATH, PATH_len + uname_len + 1);
238 if (!new_PATH)
239 continue;
240 PATH = new_PATH;
242 memcpy(PATH + PATH_len, uname, uname_len);
243 PATH_len += uname_len;
244 PATH[PATH_len++] = ':';
246 D(bug("PATH_len = %d, PATH = %.*s\n", PATH_len, PATH_len, PATH));
249 if (PATH)
251 PATH[PATH_len ? (PATH_len - 1) : 0] = '\0';
253 setenv("PATH", PATH, 1);