Rejoice! Windows now uses a safer popen() which returns 0 on program launch fail, and allows you to see stdout on initial usages.
This commit is contained in:
@@ -275,7 +275,7 @@ ${WINDIR}/sdllink.o: ${WINDIR}/sdllink.c asm_call.h gblhdr.h ${WINDIR}/sw_draw.h
|
|||||||
${WINDIR}/gl_draw.h ${WINDIR}/safelib.h
|
${WINDIR}/gl_draw.h ${WINDIR}/safelib.h
|
||||||
${WINDIR}/sw_draw.o: ${WINDIR}/sw_draw.c gblhdr.h
|
${WINDIR}/sw_draw.o: ${WINDIR}/sw_draw.c gblhdr.h
|
||||||
${WINDIR}/zfilew.o: ${WINDIR}/zfilew.c
|
${WINDIR}/zfilew.o: ${WINDIR}/zfilew.c
|
||||||
${WINDIR}/safelib.o: ${WINDIR}/safelib.c ${WINDIR}/safelib.h
|
${WINDIR}/safelib.o: ${WINDIR}/safelib.c ${WINDIR}/safelib.h argv.h
|
||||||
|
|
||||||
${ZIPDIR}/unzip.o: ${ZIPDIR}/unzip.c gblhdr.h ${ZIPDIR}/zunzip.h
|
${ZIPDIR}/unzip.o: ${ZIPDIR}/unzip.c gblhdr.h ${ZIPDIR}/zunzip.h
|
||||||
${ZIPDIR}/zpng.o: ${ZIPDIR}/zpng.c gblhdr.h ${ZIPDIR}/zpng.h
|
${ZIPDIR}/zpng.o: ${ZIPDIR}/zpng.c gblhdr.h ${ZIPDIR}/zpng.h
|
||||||
|
|||||||
152
zsnes/src/argv.h
Normal file
152
zsnes/src/argv.h
Normal file
@@ -0,0 +1,152 @@
|
|||||||
|
#ifndef ARGV_H
|
||||||
|
#define ARGV_H
|
||||||
|
|
||||||
|
static char *decode_string(char *str)
|
||||||
|
{
|
||||||
|
size_t str_len = strlen(str), i = 0;
|
||||||
|
char *dest = str;
|
||||||
|
|
||||||
|
if ((str_len > 1) && ((*str == '\"') || (*str == '\'')) && (str[str_len-1] == *str))
|
||||||
|
{
|
||||||
|
memmove(str, str+1, str_len-2);
|
||||||
|
str[str_len-2] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (*str)
|
||||||
|
{
|
||||||
|
if (*str == '\\')
|
||||||
|
{
|
||||||
|
str++;
|
||||||
|
}
|
||||||
|
dest[i++] = *str++;
|
||||||
|
}
|
||||||
|
dest[i] = 0;
|
||||||
|
return(dest);
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *find_next_match(char *str, char match_char)
|
||||||
|
{
|
||||||
|
char *pos = 0;
|
||||||
|
|
||||||
|
while (*str)
|
||||||
|
{
|
||||||
|
if (*str == match_char)
|
||||||
|
{
|
||||||
|
pos = str;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (*str == '\\')
|
||||||
|
{
|
||||||
|
if (str[1])
|
||||||
|
{
|
||||||
|
str++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
str++;
|
||||||
|
}
|
||||||
|
return(pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *get_param(char *str)
|
||||||
|
{
|
||||||
|
static char *pos = 0;
|
||||||
|
char *token = 0;
|
||||||
|
|
||||||
|
if (str) //Start a new string?
|
||||||
|
{
|
||||||
|
pos = str;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pos)
|
||||||
|
{
|
||||||
|
//Skip delimiters
|
||||||
|
while (*pos == ' ') { pos++; }
|
||||||
|
if (*pos)
|
||||||
|
{
|
||||||
|
token = pos;
|
||||||
|
|
||||||
|
//Skip non-delimiters
|
||||||
|
while (*pos && (*pos != ' '))
|
||||||
|
{
|
||||||
|
//Skip quoted characters
|
||||||
|
if ((*pos == '\"') || (*pos == '\''))
|
||||||
|
{
|
||||||
|
char *match_pos = 0;
|
||||||
|
if ((match_pos = find_next_match(pos+1, *pos)))
|
||||||
|
{
|
||||||
|
pos = match_pos;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//Skip escaped spaces
|
||||||
|
if (*pos == '\\') { pos++; }
|
||||||
|
pos++;
|
||||||
|
}
|
||||||
|
if (*pos) { *pos++ = '\0'; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return(token);
|
||||||
|
}
|
||||||
|
|
||||||
|
static size_t count_param(char *str)
|
||||||
|
{
|
||||||
|
size_t i = 0;
|
||||||
|
|
||||||
|
while (*str)
|
||||||
|
{
|
||||||
|
//Skip delimiters
|
||||||
|
while (*str == ' ') { str++; }
|
||||||
|
//Skip non-delimiters
|
||||||
|
while (*str && (*str != ' '))
|
||||||
|
{
|
||||||
|
//Skip quoted characters
|
||||||
|
if ((*str == '\"') || (*str == '\''))
|
||||||
|
{
|
||||||
|
char *match_str = 0;
|
||||||
|
if ((match_str = find_next_match(str+1, *str)))
|
||||||
|
{
|
||||||
|
str = match_str;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//Skip escaped spaces
|
||||||
|
if (*str == '\\') { str++; }
|
||||||
|
str++;
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
return(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
static char **build_argv(char *str)
|
||||||
|
{
|
||||||
|
size_t argc = count_param(str);
|
||||||
|
char **argv = (char **)malloc(sizeof(char *)*(argc+1));
|
||||||
|
|
||||||
|
if (argv)
|
||||||
|
{
|
||||||
|
char *p, **argp = argv;
|
||||||
|
for (p = get_param(str); p; p = get_param(0), argp++)
|
||||||
|
{
|
||||||
|
*argp = decode_string(p);
|
||||||
|
}
|
||||||
|
*argp = 0;
|
||||||
|
return(argv);
|
||||||
|
}
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void argv_print(char **argv)
|
||||||
|
{
|
||||||
|
char **argp = argv;
|
||||||
|
while (*argp)
|
||||||
|
{
|
||||||
|
printf("argv[%u]: %s\n", argp-argv, *argp);
|
||||||
|
argp++;
|
||||||
|
}
|
||||||
|
printf("argv[%u]: NULL\n", argp-argv);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -34,6 +34,8 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|||||||
|
|
||||||
#include "safelib.h"
|
#include "safelib.h"
|
||||||
|
|
||||||
|
#include "../argv.h"
|
||||||
|
|
||||||
//C++ style code in C
|
//C++ style code in C
|
||||||
#define bool unsigned char
|
#define bool unsigned char
|
||||||
#define true 1
|
#define true 1
|
||||||
@@ -179,154 +181,6 @@ pid_t safe_fork(int *a, size_t size)
|
|||||||
|
|
||||||
//Introducing a popen which doesn't return until it knows for sure of program launched or couldn't open -Nach
|
//Introducing a popen which doesn't return until it knows for sure of program launched or couldn't open -Nach
|
||||||
|
|
||||||
static char *decode_string(char *str)
|
|
||||||
{
|
|
||||||
size_t str_len = strlen(str), i = 0;
|
|
||||||
char *dest = str;
|
|
||||||
|
|
||||||
if ((str_len > 1) && ((*str == '\"') || (*str == '\'')) && (str[str_len-1] == *str))
|
|
||||||
{
|
|
||||||
memmove(str, str+1, str_len-2);
|
|
||||||
str[str_len-2] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (*str)
|
|
||||||
{
|
|
||||||
if (*str == '\\')
|
|
||||||
{
|
|
||||||
str++;
|
|
||||||
}
|
|
||||||
dest[i++] = *str++;
|
|
||||||
}
|
|
||||||
dest[i] = 0;
|
|
||||||
return(dest);
|
|
||||||
}
|
|
||||||
|
|
||||||
static char *find_next_match(char *str, char match_char)
|
|
||||||
{
|
|
||||||
char *pos = 0;
|
|
||||||
|
|
||||||
while (*str)
|
|
||||||
{
|
|
||||||
if (*str == match_char)
|
|
||||||
{
|
|
||||||
pos = str;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (*str == '\\')
|
|
||||||
{
|
|
||||||
if (str[1])
|
|
||||||
{
|
|
||||||
str++;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
str++;
|
|
||||||
}
|
|
||||||
return(pos);
|
|
||||||
}
|
|
||||||
|
|
||||||
static char *get_param(char *str)
|
|
||||||
{
|
|
||||||
static char *pos = 0;
|
|
||||||
char *token = 0;
|
|
||||||
|
|
||||||
if (str) //Start a new string?
|
|
||||||
{
|
|
||||||
pos = str;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pos)
|
|
||||||
{
|
|
||||||
//Skip delimiters
|
|
||||||
while (*pos == ' ') { pos++; }
|
|
||||||
if (*pos)
|
|
||||||
{
|
|
||||||
token = pos;
|
|
||||||
|
|
||||||
//Skip non-delimiters
|
|
||||||
while (*pos && (*pos != ' '))
|
|
||||||
{
|
|
||||||
//Skip quoted characters
|
|
||||||
if ((*pos == '\"') || (*pos == '\''))
|
|
||||||
{
|
|
||||||
char *match_pos = 0;
|
|
||||||
if ((match_pos = find_next_match(pos+1, *pos)))
|
|
||||||
{
|
|
||||||
pos = match_pos;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//Skip escaped spaces
|
|
||||||
if (*pos == '\\') { pos++; }
|
|
||||||
pos++;
|
|
||||||
}
|
|
||||||
if (*pos) { *pos++ = '\0'; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return(token);
|
|
||||||
}
|
|
||||||
|
|
||||||
static size_t count_param(char *str)
|
|
||||||
{
|
|
||||||
size_t i = 0;
|
|
||||||
|
|
||||||
while (*str)
|
|
||||||
{
|
|
||||||
//Skip delimiters
|
|
||||||
while (*str == ' ') { str++; }
|
|
||||||
//Skip non-delimiters
|
|
||||||
while (*str && (*str != ' '))
|
|
||||||
{
|
|
||||||
//Skip quoted characters
|
|
||||||
if ((*str == '\"') || (*str == '\''))
|
|
||||||
{
|
|
||||||
char *match_str = 0;
|
|
||||||
if ((match_str = find_next_match(str+1, *str)))
|
|
||||||
{
|
|
||||||
str = match_str;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//Skip escaped spaces
|
|
||||||
if (*str == '\\') { str++; }
|
|
||||||
str++;
|
|
||||||
}
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
return(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
static char **build_argv(char *str)
|
|
||||||
{
|
|
||||||
size_t argc = count_param(str);
|
|
||||||
char **argv = (char **)malloc(sizeof(char *)*(argc+1));
|
|
||||||
|
|
||||||
if (argv)
|
|
||||||
{
|
|
||||||
char *p, **argp = argv;
|
|
||||||
for (p = get_param(str); p; p = get_param(0), argp++)
|
|
||||||
{
|
|
||||||
*argp = decode_string(p);
|
|
||||||
}
|
|
||||||
*argp = 0;
|
|
||||||
return(argv);
|
|
||||||
}
|
|
||||||
return(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void argv_print(char **argv)
|
|
||||||
{
|
|
||||||
char **argp = argv;
|
|
||||||
while (*argp)
|
|
||||||
{
|
|
||||||
printf("argv[%u]: %s\n", argp-argv, *argp);
|
|
||||||
argp++;
|
|
||||||
}
|
|
||||||
printf("argv[%u]: NULL\n", argp-argv);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//Forks, parent is paused until child successfully execs (returns child pid) or child exits (returns failure)
|
//Forks, parent is paused until child successfully execs (returns child pid) or child exits (returns failure)
|
||||||
static pid_t parent_pause_fork()
|
static pid_t parent_pause_fork()
|
||||||
|
|||||||
@@ -172,7 +172,7 @@ JMAOBJ=${JMADIR}/7zlzma${OE} ${JMADIR}/crc32${OE} ${JMADIR}/iiostrm${OE}\
|
|||||||
${JMADIR}/winout${OE} ${JMADIR}/zsnesjma${OE}
|
${JMADIR}/winout${OE} ${JMADIR}/zsnesjma${OE}
|
||||||
|
|
||||||
MAINOBJ=cfgload${OE} endmem${OE} init${OE} initc${OE} uic${OE} patch${OE}\
|
MAINOBJ=cfgload${OE} endmem${OE} init${OE} initc${OE} uic${OE} patch${OE}\
|
||||||
ui${OE} vcache${OE} version${OE} zmovie${OE} zstate${OE} zloader${OE} \
|
ui${OE} vcache${OE} version${OE} zmovie${OE} zstate${OE} zloader${OE}\
|
||||||
cfg${OE} md${OE}
|
cfg${OE} md${OE}
|
||||||
|
|
||||||
NETOBJ=
|
NETOBJ=
|
||||||
@@ -183,12 +183,13 @@ VIDEOBJ=${VIDEODIR}/makev16b${OE} ${VIDEODIR}/makev16t${OE} ${VIDEODIR}/makevid$
|
|||||||
${VIDEODIR}/mode716e${OE} ${VIDEODIR}/mode716t${OE} ${VIDEODIR}/mode7${OE}\
|
${VIDEODIR}/mode716e${OE} ${VIDEODIR}/mode716t${OE} ${VIDEODIR}/mode7${OE}\
|
||||||
${VIDEODIR}/mode7ext${OE} ${VIDEODIR}/mv16tms${OE} ${VIDEODIR}/newg162${OE}\
|
${VIDEODIR}/mode7ext${OE} ${VIDEODIR}/mv16tms${OE} ${VIDEODIR}/newg162${OE}\
|
||||||
${VIDEODIR}/newgfx16${OE} ${VIDEODIR}/newgfx2${OE} ${VIDEODIR}/newgfx${OE}\
|
${VIDEODIR}/newgfx16${OE} ${VIDEODIR}/newgfx2${OE} ${VIDEODIR}/newgfx${OE}\
|
||||||
${VIDEODIR}/m716text${OE} ${VIDEODIR}/procvid${OE} ${VIDEODIR}/procvidc${OE} \
|
${VIDEODIR}/m716text${OE} ${VIDEODIR}/procvid${OE} ${VIDEODIR}/procvidc${OE}\
|
||||||
${VIDEODIR}/ntsc${OE}
|
${VIDEODIR}/ntsc${OE}
|
||||||
|
|
||||||
#only used on Win32
|
#only used on Win32
|
||||||
WINOBJ=${WINDIR}/copyvwin${OE} ${DRESOBJ}\
|
WINOBJ=${WINDIR}/copyvwin${OE} ${DRESOBJ}\
|
||||||
${WINDIR}/winintrf${OE} ${WINDIR}/winlink${OE} ${WINDIR}/zfilew${OE}
|
${WINDIR}/winintrf${OE} ${WINDIR}/winlink${OE} ${WINDIR}/zfilew${OE}\
|
||||||
|
${WINDIR}/safelib${OE}
|
||||||
|
|
||||||
WINVIDOBJ=${VIDEODIR}/sw_draw${OE} ${VIDEODIR}/hq2x16${OE} ${VIDEODIR}/hq2x32${OE}\
|
WINVIDOBJ=${VIDEODIR}/sw_draw${OE} ${VIDEODIR}/hq2x16${OE} ${VIDEODIR}/hq2x32${OE}\
|
||||||
${VIDEODIR}/2xsaiw${OE} ${VIDEODIR}/hq3x16${OE} ${VIDEODIR}/hq3x32${OE}\
|
${VIDEODIR}/2xsaiw${OE} ${VIDEODIR}/hq3x16${OE} ${VIDEODIR}/hq3x32${OE}\
|
||||||
@@ -393,6 +394,7 @@ ${VIDEODIR}/ntsc${OE}: ${VIDEODIR}/ntsc.c
|
|||||||
${WINDIR}/copyvwin${OE}: ${WINDIR}/copyvwin.asm macros.mac
|
${WINDIR}/copyvwin${OE}: ${WINDIR}/copyvwin.asm macros.mac
|
||||||
${WINDIR}/winintrf${OE}: ${WINDIR}/winintrf.asm macros.mac
|
${WINDIR}/winintrf${OE}: ${WINDIR}/winintrf.asm macros.mac
|
||||||
${WINDIR}/zfilew${OE}: ${WINDIR}/zfilew.c ${WINDIR}/resource.h
|
${WINDIR}/zfilew${OE}: ${WINDIR}/zfilew.c ${WINDIR}/resource.h
|
||||||
|
${WINDIR}/safelib${OE}: ${WINDIR}/safelib.c argv.h
|
||||||
ifeq (${ENV},msvc)
|
ifeq (${ENV},msvc)
|
||||||
${WINDIR}/winlink.obj: ${WINDIR}/winlink.cpp ${WINDIR}/resource.h
|
${WINDIR}/winlink.obj: ${WINDIR}/winlink.cpp ${WINDIR}/resource.h
|
||||||
${WINDIR}/zsnes.res: ${WINDIR}/zsnes.rc ${WINDIR}/afxres.h ${WINDIR}/resource.h
|
${WINDIR}/zsnes.res: ${WINDIR}/zsnes.rc ${WINDIR}/afxres.h ${WINDIR}/resource.h
|
||||||
|
|||||||
85
zsnes/src/win/safelib.c
Normal file
85
zsnes/src/win/safelib.c
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
#define _POSIX_
|
||||||
|
#include <io.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <process.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
|
||||||
|
#include "../argv.h"
|
||||||
|
|
||||||
|
//These are here because I don't believe in MSVC's prefixing affixation
|
||||||
|
#define dup _dup
|
||||||
|
#define dup2 _dup2
|
||||||
|
#define pipe _pipe
|
||||||
|
#define flushall _flushall
|
||||||
|
#define fdopen _fdopen
|
||||||
|
|
||||||
|
//Introducing a popen which doesn't return until it knows for sure of program launched or couldn't open -Nach
|
||||||
|
|
||||||
|
#define READ_FD 0
|
||||||
|
#define WRITE_FD 1
|
||||||
|
|
||||||
|
FILE *safe_popen(char *command, const char *mode)
|
||||||
|
{
|
||||||
|
FILE *ret = 0;
|
||||||
|
char **argv = build_argv(command);
|
||||||
|
if (argv)
|
||||||
|
{
|
||||||
|
int filedes[2];
|
||||||
|
|
||||||
|
if ((*mode == 'r' || *mode == 'w') &&
|
||||||
|
!pipe(filedes, 512, (mode[1] == 'b' ? O_BINARY : O_TEXT) | O_NOINHERIT))
|
||||||
|
{
|
||||||
|
int fd_original;
|
||||||
|
FILE *fp;
|
||||||
|
|
||||||
|
if (*mode == 'r')
|
||||||
|
{
|
||||||
|
fd_original = dup(STDOUT_FILENO);
|
||||||
|
dup2(filedes[WRITE_FD], STDOUT_FILENO);
|
||||||
|
if (!(fp = fdopen(filedes[READ_FD], mode)))
|
||||||
|
{
|
||||||
|
close(filedes[READ_FD]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fd_original = dup(STDIN_FILENO);
|
||||||
|
dup2(filedes[READ_FD], STDIN_FILENO);
|
||||||
|
if (!(fp = fdopen(filedes[WRITE_FD], mode)))
|
||||||
|
{
|
||||||
|
close(filedes[WRITE_FD]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fp)
|
||||||
|
{
|
||||||
|
int status;
|
||||||
|
flushall();
|
||||||
|
|
||||||
|
status = spawnvp(P_NOWAIT, argv[0], (const char* const*)argv);
|
||||||
|
if (status > 0)
|
||||||
|
{
|
||||||
|
ret = fp;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fclose(fp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*mode == 'r')
|
||||||
|
{
|
||||||
|
dup2(fd_original, STDIN_FILENO);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dup2(fd_original, STDOUT_FILENO);
|
||||||
|
}
|
||||||
|
close(fd_original);
|
||||||
|
}
|
||||||
|
free(argv);
|
||||||
|
}
|
||||||
|
return(ret);
|
||||||
|
}
|
||||||
12
zsnes/src/win/safelib.h
Normal file
12
zsnes/src/win/safelib.h
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
#ifndef SAFELIB_H
|
||||||
|
#define SAFELIB_H
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
FILE *safe_popen(char *, const char *);
|
||||||
|
void safe_pclose(FILE *);
|
||||||
|
|
||||||
|
#define popen safe_popen
|
||||||
|
#define pclose fclose
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -39,9 +39,8 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|||||||
#ifdef __WIN32__
|
#ifdef __WIN32__
|
||||||
#include <direct.h>
|
#include <direct.h>
|
||||||
#include <io.h>
|
#include <io.h>
|
||||||
|
#include "win/safelib.h"
|
||||||
#define ftruncate chsize
|
#define ftruncate chsize
|
||||||
#define popen _popen
|
|
||||||
#define pclose _pclose
|
|
||||||
#else
|
#else
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user