#include <iostream.h>
#include <vector.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
#include <signal.h>
#include <sys/wait.h>
vector<pid_t> children;
bool signaled;
struct sigaction sa,oldsa;
void sigusr1_handler(int) { signaled=true; }
int main()
{
sa.sa_flags=SA_RESTART;
sa.sa_handler=SIG_IGN;
sigaction(SIGINT,&sa,&oldsa);
sa.sa_handler=sigusr1_handler;
sigaction(SIGUSR1,&sa,&oldsa);
for (;;)
{
char buffer[256];
cout << "sh9: ";
cin.getline(buffer,256);
if (cin && *buffer!=0)
{
char *command=strtok(buffer," ");
if (strcmp(command,"exit")==0) break;
bool bg=false;
vector<char *> arg_vec;
char *s, *redir[2];
redir[0]=redir[1]=0;
while ((s=strtok(0," "))!=0)
{
if (s[0]=='&') { bg=true; break; }
if (s[0]=='<' || s[0]=='>')
{
int redir_num=(int)(s[0]=='>');
if (s[1]==0)
{
if ((s=strtok(0," "))==0) { cerr<<"illegal redir\n"; break; }
}
else ++s;
if (redir[redir_num]!=0) cerr << "multiple redir\n";
else redir[redir_num]=s;
}
else arg_vec.push_back(s);
}
int argc=1+arg_vec.size();
char **argv=new(char *)[argc+1];
argv[0]=command;
copy(arg_vec.begin(),arg_vec.end(),argv+1);
argv[argc]=0;
signaled=false;
pid_t pid=fork();
if (pid==0)
{
static int flags[2]={ O_RDONLY, O_CREAT|O_TRUNC|O_WRONLY };
if (bg && redir[0]==0) redir[0]="/dev/null";
for (int i=0;i<=1;++i)
if (redir[i]!=0)
{
int fd=open(redir[i],flags[i],0644);
if ( fd<0 || dup2(fd,i)<0 ) cerr << "redir error\n";
close(fd);
}
if (bg) { setpgid(0,0); kill(getppid(),SIGUSR1); }
else signal(SIGINT,SIG_DFL);
execvp(command,argv);
cerr << "command not found!\n";
_exit(0);
}
else if (!bg) waitpid(pid,0,0);
else { if (!signaled) pause(); children.push_back(pid); }
while (waitpid(-1,0,WNOHANG)>0);
delete[] argv;
}
}
vector<pid_t>::iterator it;
for ( it=children.begin() ; it!=children.end() ; ++it )
kill(*it,SIGTERM);
}