Updated PCI IDs to latest snapshot.
[tangerine.git] / compiler / clib / __arosc_nixmain.c
blobaed0435747f96de4734aae94d768de0d7c406693
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 char *new_argv0;
39 struct MinList old_vars;
41 /* Trigger *nix path handling on. */
42 __doupath = 1;
44 /* argv[0] usually contains the name of the program, possibly with the full
45 path to it. Here we translate that path, which is an AmigaDOS-style path,
46 into an unix-style one. */
47 if (argv && argv[0] && !__get_arosc_privdata()->acpd_parent_does_upath)
49 new_argv0 = strdup(__path_a2u(argv[0]));
50 if (new_argv0 == NULL)
51 return RETURN_FAIL;
53 old_argv0 = argv[0];
54 argv[0] = new_argv0;
57 /* Here we clone environment variables. We do this because
58 if we've been invoked as a coroutine via dos.library/RunCommand()
59 rather than as a newly created process, then we share our env variables
60 with the caller, but we do not want that. It's kind of wasteful to do
61 it even if we've been started as a fresh process, though, so if we can
62 we avoid it. */
63 if (!(__get_arosc_privdata()->acpd_flags & DO_NOT_CLONE_ENV_VARS))
65 if (!clone_vars(&old_vars))
67 __aros_startup_error = RETURN_FAIL;
68 goto err_vars;
72 /* If the PATH variable is not defined, then define it to be what CLI's path list
73 points to. */
74 if (!getenv("PATH"))
75 update_PATH();
77 /* Call the real main. */
78 if (setjmp(__aros_startup_jmp_buf) == 0)
80 __aros_startup_error = (*main)(argc, argv);
84 if (!(__get_arosc_privdata()->acpd_flags & DO_NOT_CLONE_ENV_VARS))
85 restore_vars(&old_vars);
87 err_vars:
89 /* Restore the old argv[0]. */
90 if (old_argv0 != NULL)
92 free(new_argv0);
93 argv[0] = (char *)old_argv0;
96 return __aros_startup_error;
99 /* Clone the process' environment variables list. Once this function returns,
100 the _cloned_ vars are used in place of the old ones.
102 Returns the old list's content in the old_vars argument. Use this list only as
103 argument to restore_vars() and for _nothing_ else.
105 If this function fails, then FALSE is returned, otherwise TRUE is returned.
107 One might argue that the whole affair is solved the wrong way around, that is
108 clone_vars() should return the _cloned_ list and restore_vars() should be really
109 named replace_vars() and take the cloned list as argument and replace the current
110 one with that one, but doing it this way means breaking any programs which saved
111 vars list's internals before invoking this program, although that is not even guaranteed
112 to work normally, as the called program could change the env list anytime... Well,
113 in either case it doesn't do much of a difference, since the same amount of operations
114 would be performed, only the order would change. */
116 BOOL clone_vars(struct MinList *old_vars)
118 struct MinList l;
119 struct LocalVar *lv, *newVar;
120 struct Process *me;
122 NEWLIST(&l);
124 me = (struct Process *)FindTask(NULL);
125 /* Copied and adapted from rom/dos/createnewproc.c. Perhaps there should
126 be a public function for this? */
127 ForeachNode(&me->pr_LocalVars, lv)
129 size_t copyLength;
131 if (lv->lv_Len == 0)
132 continue;
134 copyLength = strlen(lv->lv_Node.ln_Name) + 1 + sizeof(struct LocalVar);
136 newVar = (struct LocalVar *)AllocVec(copyLength, MEMF_PUBLIC);
137 if (newVar == NULL)
139 free_vars(&l);
140 return FALSE;
143 memcpy(newVar, lv, copyLength);
144 newVar->lv_Node.ln_Name = (char *)newVar + sizeof(struct LocalVar);
145 newVar->lv_Value = AllocMem(lv->lv_Len, MEMF_PUBLIC);
147 if (newVar->lv_Value == NULL)
149 FreeVec(newVar);
150 free_vars(&l);
151 return FALSE;
154 memcpy(newVar->lv_Value, lv->lv_Value, lv->lv_Len);
156 ADDTAIL(&l, newVar);
159 *old_vars = me->pr_LocalVars;
160 me->pr_LocalVars = l;
162 l.mlh_Head->mln_Pred = (struct MinNode *)&me->pr_LocalVars.mlh_Head;
163 l.mlh_TailPred->mln_Succ = (struct MinNode *)&me->pr_LocalVars.mlh_Tail;
165 return TRUE;
168 /* Restores the old env var's list content */
169 static void restore_vars(struct MinList *old_vars)
171 struct Process *me = (struct Process *)FindTask(NULL);
173 free_vars(&me->pr_LocalVars);
174 me->pr_LocalVars = *old_vars;
177 /* taken from rom/dos/createnewproc.c. */
178 static void free_vars(struct MinList *vars)
180 struct LocalVar *varNode;
181 struct Node *tempNode;
183 ForeachNodeSafe(vars, varNode, tempNode)
185 FreeMem(varNode->lv_Value, varNode->lv_Len);
186 Remove((struct Node *)varNode);
187 FreeVec(varNode);
191 /* setenv("PATH", current_cli_path, 1) */
192 static void update_PATH(void)
194 typedef struct
196 BPTR next;
197 BPTR lock;
198 } PathEntry;
200 #define PE(x) ((PathEntry *)(BADDR(x)))
202 UBYTE aname[PATH_MAX]; /* PATH_MAX Ought to enough, it would be too complicated
203 handling aname dynamically (thanks to our sucky dos.library). */
204 char *PATH = NULL;
205 size_t PATH_len = 0;
206 PathEntry *cur;
207 struct CommandLineInterface *cli = Cli();
209 /* No cli, no luck. */
210 if (cli == NULL)
211 return;
215 cur = PE(cli->cli_CommandDir);
216 cur != NULL;
217 cur = PE(cur->next)
220 char *new_PATH;
221 const char *uname;
222 size_t uname_len;
224 if (NameFromLock(cur->lock, aname, sizeof(aname)) == DOSFALSE)
225 continue;
227 D(bug("aname = %s\n", aname));
229 uname = __path_a2u(aname);
230 if (!uname)
231 continue;
232 uname_len = strlen(uname);
234 D(bug("uname = %s\n", uname));
236 new_PATH = realloc(PATH, PATH_len + uname_len + 1);
237 if (!new_PATH)
238 continue;
239 PATH = new_PATH;
241 memcpy(PATH + PATH_len, uname, uname_len);
242 PATH_len += uname_len;
243 PATH[PATH_len++] = ':';
245 D(bug("PATH_len = %d, PATH = %.*s\n", PATH_len, PATH_len, PATH));
248 if (PATH)
250 PATH[PATH_len ? (PATH_len - 1) : 0] = '\0';
252 setenv("PATH", PATH, 1);