# use AROS_LIB/INCLUDES
[AROS-Contrib.git] / regina / rexxmast / RexxMast.c
blob4d0bd3b7ab9ed25288b768aefe1b2dbbdcee8527
1 #include <proto/alib.h>
2 #include <proto/dos.h>
3 #include <proto/exec.h>
4 #include <proto/intuition.h>
5 #include <proto/regina.h>
6 #include <proto/rexxsyslib.h>
8 #include <rexx/rexxcall.h>
9 #include <exec/ports.h>
10 #include <exec/memory.h>
11 #include <intuition/intuition.h>
12 #include <dos/dosextens.h>
13 #include <dos/dostags.h>
14 #include <rexx/storage.h>
15 #include <rexx/errors.h>
16 #include <rexx/rxslib.h>
17 #include <ctype.h>
18 #include <string.h>
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <assert.h>
23 #define DEBUG 0
24 #include <aros/debug.h>
26 static LONG StartFile(struct RexxMsg *);
27 static void StartFileSlave(struct RexxMsg *);
28 static void AddLib(struct RexxMsg *);
29 static void RemLib(struct RexxMsg *);
30 static void AddCon(struct RexxMsg *);
31 static void RemCon(struct RexxMsg *);
33 static UBYTE progdir[256];
35 int main(int argc, char **argv)
37 struct MsgPort *port;
38 struct RexxMsg *msg;
39 BOOL done = FALSE;
40 ULONG mask, signals;
41 BPTR lock;
42 struct EasyStruct es =
44 sizeof(struct EasyStruct),
46 "RexxMast error",
47 NULL,
48 "OK"
51 if (argc==3 && strcmp("SUBTASK", argv[1])==0)
53 struct RexxMsg *msg;
55 sscanf(argv[2], "%p", &msg);
56 StartFileSlave(msg);
57 ReplyMsg((struct Message *)msg);
59 return 0;
62 lock = Lock("PROGDIR:", SHARED_LOCK);
63 NameFromLock(lock, progdir, sizeof(progdir));
64 D(bug("Got PROGDIR:='%s'\n", progdir));
65 UnLock(lock);
67 port = CreatePort("REXX", 0);
68 es.es_Title = "RexxMast message";
69 mask = SIGBREAKF_CTRL_C | (1<<port->mp_SigBit);
72 signals = Wait(mask);
73 if (signals & SIGBREAKF_CTRL_C)
74 done = TRUE;
75 if (signals & (1<<port->mp_SigBit))
77 while ((msg = (struct RexxMsg *)GetMsg(port)) != NULL)
79 BOOL reply=TRUE;
82 if (!IsRexxMsg(msg))
84 es.es_TextFormat = "Received message that is not a Rexx message";
85 EasyRequest(NULL, &es, NULL);
87 else
89 static UBYTE *text[] =
90 { "RXCOMM", "RXFUNC", "RXCLOSE", "RXQUERY", "UNKNOWN1",
91 "UNKNOWN2", "RXADDFH", "RXADDLIB", "RXREMLIB",
92 "RXADDCON", "RXREMCON", "RXTCOPN", "RXTCCLS",
93 "TOO HIGH"
95 LONG action = msg->rm_Action & RXCODEMASK;
96 D(bug("Got message with action %x\n", action));
97 switch (action)
99 case RXFUNC:
100 case RXCOMM:
101 if (StartFile(msg) < 0)
103 D(bug("Error executing command '%s'\n", (char *)msg->rm_Args[0]));
104 msg->rm_Result1 = RC_ERROR;
105 msg->rm_Result2 = (IPTR)ERR10_100;
107 else
109 D(bug("Command '%s' executed\n", (char *)msg->rm_Args[0]));
110 reply = FALSE;
112 break;
114 case RXADDCON:
115 AddCon(msg);
116 break;
118 case RXREMCON:
119 RemCon(msg);
120 break;
122 case RXADDFH:
123 case RXADDLIB:
124 AddLib(msg);
125 break;
127 case RXREMLIB:
128 RemLib(msg);
129 break;
131 case RXADDRSRC:
132 case RXREMRSRC:
133 case RXCHECKMSG:
134 case RXSETVAR:
135 case RXGETVAR:
136 if (!IsReginaMsg(msg))
138 msg->rm_Result1 = RC_ERROR;
139 msg->rm_Result2 = (IPTR)ERR10_010;
141 else if (action==RXCHECKMSG)
143 msg->rm_Result1 = RC_OK;
145 else
147 /* Forward to the appropriate port */
148 PutMsg( (struct MsgPort *)msg->rm_Private1, (struct Message *)msg );
149 reply = FALSE;
151 break;
153 case RXCLOSE:
154 done = TRUE;
155 default:
156 es.es_TextFormat = "Rexx message with command \"%s\" received";
157 if (action <= RXTCCLS)
158 EasyRequest(NULL, &es, NULL, text[(action >> 24) - 1]);
159 else
160 EasyRequest(NULL, &es, NULL, text[(RXTCCLS >> 24)]);
161 break;
164 if (reply)
166 D(bug("Replying message\n"));
167 ReplyMsg((struct Message *)msg);
169 else
170 D(bug("Not replying to message\n"));
173 } while(!done);
175 DeletePort(port);
177 return 0;
180 static LONG StartFile(struct RexxMsg *msg)
182 char text[300];
184 sprintf(text, "\"%s%sRexxMast\" SUBTASK %p", progdir,
185 progdir[strlen(progdir)-1] == ':' ? "" : "/",
186 (void*)msg
189 /* FIXME: thread should be used to handle more then one message at a time, not SystemTags */
190 return SystemTags(text, SYS_Asynch, TRUE, SYS_Input, NULL,
191 SYS_Output, NULL, TAG_DONE
195 static void StartFileSlave(struct RexxMsg *msg)
197 UBYTE *comm = (UBYTE *)msg->rm_Args[0];
198 BPTR lock, oldlock = BNULL;
199 unsigned int len=0, extlen, commlen = LengthArgstring(comm);
200 BPTR input = BNULL, output = BNULL, error = BNULL;
201 struct Process *process = (struct Process *)msg->rm_Node.mn_ReplyPort->mp_SigTask;
203 /* Input arguments for calling the RexxStart procedure */
204 LONG argcount = 0;
205 RXSTRING rxargs[15], rxresult;
206 PSZ progname = NULL;
207 PRXSTRING instore = NULL;
208 USHORT rc;
210 /* Set input/output to the task that sent the message */
211 if (!(msg->rm_Action & RXFF_NOIO))
213 lock = BNULL;
214 oldlock = BNULL;
215 if (process->pr_Task.tc_Node.ln_Type == NT_PROCESS)
217 input = process->pr_CIS;
218 output = process->pr_COS;
219 error = process->pr_CES;
220 lock = DupLock(process->pr_CurrentDir);
221 if (lock != BNULL)
223 lock = CurrentDir(lock);
224 oldlock = DupLock(lock);
225 UnLock(lock);
228 if (msg->rm_Stdin != BNULL)
229 input = msg->rm_Stdin;
230 if (msg->rm_Stdout != BNULL)
231 output = msg->rm_Stdout;
233 input = SelectInput(input);
234 output = SelectOutput(output);
235 error = SelectErrorOutput(error);
236 updatestdio();
239 if ((msg->rm_Action & RXFF_STRING))
241 void *t;
243 progname = strdup("intern");
244 instore = malloc(2*sizeof(RXSTRING));
245 t = malloc(commlen);
246 memcpy(t, comm, commlen);
247 MAKERXSTRING(instore[0], t, commlen);
248 MAKERXSTRING(instore[1], NULL, 0);
250 else if (comm[0] == '\'' || comm[0] == '"')
252 char c = comm[0];
253 int i;
254 void *t;
256 for (i = 1; comm[i] != c && i < commlen; i++)
259 progname = strdup("intern");
260 instore = malloc(2*sizeof(RXSTRING));
261 t = malloc(i-1);
262 memcpy(t, comm + 1, i - 1);
263 MAKERXSTRING(instore[0], t, i-1);
264 MAKERXSTRING(instore[1], NULL, 0);
266 else
268 BOOL iscommand = ((msg->rm_Action & RXCODEMASK) == RXCOMM);
269 UBYTE *s = comm;
271 if (iscommand)
273 /* For a command the characters up to the first space is the progname */
274 while (*s != 0 && !isspace(*s)) s++;
275 len = s - comm;
277 else
279 /* For a function whole ARG0 is the progname */
280 len = LengthArgstring((UBYTE *)msg->rm_Args[0]);
283 extlen = msg->rm_FileExt==NULL ? 5 : strlen(msg->rm_FileExt);
284 progname = malloc(len + 6 + extlen);
286 memcpy(progname, (char *)msg->rm_Args[0], len);
287 progname[len] = 0;
288 lock = Lock(progname, ACCESS_READ);
289 if (lock == BNULL)
291 strcat(progname, msg->rm_FileExt==NULL ? ".rexx" : (const char *)msg->rm_FileExt);
292 lock = Lock(progname, ACCESS_READ);
294 if (lock == BNULL && strchr(progname, ':') == NULL)
296 strcpy(progname, "REXX:");
297 strncat(progname, (char *)msg->rm_Args[0], len);
298 lock = Lock(progname, ACCESS_READ);
300 if (lock == BNULL)
302 strcat(progname, msg->rm_FileExt==NULL ? ".rexx" : (const char *)msg->rm_FileExt);
303 lock = Lock(progname, ACCESS_READ);
305 if (lock == BNULL)
307 msg->rm_Result1 = 5;
308 msg->rm_Result2 = 1;
309 free(progname);
310 if (oldlock != BNULL)
311 UnLock(CurrentDir(oldlock));
312 return;
314 UnLock(lock);
316 if (iscommand)
318 while (isspace(*s))
319 s++;
321 if (!(msg->rm_Action & RXFF_TOKEN))
323 if (*s == 0)
324 argcount = 0;
325 else
327 argcount = 1;
328 len = LengthArgstring((UBYTE *)msg->rm_Args[0]) - (s - (UBYTE *)msg->rm_Args[0]);
329 MAKERXSTRING(rxargs[0], s, len);
332 else
334 UBYTE *s2;
335 while (*s != 0)
337 s2 = s;
338 while((*s2 != 0) && !isspace(*s2)) s2++;
339 MAKERXSTRING(rxargs[argcount], s, s2-s);
341 while((*s2 != 0) && isspace(*s2) ) s2++;
342 s = s2;
343 argcount++;
347 else /* is a function call */
349 int arguments = msg->rm_Action & RXARGMASK;
351 for (argcount = 0; argcount < arguments; argcount++)
353 UBYTE *argstr = (UBYTE *)msg->rm_Args[1+argcount];
354 if (argstr == NULL)
355 MAKERXSTRING(rxargs[argcount], NULL, 0);
356 else
357 MAKERXSTRING(rxargs[argcount], argstr, LengthArgstring(argstr));
362 MAKERXSTRING(rxresult, NULL, 0);
363 D(bug("[RexxMast/StartFileSlave()] Executing '%s'\n", progname));
364 RexxStart(argcount, rxargs, progname, instore, msg->rm_CommAddr, RXFUNCTION, NULL, &rc, &rxresult);
365 D(bug("[RexxMast/StartFileSlave()] Return rc=%d, rxresult='%s'\n",
366 rc, rxresult
368 /* Return to the old input/output if it was changed */
369 if (!(msg->rm_Action & RXFF_NOIO))
371 if (input != BNULL)
372 SelectInput(input);
373 if (output != BNULL)
374 SelectOutput(output);
375 if (error != BNULL)
376 SelectErrorOutput(error);
377 updatestdio();
378 if (oldlock != BNULL)
379 UnLock(CurrentDir(oldlock));
382 fflush(stdout);
383 msg->rm_Result1 = rc;
384 if (rc==0 && (msg->rm_Action & RXFF_RESULT) && RXVALIDSTRING(rxresult))
385 msg->rm_Result2 = (IPTR)CreateArgstring(RXSTRPTR(rxresult), RXSTRLEN(rxresult));
386 else
387 msg->rm_Result2 = 0;
389 if (RXSTRPTR(rxresult) != NULL)
390 free(RXSTRPTR(rxresult));
391 if (progname != NULL)
392 free(progname);
393 if (instore != NULL)
395 free(RXSTRPTR(instore[0]));
396 free(instore);
400 static void AddLib(struct RexxMsg *msg)
402 struct RexxRsrc *rsrc;
404 if (msg->rm_Args[0] == 0 || msg->rm_Args[1] == 0)
406 msg->rm_Result1 = 20;
407 msg->rm_Result2 = 0;
408 return;
411 rsrc = (struct RexxRsrc *)AllocMem(sizeof(struct RexxRsrc), MEMF_ANY | MEMF_CLEAR);
412 rsrc->rr_Size = sizeof(struct RexxRsrc);
413 rsrc->rr_Node.ln_Pri = atoi((char *)msg->rm_Args[1]);
414 rsrc->rr_Node.ln_Name = CreateArgstring((UBYTE *)msg->rm_Args[0], strlen((char *)msg->rm_Args[0]));
416 if ((msg->rm_Action & RXCODEMASK) == RXADDLIB)
418 rsrc->rr_Node.ln_Type = RRT_LIB;
419 if (msg->rm_Args[2] == 0)
421 msg->rm_Result1 = 20;
422 msg->rm_Result2 = 0;
423 FreeMem(rsrc, rsrc->rr_Size);
424 return;
426 rsrc->rr_Arg1 = (LONG)atoi((char *)msg->rm_Args[2]);
427 rsrc->rr_Arg2 = (msg->rm_Args[3] == 0) ? (LONG)0 : (LONG)atoi((char *)msg->rm_Args[3]);
429 else
430 rsrc->rr_Node.ln_Type = RRT_HOST;
432 LockRexxBase(0);
433 if (FindName(&RexxSysBase->rl_LibList, rsrc->rr_Node.ln_Name))
435 msg->rm_Result1 = 5;
436 msg->rm_Result2 = 0;
437 FreeMem(rsrc, rsrc->rr_Size);
439 else
441 Enqueue(&RexxSysBase->rl_LibList, (struct Node *)rsrc);
442 msg->rm_Result1 = 0;
443 msg->rm_Result2 = 0;
444 RexxSysBase->rl_NumLib++;
446 UnlockRexxBase(0);
449 static void RemLib(struct RexxMsg *msg)
451 struct RexxRsrc *rsrc;
453 if (msg->rm_Args[0] == 0)
455 msg->rm_Result1 = 20;
456 msg->rm_Result2 = 0;
457 return;
460 LockRexxBase(0);
461 rsrc = (struct RexxRsrc *)FindName(&RexxSysBase->rl_LibList, (STRPTR)msg->rm_Args[0]);
462 if (rsrc == NULL)
464 msg->rm_Result1 = 5;
465 msg->rm_Result2 = 0;
467 else
469 Remove((struct Node *)rsrc);
470 RexxSysBase->rl_NumLib--;
471 DeleteArgstring(rsrc->rr_Node.ln_Name);
472 FreeMem(rsrc, rsrc->rr_Size);
473 msg->rm_Result1 = 0;
474 msg->rm_Result2 = 0;
476 UnlockRexxBase(0);
479 static void AddCon(struct RexxMsg *msg)
481 struct RexxRsrc *rsrc;
483 LockRexxBase(0);
484 rsrc = (struct RexxRsrc *)FindName(&RexxSysBase->rl_ClipList, (char *)msg->rm_Args[0]);
485 if (rsrc == NULL)
487 rsrc = (struct RexxRsrc *)AllocMem(sizeof(struct RexxRsrc), MEMF_ANY | MEMF_CLEAR);
488 rsrc->rr_Node.ln_Type = RRT_CLIP;
489 rsrc->rr_Node.ln_Name = CreateArgstring((UBYTE *)msg->rm_Args[0], strlen((char *)msg->rm_Args[0]));
490 rsrc->rr_Size = sizeof(struct RexxRsrc);
491 rsrc->rr_Arg1 = (IPTR)CreateArgstring((UBYTE *)msg->rm_Args[1], (ULONG)msg->rm_Args[2]);
493 AddTail(&RexxSysBase->rl_ClipList, (struct Node *)rsrc);
495 else
497 DeleteArgstring((UBYTE *)rsrc->rr_Arg1);
498 rsrc->rr_Arg1 = (IPTR)CreateArgstring((UBYTE *)msg->rm_Args[1], (ULONG)msg->rm_Args[2]);
500 UnlockRexxBase(0);
502 msg->rm_Result1 = 0;
503 msg->rm_Result2 = 0;
504 return;
507 static void RemCon(struct RexxMsg *msg)
509 struct RexxRsrc *rsrc;
511 LockRexxBase(0);
512 rsrc = (struct RexxRsrc *)FindName(&RexxSysBase->rl_ClipList, (STRPTR)msg->rm_Args[0]);
513 if (rsrc == NULL)
515 msg->rm_Result1 = 0;
517 else
519 Remove(&rsrc->rr_Node);
520 DeleteArgstring(rsrc->rr_Node.ln_Name);
521 DeleteArgstring((UBYTE *)rsrc->rr_Arg1);
522 FreeMem(rsrc, rsrc->rr_Size);
524 msg->rm_Result1 = 0;
526 UnlockRexxBase(0);
528 msg->rm_Result2 = 0;
529 return;