commit 6615d46

zzo38  ·  2023-05-18 20:38:50 +0000 UTC
parent c438658
Add -e switch to execute and connect this uxn instance to another program.
2 files changed,  +42, -6
M main.c
+5, -0
 1@@ -48,6 +48,11 @@
 2 -d
 3   Enable some debugging features. (Some will work even without this.)
 4 
 5+-e #
 6+  Execute another program (with "sh -c"), which will be connected to this
 7+  one using the standard I/O. For example, it can be used with nc to make
 8+  remote two players.
 9+
10 -h #
11   Set default screen height.
12 
M main.c
+37, -6
  1@@ -196,6 +196,8 @@ static Uint8*bglayer;
  2 static Uint8*fglayer;
  3 static UxnFile uxnfile0;
  4 static UxnFile uxnfile1;
  5+static FILE*inf;
  6+static FILE*outf;
  7 
  8 static const char*rom_name;
  9 static Uint8 use_console=1;
 10@@ -260,7 +262,7 @@ static void debug(int i) {
 11 
 12 static void uxnerr(int n,int pc) {
 13   if(use_debug) debug(-1);
 14-  fflush(stdout);
 15+  fflush(outf);
 16   fflush(stderr);
 17   errx(2,"Uxn error %d at 0x%04X",n,pc);
 18 }
 19@@ -353,7 +355,7 @@ static void run(Uint16 pc) {
 20     paused=debugger=picture_changed=1;
 21     break_pc=pc-1;
 22   }
 23-  fflush(stdout);
 24+  fflush(outf);
 25   return;
 26   error:
 27   uxnerr(v,pc);
 28@@ -404,7 +406,7 @@ static void system_out(Device*dev,Uint8 id) {
 29 
 30 static void console_out(Device*dev,Uint8 id) {
 31   switch(id) {
 32-    case 8: putchar(dev->d[8]); break;
 33+    case 8: fputc(dev->d[8],outf); break;
 34     case 9: fputc(dev->d[9],stderr); break;
 35   }
 36 }
 37@@ -1352,7 +1354,7 @@ static int stdin_thread_fn(void*unused) {
 38   int c;
 39   SDL_Event e;
 40   e.type=SDL_USEREVENT+1;
 41-  while((c=getchar())>=0) {
 42+  while((c=fgetc(inf))>=0) {
 43     e.user.code=c;
 44     SDL_PushEvent(&e);
 45   }
 46@@ -1459,6 +1461,33 @@ static void set_joystick(char*s) {
 47   }
 48 }
 49 
 50+static void set_other_program(const char*s) {
 51+  int pf[4];
 52+  pid_t pi;
 53+  if(pipe(pf) || pipe(pf+2)) err(1,"Pipe failed");
 54+  pi=fork();
 55+  if(pi==(pid_t)(-1)) err(1,"Fork failed");
 56+  if(pi) {
 57+    // Parent
 58+    close(pf[1]);
 59+    close(pf[2]);
 60+    inf=fdopen(pf[0],"r");
 61+    if(!inf) err(1,"Cannot open pipe for input");
 62+    outf=fdopen(pf[3],"w");
 63+    if(!outf) err(1,"Cannot open pipe for output");
 64+  } else {
 65+    // Child
 66+    close(pf[0]);
 67+    close(pf[3]);
 68+    if(dup2(pf[1],1)<0 || dup2(pf[2],0)<0) err(1,"Cannot duplicate file descriptors");
 69+    close(pf[1]);
 70+    close(pf[2]);
 71+    execl("/bin/sh","/bin/sh","-c",s,(char*)0);
 72+    fprintf(stderr,"Cannot exec\n");
 73+    _exit(1);
 74+  }
 75+}
 76+
 77 int main(int argc,char**argv) {
 78   int i,j;
 79   for(i=0;i<16;i++) {
 80@@ -1471,7 +1500,8 @@ int main(int argc,char**argv) {
 81   device[10].aux=&uxnfile0;
 82   device[11].aux=&uxnfile1;
 83   device[12].in=datetime_in;
 84-  while((i=getopt(argc,argv,"+ADFIJ:NOQST:YZa:dh:ijnp:qs:t:w:xyz:"))>0) switch(i) {
 85+  inf=stdin; outf=stdout;
 86+  while((i=getopt(argc,argv,"+ADFIJ:NOQST:YZa:de:h:ijnp:qs:t:w:xyz:"))>0) switch(i) {
 87     case 'D': scrflags|=SDL_DOUBLEBUF; break;
 88     case 'F': scrflags|=SDL_FULLSCREEN; break;
 89     case 'I': use_thread=1; break;
 90@@ -1485,6 +1515,7 @@ int main(int argc,char**argv) {
 91     case 'Z': use_utc=1; break;
 92     case 'a': set_audio(optarg); break;
 93     case 'd': use_debug=1; break;
 94+    case 'e': set_other_program(optarg); break;
 95     case 'h': default_height=strtol(optarg,0,10); break;
 96     case 'i': hide_cursor=1; break;
 97     case 'j': joypad_repeat=1; break;
 98@@ -1552,7 +1583,7 @@ int main(int argc,char**argv) {
 99     run_audio();
100   } else {
101     device[1].d[7]=1;
102-    while((device[1].d[0] || device[1].d[1]) && ((i=getchar())>=0)) {
103+    while((device[1].d[0] || device[1].d[1]) && ((i=fgetc(inf))>=0)) {
104       device[1].d[2]=i;
105       run(GET16(device[1].d));
106     }