/***********************************************************/
/* ntux: native translation und extension */
/* Copyright (C) 2016--2018 Z. Gilboa */
/* Released under GPLv2 and GPLv3; see COPYING.NTUX. */
/***********************************************************/
#include <ntapi/ntapi.h>
#include <ntapi/nt_termios.h>
#include <psxabi/sys_sysapi.h>
#include <psxabi/sys_strace.h>
#include <psxabi/sys_fcntl.h>
#include <psxabi/sys_errno.h>
#include <ntux/ntux.h>
#include "ntux_driver_impl.h"
#include "ntux_nolibc_impl.h"
#include "ntux_errinfo_impl.h"
int ntux_cmd_strace(const struct ntux_driver_ctx * dctx)
{
int ret;
int32_t status;
pid_t pid;
const char ** argv;
const char ** envp;
unsigned char * program;
unsigned char * logfile;
struct __strace strace;
ssize_t rbytes;
ssize_t wbytes;
char * ch;
char buf[2048];
int fdlog[2];
int i;
/* init */
ntux_driver_set_ectx(
dctx,0,
dctx->cctx->sargv[0]);
argv = (const char **)dctx->cctx->sargv;
envp = (const char **)dctx->cctx->senvp;
program = (unsigned char *)dctx->cctx->sargv[0];
logfile = (unsigned char *)dctx->cctx->logfile;
/* fdlog */
if (logfile) {
if ((fdlog[1] = __sys_openat(
ntux_driver_fdcwd(dctx),
logfile,O_CREAT|O_TRUNC|O_WRONLY,0)) < 0)
if (ntux_errno_set(dctx,fdlog[1]))
return NTUX_SYSTEM_ERROR(dctx);
} else {
if ((ret = __sys_pipe(fdlog)) < 0)
if (ntux_errno_set(dctx,ret))
return NTUX_SYSTEM_ERROR(dctx);
}
/* strace */
strace.size = sizeof(strace);
strace.loader = dctx->cctx->loader;
strace.fdlog = fdlog[1];
strace.flags = 0;
for (i=0; i<16; i++)
strace.sysmask[i] = 0xFFFFFFFF;
for (i=0; i<16; i++)
strace.dbgmask[i] = 0;
for (i=0; i<32; i++)
strace.osmask[i] = 0;
/* spawn */
pid = __sys_vfork();
/* failed? */
if (pid < 0)
if (ntux_errno_set(dctx,pid))
return NTUX_SYSTEM_ERROR(dctx);
/* child */
if (pid == 0)
if ((status = __sys_strace(program,argv,envp,&strace)))
if (ntux_errno_set(dctx,status))
if (NTUX_SYSTEM_ERROR(dctx))
__sys_exit(0);
/* parent */
__sys_close(fdlog[1]);
if (dctx->cctx->logfile) {
__sys_wait4(
pid,&status,
0,0);
return 0;
}
/* piped strace output */
rbytes = __sys_read(fdlog[0],buf,sizeof(buf));
while (rbytes == -EINTR)
rbytes = __sys_read(fdlog[0],buf,sizeof(buf));
while (rbytes > 0) {
for (ch=buf; rbytes; ch += wbytes) {
wbytes = __sys_write(2,ch,rbytes);
while (wbytes == -EINTR)
wbytes = __sys_write(2,buf,rbytes);
if (wbytes < 0) {
__sys_close(fdlog[0]);
ntux_errno_set(dctx,wbytes);
return NTUX_SYSTEM_ERROR(dctx);
}
rbytes -= wbytes;
}
rbytes = __sys_read(fdlog[0],buf,sizeof(buf));
while (rbytes == -EINTR)
rbytes = __sys_read(fdlog[0],buf,sizeof(buf));
}
__sys_close(fdlog[0]);
if (rbytes < 0)
if (ntux_errno_set(dctx,rbytes))
return NTUX_SYSTEM_ERROR(dctx);
/* wait */
__sys_wait4(
pid,&status,
0,0);
return 0;
}