/* rsxnt.h (rsxnt) -- Copyright (c) 1996-1998 Rainer Schnitker */

#ifndef _RSXNT_H_
#define _RSXNT_H_

#define WIN32_LEAN_AND_MEAN
#define STRICT
#include <windows.h>

#ifdef __EMX__
#include <emx/syscalls.h>
#include <sys/signal.h>
#include <sys/errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/fcntl.h>
#include <sys/ioctl.h>
#include <sys/timeb.h>
#include <sys/ptrace.h>
#include <sys/process.h>
#include <sys/ulimit.h>
#include <sys/time.h>
#include <sys/stat.h>
#include <sys/termio.h>
#include <sys/so_ioctl.h>

#else /* __EMX__ */

#define __const__ const
#define __attribute__(x)
#define _SIZE_T

#include <rsxnt\syscalls.h>
#include <rsxnt\signal.h>
#include <rsxnt\errno.h>
#include <rsxnt\types.h>
#include <rsxnt\stat.h>
#include <rsxnt\fcntl.h>
#include <rsxnt\ioctl.h>
#include <rsxnt\timeb.h>
#include <rsxnt\ptrace.h>
#include <rsxnt\process.h>
#include <rsxnt\ulimit.h>
#include <rsxnt\time.h>
#include <rsxnt\stat.h>
#include <rsxnt\termio.h>
#include <rsxnt\so_ioctl.h>

#endif /* __EMX__ */

#define N_FILES     256     /* defined in C-Library	    */
#define MAX_CHILD   20	    /* number of childs for wait()  */
#define MAX_PROCESS 20	    /* only for win32s		    */
#define MAX_THREADS 20	    /* number of threads	    */
#define MAX_CLD_TID 20	    /* number of child threads	    */

#define SIGSA(no)   ((no)-1)
#define SIGMASK(no) (1L<<((no)-1))
#define SIGBLOCK    (~(SIGSA(SIGKILL)))
#define SA_NOTBSD   (SA_SYSV | SA_ACK)

#define MAKEPERM(x) (((x) >> 6) * 0111)
#define BAD_FS_HANDLE ((HANDLE)-2)

/* **** RSXNT internal structures ****************************************** */

struct file {
    unsigned short	    f_mode;	    /* HT_TYPES */
    unsigned short	    f_flags;	    /* NDELAY etc */
    HANDLE		    f_handle;	    /* real dos handle or -1 */
};

struct child {
    int     pid;
    int     flags;
    HANDLE  hProcess;
    DWORD   dwProcessId;
    HANDLE  hThread;
    DWORD   dwThreadId;
};

enum {
    DEB_INVALID = 0, DEB_INIT, DEB_RUNNING
};

struct debuggee {
    int     pid;
    int     wait_status;
    int     status;
    HANDLE  hProcess;
    DWORD   dwProcessId;
    HANDLE  hCurrentThread;
    DWORD   dwCurrentThreadId;
    HANDLE  hThread[MAX_CLD_TID];
    DWORD   dwThreadId[MAX_CLD_TID];
};

#define TTY_BUF_SIZE  128
struct tty_queue {
    int head;
    int tail;
    char buf[TTY_BUF_SIZE];
};

struct tty_struct {
    struct termio *termios;
    int canon_data;
    int canon_head;
    unsigned long timeout;
    unsigned int erasing:1;
    unsigned int lnext:1;
    unsigned long secondary_flags[TTY_BUF_SIZE / (sizeof(long))];
    struct tty_queue secondary;
};

typedef struct {
     unsigned long
	gs, fs, es, ds,
	edi, esi, ebp, esp, ebx, edx, ecx, eax,
	faultno, err, eip, cs, eflags, emx_esp, emx_ss;
} REG386;

