All pastes #930955 Raw Edit

Someone

public text v1 · immutable
·published 2008-03-06 21:53 UTC
rendered paste body
#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");
	}
}


void rem_char( char *s, char t ){
	if( !s || !*s ) return;

	while( *s++ != t ) if( !*s ) return;
	while( *(s-1)=*s++ );
}



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);
	rem_char(filename, '\n');
	
	//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);
	int fdStdin = dup(0);
	
	if(pip0!=-1 && pip1==-1){ //there's something to read
		int tpip[2];
		pipe(tpip);

		printf("now reading from pipe\n");
		dup2(tpip[1], fdStdout);
		dup2(tpip[0], fdStdin);
		//parse pipeArgs an give them to run command
		run_command(args, argsNb, bg);
		printf("%s", pipeArgs);
		
		close(tpip[0]);
		close(tpip[1]);
		//dup2(fdStdin, 0);
		//dup2(fdStdout, 1);
		//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);
	
	rem_char(filename, '\n');
		
	// open file in read mode
	//file = fopen(filename, "r");
	file = open(filename, O_RDONLY);
		
	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 fdOut=-1;
	int fdIn=-1;
	int 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
		p++;
		redirect(&p,args, argsNb, 0, pip);//file is next argument output is execution of args[0]
		fdOut=-1;
		fdIn=-1;
		break;
	case '<':
		p++;
		readArgs(&p, args, argsNb, 0, pip);
		//(++p);//gives arguments for call
		fdOut=-1;
		fdIn=-1;
		break;
	case '|': 
		curr = args[0];
		if(*(++p)== '|'){//execute and check status of first command
		  if(pipline(args, argsNb,0, fdOut, fdIn, pipeArgs)==0)
		    ++p; //do not execute next command
		  fdOut=-1;
		  fdIn=-1;
		} 
		else {// pipe
			
			pipe(pip); //create new pipe pair
			fdOut=pip[0]; //upcoming func should read from fd
			pipline(args, argsNb,0, pip[0], pip[1], pipeArgs);
			//fdIn=pip[1]; //upcoming func should read from fdIn
			//fdOut=pip[0]; //upcoming func should read from fdOut
			//pipline(args, argsNb,0, fdOut, fdIn, pipeArgs);
			//fdIn=-1;
			}				
		break;
		
	case '&':
		if(*(++p)== '&'){//execute and check status of first command
		  if(pipline(args, argsNb,0, fdOut, fdIn, pipeArgs)!=0)
		    ++p;
		}
		else			//run in bg
		  pipline(args, argsNb, 0, fdOut, fdIn, pipeArgs);
		  //run_command(args, argsNb, 1);
		fdOut=-1;
		fdIn=-1;
		break;
		
	case '\n':
		printf("found commande: %s\n", *args);
		pipline(args, argsNb, 0, fdOut, fdIn, pipeArgs);
		fdOut=-1;
		fdIn=-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);
}