#include <sys/wait.h>
#include <sys/fcntl.h>
#include <sys/types.h>
#include <sys/param.h>
#include <err.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <ctype.h>
#include <stdio.h>
#include <signal.h>
static int error;
static int status=0;
static int inout[2];
/*
* cwd contains the current working directory.
*/
char cwd[MAXPATHLEN+1];
typedef int (*builtin_cmd)(int, char **);
struct builtin {
const char *name;
builtin_cmd func;
};
#define BIN(n) { #n, builtin_ ## n }
int builtin_cd(int argc, char **argv)
{
/* body of cd builtin command */
/* add your code here */
if(argc < 2 || argc > 2){
printf("Error, cd needs 1 arguments");
}else{
status = chdir(argv[1]);
}
return(status);
}
int builtin_exit(int argc, char **argv)
{
/* body of exit builtin command */
/* add your code here */
exit(0);
return(0);
}
int builtin_status(int argc, char **argv)
{
/* body of the status builtin command */
/* add your code here */
printf("Status of last command is: %d\n", status);
return(0);
}
static struct builtin builtins[] = {
BIN(cd),
BIN(exit),
BIN(status),
{ NULL }
};
/*
* run_builtin handles setting up the handlers for your builtin commands
*
* It accepts the array of strings, and tries to match the first argument
* with the builtin mappings defined in the builtins[].
* Returns 0 if it did not manage to find builtin command, or 1 if args
* contained a builtin command
*/
static int run_builtin(char **args)
{
int argc;
struct builtin *b;
for (b = builtins; b->name != NULL; b++) {
if (strcmp(b->name, args[0]) == 0) {
for (argc = 0; args[argc] != NULL; argc++)
/* NOTHING */;
error = b->func(argc, args);
printf("Run builtin\n");
return (1);
}
}
return (0);
}
void sigint_handler(int signum)
{
if (signum == SIGINT) {
// Need to transmit signal to fg job?
printf("\n^C caught\n");
} else {
perror("sigint_handler: Unsupported signal caught");
}
}
static int run_command(char **args, int argsNb, int background)
{
char * arguments[argsNb];
char cmd[strlen(args[0])];
strcpy (cmd, args[0]);
int parentPid;
int status;
int i;
for(i = 0; i < argsNb; i++){
arguments[i] = malloc(sizeof(char)*strlen(args[i]));
arguments[i] = args[i];
}
arguments[argsNb] = malloc(sizeof(NULL)); //useful?
arguments[argsNb] = NULL;
if (!run_builtin(args)){
printf("Run command\n");
if(fork() == 0){
if(background){
printf("Process %d started\n", getpid());
}
status = execvp (cmd, arguments);
}else{
parentPid = getpid();
if(background){
if(fork() == 0){
}else{
wait(NULL);
printf("Process %d done\n", getpid()+1);
}
}else{
wait(NULL);
}
}
}
return(0);
}
static char * parseword(char **pp)
{
char *p = *pp;
char *word;
for (; isspace(*p); p++)
/* NOTHING */;
word = p;
for (; strchr(" \t;&|><\n", *p) == NULL; p++)
/* NOTHING */;
*pp = p;
return (p != word ? word : NULL);
}
static int redirect(char* dest, char **args, int argsNb, int bg, int* pip){
char *filename;
filename = parseword(&dest);
//creating fd for redirection
int fdDest = open(filename, O_CREAT, 0744);
fdDest = open(filename, O_WRONLY);
if(fdDest==-1){
printf("Error opening file\n");
return(-1);
} else {
printf("Redirection to %s (fd:%d)\n", filename, fdDest);
}
//saving stdout fd
int fdStdout = dup(1);
//redirecting to new fd
dup2(fdDest,1);
run_command(args, argsNb, bg);
//close & restore
close(fdDest);
dup2(fdStdout, 1);
return(0);
}
static int pipline(char **args, int argsNb,int bg, int pip0, int pip1, char *pipeArgs){
printf("in piplien fun\n");
//saving stdout fd
int fdStdout = dup(1);
if(pip0!=-1 && pip1==-1){ //there's something to read
printf("now reading from pipe\n");
//parse pipeArgs an give them to run command
//run_command(pipeArgs, argsNb, bg);
printf("got from pipe: %s\n", pipeArgs);
}
else if(pip1!=-1){ // now redirect output to pipe
printf("now start writing to pipe\n");
dup2(pip1,1);
setvbuf(stdout,(char*)NULL,_IONBF,0);
printf("------pipe starts here\n");
run_command(args, argsNb, bg);
int res = read(pip0, pipeArgs, 1000); //read from pipe
//int res = read(pip0, pipeArgs, sizeof(pipeArgs)); //read from pipe
if (res == -1) return (error);
else printf("ok: reading from pipe\n");
printf("------pipe ends here\n");
//restore
close(pip1);
dup2(fdStdout,1);
printf("writing back to stdout\n");
}
else
run_command(args, argsNb, bg);
printf("exit of piplien fun\n");
return(0);
}
static int * readArgs(char* input, char **args, int argsNb, int bg, int* pip){
FILE *file;
char *filename = parseword(&input);
// open file in read mode
file = fopen(filename, "r");
if(file == (FILE*) NULL){
printf("Error, impossible to open file %s in read mode!\n", filename);
return 1;
}
//saving stdin fd
int fdStdin = dup(0);
//redirecting to new fd
dup2(file, 0);
run_command(args, argsNb, bg);
//close & restore
close(file);
dup2(fdStdin, 0);
return(0);
}
static int process(char *line)
{
int ch, ch2;
char *p = line, *word;
char *curr;
char *args[100], **narg;
char *output;
char pipeArgs[1000];
int pip[2];
int fd=-1, mode;
int argsNb = 0;
pip[0]=-1;
pip[1]=-1;
newcmd:
inout[0] = STDIN_FILENO;
inout[1] = STDOUT_FILENO;
newcmd2:
narg = args;
*narg = NULL;
for (;;) {
if (*p == 0 && ch==0)
break;
if (p != line)
p++;
word = parseword(&p);
ch = *p;
*p = 0;
if (word != NULL) {
*narg++ = word;
*narg = NULL;
argsNb++;
}
nextch:
/*
* Here you should put your code for processing the commands
* Up to this point, pointer word points to the next word,
* ch points to the first character after the word
* You should process according to what is in the ch.
* For example, use switch(). Next example will skip whitespaces
* and detect the redirection of the standard output.
*
*/
switch (ch) {
case ' ':
case '\t': break;
case '>':
//execute command and redirect output
redirect(++p,args, argsNb, 0, pip);//file is next argument output is execution of args[0]
fd=-1;
break;
case '<':
readArgs(++p, args, argsNb, 0, pip);
//(++p);//gives arguments for call
fd=-1;
break;
case '|':
curr = args[0];
if(*(++p)== '|'){//execute and check status of first command
if(pipline(args, argsNb,0, fd, -1, pipeArgs)==0)
++p; //do not execute next command
fd=-1;
}
else {// pipe
pipe(pip); //create new pipe pair
fd=pip[0]; //upcoming func should read from fd
pipline(args, argsNb,0, pip[0], pip[1], pipeArgs);
}
break;
case '&':
if(*(++p)== '&'){//execute and check status of first command
if(pipline(args, argsNb,0, fd, -1, pipeArgs)!=0)
++p;
}
else //run in bg
pipline(args, argsNb, 0, fd, -1, pipeArgs);
//run_command(args, argsNb, 1);
fd=-1;
break;
case '\n':
printf("found commande: %s\n", *args);
pipline(args, argsNb, 0, fd, -1, pipeArgs);
fd=-1;
break;
default:
printf("default entered\n");
};
}
return(0);
}
int main(void)
{
char line[1000];
int position = 0;
/* Catching program interrupt signal, C-c */
signal(SIGINT, SIG_IGN);
signal(SIGINT, sigint_handler);
do {
#ifdef __GNU_LIBRARY__
getcwd(cwd, MAXPATHLEN);
#else
getwd(cwd);
#endif
position = strlen(cwd);
if (position > MAXPATHLEN - 2)
position = MAXPATHLEN - 2;
cwd[position] = '>';
cwd[position+1] = ' ';
cwd[position+2] = 0;
fputs(cwd, stdout);
char *res = fgets(line, sizeof(line), stdin);
if (res == NULL) return (error);
process(line);
} while (1);
return (error);
}