bringing SDL 1.2.14 from vendor into the main branch
[AROS-Contrib.git] / regina / arscmd.c
blob39c4308bc899926f86f21991cce364662d4a7fea
1 #include "rexx.h"
3 #include <proto/alib.h>
4 #include <proto/exec.h>
5 #include <proto/dos.h>
6 #include <proto/utility.h>
7 #include <utility/tagitem.h>
8 #include <dos/dos.h>
9 #include <dos/dostags.h>
10 #include <dos/dosextens.h>
11 #include <dos/filesystem.h>
12 #include <exec/memory.h>
13 #include <exec/io.h>
14 #include <exec/lists.h>
15 #include <exec/nodes.h>
17 #include <assert.h>
18 #include <errno.h>
20 typedef struct {
21 struct FileHandle *fhin, *fhout;
22 struct MsgPort *port;
23 struct IOFileSys *pendingread;
24 ULONG bytesread;
25 struct IOFileSys *pendingwrite;
26 ULONG flags;
27 BOOL isinput;
28 } FileHandleInfo;
30 #define FHI_WAIT (1<<0)
31 #define FHI_READRETURNED (1<<1)
33 typedef struct {
34 const tsd_t *TSD;
35 struct Task *parent, *child;
36 BYTE psigbit, csigbit;
37 environment *parentenv;
38 const char *childcmd;
39 int retval;
40 FileHandleInfo files[3];
41 } AsyncInfo;
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);
48 if (iofs == NULL)
49 return NULL;
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;
59 #endif
61 return iofs;
64 static BPTR DupFH(BPTR fh, LONG mode)
66 BPTR ret = NULL;
68 if (fh)
70 BPTR olddir = CurrentDir(fh);
71 ret = Open("", mode);
73 CurrentDir(olddir);
76 return ret;
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));
89 int i;
91 ai->TSD = TSD;
93 for(i=0; i<3; i++)
94 ai->files[i].fhin = NULL;
96 return (void *)ai;
99 void delete_async_info(void *async_info)
101 AsyncInfo *ai = (AsyncInfo *)async_info;
103 if (ai == NULL)
104 return;
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;
130 int slot;
132 for (slot=0; slot<3 && ai->files[slot].fhin!=NULL; slot++)
135 if (slot==3)
137 errno = EMFILE;
138 return -1;
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)
146 errno = EACCES;
147 return -1;
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;
157 errno = ENOMEM;
158 return -1;
160 ai->files[slot].bytesread = 0;
162 ai->files[slot].isinput = ep->flags.isinput;
163 if (ep->flags.isinput)
165 ep->hdls[0] = -1;
166 ep->hdls[1] = slot;
168 else
170 ep->hdls[0] = slot;
171 ep->hdls[1] = -1;
174 return 0;
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;
192 else
193 ReplyMsg((struct Message *)iofs);
198 int __regina_close(int handle, void *async_info)
200 AsyncInfo *ai = async_info;
201 FileHandleInfo *fhi;
203 assert(handle<3 && handle>=0);
205 fhi = &ai->files[handle];
207 handle_msgs(fhi);
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));
222 if (fhi->isinput)
223 Close(fhi->fhout);
224 else
225 Close(fhi->fhin);
226 fhi->fhin = NULL;
227 DeletePort(fhi->port);
229 return 0;
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;
248 FileHandleInfo *fhi;
250 assert(handle<3);
252 fhi = &ai->files[handle];
254 if (fhi->fhin == NULL)
255 return -EBADF;
257 if (fhi->pendingread == NULL)
259 struct IOFileSys *iofs;
261 fhi->pendingread = iofs = CreateIOFS(FSA_READ, fhi->port, fhi->fhin);
262 if (iofs == NULL)
263 return -ENOMEM;
265 iofs->io_Union.io_READ.io_Buffer = AllocVec(size, MEMF_PUBLIC);
266 iofs->io_Union.io_READ.io_Length = size;
268 SendIO(&iofs->IOFS);
271 handle_msgs(fhi);
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;
286 fhi->bytesread = 0;
287 fhi->flags &= ~FHI_READRETURNED;
290 return size;
292 else
293 return -EAGAIN;
297 int __regina_write(int handle, const void *buf, unsigned size, void *async_info)
299 AsyncInfo *ai = (AsyncInfo *)async_info;
300 FileHandleInfo *fhi;
302 assert(handle<3);
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;
315 return 0;
318 if (fhi->fhin == NULL)
319 return -EBADF;
321 handle_msgs(fhi);
323 if (fhi->pendingwrite == NULL)
325 struct IOFileSys *iofs;
327 fhi->pendingwrite = iofs = CreateIOFS(FSA_WRITE, fhi->port, fhi->fhout);
328 if (iofs == NULL)
329 return -ENOMEM;
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;
335 SendIO(&iofs->IOFS);
337 return (int)size;
339 else
340 return -EAGAIN;
344 void wait_async_info(void *async_info)
346 AsyncInfo *ai = (AsyncInfo *)async_info;
347 int i;
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)
359 Wait(mask);
362 GLOBAL_PROTECTION_VAR(startcommand)
363 static AsyncInfo *childai;
365 void StartCommand(void)
367 AsyncInfo *ai = childai;
368 char *cmd;
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)
387 FreeVec(cmd);
388 ai->retval = 20;
389 Signal(ai->parent, 1<<ai->psigbit);
390 CloseLibrary((struct Library *)DOSBase);
391 return;
394 tags = AllocateTagItems(5);
395 if (tags == NULL)
397 FreeVec(cmd);
398 CloseLibrary(UtilityBase);
399 ai->retval = 20;
400 Signal(ai->parent, 1<<ai->psigbit);
401 CloseLibrary((struct Library *)DOSBase);
402 return;
405 ai->retval = SystemTagList(cmd, NULL);
406 FreeVec(cmd);
408 FreeTagItems(tags);
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)
422 case SUBENVIR_PATH:
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);
431 if (ai->psigbit < 0)
433 errno = ECHILD;
434 return -1;
436 ai->parent = FindTask(NULL);
437 ai->parentenv = env;
438 ai->childcmd = cmdline;
440 THREAD_PROTECT(startcommand)
441 childai = ai;
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,
450 NP_Cli, TRUE,
451 TAG_DONE, NULL);
452 Wait(1<<ai->psigbit);
453 THREAD_UNPROTECT(startcommand)
454 Signal(ai->child, 1<<ai->csigbit);
456 return (int)ai;
457 break;
459 case SUBENVIR_REXX:
460 errno = ENOSYS;
461 return -1;
464 errno = ENOSYS;
465 return -1;
468 int __regina_wait(int process)
470 AsyncInfo *ai = (AsyncInfo *)process;
472 Wait(1<<ai->psigbit);
473 FreeSignal(ai->psigbit);
474 ai->psigbit = -1;
476 return ai->retval;
479 #include "utsname.h"
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" );
489 return 0;