3 #include <proto/alib.h>
4 #include <proto/exec.h>
6 #include <proto/utility.h>
7 #include <utility/tagitem.h>
9 #include <dos/dostags.h>
10 #include <dos/dosextens.h>
11 #include <exec/memory.h>
13 #include <exec/lists.h>
14 #include <exec/nodes.h>
24 #include <aros/debug.h>
30 #define BNULL ((BPTR)NULL)
37 struct Task
*parent
, *child
;
38 BYTE psigbit
, csigbit
;
39 environment
*parentenv
;
53 /* On amiga(-like) systems the pipe used for communicating
54 is asynchronous from itself and does not to be handled
57 static void *Amiga_create_async_info(const tsd_t
*TSD
)
59 D(bug("[Amiga_create_async_info] TSD=%p\n", TSD
));
61 /* Amiga pipes are async */
65 static void Amiga_delete_async_info(void *async_info
)
67 D(bug("[Amiga_delete_async_info] async_info=%p\n", async_info
));
68 /* Amiga pipes are async */
71 /* Reset FHI_WAIT flag */
72 static void Amiga_reset_async_info(void *async_info
)
74 D(bug("[Amiga_reset_async_info] async_info=%p\n", async_info
));
75 /* Amiga pipes are async */
78 /* Mark handle to wait for it */
79 static void Amiga_add_async_waiter(void *async_info
, int handle
, int add_as_read_handle
)
81 /* Amiga pipes are async */
84 /* For a subprocess connection on amiga a pipe will be opened
85 and both read and write ends will be stored.
86 Only a read or write handle will be returned depending on wether
87 this connection is input or output.
88 We can't just cast a BPTR to int in this function as on some archs
89 sizeof(int) < sizeof(void *).
91 static int Amiga_open_subprocess_connection(const tsd_t
*TSD
, environpart
*ep
)
93 AmigaPipeInfo
*pipein
, *pipeout
;
96 D(bug("[Amiga_open_subprocess_connection] Entering\n"));
98 pipein
= malloc(sizeof(AmigaPipeInfo
));
104 pipein
->type
= PIPE_READ
;
105 pipein
->file
= BNULL
;
107 pipeout
= malloc(sizeof(AmigaPipeInfo
));
113 pipeout
->type
= PIPE_WRITE
;
114 pipeout
->file
= BNULL
;
116 hndlin
= __amiga_ptr2int(TSD
, pipein
);
117 hndlout
= __amiga_ptr2int(TSD
, pipeout
);
118 if (hndlin
== -1 || hndlout
== -1)
126 ep
->hdls
[0] = hndlin
;
127 ep
->hdls
[1] = hndlout
;
132 /* First abort pending IOs, then close filehandle */
133 static int Amiga_close(int handle
, void *async_info
)
135 const tsd_t
*TSD
= GLOBAL_ENTRY_POINT();
136 AmigaPipeInfo
*pipe
= __amiga_getptr( TSD
, handle
);
138 D(bug("[Amiga_close] handle=%d\n", handle
));
140 if(pipe
->file
!= BNULL
)
142 __amiga_clearptr(TSD
, handle
);
148 /* We don't have special filehandles */
149 static void Amiga_close_special( int handle
)
151 assert( handle
== -1 );
155 /* Amiga uses pipes so cannot restart file */
156 static void Amiga_restart_file(int handle
)
158 assert( handle
== -1 );
161 static void Amiga_unblock_handle(int *handle
, void *async_info
)
163 /* All handles are non-blocking on AROS => do nothing */
166 static int Amiga_read(int handle
, void *buf
, unsigned size
, void *async_info
)
168 const tsd_t
*TSD
= GLOBAL_ENTRY_POINT();
169 AmigaPipeInfo
*pipe
= __amiga_getptr( TSD
, handle
);
172 D(bug("[Amiga_read] hndl=%d\n"));
174 assert(pipe
->type
== PIPE_READ
);
175 assert(pipe
->file
!= BNULL
);
177 retval
= Read( pipe
->file
, buf
, size
);
181 D(bug("[Amiga_read] retval=%d\n", retval
));
186 static int Amiga_write(int handle
, const void *buf
, unsigned size
, void *async_info
)
188 const tsd_t
*TSD
= GLOBAL_ENTRY_POINT();
189 AmigaPipeInfo
*pipe
= __amiga_getptr( TSD
, handle
);
192 D(bug("[Amiga_write] hndl=%d\n"));
194 assert(pipe
->type
== PIPE_WRITE
);
195 assert(pipe
->file
!= BNULL
);
197 retval
= Write( pipe
->file
, buf
, size
);
201 D(bug("[Amiga_write] retval=%d\n", retval
));
207 static void Amiga_wait_async_info(void *async_info
)
209 /* Amiga pipes are async */
212 GLOBAL_PROTECTION_VAR(startcommand
)
213 static ChildInfo
*childinfo
;
215 static void StartCommand(void)
217 ChildInfo
*info
= childinfo
;
219 struct Library
*UtilityBase
;
220 struct DosLibrary
*DOSBase
;
222 D(bug("[Startcommand]: Entering\n"));
224 DOSBase
= (struct DosLibrary
*)OpenLibrary("dos.library", 0);
226 info
->child
= FindTask(NULL
);
227 info
->csigbit
= AllocSignal(-1);
228 cmd
= AllocVec(strlen(info
->childcmd
)+1, MEMF_PUBLIC
|MEMF_CLEAR
);
229 strcpy(cmd
, info
->childcmd
);
230 D(bug("[Startcommand]: cmd='%s'\n", cmd
));
232 D(bug("[Startcommand]: Signaling parent\n"));
233 Signal(info
->parent
, 1<<info
->psigbit
);
234 D(bug("[Startcommand]: Waiting for parent\n"));
235 Wait(1<<info
->csigbit
);
236 FreeSignal(info
->csigbit
);
238 UtilityBase
= OpenLibrary("utility.library", 0);
239 if (UtilityBase
== NULL
)
243 Signal(info
->parent
, 1<<info
->psigbit
);
244 CloseLibrary((struct Library
*)DOSBase
);
248 info
->retval
= SystemTags(cmd
, NP_Synchronous
, TRUE
, TAG_DONE
, NULL
);
249 D(bug("[Startcommand]: retval=%d\n", info
->retval
));
252 CloseLibrary(UtilityBase
);
254 D(bug("[Startcommand]: Signaling parent\n"));
255 Signal(info
->parent
, 1<<info
->psigbit
);
257 CloseLibrary((struct Library
*)DOSBase
);
260 static int Amiga_fork_exec(tsd_t
*TSD
, environment
*env
, const char *cmdline
, int *rcode
)
262 switch (env
->subtype
)
265 case SUBENVIR_COMMAND
:
266 case SUBENVIR_SYSTEM
:
268 ChildInfo
*info
= malloc( sizeof(ChildInfo
) );
270 int inhndl
= env
->input
.hdls
[1],
271 outhndl
= env
->output
.hdls
[0],
272 errhndl
= env
->error
.hdls
[0];
273 BPTR sub_input
= BNULL
, sub_output
= BNULL
, sub_error
= BNULL
;
274 BOOL close_input
, close_output
, close_error
;
275 AmigaPipeInfo
*pipe
= NULL
;
277 struct Process
*me
= (struct Process
*)FindTask(NULL
);
279 D(bug("[Amiga_fork_exec]: Entering cmdline='%s'\n", cmdline
));
287 proc
= __amiga_ptr2int( TSD
, info
);
288 D(bug("[Amiga_fork_exec]: Got proc=%d\n", proc
));
296 info
->psigbit
= AllocSignal(-1);
297 if (info
->psigbit
< 0)
302 info
->parent
= FindTask(NULL
);
303 info
->parentenv
= env
;
304 info
->childcmd
= cmdline
;
308 pipe
= (AmigaPipeInfo
*)__amiga_getptr(TSD
, inhndl
);
309 /* Regina will write into input of subcommand */
310 assert(pipe
->type
== PIPE_WRITE
);
312 snprintf(buff
, sizeof(buff
), "PIPE:rexx-%p-in", me
);
313 pipe
->file
= Open(buff
, MODE_NEWFILE
);
314 if (pipe
->file
!= BNULL
)
316 /* Input() of subcommand with read from pipe */
317 sub_input
= Open(buff
, MODE_OLDFILE
);
318 if(sub_input
== BNULL
)
342 pipe
= (AmigaPipeInfo
*)__amiga_getptr(TSD
, outhndl
);
343 /* Regina will read output of subcommand */
344 assert(pipe
->type
== PIPE_READ
);
346 snprintf(buff
, sizeof(buff
), "PIPE:rexx-%p-out", me
);
347 /* Output() of subcommand will write in pipe */
348 sub_output
= Open(buff
, MODE_NEWFILE
);
349 if (sub_output
!= BNULL
)
351 pipe
->file
= Open(buff
, MODE_OLDFILE
);
352 if(pipe
->file
== BNULL
)
370 sub_output
= Output();
371 close_output
= FALSE
;
376 pipe
= (AmigaPipeInfo
*)__amiga_getptr(TSD
, errhndl
);
377 /* Regina will read error output of subcommand */
378 assert(pipe
->type
== PIPE_READ
);
380 snprintf(buff
, sizeof(buff
), "PIPE:rexx-%p-err", me
);
381 /* Error() of subcommand will write in pipe */
382 sub_error
= Open(buff
, MODE_NEWFILE
);
383 if (sub_error
!= BNULL
)
385 pipe
->file
= Open(buff
, MODE_OLDFILE
);
386 if(pipe
->file
== BNULL
)
404 sub_error
= me
->pr_CES
;
408 THREAD_PROTECT(startcommand
)
411 D(bug("[Amiga_fork_exec]: Starting command\n"));
415 NP_Entry
, StartCommand
,
416 NP_Input
, sub_input
, NP_CloseInput
, close_input
,
417 NP_Output
, sub_output
, NP_CloseOutput
, close_output
,
418 NP_Error
, sub_error
, NP_CloseError
, close_error
,
422 D(bug("[Amiga_fork_exec]: Waiting child cache of info\n"));
423 Wait(1<<info
->psigbit
);
424 THREAD_UNPROTECT(startcommand
)
425 D(bug("[Amiga_fork_exec]: Signaling child\n"));
426 Signal(info
->child
, 1<<info
->csigbit
);
428 D(bug("[Amiga_fork_exec]: Returning proc=%d\n", proc
));
442 static int Amiga_wait(int process
)
444 const tsd_t
*TSD
= GLOBAL_ENTRY_POINT();
445 ChildInfo
*info
= __amiga_getptr( TSD
, process
);
448 D(bug("[Amiga_wait] Waiting for child\n"));
450 Wait( 1<<info
->psigbit
);
451 retval
= info
->retval
;
452 FreeSignal( info
->psigbit
);
454 __amiga_clearptr( TSD
, process
);
457 D(bug("[Amiga_wait] retval=%d\n", retval
));
462 static void Amiga_init(void)
466 static int Amiga_setenv(const char *name
, const char *value
)
468 return setenv(name
, value
, 1);
473 static int Amiga_uname(struct regina_utsname
*name
)
475 strcpy( name
->sysname
, "AMIGA" );
476 sprintf( name
->version
, "%d", 0 );
477 sprintf( name
->release
, "%d", 0 );
478 strcpy( name
->nodename
, "standalone" );
480 strcpy( name
->machine
, "ppc" );
482 strcpy( name
->machine
, "i386" );
488 OS_Dep_funcs __regina_OS_Amiga
=
490 Amiga_init
, /* init */
491 Amiga_setenv
, /* setenv */
492 Amiga_fork_exec
, /* fork_exec */
493 Amiga_wait
, /* wait */
494 Amiga_open_subprocess_connection
, /* open_subprocess_connection */
495 Amiga_unblock_handle
, /* unblock_handle */
496 Amiga_restart_file
, /* restart_file */
497 Amiga_close
, /* close */
498 Amiga_close_special
, /* close_special */
499 Amiga_read
, /* read */
500 Amiga_write
, /* write */
501 Amiga_create_async_info
, /* create_async_info */
502 Amiga_delete_async_info
, /* delete_async_info */
503 Amiga_reset_async_info
, /* reset_async_info */
504 Amiga_add_async_waiter
, /* add_async_waiter */
505 Amiga_wait_async_info
, /* wait_async_info */
506 Amiga_uname
/* uname */