Build FileSystem.resource for sam port.
[AROS.git] / compiler / startup / detach.c
blob432b27a6f2a9f65cd04dd9fd2728d08177a87e80
1 /*
2 Copyright © 1995-2009, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: Common startup code
6 Lang: english
8 Use: To make a program detach itself from the launching CLI, use
9 detach.o as your program's start file, before any other usual start
10 file.
12 If you want the detached process to have a name different than the
13 detacher's one, define the following variable in your program's
14 source code:
16 STRPTR __detached_name = "My Preferred Program Name";
18 You can also decide to control exactly when to detach your program
19 from the shell. To do so, simply use the function
21 Detach();
23 declared in
25 <aros/detach.h>
27 when you want to detach the program. Not using this function will
28 result in your program being detached from the shell before the main()
29 function is reached.
31 #define DEBUG 0
33 #include <aros/config.h>
34 #include <dos/dos.h>
35 #include <proto/exec.h>
36 #include <proto/dos.h>
37 #include <aros/asmcall.h>
38 #include <aros/debug.h>
39 #include <aros/symbolsets.h>
40 #include <aros/startup.h>
42 int __detached_manages_detach;
43 int __detacher_go_away;
44 STRPTR __detached_name;
45 LONG __detached_return_value;
46 struct Process *__detacher_process;
48 AROS_UFP3S(LONG, __detach_trampoline,
49 AROS_UFPA(char *,argstr,A0),
50 AROS_UFPA(ULONG,argsize,D0),
51 AROS_UFPA(struct ExecBase *,SysBase,A6));
53 static void __startup_detach(void)
55 struct CommandLineInterface *cli;
56 struct Process *newproc;
57 BPTR mysegment = BNULL;
58 STRPTR detached_name;
60 D(bug("Entering __startup_detach()\n"));
62 cli = Cli();
63 /* Without a CLI detaching makes no sense, just jump to
64 the real program. */
65 if (!cli)
67 D(bug("Wasn't started from cli.\n"));
68 __startup_entries_next();
70 else
72 D(bug("Was started from cli.\n"));
73 mysegment = cli->cli_Module;
74 cli->cli_Module = BNULL;
76 detached_name = __detached_name ? __detached_name : (STRPTR) FindTask(NULL)->tc_Node.ln_Name;
79 struct TagItem tags[] =
81 { NP_Seglist, (IPTR)mysegment },
82 { NP_Entry, (IPTR)&__detach_trampoline },
83 { NP_Name, (IPTR)detached_name },
84 { NP_Arguments, (IPTR)__argstr },
85 { NP_Cli, TRUE },
86 { TAG_DONE, 0 }
89 __detacher_process = (struct Process *)FindTask(NULL);
91 /* CreateNewProc() will take care of freeing the seglist */
92 newproc = CreateNewProc(tags);
95 D(bug("Process \"%s\" = 0x%x.\n", detached_name, newproc));
96 if (!newproc)
98 cli->cli_Module = mysegment;
99 __detached_return_value = RETURN_ERROR;
101 else
102 while (!__detacher_go_away) Wait(SIGF_SINGLE);
104 D(bug("__detached_return_value = %d.\n", __detached_return_value));
105 if (__detached_return_value != RETURN_OK)
107 PutStr(FindTask(NULL)->tc_Node.ln_Name); PutStr(": Failed to detach.\n");
110 if (newproc)
112 Forbid();
113 Signal(&newproc->pr_Task, SIGF_SINGLE);
116 __startup_error = __detached_return_value;
119 D(bug("Leaving __startup_detach\n"));
122 ADD2SET(__startup_detach, program_entries, -100);
124 void __Detach(LONG retval);
126 AROS_UFH3S(LONG, __detach_trampoline,
127 AROS_UFHA(char *,argstr,A0),
128 AROS_UFHA(ULONG,argsize,D0),
129 AROS_UFHA(struct ExecBase *,SysBase,A6))
131 AROS_USERFUNC_INIT
133 LONG retval = RETURN_OK;
135 D(bug("Entering __detach_trampoline()\n"));
137 /* The program has two options: either take care of telling the detacher
138 process when exactly to go away, via the Detach() function, or let this
139 startup code take care of it. If __detached_manages_detach is TRUE, then
140 the detached process handles it, otherwise we handle it. */
142 if (!__detached_manages_detach)
143 __Detach(RETURN_OK);
145 __startup_entries_next();
147 /* At this point the detacher process might still be around,
148 If the program forgot to detach, or if it couldn't, but in any
149 case we need to tell the detacher to go away. */
150 __Detach(retval);
152 D(bug("Leaving __detach_trampoline\n"));
154 return 0;
156 AROS_USERFUNC_EXIT
159 void __Detach(LONG retval)
161 D(bug("Entering __Detach(%d)\n", retval));
163 if (__detacher_process != NULL)
165 __detached_return_value = retval;
166 __detacher_go_away = TRUE;
168 SetSignal(0, SIGF_SINGLE);
169 /* Tell the detacher process it can now go away */
170 Signal(&__detacher_process->pr_Task, SIGF_SINGLE);
172 /* Wait for it to say "goodbye" */
173 Wait(SIGF_SINGLE);
174 __detacher_process = NULL;
177 D(bug("Leaving __Detach\n"));