/****************************************************************************
 *
 * $Source: /usr/local/cvsroot/gccsdk/unixlib/source/clib/unixlib/unix.h,v $
 * $Date: 2003/06/23 20:33:03 $
 * $Revision: 1.7 $
 * $State: Exp $
 * $Author: joty $
 *
 * UNIX is a registered trademark of AT&T Bell Laboratories
 *
 ***************************************************************************/

#ifndef __UNIXLIB_UNIX_H
#define __UNIXLIB_UNIX_H 1

#ifndef __UNIXLIB_FEATURES_H
#include <unixlib/features.h>
#endif
#ifndef __UNIXLIB_TYPES_H
#include <unixlib/types.h>
#endif
#ifndef __UNIXLIB_FD_H
#include <unixlib/fd.h>
#endif
#ifndef __UNIXLIB_SIGSTATE_H
#include <unixlib/sigstate.h>
#endif

#ifndef __UNIXLIB_TTY_H
#include <unixlib/tty.h>
#endif
#ifndef __SETJMP_H
#include <setjmp.h>
#endif
#ifndef __SYS_TIME_H
#include <sys/time.h>
#endif
#ifndef __SYS_RESOURCE_H
#include <sys/resource.h>
#endif
#ifndef __SYS_TYPES_H
#include <sys/types.h>
#endif
#ifndef __LIMITS_H
#include <limits.h>
#endif
#ifndef __KERNEL_H
#include <kernel.h>
#endif

__BEGIN_DECLS

#ifdef __UNIXLIB_INTERNALS

struct __process
{
  /* This process has a parent process.  */
  unsigned int has_parent : 1;
  /* This process terminated through a signal handler.  */
  unsigned int signal_exit : 1;
  /* This process terminated with a core dump.  */
  unsigned int core_dump : 1;
  /* This process just stopped.  */
  unsigned int stopped : 1;
  /* This process is controlling the tty. */
  unsigned int tty_control : 1;
  /* The type of tty this process is controlling.  */
  unsigned int tty_type : 8;
  /* The number of the signal we terminated with.  */
  unsigned int signal : 8;
  /* The return code of this process.  */
  unsigned int return_code : 8;
};

struct __child_process
{
  __uid_t uid;
  __gid_t gid;
  __pid_t pid;
  int ppri, gpri, upri;
  struct __process status;
  struct rusage usage;
  jmp_buf vreg; /* Process context.  */
};

/* UnixLib 3.7b == 0xfedcfa5f.  */
/* UnixLib 3.7c.beta == 0xfedcfa60.  */
/* UnixLib 3.7c.19970803 == 0xfedcfa61.  */
/* UnixLib 3.7c.19980504 == 0xfedcfa62  */
#define _PROCMAGIC 0xfedcfa62

struct proc
{
  unsigned int __magic;  /* Magic word.  */
  int argc, envc;  /* Command line and environment argument count.  */
  char **envp;  /* Environment argument list.  */
  char **argv;  /* Command line arguments.  */
  struct __unixlib_fd fd[MAXFD];  /* File descriptors.  */
  struct tty *tty;
  __uid_t uid, euid;  /* Real and effective UID.  */
  __gid_t gid, egid;  /* Real and effective GID.  */
  __pid_t pgrp;  /* ID of process group that process belongs to.  */
  __pid_t pid;  /* Process ID.  */
  __pid_t ppid;  /* Parent process ID.  */
  int ppri, gpri, upri;  /* Process priority, process group priority
      	    	  	    and user process priority.  */
  __mode_t umask;  /* File creation mode mask.  */
  struct __process status;  /* Process status.  */
  struct itimerval itimers[__MAX_ITIMERS];  /* Defined interval timers.  */
  struct rlimit limit[RLIMIT_NLIMITS];  /* Process resource limits.  */
  struct rusage usage;  /* Resource usage of the process.  */
  struct proc *pproc;  /* Pointer to the parent process's structure.  */
  /* Details recorded about stopped or terminated children.  */
  struct __child_process child[CHILD_MAX];
  /* The signal states for this process. */
  struct unixlib_sigstate sigstate;
  /* Set to 1 if this process is currently sleeping, orphaned or stopped.
     These could change at any time.  */
  volatile int sleeping, orphaned, stopped;
  jmp_buf vreg;  /* Process context.  */
  /* UGLY HACK: We store cli malloc pointer here prior to calling child
     process.  The malloc store is then freed in __exret.  */
  void *cli;
};

extern struct proc *__u;	/* current process */

struct pipe
{
  struct __unixlib_fd *p[2];
  char *file;
  struct pipe *next;
};

extern struct pipe *__pipe;	/* list of currently active pipes */


extern int __funcall_error (const char *, int, unsigned int);
#ifndef __PARANOID
#define __funcall(f,p) ((f)p)
#else
#define __funcall(f,p) \
  ((((void *)(f) >= __base) && (((unsigned int)(f) & ~3) == (unsigned int)(f)) \
   ? 0 : __funcall_error(__FILE__,__LINE__,(unsigned int)(f))), (f)p)
#endif


/* Assembler exit.  */
extern void __exit (int) __attribute__ ((__noreturn__));
extern void __exit_no_code (void) __attribute__ ((__noreturn__));

/* __break is initialised to __lomem & __stack to __himem - STAKSIZ;
 * __stack is extended downwards in chunks by x$stack_overflow()
 * and __break is extended upwards by brk() and sbrk(). The sl
 * register is kept equal to __stack + 512. Should x$stack_overflow()
 * attempt to extend __stack below __break then SIGEMT is raised.
 * Should brk() or sbrk() be asked to extend __break above __stack
 * then they return with ENOMEM. */

