2 Copyright © 1995-2003, The AROS Development Team. All rights reserved.
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.
13 #include "__arosc_privdata.h"
15 #include <proto/exec.h>
16 #include <proto/dos.h>
17 #include <exec/lists.h>
19 #include <aros/startup.h>
21 #include <aros/debug.h>
26 #include <sys/param.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
;
39 struct MinList old_vars
;
41 /* Trigger *nix path handling on. */
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
)
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
63 if (!(__get_arosc_privdata()->acpd_flags
& DO_NOT_CLONE_ENV_VARS
))
65 if (!clone_vars(&old_vars
))
67 __aros_startup_error
= RETURN_FAIL
;
72 /* If the PATH variable is not defined, then define it to be what CLI's path list
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
);
89 /* Restore the old argv[0]. */
90 if (old_argv0
!= NULL
)
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
)
119 struct LocalVar
*lv
, *newVar
;
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
)
134 copyLength
= strlen(lv
->lv_Node
.ln_Name
) + 1 + sizeof(struct LocalVar
);
136 newVar
= (struct LocalVar
*)AllocVec(copyLength
, MEMF_PUBLIC
);
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
)
154 memcpy(newVar
->lv_Value
, lv
->lv_Value
, lv
->lv_Len
);
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
;
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
);
191 /* setenv("PATH", current_cli_path, 1) */
192 static void update_PATH(void)
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). */
207 struct CommandLineInterface
*cli
= Cli();
209 /* No cli, no luck. */
215 cur
= PE(cli
->cli_CommandDir
);
224 if (NameFromLock(cur
->lock
, aname
, sizeof(aname
)) == DOSFALSE
)
227 D(bug("aname = %s\n", aname
));
229 uname
= __path_a2u(aname
);
232 uname_len
= strlen(uname
);
234 D(bug("uname = %s\n", uname
));
236 new_PATH
= realloc(PATH
, PATH_len
+ uname_len
+ 1);
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
));
250 PATH
[PATH_len
? (PATH_len
- 1) : 0] = '\0';
252 setenv("PATH", PATH
, 1);