added system call macros for x86 and x86_64 for implementing pio based on vfork
This commit is contained in:
@ -550,13 +550,23 @@ int qse_pio_init (
|
||||
|
||||
/* DOS not multi-processed. can't support pio */
|
||||
|
||||
#elif defined(HAVE_POSIX_SPAWN)
|
||||
#elif defined(HAVE_POSIX_SPAWN) && !(defined(QSE_SYSCALL0) && defined(SYS_vfork))
|
||||
posix_spawn_file_actions_t fa;
|
||||
int fa_inited = 0;
|
||||
int pserr;
|
||||
#if defined(__linux)
|
||||
posix_spawnattr_t psattr;
|
||||
#endif
|
||||
qse_pio_pid_t pid;
|
||||
param_t param;
|
||||
extern char** environ;
|
||||
#elif defined(QSE_SYSCALL0) && defined(SYS_vfork)
|
||||
qse_pio_pid_t pid;
|
||||
param_t param;
|
||||
extern char** environ;
|
||||
char** envarr;
|
||||
int highest_fd;
|
||||
int dummy;
|
||||
#else
|
||||
qse_pio_pid_t pid;
|
||||
param_t param;
|
||||
@ -1178,7 +1188,7 @@ create_process:
|
||||
pio->errnum = QSE_PIO_ENOIMPL;
|
||||
return -1;
|
||||
|
||||
#elif defined(HAVE_POSIX_SPAWN)
|
||||
#elif defined(HAVE_POSIX_SPAWN) && !(defined(QSE_SYSCALL0) && defined(SYS_vfork))
|
||||
if (flags & QSE_PIO_WRITEIN)
|
||||
{
|
||||
if (QSE_PIPE(&handle[0]) <= -1)
|
||||
@ -1379,9 +1389,22 @@ create_process:
|
||||
goto oops;
|
||||
}
|
||||
|
||||
#if defined(__linux)
|
||||
posix_spawnattr_init (&psattr);
|
||||
#if !defined(POSIX_SPAWN_USEVFORK)
|
||||
# define POSIX_SPAWN_USEVFORK 0x40
|
||||
#endif
|
||||
posix_spawnattr_setflags (&psattr, POSIX_SPAWN_USEVFORK);
|
||||
#endif
|
||||
|
||||
pserr = posix_spawn(
|
||||
&pid, param.argv[0], &fa, QSE_NULL, param.argv,
|
||||
&pid, param.argv[0], &fa, &psattr, param.argv,
|
||||
(env? qse_env_getarr(env): environ));
|
||||
|
||||
#if defined(__linux)
|
||||
posix_spawnattr_destroy (&psattr);
|
||||
#endif
|
||||
|
||||
free_param (pio, ¶m);
|
||||
if (fa_inited)
|
||||
{
|
||||
@ -1411,6 +1434,210 @@ create_process:
|
||||
handle[5] = QSE_PIO_HND_NIL;
|
||||
}
|
||||
|
||||
#elif defined(QSE_SYSCALL0) && defined(SYS_vfork)
|
||||
if (flags & QSE_PIO_WRITEIN)
|
||||
{
|
||||
if (QSE_PIPE(&handle[0]) <= -1)
|
||||
{
|
||||
pio->errnum = syserr_to_errnum (errno);
|
||||
goto oops;
|
||||
}
|
||||
minidx = 0; maxidx = 1;
|
||||
}
|
||||
|
||||
if (flags & QSE_PIO_READOUT)
|
||||
{
|
||||
if (QSE_PIPE(&handle[2]) <= -1)
|
||||
{
|
||||
pio->errnum = syserr_to_errnum (errno);
|
||||
goto oops;
|
||||
}
|
||||
if (minidx == -1) minidx = 2;
|
||||
maxidx = 3;
|
||||
}
|
||||
|
||||
if (flags & QSE_PIO_READERR)
|
||||
{
|
||||
if (QSE_PIPE(&handle[4]) <= -1)
|
||||
{
|
||||
pio->errnum = syserr_to_errnum (errno);
|
||||
goto oops;
|
||||
}
|
||||
if (minidx == -1) minidx = 4;
|
||||
maxidx = 5;
|
||||
}
|
||||
|
||||
if (maxidx == -1)
|
||||
{
|
||||
pio->errnum = QSE_PIO_EINVAL;
|
||||
goto oops;
|
||||
}
|
||||
|
||||
if (make_param (pio, cmd, flags, ¶m) <= -1) goto oops;
|
||||
|
||||
/* check if the command(the command requested or /bin/sh) is
|
||||
* exectuable to return an error without trying to execute it
|
||||
* though this check alone isn't sufficient */
|
||||
if (assert_executable (pio, param.argv[0]) <= -1)
|
||||
{
|
||||
free_param (pio, ¶m);
|
||||
goto oops;
|
||||
}
|
||||
|
||||
if (!(flags & QSE_PIO_NOCLOEXEC))
|
||||
highest_fd = get_highest_fd ();
|
||||
envarr = env? qse_env_getarr(env): environ;
|
||||
|
||||
QSE_SYSCALL0 (pid, SYS_vfork);
|
||||
if (pid <= -1)
|
||||
{
|
||||
pio->errnum = QSE_PIO_EINVAL;
|
||||
free_param (pio, ¶m);
|
||||
goto oops;
|
||||
}
|
||||
|
||||
if (pid == 0)
|
||||
{
|
||||
/* child */
|
||||
qse_pio_hnd_t devnull = -1;
|
||||
|
||||
if (!(flags & QSE_PIO_NOCLOEXEC))
|
||||
{
|
||||
int fd = highest_fd;
|
||||
|
||||
/* close all other unknown open handles except
|
||||
* stdin/out/err and the pipes. */
|
||||
while (--fd > 2)
|
||||
{
|
||||
if (fd != handle[0] && fd != handle[1] &&
|
||||
fd != handle[2] && fd != handle[3] &&
|
||||
fd != handle[4] && fd != handle[5])
|
||||
{
|
||||
QSE_SYSCALL1 (dummy, SYS_close, fd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (flags & QSE_PIO_WRITEIN)
|
||||
{
|
||||
/* child should read */
|
||||
QSE_SYSCALL1 (dummy, SYS_close, handle[1]);
|
||||
/*handle[1] = QSE_PIO_HND_NIL;*/
|
||||
QSE_SYSCALL2 (dummy, SYS_dup2, handle[0], 0);
|
||||
if (dummy <= -1) goto child_oops;
|
||||
QSE_SYSCALL1 (dummy, SYS_close, handle[0]);
|
||||
/*handle[0] = QSE_PIO_HND_NIL;*/
|
||||
}
|
||||
|
||||
if (flags & QSE_PIO_READOUT)
|
||||
{
|
||||
/* child should write */
|
||||
QSE_SYSCALL1 (dummy, SYS_close, handle[2]);
|
||||
/*handle[2] = QSE_PIO_HND_NIL;*/
|
||||
QSE_SYSCALL2 (dummy, SYS_dup2, handle[3], 1);
|
||||
if (dummy <= -1) goto child_oops;
|
||||
|
||||
if (flags & QSE_PIO_ERRTOOUT)
|
||||
{
|
||||
QSE_SYSCALL2 (dummy, SYS_dup2, handle[3], 2);
|
||||
if (dummy <= -1) goto child_oops;
|
||||
}
|
||||
|
||||
QSE_SYSCALL1 (dummy, SYS_close, handle[3]);
|
||||
/*handle[3] = QSE_PIO_HND_NIL;*/
|
||||
}
|
||||
|
||||
if (flags & QSE_PIO_READERR)
|
||||
{
|
||||
/* child should write */
|
||||
QSE_SYSCALL1 (dummy, SYS_close, handle[4]);
|
||||
/*handle[4] = QSE_PIO_HND_NIL;*/
|
||||
QSE_SYSCALL2 (dummy, SYS_dup2, handle[5], 2);
|
||||
if (dummy <= -1) goto child_oops;
|
||||
|
||||
if (flags & QSE_PIO_OUTTOERR)
|
||||
{
|
||||
QSE_SYSCALL2 (dummy, SYS_dup2, handle[5], 1);
|
||||
if (dummy <= -1) goto child_oops;
|
||||
}
|
||||
|
||||
QSE_SYSCALL1 (dummy, SYS_close, handle[5]);
|
||||
/*handle[5] = QSE_PIO_HND_NIL;*/
|
||||
}
|
||||
|
||||
if ((flags & QSE_PIO_INTONUL) ||
|
||||
(flags & QSE_PIO_OUTTONUL) ||
|
||||
(flags & QSE_PIO_ERRTONUL))
|
||||
{
|
||||
#if defined(O_LARGEFILE)
|
||||
QSE_SYSCALL3 (devnull, SYS_open, QSE_MT("/dev/null"), O_RDWR|O_LARGEFILE, 0);
|
||||
#else
|
||||
QSE_SYSCALL3 (devnull, SYS_open, QSE_MT("/dev/null"), O_RDWR, 0);
|
||||
#endif
|
||||
if (devnull <= -1) goto child_oops;
|
||||
}
|
||||
|
||||
if (flags & QSE_PIO_INTONUL)
|
||||
{
|
||||
QSE_SYSCALL2 (dummy, SYS_dup2, devnull, 0);
|
||||
if (dummy <= -1) goto child_oops;
|
||||
}
|
||||
if (flags & QSE_PIO_OUTTONUL)
|
||||
{
|
||||
QSE_SYSCALL2 (dummy, SYS_dup2, devnull, 1);
|
||||
if (dummy <= -1) goto child_oops;
|
||||
}
|
||||
if (flags & QSE_PIO_ERRTONUL)
|
||||
{
|
||||
QSE_SYSCALL2 (dummy, SYS_dup2, devnull, 2);
|
||||
if (dummy <= -1) goto child_oops;
|
||||
}
|
||||
|
||||
if ((flags & QSE_PIO_INTONUL) ||
|
||||
(flags & QSE_PIO_OUTTONUL) ||
|
||||
(flags & QSE_PIO_ERRTONUL))
|
||||
{
|
||||
QSE_SYSCALL1 (dummy, SYS_close, devnull);
|
||||
devnull = -1;
|
||||
}
|
||||
|
||||
if (flags & QSE_PIO_DROPIN) QSE_SYSCALL1 (dummy, SYS_close, 0);
|
||||
if (flags & QSE_PIO_DROPOUT) QSE_SYSCALL1 (dummy, SYS_close, 1);
|
||||
if (flags & QSE_PIO_DROPERR) QSE_SYSCALL1 (dummy, SYS_close, 2);
|
||||
|
||||
QSE_SYSCALL3 (dummy, SYS_execve, param.argv[0], param.argv, envarr);
|
||||
if (dummy == -1)
|
||||
{
|
||||
printf ("hello\n");
|
||||
}
|
||||
/*free_param (pio, ¶m); */
|
||||
|
||||
child_oops:
|
||||
if (devnull >= 0) QSE_SYSCALL1 (dummy, SYS_close, devnull);
|
||||
QSE_SYSCALL1 (dummy, SYS_exit, 128);
|
||||
}
|
||||
|
||||
/* parent */
|
||||
free_param (pio, ¶m);
|
||||
pio->child = pid;
|
||||
|
||||
if (flags & QSE_PIO_WRITEIN)
|
||||
{
|
||||
QSE_CLOSE (handle[0]);
|
||||
handle[0] = QSE_PIO_HND_NIL;
|
||||
}
|
||||
|
||||
if (flags & QSE_PIO_READOUT)
|
||||
{
|
||||
QSE_CLOSE (handle[3]);
|
||||
handle[3] = QSE_PIO_HND_NIL;
|
||||
}
|
||||
|
||||
if (flags & QSE_PIO_READERR)
|
||||
{
|
||||
QSE_CLOSE (handle[5]);
|
||||
handle[5] = QSE_PIO_HND_NIL;
|
||||
}
|
||||
#else
|
||||
|
||||
if (flags & QSE_PIO_WRITEIN)
|
||||
@ -1485,7 +1712,10 @@ create_process:
|
||||
{
|
||||
if (fd != handle[0] && fd != handle[1] &&
|
||||
fd != handle[2] && fd != handle[3] &&
|
||||
fd != handle[4] && fd != handle[5]) QSE_CLOSE (fd);
|
||||
fd != handle[4] && fd != handle[5])
|
||||
{
|
||||
QSE_CLOSE (fd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1703,7 +1933,7 @@ oops:
|
||||
#elif defined(__DOS__)
|
||||
|
||||
/* DOS not multi-processed. can't support pio */
|
||||
#elif defined(HAVE_POSIX_SPAWN)
|
||||
#elif defined(HAVE_POSIX_SPAWN) && !(defined(QSE_SYSCALL0) && defined(SYS_vfork))
|
||||
if (fa_inited)
|
||||
{
|
||||
posix_spawn_file_actions_destroy (&fa);
|
||||
@ -1713,6 +1943,11 @@ oops:
|
||||
{
|
||||
if (handle[i] != QSE_PIO_HND_NIL) QSE_CLOSE (handle[i]);
|
||||
}
|
||||
#elif defined(QSE_SYSCALL0) && defined(SYS_vfork)
|
||||
for (i = minidx; i < maxidx; i++)
|
||||
{
|
||||
if (handle[i] != QSE_PIO_HND_NIL) QSE_CLOSE (handle[i]);
|
||||
}
|
||||
#else
|
||||
for (i = minidx; i < maxidx; i++)
|
||||
{
|
||||
|
@ -173,6 +173,12 @@
|
||||
# define QSE_FORK() fork()
|
||||
#endif
|
||||
|
||||
#if defined(SYS_vfork)
|
||||
# define QSE_VFORK() syscall(SYS_vfork)
|
||||
#else
|
||||
# define QSE_VFORK() vfork()
|
||||
#endif
|
||||
|
||||
#if defined(SYS_execve)
|
||||
# define QSE_EXECVE(path,argv,envp) syscall(SYS_execve,path,argv,envp)
|
||||
#else
|
||||
@ -349,4 +355,110 @@
|
||||
# define QSE_UTIMES(path,t) utimes(path,t)
|
||||
#endif
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
#if defined(__linux) && defined(__GNUC__) && defined(__x86_64)
|
||||
|
||||
#include <sys/syscall.h>
|
||||
|
||||
/*
|
||||
#define QSE_SYSCALL0(ret,num) \
|
||||
__asm__ volatile ( \
|
||||
"movq %1, %%rax\n\t" \
|
||||
"syscall\n": \
|
||||
"=&a"(ret): \
|
||||
"g"((qse_uint64_t)num): \
|
||||
"%rcx", "%r11")
|
||||
|
||||
#define QSE_SYSCALL1(ret,num,arg1) \
|
||||
__asm__ volatile ( \
|
||||
"movq %1, %%rax\n\t" \
|
||||
"movq %2, %%rdi\n\t" \
|
||||
"syscall\n": \
|
||||
"=&a"(ret): \
|
||||
"g"((qse_uint64_t)num), "g"((qse_uint64_t)arg1): \
|
||||
"%rdi", "%rcx", "%r11")
|
||||
|
||||
#define QSE_SYSCALL2(ret,num,arg1,arg2) \
|
||||
__asm__ volatile ( \
|
||||
"movq %1, %%rax\n\t" \
|
||||
"movq %2, %%rdi\n\t" \
|
||||
"movq %3, %%rsi\n\t" \
|
||||
"syscall\n": \
|
||||
"=&a"(ret): \
|
||||
"g"((qse_uint64_t)num), "g"((qse_uint64_t)arg1), "g"((qse_uint64_t)arg2): \
|
||||
"%rdi", "%rsi", "%rcx", "%r11")
|
||||
|
||||
#define QSE_SYSCALL3(ret,num,arg1,arg2,arg3) \
|
||||
__asm__ volatile ( \
|
||||
"movq %1, %%rax\n\t" \
|
||||
"movq %2, %%rdi\n\t" \
|
||||
"movq %3, %%rsi\n\t" \
|
||||
"movq %4, %%rdx\n\t" \
|
||||
"syscall\n": \
|
||||
"=&a"(ret): \
|
||||
"g"((qse_uint64_t)num), "g"((qse_uint64_t)arg1), "g"((qse_uint64_t)arg2), "g"((qse_uint64_t)arg3): \
|
||||
"%rdi", "%rsi", "%rdx", "%rcx", "%r11")
|
||||
*/
|
||||
|
||||
#define QSE_SYSCALL0(ret,num) \
|
||||
__asm__ volatile ( \
|
||||
"syscall\n": \
|
||||
"=a"(ret): \
|
||||
"a"((qse_uint64_t)num) : \
|
||||
"%rcx", "%r11")
|
||||
|
||||
#define QSE_SYSCALL1(ret,num,arg1) \
|
||||
__asm__ volatile ( \
|
||||
"syscall\n": \
|
||||
"=a"(ret): \
|
||||
"a"((qse_uint64_t)num), "D"((qse_uint64_t)arg1): \
|
||||
"%rcx", "%r11")
|
||||
|
||||
#define QSE_SYSCALL2(ret,num,arg1,arg2) \
|
||||
__asm__ volatile ( \
|
||||
"syscall\n": \
|
||||
"=a"(ret): \
|
||||
"a"((qse_uint64_t)num), "D"((qse_uint64_t)arg1), "S"((qse_uint64_t)arg2): \
|
||||
"%rcx", "%r11")
|
||||
|
||||
#define QSE_SYSCALL3(ret,num,arg1,arg2,arg3) \
|
||||
__asm__ volatile ( \
|
||||
"syscall\n": \
|
||||
"=a"(ret): \
|
||||
"a"((qse_uint64_t)num), "D"((qse_uint64_t)arg1), "S"((qse_uint64_t)arg2), "d"((qse_uint64_t)arg3): \
|
||||
"%rcx", "%r11")
|
||||
|
||||
#elif defined(__linux) && defined(__GNUC__) && defined(__i386)
|
||||
|
||||
#include <sys/syscall.h>
|
||||
|
||||
#define QSE_SYSCALL0(ret,num) \
|
||||
__asm__ volatile ( \
|
||||
"int $0x80\n": \
|
||||
"=a"(ret): \
|
||||
"a"((qse_uint32_t)num))
|
||||
|
||||
#define QSE_SYSCALL1(ret,num,arg1) \
|
||||
__asm__ volatile ( \
|
||||
"int $0x80\n": \
|
||||
"=a"(ret): \
|
||||
"a"((qse_uint32_t)num), "b"((qse_uint32_t)arg1))
|
||||
|
||||
#define QSE_SYSCALL2(ret,num,arg1,arg2) \
|
||||
__asm__ volatile ( \
|
||||
"int $0x80\n": \
|
||||
"=a"(ret): \
|
||||
"a"((qse_uint32_t)num), "b"((qse_uint32_t)arg1), "c"((qse_uint32_t)arg2))
|
||||
|
||||
#define QSE_SYSCALL3(ret,num,arg1,arg2,arg3) \
|
||||
__asm__ volatile ( \
|
||||
"int $0x80\n": \
|
||||
"=a"(ret): \
|
||||
"a"((qse_uint32_t)num), "b"((qse_uint32_t)arg1), "c"((qse_uint32_t)arg2), "d"((qse_uint32_t)arg3))
|
||||
|
||||
#endif
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
#endif
|
||||
|
Reference in New Issue
Block a user