extern char *__cli;		/* command line from OS_GetEnv */
extern void *__base;		/* BASE = Image$$RO$$Base */
extern void *__lomem;		/* LOMEM = Image$$RW$$Limit */
extern void *__himem;		/* HIMEM from OS_GetEnv */
extern void *__real_himem;	/* Real HIMEM  - application space limit */
extern void *__rwlimit;

extern void *__break;		/* end of data area */
extern void *__real_break;	/* real end of data area */
extern void *__stack;		/* bottom of stack */
extern void *__stack_limit;
extern int __codeshift;
extern int __dynamic_num;
extern void __dynamic_area_exit (void);

extern void __munmap_all (void);	/* Deallocate all mappings.  */

/* Zero if we are not executing within a TaskWindow.  Non-zero otherwise.  */
extern int __taskwindow;
/* Zero if we are running in command mode (not as a WIMP program).  Non-zero
   otherwise.  */
extern int __wimpprogram;
/* Zero if we are running in 26-bit, non-zero for 32-bit */
extern int __32bit;

extern unsigned int __time[2];	/* start time */

#define __OS_ARTHUR	0xA0
#define __OS_RISCOS_200 0xA1
#define __OS_RISCOS_201 0xA2
#define __OS_RISCOS_300 0xA3
#define __OS_RISCOS_310 0xA4
#define __OS_RISCOS_350	0xA5
#define	__OS_RISCOS_360 0xA6
#define __OS_RISCOS_370 0xA7
#define __OS_RISCOS_400 0xA8

/* FP flag reflecting Floating Point presence or not.  */
extern int __fpflag;

/* Stop the interval timers.  */
extern void __stop_itimers (void);

/* OS_ChangeEnvironment is used to set up exception handlers. These
 * handlers use OS_CallBack to raise signals in the foreground process.
 * RTFM (RISC OS PRM - 'The Program Environment') for more info. */

/* Reset handlers, etc. back to original state.  */
extern void __env_riscos (void);
extern void __env_unixlib (void);
extern void __env_read (void);

/* vfork() & exec() */

extern void __vret (int);	/* return from child - calls __vexit() */

extern int *__vfork (void);	/* fork to child context */
extern int *__vexit (int);	/* restore to parent context */

extern void __exret (void);	/* return from __exec() - calls __vret() */

extern void (*__exptr) (char *); /* pointer to __exec() routine */
extern int __exlen;		/* length of __exec() routine */
extern int __exshift;		/* __exec() shift */

/* vfork weak link.  */

extern void (*___vret) (int);

/* Return unsigned int from STRING.  END, if non-null, points to character
   after number.  */
extern unsigned int __decstrtoui (const char *__string, char **__end);

/* If this variable is non-null then we allocated the current environment.  */
extern char **__last_environ;

/* UnixLib's prefix for global RISC OS environment variables. I considered
   using Unix$ rather than UnixEnv$, but that means the environment variable
   PATH would get confused with Unix$Path which is used in makefiles.  */
#define __UNIX_ENV_PREFIX "UnixEnv$"

/* Add NAME=VALUE to the environment. If NAME is already in the environment,
   only add when REPLACE is non-zero. If NAME is added to the environment
   and ADD_TO_OS is non-zero, then also add it to the RISC OS global
   environment.  */
extern char *__addenv (const char *__name, const char *__value,
		       int __replace, int __add_to_os);

/* Lookup NAME in the environment and return value if found.  */
extern char *__chkenv (const char *__name);

/* Get environment value from OS and copy into BUF and return a pointer to BUF.
   If no match found then return NULL.  If BUF is NULL, then allocate space
   as necessary, otherwise BUFLEN is length of supplied buffer.  */
extern char *__getenv_from_os (const char *__name, char *__buf,
			       size_t __buflen);

/* If CACHE is non-zero, then lookup NAME in the program's environment first.
   If CACHE is zero or NAME was not found in the program's environment, then
   look it up in the RISC OS global environment.  If found there, then add
   it to the program's environment. Return found value or NULL.  */
extern char *__getenv (const char *__name, int __cache);

/* Return the integer value of NAME, from the RISC OS global environment.  */
extern int __intenv (const char *__name);

/* Remove NAME from the OS environment. Returns -1 on failure or not found.  */
extern int __remenv_from_os (const char *__name);

/* Set runtime features according to system variables.  */
extern void __runtime_features (const char *__cmdline);

/* Print an error and exit the process.  */
extern void
__unixlib_fatal (const char *__message) __attribute__ ((__noreturn__));

/* Initialize the signal code.  */
extern void __unixlib_signal_initialise (struct proc *__p);

/* Resource limit initialisation */
extern void __resource_initialise (struct proc *__p);

/* Stack manipulation */

#define STACK_CHUNK_MAGIC 0xf60690ff

/* Structure representing the bottom part of a stack chunk */
/* See _syslib.s for more details */
struct __stack_chunk
{
  unsigned int magic;
  struct __stack_chunk *next;
  struct __stack_chunk *prev;
  unsigned int size;
  void (*dealloc) (void *);
  void (*returnaddr) (void);
};

extern void __stackalloc_init (void);
extern void *__stackalloc (size_t __size);
extern void __stackfree (void *__ptr);
extern int __stackalloc_trim (void);
extern void __free_stack_chain (void *__ptr);
extern void *__stackalloc_incr_wimpslot (int __incr);

/* Initialise the UnixLib world.  */
void __unixinit (void);

void _main (void);

extern const speed_t __bsd_speeds[16];

/* Shared between sys/exec.c & sys/_exec.s */
extern _kernel_oserror *__exerr;

#endif  /* __UNIXLIB_INTERNALS */

__END_DECLS

#endif
