Blame src/cmds/ntux_cmd_strace.c

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