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
;
38 struct MinList old_vars
;
40 /* Trigger *nix path handling on. */
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
)
50 new_argv0
= strdup(__path_a2u(argv
[0]));
51 if (new_argv0
== NULL
)
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
64 if (!__get_arosc_privdata()->acpd_spawned
)
66 if (!clone_vars(&old_vars
))
68 __aros_startup_error
= RETURN_FAIL
;
73 /* If the PATH variable is not defined, then define it to be what CLI's path list
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
);
90 /* Restore the old argv[0]. */
91 if (old_argv0
!= NULL
)
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
)
120 struct LocalVar
*lv
, *newVar
;
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
)
135 copyLength
= strlen(lv
->lv_Node
.ln_Name
) + 1 + sizeof(struct LocalVar
);
137 newVar
= (struct LocalVar
*)AllocVec(copyLength
, MEMF_PUBLIC
);
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
)
155 memcpy(newVar
->lv_Value
, lv
->lv_Value
, lv
->lv_Len
);
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
;
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
);
192 /* setenv("PATH", current_cli_path, 1) */
193 static void update_PATH(void)
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). */
208 struct CommandLineInterface
*cli
= Cli();
210 /* No cli, no luck. */
216 cur
= PE(cli
->cli_CommandDir
);
225 if (NameFromLock(cur
->lock
, aname
, sizeof(aname
)) == DOSFALSE
)
228 D(bug("aname = %s\n", aname
));
230 uname
= __path_a2u(aname
);
233 uname_len
= strlen(uname
);
235 D(bug("uname = %s\n", uname
));
237 new_PATH
= realloc(PATH
, PATH_len
+ uname_len
+ 1);
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
));
251 PATH
[PATH_len
? (PATH_len
- 1) : 0] = '\0';
253 setenv("PATH", PATH
, 1);