/* syscall frame for __syscall() */
typedef union syscall_frame {
  struct {
      long edi,esi,ebp,esp,ebx,edx,ecx,eax,eflags,eip;
    } e;
  struct{
      unsigned short di, di2, si, si2, bp, bp2, sp, sp2, bx, bx2, dx, dx2,
		     cx, cx2, ax, ax2, flags, flags2, ip, ip2;
    } x;
  struct
    {
      unsigned long edi, esi, ebp, esp;
      unsigned char bl, bh, bx2[2];
      unsigned char dl, dh, dx2[2];
      unsigned char cl, ch, cx2[2];
      unsigned char al, ah, ax2[2];
      unsigned long eflags, eip;
    } h;
} SYSCALL_FRAME;

typedef void (*SA_HANDLER)(int _sig);

struct rsxnt_opt
{
    unsigned long heapsize;
    unsigned long handles;

    unsigned long truncate:1;	/* truncate filenames */
    unsigned long nocore:2;	/* do not write core file */
    unsigned long quote:3;	/* quote args */
    unsigned long ansi:4;	/* enable ansi calls */
    unsigned long redir:5;	/* redirect strerr */

    unsigned char defdisk;
};

#define SYSCALL_STATE_NONE	0
#define SYSCALL_STATE_DLLINIT	1
#define SYSCALL_STATE_INIT	2

typedef struct {
    int                 pid;
    HANDLE		hProcess;
    DWORD		dwProcessId;
    int 		syscall_state;
    unsigned		p_status;
    unsigned		p_flags;
    void *		data_start;
    DWORD		pagesize;
    void *		heapmem;
    void *		heap_start;
    void *		heap_brk;
    void *		heap_pagebrk;
    void *		heap_end;
    struct file 	file[N_FILES];
    DWORD		close_on_exec[((N_FILES+31)/32)];
    DWORD		time_tic;
    DWORD		time_alarm;
    BOOL		bConsoleApp;
    DWORD		umask_bits;
    DWORD		uflags;
    struct child	childs[MAX_CHILD];
    struct debuggee	debuggee;
    HANDLE		hEventSignal;
    HANDLE		hEventAlarm;
    HANDLE		hThreadAlarm;
    CRITICAL_SECTION	CritSectFiles;
    CRITICAL_SECTION	CritSectHeap;
    int 		alarm_flags;
    REG386		regs;
    sigset_t		sig_raised;
    sigset_t		sig_blocked;
    struct sigaction	sigaction[NSIG];
    struct termio	termio;
    struct tty_struct	tty;
    struct rsxnt_opt	rsxnt_opt;
} EMXPROCESS;

struct layout
{
    DWORD text_base;		  /* Base address of the text segment */
    DWORD text_end;		  /* End address of the text segment */
    DWORD data_base;		  /* Base address of initialized data */
    DWORD data_end;		  /* End address of initialized data */
    DWORD bss_base;		  /* Base address of uninitialized data */
    DWORD bss_end;		  /* End address of uninitialized data */
    DWORD heap_base;		  /* Base address of the heap */
    DWORD heap_end;		  /* End address of the heap */
    DWORD heap_brk;		  /* End address of the used heap space */
    DWORD heap_off;		  /* Location of heap data in the executable */
    DWORD os2_dll;		  /* Address of the import table for (I1) */
    DWORD stack_base;		  /* Base address of the stack */
    DWORD stack_end;		  /* End address of the stack */
    DWORD flags;		  /* Flags (DLL) and interface number */
    DWORD reserved[2];		  /* Not yet used */
    unsigned char options[64];	  /* emx options to be used under OS/2 */
};

#define fd_mask(c) (1 << ((c) & 31))
#define fd_index(c) ((c) >> 5)
#define EMX_FD_SET(fd, map)	((map)[fd_index(fd)] |= fd_mask(fd))
#define EMX_FD_CLR(fd, map)	((map)[fd_index(fd)] &= ~(fd_mask(fd)))
#define EMX_FD_ISSET(fd, map)	((map)[fd_index(fd)] & fd_mask(fd))
#define EMX_FD_ZERO(s)		(void)memset(s, 0, sizeof (*(s)))

