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 <dos/filesystem.h>
12 #include <exec/memory.h>
14 #include <exec/lists.h>
15 #include <exec/nodes.h>
21 struct FileHandle
*fhin
, *fhout
;
23 struct IOFileSys
*pendingread
;
25 struct IOFileSys
*pendingwrite
;
30 #define FHI_WAIT (1<<0)
31 #define FHI_READRETURNED (1<<1)
35 struct Task
*parent
, *child
;
36 BYTE psigbit
, csigbit
;
37 environment
*parentenv
;
40 FileHandleInfo files
[3];
44 static struct IOFileSys
*CreateIOFS(ULONG type
, struct MsgPort
*port
, struct FileHandle
*fh
)
46 struct IOFileSys
*iofs
= (struct IOFileSys
*)AllocMem(sizeof(struct IOFileSys
), MEMF_PUBLIC
|MEMF_CLEAR
);
51 iofs
->IOFS
.io_Message
.mn_Node
.ln_Type
= NT_REPLYMSG
;
52 iofs
->IOFS
.io_Message
.mn_ReplyPort
= port
;
53 iofs
->IOFS
.io_Message
.mn_Length
= sizeof(struct IOFileSys
);
54 iofs
->IOFS
.io_Command
= type
;
55 iofs
->IOFS
.io_Flags
= 0;
56 #if defined(__AROS__) && !defined(AROS_DOS_PACKETS)
57 iofs
->IOFS
.io_Device
= fh
->fh_Device
;
58 iofs
->IOFS
.io_Unit
= fh
->fh_Unit
;
64 static BPTR
DupFH(BPTR fh
, LONG mode
)
70 BPTR olddir
= CurrentDir(fh
);
80 void DeleteIOFS(struct IOFileSys
*iofs
)
82 FreeMem(iofs
, sizeof(struct IOFileSys
));
86 void *create_async_info(const tsd_t
*TSD
)
88 AsyncInfo
*ai
= MallocTSD(sizeof(AsyncInfo
));
94 ai
->files
[i
].fhin
= NULL
;
99 void delete_async_info(void *async_info
)
101 AsyncInfo
*ai
= (AsyncInfo
*)async_info
;
106 assert(ai
->files
[0].fhin
== NULL
&& ai
->files
[1].fhin
== NULL
&& ai
->files
[2].fhin
== NULL
);
108 Free_TSD(ai
->TSD
, ai
);
111 void reset_async_info(void *async_info
)
113 AsyncInfo
*ai
= (AsyncInfo
*)async_info
;
115 ai
->files
[0].flags
= 0;
116 ai
->files
[1].flags
= 0;
117 ai
->files
[2].flags
= 0;
120 void add_async_waiter(void *async_info
, int handle
, int add_as_read_handle
)
122 AsyncInfo
*ai
= (AsyncInfo
*)async_info
;
124 ai
->files
[handle
].flags
|= FHI_WAIT
;
127 int open_subprocess_connection(const tsd_t
*TSD
, environpart
*ep
, void *async_info
)
129 AsyncInfo
*ai
= (AsyncInfo
*)async_info
;
132 for (slot
=0; slot
<3 && ai
->files
[slot
].fhin
!=NULL
; slot
++)
141 /* Reset everything to NULL or 0 */
142 memset(&ai
->files
[slot
], 0, sizeof(FileHandleInfo
));
144 if (Pipe("PIPEFS:", &(ai
->files
[slot
].fhin
), &(ai
->files
[slot
].fhout
)) != DOSTRUE
)
150 ai
->files
[slot
].port
= CreatePort(NULL
, 0);
151 if (ai
->files
[slot
].port
== NULL
)
153 Close(ai
->files
[slot
].fhin
);
154 ai
->files
[slot
].fhin
= NULL
;
155 Close(ai
->files
[slot
].fhout
);
156 ai
->files
[slot
].fhout
= NULL
;
160 ai
->files
[slot
].bytesread
= 0;
162 ai
->files
[slot
].isinput
= ep
->flags
.isinput
;
163 if (ep
->flags
.isinput
)
178 void handle_msgs(FileHandleInfo
*fhi
)
180 struct IOFileSys
*iofs
;
182 while ((iofs
= (struct IOFileSys
*)GetMsg(fhi
->port
)) != NULL
)
184 if (iofs
== fhi
->pendingread
)
185 fhi
->flags
|= FHI_READRETURNED
;
186 else if (iofs
== fhi
->pendingwrite
)
188 FreeVec(iofs
->io_Union
.io_WRITE
.io_Buffer
);
189 FreeMem(iofs
, sizeof(struct IOFileSys
));
190 fhi
->pendingwrite
= NULL
;
193 ReplyMsg((struct Message
*)iofs
);
198 int __regina_close(int handle
, void *async_info
)
200 AsyncInfo
*ai
= async_info
;
203 assert(handle
<3 && handle
>=0);
205 fhi
= &ai
->files
[handle
];
208 if (fhi
->pendingread
!= NULL
&& !(fhi
->flags
& FHI_READRETURNED
))
210 AbortIO((struct IORequest
*)fhi
->pendingread
);
211 WaitIO((struct IORequest
*)fhi
->pendingread
);
212 FreeVec(fhi
->pendingread
->io_Union
.io_READ
.io_Buffer
);
213 FreeMem(fhi
->pendingread
, sizeof(struct IOFileSys
));
215 if (fhi
->pendingwrite
!= NULL
)
217 AbortIO((struct IORequest
*)fhi
->pendingwrite
);
218 WaitIO((struct IORequest
*)fhi
->pendingwrite
);
219 FreeVec(fhi
->pendingwrite
->io_Union
.io_READ
.io_Buffer
);
220 FreeMem(fhi
->pendingwrite
, sizeof(struct IOFileSys
));
227 DeletePort(fhi
->port
);
233 void restart_file(int handle
)
235 /* AROS uses pipes so cannot restart file */
236 assert(handle
== -1);
239 void unblock_handle(int *handle
, void *async_info
)
241 /* All handles are non-blocking on AROS => do nothing */
245 int __regina_read(int handle
, void *buf
, unsigned size
, void *async_info
)
247 AsyncInfo
*ai
= async_info
;
252 fhi
= &ai
->files
[handle
];
254 if (fhi
->fhin
== NULL
)
257 if (fhi
->pendingread
== NULL
)
259 struct IOFileSys
*iofs
;
261 fhi
->pendingread
= iofs
= CreateIOFS(FSA_READ
, fhi
->port
, fhi
->fhin
);
265 iofs
->io_Union
.io_READ
.io_Buffer
= AllocVec(size
, MEMF_PUBLIC
);
266 iofs
->io_Union
.io_READ
.io_Length
= size
;
273 if (fhi
->flags
& FHI_READRETURNED
)
275 if (fhi
->bytesread
+ size
> fhi
->pendingread
->io_Union
.io_READ
.io_Length
)
276 size
= fhi
->pendingread
->io_Union
.io_READ
.io_Length
- fhi
->bytesread
;
278 memcpy(buf
, fhi
->pendingread
->io_Union
.io_READ
.io_Buffer
, size
);
279 fhi
->bytesread
+= size
;
281 if (fhi
->bytesread
== fhi
->pendingread
->io_Union
.io_READ
.io_Length
)
283 FreeVec(fhi
->pendingread
->io_Union
.io_READ
.io_Buffer
);
284 FreeMem(fhi
->pendingread
, sizeof(struct IOFileSys
));
285 fhi
->pendingread
= NULL
;
287 fhi
->flags
&= ~FHI_READRETURNED
;
297 int __regina_write(int handle
, const void *buf
, unsigned size
, void *async_info
)
299 AsyncInfo
*ai
= (AsyncInfo
*)async_info
;
304 fhi
= &ai
->files
[handle
];
306 if (buf
==NULL
&& size
==0)
308 if (fhi
->pendingwrite
!=NULL
)
310 WaitIO((struct IORequest
*)fhi
->pendingwrite
);
311 FreeVec(fhi
->pendingwrite
->io_Union
.io_READ
.io_Buffer
);
312 FreeMem(fhi
->pendingwrite
, sizeof(struct IOFileSys
));
313 fhi
->pendingwrite
= NULL
;
318 if (fhi
->fhin
== NULL
)
323 if (fhi
->pendingwrite
== NULL
)
325 struct IOFileSys
*iofs
;
327 fhi
->pendingwrite
= iofs
= CreateIOFS(FSA_WRITE
, fhi
->port
, fhi
->fhout
);
331 iofs
->io_Union
.io_WRITE
.io_Buffer
= AllocVec(size
, MEMF_PUBLIC
);
332 memcpy(iofs
->io_Union
.io_WRITE
.io_Buffer
, buf
, size
);
333 iofs
->io_Union
.io_WRITE
.io_Length
= size
;
344 void wait_async_info(void *async_info
)
346 AsyncInfo
*ai
= (AsyncInfo
*)async_info
;
348 ULONG mask
= SIGBREAKF_CTRL_C
;
350 for (i
= 0; i
< 3; i
++)
352 if (ai
->files
[i
].fhin
!= NULL
&& ai
->files
[i
].flags
& FHI_WAIT
&&
353 (ai
->files
[i
].pendingwrite
!= NULL
|| (ai
->files
[i
].pendingread
!= NULL
&& !(ai
->files
[i
].flags
& FHI_READRETURNED
)))
355 mask
|= 1<<ai
->files
[i
].port
->mp_SigBit
;
358 if (mask
!= SIGBREAKF_CTRL_C
)
362 GLOBAL_PROTECTION_VAR(startcommand
)
363 static AsyncInfo
*childai
;
365 void StartCommand(void)
367 AsyncInfo
*ai
= childai
;
369 struct Library
*UtilityBase
;
370 struct TagItem
*tags
;
371 struct DosLibrary
*DOSBase
;
373 DOSBase
= (struct DosLibrary
*)OpenLibrary("dos.library", 0);
375 ai
->child
= FindTask(NULL
);
376 ai
->csigbit
= AllocSignal(-1);
377 cmd
= AllocVec(strlen(ai
->childcmd
)+1, MEMF_PUBLIC
|MEMF_CLEAR
);
378 strcpy(cmd
, ai
->childcmd
);
380 Signal(ai
->parent
, 1<<ai
->psigbit
);
381 Wait(1<<ai
->csigbit
);
382 FreeSignal(ai
->csigbit
);
384 UtilityBase
= OpenLibrary("utility.library", 0);
385 if (UtilityBase
== NULL
)
389 Signal(ai
->parent
, 1<<ai
->psigbit
);
390 CloseLibrary((struct Library
*)DOSBase
);
394 tags
= AllocateTagItems(5);
398 CloseLibrary(UtilityBase
);
400 Signal(ai
->parent
, 1<<ai
->psigbit
);
401 CloseLibrary((struct Library
*)DOSBase
);
405 ai
->retval
= SystemTagList(cmd
, NULL
);
409 CloseLibrary(UtilityBase
);
411 Signal(ai
->parent
, 1<<ai
->psigbit
);
413 CloseLibrary((struct Library
*)DOSBase
);
416 int fork_exec(tsd_t
*TSD
, environment
*env
, const char *cmdline
, void *async_info
)
418 AsyncInfo
*ai
= (AsyncInfo
*)async_info
;
420 switch (env
->subtype
)
423 case SUBENVIR_COMMAND
:
424 case SUBENVIR_SYSTEM
:
426 int inhndl
= env
->input
.hdls
[1],
427 outhndl
= env
->output
.hdls
[0],
428 errhndl
= env
->error
.hdls
[0];
430 ai
->psigbit
= AllocSignal(-1);
436 ai
->parent
= FindTask(NULL
);
438 ai
->childcmd
= cmdline
;
440 THREAD_PROTECT(startcommand
)
443 CreateNewProcTags(NP_Entry
, StartCommand
,
444 NP_Input
, (inhndl
== -1) ? Input() : ai
->files
[inhndl
].fhin
,
445 NP_CloseInput
, inhndl
!= -1,
446 NP_Output
, (outhndl
== -1) ? Output() : ai
->files
[outhndl
].fhout
,
447 NP_CloseOutput
, outhndl
!= -1,
448 NP_Error
, (errhndl
== -1) ? Error() : ai
->files
[errhndl
].fhout
,
449 NP_CloseError
, errhndl
!= -1,
452 Wait(1<<ai
->psigbit
);
453 THREAD_UNPROTECT(startcommand
)
454 Signal(ai
->child
, 1<<ai
->csigbit
);
468 int __regina_wait(int process
)
470 AsyncInfo
*ai
= (AsyncInfo
*)process
;
472 Wait(1<<ai
->psigbit
);
473 FreeSignal(ai
->psigbit
);
481 int uname(struct utsname
*name
)
483 strcpy( name
->sysname
, "AMIGA" );
484 sprintf( name
->version
, "%d", 0 );
485 sprintf( name
->release
, "%d", 0 );
486 strcpy( name
->nodename
, "standalone" );
487 strcpy( name
->machine
, "i386" );