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:
n-a-c-h
2006-03-08 01:46:06 +00:00
parent 832160f00f
commit 6573b3b18c
7 changed files with 258 additions and 154 deletions

View File

@@ -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
View 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

View File

@@ -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()

View File

@@ -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
View 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
View 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

View File

@@ -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