/* process status */
#define PS_EMPTY	0	/* free process */
#define PS_ZOMBIE	1	/* process exit, wait for father wait() */
#define PS_RUN		2	/* process running */
#define PS_STOP 	3	/* process stopped */
#define PS_WAIT 	4	/* process is waiting */
#define PS_SLEEP	5	/* process is sleeping */
#define PS_READKBD	6	/* process is in readbd, ignore signals */

/* process flags */
#define PF_DEBUG	1	/* process debugged by ptrace */
#define PF_TERMIO	4	/* termio used */
#define PF_WAIT_WAIT	8	/* wait for father wait() */

#define ALARM_START	1
#define ALARM_RESTART	2
#define ALARM_END	3

/* current win32 version */
typedef enum {
  EMPTY,
  WIN32S,
  WIN32C,
  WIN32NT
  } VERSION_INFO;

struct file_operations {
    int     (*read)	(int, void *, size_t);
    int     (*write)	(int, const void *, size_t);
    int     (*select)	(int, struct _fd_set *, struct _fd_set *, struct _fd_set *, const struct timeval *);
    int     (*ioctl)	(int, int, int);
    int     (*close)	(int);
    int     (*fcntl)	(int, int, int);
};

typedef int (*WAIT_DEBUG) (int *status);

/* **** RSXNT internal functions ******************************************* */

extern		VERSION_INFO _rsxnt_win32_version;
extern		struct file_operations _rsxnt_socket_fop;

EMXPROCESS *	_rsxnt_get_process_ptr ();
void		_rsxnt_init_files  (EMXPROCESS *);
int		_rsxnt_init_memory (EMXPROCESS *);
int		_rsxnt_init_signals(EMXPROCESS *);
void		_rsxnt_init_termio (EMXPROCESS *);
int		_rsxnt_dos_call    (SYSCALL_FRAME *);
int		_rsxnt_emx_call    (SYSCALL_FRAME *);

int		_rsxnt_get_last_errno (void);
int		_rsxnt_errno (int);

int		_rsxnt_get_new_file (EMXPROCESS *);
void		_rsxnt_truncate_name (char *, const char *);
void		_rsxnt_check_console_handle (EMXPROCESS *, int);
unsigned long	_rsxnt_stat_ino ();
unsigned long	_rsxnt_get_ht_type (HANDLE);
int		_rsxnt_check_npipe (const char *);
int		_rsxnt_dir_check (const char *path, const char *dir);

int		_rsxnt_init_heap (EMXPROCESS *);
void *		_rsxnt_grow_heap (EMXPROCESS *, int);
void *		_rsxnt_shrink_heap (EMXPROCESS *p, int);

int		_rsxnt_check_signals(void);
int		_rsxnt_do_signal(int);
int		_rsxnt_send_signal(EMXPROCESS *, int);

void		_rsxnt_init_sockets();
void		_rsxnt_exit_sockets();

unsigned long	_rsxnt_st2gmt(SYSTEMTIME *);
void		_rsxnt_gmt2st(unsigned long *, SYSTEMTIME *);
unsigned long	_rsxnt_ft2gmt(FILETIME *ft);
void		_rsxnt_gmt2ft(unsigned long time, FILETIME *ft);
void		_rsxnt_ft2stat(struct stat *, FILETIME *, FILETIME *, FILETIME *);

int		_rsxnt_do_fork(SYSCALL_FRAME * f);
int		_rsxnt_do_ptrace(int, int, int, int, int *);

int		_rsxnt_termio_ioctl(EMXPROCESS *, unsigned, int);
int		_rsxnt_termio_read(EMXPROCESS *, void *, int);
int		_rsxnt_write_with_ansi(const char *, size_t);

int             _rsxnt_wait_debuggee(int * status);

/* rsxide interface */
int		WINAPI win32s_init(void);
int		WINAPI win32s_read(int fd, char *buf, size_t nbyte);
int		WINAPI win32s_write(int fd, const void *buf, size_t nbyte);

#endif /* _RSXNT_H_ */
