2 Copyright © 1995-2017, The AROS Development Team. All rights reserved.
5 Desc: Common startup code
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
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
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
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()
33 #include <aros/config.h>
35 #include <dos/stdio.h>
36 #include <proto/exec.h>
37 #include <proto/dos.h>
38 #include <aros/asmcall.h>
39 #include <aros/debug.h>
40 #include <aros/symbolsets.h>
41 #include <aros/startup.h>
43 int __detached_manages_detach
;
44 int __detacher_go_away
;
45 STRPTR __detached_name
;
46 LONG __detached_return_value
;
47 struct Process
*__detacher_process
;
49 AROS_PROCP(__detach_trampoline
);
51 static void __startup_detach(struct ExecBase
*SysBase
)
53 struct CommandLineInterface
*cli
;
54 struct Process
*newproc
;
55 BPTR mysegment
= BNULL
;
58 D(bug("Entering __startup_detach()\n"));
61 /* Without a CLI detaching makes no sense, just jump to
65 D(bug("Wasn't started from cli.\n"));
66 __startup_entries_next();
70 D(bug("Was started from cli.\n"));
71 mysegment
= cli
->cli_Module
;
72 cli
->cli_Module
= BNULL
;
75 detached_name
= __detached_name
? __detached_name
: (STRPTR
) FindTask(NULL
)->tc_Node
.ln_Name
;
77 in
= OpenFromLock(DupLockFromFH(Input()));
78 out
= OpenFromLock(DupLockFromFH(Output()));
79 if (IsInteractive(in
))
80 SetVBuf(in
, NULL
, BUF_LINE
, -1);
81 if (IsInteractive(out
))
82 SetVBuf(out
, NULL
, BUF_LINE
, -1);
85 struct TagItem tags
[] =
87 { NP_Seglist
, (IPTR
)mysegment
},
88 { NP_Entry
, (IPTR
)&__detach_trampoline
},
89 { NP_Name
, (IPTR
)detached_name
},
90 { NP_Arguments
, (IPTR
)__argstr
},
91 { NP_Input
, (IPTR
)in
},
92 { NP_CloseInput
,FALSE
},
93 { NP_Output
, (IPTR
)out
},
94 { NP_CloseOutput
,FALSE
},
99 __detacher_process
= (struct Process
*)FindTask(NULL
);
101 /* CreateNewProc() will take care of freeing the seglist */
102 newproc
= CreateNewProc(tags
);
105 D(bug("Process \"%s\" = 0x%x.\n", detached_name
, newproc
));
108 cli
->cli_Module
= mysegment
;
109 __detached_return_value
= RETURN_ERROR
;
112 while (!__detacher_go_away
) Wait(SIGF_SINGLE
);
114 D(bug("__detached_return_value = %d.\n", __detached_return_value
));
115 if (__detached_return_value
!= RETURN_OK
)
117 PutStr((CONST_STRPTR
)FindTask(NULL
)->tc_Node
.ln_Name
); PutStr((CONST_STRPTR
)": Failed to detach.\n");
123 Signal(&newproc
->pr_Task
, SIGF_SINGLE
);
126 __startup_error
= __detached_return_value
;
129 D(bug("Leaving __startup_detach\n"));
132 ADD2SET(__startup_detach
, PROGRAM_ENTRIES
, -100);
134 void __Detach(LONG retval
);
136 AROS_PROCH(__detach_trampoline
, argstr
, argsize
, SysBase
)
140 LONG retval
= RETURN_OK
;
142 D(bug("Entering __detach_trampoline()\n"));
144 /* We have a CLI that is not 'attached' to a Shell,
145 * and to get WB 1.3's C:Status to list us properly,
146 * we need to set cli_Module to something.
148 Cli()->cli_Module
= (BPTR
)-1;
150 /* The program has two options: either take care of telling the detacher
151 process when exactly to go away, via the Detach() function, or let this
152 startup code take care of it. If __detached_manages_detach is TRUE, then
153 the detached process handles it, otherwise we handle it. */
155 if (!__detached_manages_detach
)
158 __startup_entries_next();
160 /* At this point the detacher process might still be around,
161 If the program forgot to detach, or if it couldn't, but in any
162 case we need to tell the detacher to go away. */
165 D(bug("Leaving __detach_trampoline\n"));
172 void __Detach(LONG retval
)
174 D(bug("Entering __Detach(%d)\n", retval
));
176 if (__detacher_process
!= NULL
)
178 __detached_return_value
= retval
;
179 __detacher_go_away
= TRUE
;
181 SetSignal(0, SIGF_SINGLE
);
182 /* Tell the detacher process it can now go away */
183 Signal(&__detacher_process
->pr_Task
, SIGF_SINGLE
);
185 /* Wait for it to say "goodbye" */
187 __detacher_process
= NULL
;
195 D(bug("Leaving __Detach\n"));