|
|
1.1 root 1: /*
2: * UAE - The Un*x Amiga Emulator
3: *
4: * ami-rexx.c
5: *
6: * Copyright 1996 Samuel Devulder.
7: *
8: * History:
9: * 05/09/97: Added UAEEXE support.
10: */
11:
12: #include <proto/exec.h>
13: #include <proto/rexxsyslib.h>
14: #include <proto/dos.h>
15: #ifndef __SASC
16: #include <proto/alib.h>
17: #endif
18:
19: #include <rexx/storage.h>
20: #include <rexx/errors.h>
21:
22: /* this prevent a conflict between <rexx/rexxio.h> and <sys/dirent.h> */
23: #undef DT_DIR
24:
25: /****************************************************************************/
26:
27: #include "sysconfig.h"
28: #include "sysdeps.h"
29:
30: #include "uae.h"
31: #include "config.h"
32: #include "options.h"
33: #ifdef __GNUC__
34: #include "../include/memory.h" /* or else gcc includes machdep/memory.h */
35: #endif
36: #include "custom.h"
37: #include "readcpu.h"
38: #include "newcpu.h"
39: #include "disk.h"
40: #include "gui.h"
41: #include "sound.h"
42: #include "gensound.h"
43: #include "uaeexe.h"
44: #include "threaddep/penguin.h"
45: #include "xwin.h"
46:
47: #include <ctype.h>
48:
49: /****************************************************************************/
50:
51: #define UAE_PORTNAME "UAE"
52: #define RESULT_LEN 1024
53: #define PORT_LEN 80
54: #define CMD_LEN 1024
55:
56: typedef struct
57: {
58: char port[PORT_LEN];
59: char cmd_on[CMD_LEN];
60: char cmd_off[CMD_LEN];
61: } gui_rexx_s;
62:
63: enum {LED_POW, LED_DF0, LED_DF1, LED_DF2, LED_DF3,
64: NAME_DF0, NAME_DF1, NAME_DF2, NAME_DF3,
65: ON_EXIT,
66: GUI_REXX_MAX};
67:
68: /****************************************************************************/
69:
70: int rexx_init(void);
71: void rexx_exit(void);
72: void rexx_led(int led, int on);
73: void rexx_filename(int num, char *name);
74: void rexx_handle_events(void);
75:
76: /****************************************************************************/
77:
78: #ifdef __GNUC__
79: struct RxsLib
80: #else
81: struct Library
82: #endif
83: *RexxSysBase;
84: static struct MsgPort *ARexxPort;
85: static gui_rexx_s gui_rexx[GUI_REXX_MAX];
86: static char RESULT[RESULT_LEN];
87: static int led_state[5];
88:
89: static int ADDRESS(char *hostname, char *cmd);
90: static int matchstr(char **line,char *pat);
91: static void extractstr(char **line, char *result, int len);
92: static int matchnum(char **line);
93:
94: /****************************************************************************/
95:
96: extern int quit_program; /* ami-gui.c */
97: extern void activate_debugger(void); /* debug.c */
98: extern char *to_unix_path(char *s); /* ami-disk.c */
99: extern char *from_unix_path(char *s); /* ami-disk.c */
100:
101: /****************************************************************************/
102:
103: int rexx_init(void)
104: {
105: quit_program = 0;
106: RexxSysBase = (void*)OpenLibrary("rexxsyslib.library",0L);
107: if(!RexxSysBase) {
108: fprintf(stderr, "Can't find rexxsyslib.library!\n");
109: return 1;
110: }
111: if(FindPort(UAE_PORTNAME)) {
112: fprintf(stderr, "Port \"%s\" already exists!\n",UAE_PORTNAME);
113: return 1;
114: }
115: ARexxPort = CreatePort(UAE_PORTNAME,0);
116: if(!ARexxPort) {
117: fprintf(stderr, "Failed to open AREXX port \"%s\"!\n",UAE_PORTNAME);
118: return 1;
119: }
120: fprintf(stderr,"Rexx port \"%s\" installed.\n", UAE_PORTNAME);
121: rexx_handle_events();
122: return 0;
123: }
124:
125: /****************************************************************************/
126:
127: void rexx_exit(void)
128: {
129: if(ARexxPort) {
130: struct RexxMsg *msg;
131: gui_rexx_s *gui = &gui_rexx[ON_EXIT];
132:
133: if(gui->port[0] && gui->cmd_on[0]) {
134: if(ADDRESS(gui->port, gui->cmd_on) != RC_OK) {
135: fprintf(stderr,"%s:%s:%s\n", gui->port,
136: gui->cmd_on,
137: RESULT);
138: }
139: gui->port[0] = '\0';
140: }
141: Forbid();
142: while((msg = (struct RexxMsg*)GetMsg(ARexxPort))) {
143: msg->rm_Result1 = RC_ERROR;
144: msg->rm_Result2 = NULL;
145: ReplyMsg((void*)msg);
146: }
147: DeletePort(ARexxPort);
148: Permit();
149: ARexxPort = NULL;
150: }
151: if(RexxSysBase) {
152: CloseLibrary((void*)RexxSysBase);
153: RexxSysBase = NULL;
154: }
155: }
156:
157: /****************************************************************************/
158:
159: static int EJECT(char *line)
160: {
161: int drive = matchnum(&line);
162: if(drive<0 || drive>3) return RC_WARN;
163: disk_eject(drive);
164: sprintf(RESULT,"Drive %d ejected",drive);
165: return RC_OK;
166: }
167:
168: /****************************************************************************/
169:
170: static int INSERT(char *line)
171: {
172: int drive = matchnum(&line);
173: if(drive<0 || drive>3) return RC_WARN;
174: if(disk_empty(drive)) {
175: char buff[256];
176: char *name;
177: extractstr(&line, buff, 256);
178: name = to_unix_path(buff);
179: disk_insert(drive, name);
180: free(name);
181: } else {
182: sprintf(RESULT,"Drive %d not empty!",drive);
183: return RC_WARN;
184: }
185: return RC_OK;
186: }
187:
188: /****************************************************************************/
189:
190: static void QUIT(void)
191: {
192: broken_in = 1;
193: regs.spcflags |= SPCFLAG_BRK;
194: quit_program = 1;
195: }
196:
197: /****************************************************************************/
198:
199: static int QUERY(char *line)
200: {
201: char *res = NULL;
202: int alc = 0;
203:
204: if (matchstr(&line, "LED_POW")) res = led_state[0]?"1":"0";
205: else if(matchstr(&line, "LED_DF0")) res = led_state[1]?"1":"0";
206: else if(matchstr(&line, "LED_DF1")) res = led_state[2]?"1":"0";
207: else if(matchstr(&line, "LED_DF2")) res = led_state[3]?"1":"0";
208: else if(matchstr(&line, "LED_DF3")) res = led_state[4]?"1":"0";
209: else if(matchstr(&line, "NAME_DF0")) res = from_unix_path(currprefs.df[0]), alc = 1;
210: else if(matchstr(&line, "NAME_DF1")) res = from_unix_path(currprefs.df[1]), alc = 1;
211: else if(matchstr(&line, "NAME_DF2")) res = from_unix_path(currprefs.df[2]), alc = 1;
212: else if(matchstr(&line, "NAME_DF3")) res = from_unix_path(currprefs.df[3]), alc = 1;
213: else if(matchstr(&line, "FAKEJOYSTICK")) res = currprefs.fake_joystick?"1":"0";
214: else if(matchstr(&line, "DISPLAY")) res = inhibit_frame?"0":"1";
215: else if(matchstr(&line, "FRAMERATE")) {
216: sprintf(RESULT,"%d",currprefs.framerate);
217: return RC_OK;
218: } else if(matchstr(&line, "SOUND")) {
219: sprintf(RESULT,"%d",sound_available?currprefs.produce_sound:-1);
220: return RC_OK;
221: }
222: else return RC_ERROR;
223:
224: if(res) {
225: strncpy(RESULT, res, RESULT_LEN);
226: if(alc) free(res);
227: }
228: return RC_OK;
229: }
230:
231: /****************************************************************************/
232:
233: static int FEEDBACK(char *line)
234: {
235: gui_rexx_s *gui = NULL;
236:
237: if (matchstr(&line,"LED_POW")) gui = &gui_rexx[LED_POW];
238: else if(matchstr(&line,"LED_DF0")) gui = &gui_rexx[LED_DF0];
239: else if(matchstr(&line,"LED_DF1")) gui = &gui_rexx[LED_DF1];
240: else if(matchstr(&line,"LED_DF2")) gui = &gui_rexx[LED_DF2];
241: else if(matchstr(&line,"LED_DF3")) gui = &gui_rexx[LED_DF3];
242: else if(matchstr(&line,"NAME_DF0")) gui = &gui_rexx[NAME_DF0];
243: else if(matchstr(&line,"NAME_DF1")) gui = &gui_rexx[NAME_DF1];
244: else if(matchstr(&line,"NAME_DF2")) gui = &gui_rexx[NAME_DF2];
245: else if(matchstr(&line,"NAME_DF3")) gui = &gui_rexx[NAME_DF3];
246: else if(matchstr(&line,"ON_EXIT")) gui = &gui_rexx[ON_EXIT];
247: else return RC_ERROR;
248:
249: while(1) {
250: if(matchstr(&line, "ADDRESS") ||
251: matchstr(&line, "PORT")) {
252: extractstr(&line, gui->port, PORT_LEN);
253: } else if(matchstr(&line,"COMMAND") ||
254: matchstr(&line,"CMD") ||
255: matchstr(&line,"CMD_ON")) {
256: extractstr(&line, gui->cmd_on, CMD_LEN);
257: } else if(matchstr(&line,"CMD_OFF")) {
258: extractstr(&line, gui->cmd_off, CMD_LEN);
259: } else break;
260: }
261: return RC_OK;
262: }
263:
264: /****************************************************************************/
265:
266: static int VERSION(char *line)
267: {
268: if(matchstr(&line,"STRING")) {
269: sprintf(RESULT,
270: "UAE-%d.%d.%d � by Bernd Schmidt & contributors, "
271: "Amiga Port by Samuel Devulder.",
272: (version / 100) % 10, (version / 10) % 10, version % 10);
273: } else if(matchstr(&line,"NUM")) {
274: sprintf(RESULT,"%d",version);
275: } else if(matchstr(&line,"AUTHOR")) {
276: sprintf(RESULT,"� by Bernd Schmidt & contributors");
277: } else if(matchstr(&line,"PORT")) {
278: sprintf(RESULT,"Amiga Port by Samuel Devulder");
279: } else return RC_ERROR;
280: return RC_OK;
281: }
282:
283: /****************************************************************************/
284:
285: static int FRAMERATE(char *line)
286: {
287: int num;
288: num = matchnum(&line);
289: if(num>=1 && num<=20) {
290: currprefs.framerate = num;
291: } else {
292: sprintf(RESULT,"Invalid frame rate: %d\n", num);
293: return RC_WARN;
294: }
295: return RC_OK;
296: }
297:
298: /****************************************************************************/
299:
300: static int FAKEJOYSTICK(char *line)
301: {
302: if (matchstr(&line,"ON")) currprefs.fake_joystick = 2;
303: else if(matchstr(&line,"OFF")) currprefs.fake_joystick = 0;
304: else if(matchstr(&line,"TOGGLE")) currprefs.fake_joystick =
305: currprefs.fake_joystick?0:2;
306: else return RC_ERROR;
307: return RC_OK;
308: }
309:
310: /****************************************************************************/
311:
312: static int DISPLAY(char *line)
313: {
314: if (matchstr(&line,"ON")) inhibit_frame = 0;
315: else if(matchstr(&line,"OFF")) inhibit_frame = 1;
316: else if(matchstr(&line,"TOGGLE")) inhibit_frame = inhibit_frame?0:1;
317: else return RC_ERROR;
318: return RC_OK;
319: }
320:
321: /****************************************************************************/
322:
323: static int SOUND(char *line)
324: {
325: if(!sound_available) {
326: sprintf(RESULT,"Sound not available!");
327: return RC_WARN;
328: }
329:
330: if (matchstr(&line,"ON")) currprefs.produce_sound = 2;
331: else if(matchstr(&line,"OFF")) currprefs.produce_sound = 1;
332: else if(matchstr(&line,"BEST")) currprefs.produce_sound = 3;
333: else if(matchstr(&line,"TOGGLE")) currprefs.produce_sound =
334: currprefs.produce_sound<=1?2:1;
335: else return RC_ERROR;
336: return RC_OK;
337: }
338:
339: /****************************************************************************/
340:
341: static int UAEEXE(char *line)
342: {
343: if(uaeexe(line)) {
344: sprintf(RESULT,"Remote CLI failed!");
345: return RC_WARN;
346: }
347: return RC_OK;
348: }
349:
350: /****************************************************************************/
351:
352: static int process_cmd(char *line)
353: {
354: RESULT[0] = '\0';
355: if (matchstr(&line, "EJECT")) return EJECT(line);
356: else if(matchstr(&line, "INSERT")) return INSERT(line);
357: else if(matchstr(&line, "QUERY")) return QUERY(line);
358: else if(matchstr(&line, "FEEDBACK")) return FEEDBACK(line);
359: else if(matchstr(&line, "VERSION")) return VERSION(line);
360: else if(matchstr(&line, "BYE")) QUIT();
361: else if(matchstr(&line, "QUIT")) QUIT();
362: else if(matchstr(&line, "DEBUG")) activate_debugger();
363: else if(matchstr(&line, "RESET")) m68k_reset();
364: else if(matchstr(&line, "DISPLAY")) return DISPLAY(line);
365: else if(matchstr(&line, "FRAMERATE")) return FRAMERATE(line);
366: else if(matchstr(&line, "FAKEJOYSTICK")) return FAKEJOYSTICK(line);
367: else if(matchstr(&line, "SOUND")) return SOUND(line);
368: else if(matchstr(&line, "UAEEXE")) return UAEEXE(line);
369: else return RC_ERROR;
370: return RC_OK;
371: }
372:
373: /****************************************************************************/
374:
375: void rexx_handle_events(void)
376: {
377: struct RexxMsg *msg;
378: while((msg = (struct RexxMsg*)GetMsg(ARexxPort))) {
379: if(!(msg->rm_Action & RXCOMM)) {
380: fprintf(stderr,"Unknown action '%08X' recieved!\n",
381: msg->rm_Action);
382: continue;
383: }
384: msg->rm_Result1 = process_cmd(msg->rm_Args[0]);
385: msg->rm_Result2 = NULL;
386: if(msg->rm_Action & RXFF_RESULT) {
387: msg->rm_Result2 = (LONG)CreateArgstring(RESULT,strlen(RESULT));
388: }
389: ReplyMsg((void*)msg);
390: }
391: }
392:
393: /****************************************************************************/
394:
395: void rexx_led(int led, int on)
396: {
397: gui_rexx_s *gui = NULL;
398:
399: if(led < 0 || led > 4) return;
400: led_state[led] = on;
401:
402: if(led == 0) gui = &gui_rexx[LED_POW];
403: if(led == 1) gui = &gui_rexx[LED_DF0];
404: if(led == 2) gui = &gui_rexx[LED_DF1];
405: if(led == 3) gui = &gui_rexx[LED_DF2];
406: if(led == 4) gui = &gui_rexx[LED_DF3];
407:
408: if(gui->port[0] && gui->cmd_on[0] && gui->cmd_off[0]) {
409: if(ADDRESS(gui->port, on ? gui->cmd_on : gui->cmd_off) != RC_OK) {
410: fprintf(stderr,"%s:%s:%s\n", gui->port,
411: on ? gui->cmd_on : gui->cmd_off,
412: RESULT);
413: }
414: }
415: }
416:
417: /****************************************************************************/
418:
419: void rexx_filename(int num, char *filename)
420: {
421: gui_rexx_s *gui = NULL;
422: if(num < 0 || num > 3) return;
423: gui = &gui_rexx[NAME_DF0 + num];
424: if(gui->port[0] && gui->cmd_on[0]) {
425: char buf[CMD_LEN];
426: if(!(filename = from_unix_path(filename))) return;
427: sprintf(buf, gui->cmd_on, filename);
428: free(filename);
429: if(ADDRESS(gui->port, buf) != RC_OK) {
430: fprintf(stderr,"%s:%s:%s\n", gui->port, buf, RESULT);
431: }
432: }
433: }
434:
435: /****************************************************************************/
436: /* send a message to an AREXX port.
437: */
438: static int ADDRESS(char *hostname, char *cmd)
439: {
440: struct MsgPort *RexxPort,
441: *ReplyPort;
442: struct RexxMsg *HostMsg,
443: *answer;
444: int result = RC_WARN;
445:
446: if(!stricmp(hostname, "COMMAND")) {
447: return SystemTagList(cmd,NULL);
448: }
449:
450: if((RexxPort = (void *)FindPort(hostname))) {
451: if((ReplyPort = (void *)CreateMsgPort())) {
452: if((HostMsg = CreateRexxMsg(ReplyPort, NULL, hostname))) {
453: if((HostMsg->rm_Args[0] = CreateArgstring(cmd,strlen(cmd)))) {
454: HostMsg->rm_Action = RXCOMM | RXFF_RESULT;
455: PutMsg(RexxPort, (void*)HostMsg);
456: WaitPort(ReplyPort);
457: while(!(answer = (void *)GetMsg(ReplyPort)));
458: result = answer->rm_Result1;
459: if(result == RC_OK) {
460: if(answer->rm_Result2) {
461: strncpy(RESULT,(char *)answer->rm_Result2,RESULT_LEN);
462: DeleteArgstring((char *)answer->rm_Result2);
463: } else RESULT[0] = '\0';
464: }
465: DeleteArgstring(HostMsg->rm_Args[0]);
466: } else strcpy(RESULT, "Can't create argstring!");
467: DeleteRexxMsg(HostMsg);
468: } else strcpy(RESULT, "Can't create rexx message!");
469: DeleteMsgPort(ReplyPort);
470: } else strcpy(RESULT, "Can't alloc reply port!");
471: } else sprintf(RESULT, "Port \"%s\" not found!",hostname);
472: return result;
473: }
474:
475: /****************************************************************************/
476: /* argument parsing routines
477: */
478: static int matchstr(char **line,char *pat)
479: {
480: char *s = *line;
481: char match = 0;
482: while(isspace(*s)) ++s;
483: if(*s=='\"' || *s== '\'') match = *s++;
484: while(*s && (tolower(*s)==tolower(*pat)) && (!match || *s!=match)) {++s;++pat;}
485: if(match && *s==match && s[1]) ++s;
486: if(!*pat && (!*s || isspace(*s))) {
487: while(isspace(*s)) ++s;
488: *line = s;
489: return 1;
490: }
491: return 0;
492: }
493:
494: /****************************************************************************/
495:
496: static void extractstr(char **line, char *result, int len)
497: {
498: char *s = *line;
499: char match = 0;
500:
501: while(isspace(*s)) ++s;
502:
503: if(*s=='\"' || *s=='\'') match = *s++;
504: while(*s && *s != match) {
505: if(*s == '\\' && (s[1] == '\'' || s[1] == '\"')) ++s;
506: if(len > 1) {*result++ = *s;--len;}
507: ++s;
508: if(!match && isspace(*s)) break;
509: }
510: if(match && *s == match) ++s;
511: while(isspace(*s)) ++s;
512:
513: *result = '\0';
514: *line = s;
515: }
516:
517: /****************************************************************************/
518:
519: static int matchnum(char **line)
520: {
521: char *s = *line, match = 0;
522: int sign = 1, num = 0;
523:
524: while(isspace(*s)) ++s;
525: if(*s=='\"' || *s=='\'') match = *s++;
526: if(*s=='-') {sign = -1;++s;}
527: if(*s=='+') ++s;
528: while(isspace(*s)) ++s;
529: while(*s>='0' && *s<='9') num = num*10 + (*s++ - '0');
530: if(match && *s==match && s[1]) ++s;
531: while(isspace(*s)) ++s;
532: *line = s;
533: return sign>0?num:-num;
534: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.