/*
 * Copyright 1993 Hamish Macdonald
 *
 * This file is subject to the terms and conditions of the GNU General Public
 * License.  See the file README.legal in the main directory of this archive
 * for more details.
 */

#include <stdarg.h>
#include <sys/types.h>
#include <wait.h>
#include <linux/fcntl.h>
#include <linux/unistd.h>
#include <linux/stat.h>

#define MESSAGE "Hello World!\n"

static inline _syscall3(int,write,int,fd,const char *,buf,off_t,count)
static inline _syscall3(int,read,int,fd,char *,buf,off_t,count)
static inline _syscall1(int,close,int,fd)
static inline _syscall2(int,fchmod,int,fd,int,mode)
static inline _syscall0(int,fork)
static inline _syscall0(int,sync)
static inline _syscall3(int,lseek,int,fd,long,offset,int,whence)
static inline _syscall3(int,execve,const char *,file,char **,argv,
			char **,envp)
static inline _syscall1(int,unlink,const char *,file)

int errno;
int cons;
extern int printf (const char *, ...);
extern void subproc(void);
extern void showstat (int pid, union wait status);

void init(void)
{
    int pid;
    union wait status;

    cons = open ("/dev/console", O_RDWR);

    printf (MESSAGE);

    if (fork() == 0)
	subproc();

    while (1) {
	pid = waitpid(-1,&status.w_status,WUNTRACED);
	if (pid != -1)
	    showstat (pid, status);
    }
}

void showstat (int pid, union wait status)
{
    if (WIFSTOPPED(status))
	printf ("pid %d stopped with signal %d\n", pid, WSTOPSIG(status));
    else if (WIFSIGNALED(status))
	printf ("pid %d terminated with signal %d\n", pid, WTERMSIG(status));
    else if (WIFEXITED(status))
	printf ("pid %d exited with code %d\n", pid, WEXITSTATUS(status));
}

int printf (const char *fmt, ...)
{
    extern int vsprintf(char * buf, const char * fmt, va_list args);
    static char buf[256];
    va_list args;
    int i;

    va_start (args, fmt);
    i = vsprintf (buf, fmt, args);
    va_end (args);

    write (cons, buf, i);

    return i;
}

void subproc(void)
{
    int fd, nr;
    char buffer[80];
    unsigned long sum;
    extern char progdata[];
    extern int progsize;

    if (unlink ("/bin/sh") == -1) {
	printf ("unlink of /bin/sh failed.  errno=%d\n", errno);
	_exit(1);
    }

    fd = open ("/bin/texec", O_CREAT | O_WRONLY | O_TRUNC);

    if (fd == -1) {
	printf ("open (write) of /bin/texec failed.  errno=%d\n", errno);
	_exit(1);
    }

    if (write (fd, progdata, progsize) != progsize) {
	printf ("write of /bin/texec failed.  errno=%d\n", errno);
	_exit(1);
    }

    if (fchmod (fd, S_IRWXU) == -1) {
	printf ("fchmod of /bin/texec failed.  errno=%d\n", errno);
	_exit(1);
    }

    close (fd);

    printf ("wrote to /bin/texec\n");

    if (execve ("/bin/texec", 0, 0) == -1) {
	printf ("execve of /bin/texec failed.  errno=%d\n", errno);
	_exit(1);
    }

    _exit(0);
}
