#include <stdio.h>
#include <types.h>
#include <stat.h>
#include <dir.h>
#include <filesys.h>
#include <signal.h>

#define tty 1

char line[128];
int pid;
int chstat;
int bkround;
char cmd[30], arg1[30], arg2[30], arg3[30], arg4[30], arg5[30];

extern int errno;

_main(argc,argval)
int argc;
char *argval[];
{
    int rdev;
    int count;
    int interact;
    struct filesys fsys;
    int nread;
    int j;
    FILE *fp;
    char *argv[7];

    char *fgets();

    interact = isatty(fileno(stdin));
    
    if (interact)
	signal(SIGINT,SIG_IGN);

    for(;;)
    {
	if (interact)
	    pline("> ");

	if (fgets(line,sizeof(line),fp) == NULL)
	    exit(0);

	cmd[0] = '\0';
	*arg1 = '\0';
	arg2[0] = '\0';
	arg3[0] = '\0';
	arg4[0] = '\0';
	arg5[0] = '\0';
	count = sscanf(line,"%s %s %s %s %s %s",cmd, arg1, arg2, arg3);
	if (count == 0 || cmd[0] == '\n')
	    continue;

	sync();

	if (cmd[0] == '\0')
	    continue;

	if (strcmp(cmd,"exit") == 0)
	{
	    _exit(0);
	}
	else if (strcmp(cmd,"cd") == 0)
	{
	    if (*arg1 )
	    {
		if (chdir(arg1) != 0)
		{
		    perror("cd");
		}
	    }
	}
	else if (strcmp(cmd,"df") == 0)
	{
	    for (j=0; j < 32; ++j)  /* Arbirtary upper limit */
	    {
		if (getfsys(j,&fsys)==0)
		{
		    sprintf(line,"%d:   %u blks used %u blks free %u inodes used %u inodes free\n",
		    j,(fsys.s_fsize - fsys.s_isize)-fsys.s_tfree, fsys.s_tfree,
		    (8*(fsys.s_isize-2)-fsys.s_tinode), fsys.s_tinode);
		    pline(line);
		}
	    }
	}
	else if (strcmp(cmd,"setuid") == 0)
	{
            if (*arg1 )
		if (setuid(atoi(arg1)))
		    pline("Setuid error.\n");
	}
	else
	{
	    argv[0] = cmd;
	    argv[1] = *arg1 ? arg1 : NULL;
	    argv[2] = *arg2 ? arg2 : NULL;
	    argv[3] = *arg3 ? arg3 : NULL;
	    argv[4] = *arg4 ? arg4 : NULL;
	    argv[5] = *arg5 ? arg5 : NULL;
	    argv[6] = (char *)NULL;

	    bkround = 0;
            if (argv[count-1][0] == '&')
	    {
		bkround = 1;
		argv[count-1] = NULL;
	    }

	    fflush(stdout);
	    fflush(stderr);
	    pid = fork();
	    if (pid == -1)
		perror("sh");
	    else if (pid == 0) /* Child */
	    {
		    if (bkround==0)
		 	signal(SIGINT,SIG_DFL);
		    execve(cmd,argv, &argv[4]);
		    if (cmd[0] != '.' && cmd[0] != '/')
	   	    {
			sprintf(line,"/bin/%s",cmd);
			execve(line,argv, &argv[4]);
			sprintf(line,"/%s",cmd);
			execve(line,argv, &argv[4]);
	    	    }

		    /* Try executing as a shell script */

		    fclose(stdin);
		    open(cmd,0);
		    argv[0] = "sh";
		    execve("/bin/sh",argv,&argv[4]);
	  	    perror("No shell");
		    _exit(99);
  	    }
	    else  /* Parent */
	    {
               if (bkround==0)
		    do ; while (wait(&chstat) != pid);
	    }

	}
    }
}


pline(line)
char *line;
{
    write(tty,line,(uint16)strlen(line));
}



/* Get string from buffered file */
char *fgets(s, maxsize, fp)
char *s;
FILE *fp;
	{
	register int c, size;
	register char *ps, *q;

	ps = s;
	while (--maxsize > 0 && (c = getc(fp)) != EOF)
		if ((*ps++ = c) == '\n')
			break;
	*ps = '\0';
	return ((c == EOF && ps == s) ? NULL : s);
	}
