char* read_into_buffer(int (*get_next_byte) (void *), void *get_next_byte_argument) { size_t n, buf_size; char next_byte; char *buf; buf_size = 1024; n = 0; buf = (char *) checked_malloc(sizeof(char)*buf_size); while ((next_byte = get_next_byte(get_next_byte_argument)) != EOF) { if (next_byte == '#') { next_byte = get_next_byte(get_next_byte_argument); while (next_byte != '\n' && next_byte != EOF) next_byte = get_next_byte(get_next_byte_argument); } if (next_byte != EOF) { buf[n] = next_byte; n++; if (n == buf_size) buf = checked_grow_alloc(buf, &buf_size); } } if (n < buf_size - 1) { buf[n] = '\0'; } else { buf = (char *) checked_grow_alloc(buf, &buf_size); buf[n] = '\0'; } return buf; }
void process_command(command_t c, char** arg, size_t* size, size_t* mem) { char** w; switch (c->type){ case SEQUENCE_COMMAND: process_command(c->u.command[0], arg, size, mem); process_command(c->u.command[1], arg, size, mem); break; case SIMPLE_COMMAND: if (c->input != NULL) { if (not_enough_mem (arg, size, sizeof (char*), *mem)) { arg = checked_grow_alloc (arg, mem); } arg[*size] = c->input; (*size)++; } else if( c->output != NULL) { if (not_enough_mem (arg, size, sizeof (char*), *mem)) { arg = checked_grow_alloc (arg, mem); } arg[*size] = c->output; (*size)++; } w=&(c->u.word[1]); while(*++w) { if (not_enough_mem (arg, size, sizeof (char*), *mem)) { arg = checked_grow_alloc (arg, mem); } arg[*size] = *w; (*size)++; } break; case SUBSHELL_COMMAND: if (c->input != NULL) { if (not_enough_mem (arg, size, sizeof (char*), *mem)) { arg = checked_grow_alloc (arg, mem); } arg[*size] = c->input; (*size)++; } else if (c->output != NULL) { if (not_enough_mem (arg, size, sizeof (char*), *mem)) { arg = checked_grow_alloc (arg, mem); } arg[*size] = c->output; (*size)++; } process_command (c->u.subshell_command, arg, size, mem); break; default: process_command(c->u.command[0], arg, size, mem); process_command(c->u.command[1], arg, size, mem); break; } return; }
//gets all characters/bytes from the script being run char* pullBytes(int (*get_next_byte) (void*), void *get_next_byte_argument) { size_t line_size = SIZE_COM_ALLOC; char *line = (char *) checked_malloc(sizeof(char *) * line_size); int i = (*get_next_byte)(get_next_byte_argument); if ( i == EOF || i < 0 ) return NULL; size_t position = 0; while( true ) { if ( DEBUG != 0 ) printf("Reading char = %c\n", (char)i); if ( position == line_size ) { line_size *= 2; line = (char *) checked_grow_alloc((void *) line, &line_size); } if ( i < 0 || ((char) i) == '\n' ) { line[position] = '\0'; return line; } line[position] = ((char) i); position++; i = (*get_next_byte)(get_next_byte_argument); } if ( DEBUG == 1 ) printf("pullBytes: Finished reading input\n"); }
//Create_buffer simply stores the file into a buffer char* create_buffer(int(*get_next_byte) (void *), void *get_next_byte_argument) { size_t iter = 0; size_t buffer_size = 1024; char *buffer = (char *)checked_malloc(buffer_size); char current_byte; //Iterates through entire file while ((current_byte = get_next_byte(get_next_byte_argument)) != EOF) { //Skips over characters included in a comment if (current_byte == '#') { while ((current_byte = get_next_byte(get_next_byte_argument)) != '\n') { if (current_byte == EOF) break; //fprintf(stderr, "%d", current_byte); //Continue iterating until the end of the comment is reached. } continue; } buffer[iter++] = current_byte; if (iter == buffer_size) buffer = (char *)checked_grow_alloc(buffer, &buffer_size); } buffer[iter] = '\0'; fprintf(stderr, "%s", buffer); return buffer; }
void push_command_stack(struct command *command, size_t *size, struct CStack *cstack) { if (command != NULL) { if (*size <= (cstack->last_item) * sizeof(command_t)) cstack->command_stack = (command_t *) checked_grow_alloc(cstack->command_stack, size); (cstack->last_item)++; cstack->command_stack[cstack->last_item] = command; } }
command_t retrieve_simple_command(char* char_buffer, int* index) { /* code to retrieve simple command should pass its char buffer into make_simple_command to create the actual struct */ /*temporary initial size of buffer, will resize if needed */ size_t buffer_size = (size_t) (sizeof(char) * 16); /*char buffer for array */ char* buffer; buffer = (char*) checked_malloc(buffer_size); int position = 0; /*will be the char of the head of the stream we are looking at to retrieve the simple command */ char head = char_buffer[*index]; while (head != EOF && head != '\n' && head != ';') { /* we have a valid simple word character that we need to attach to the buffer */ if (check_for_simple(head) == 1 || head == ' ') { if (((position+1) * sizeof(char)) == buffer_size) { buffer = (char*) checked_grow_alloc(buffer, &buffer_size); } buffer[position] = head; position++; *index = *index + 1; head = char_buffer[*index]; } else { buffer[position] = '\0'; /*free the buffer since we are done using it */ *index = *index - 1; /*we are done retrieving all the simple command characters so we can create the simple command */ return make_simple_command(buffer); } } buffer[position] = '\0'; *index = *index - 1; command_t temp = make_simple_command(buffer); return temp; }
command_stream_t make_command_stream (int (*get_next_byte) (void *), void *get_next_byte_arg) { size_t count = 0; size_t buffer_size = 1000; char* buffer = checked_malloc(buffer_size); //create a buffer of charactors to store the readin chars // create buffer of input with comments stripped out char ch; do { ch = get_next_byte(get_next_byte_arg); if (ch == '#') // for comments: ignore everything until '\n' or EOF { ch = get_next_byte(get_next_byte_arg); while(ch != EOF && ch!='\n') ch = get_next_byte(get_next_byte_arg); } //skip all the words until \n if (ch!= -1) { // load into buffer buffer[count] = ch; count++; // expand buffer if necessary //if (count == INT_MAX) //{ // error(1, 0, "Line -1: Input size over INT_MAX."); //} if (count == buffer_size) { buffer_size = buffer_size * 2; buffer = checked_grow_alloc (buffer, &buffer_size); } } } while(ch != -1); token_stream_t return_point = convert_buffer_to_token_stream(buffer,count); //build command_tree //nuild the first command_tree //command_stream_t command_stream_first = init_command_stream (); command_t new_command_t = make_command_tree (return_point); add_command_to_stream(new_command_t ); //build the rest command_tree while (return_point->next != NULL) { //make return_point point to next token stream token_stream_t temp = return_point->next; //free(return_point); return_point = temp; new_command_t = make_command_tree (return_point); add_command_to_stream(new_command_t); } return command_stream_head; }
/*code to create a simple command struct */ command_t make_simple_command(char *simple_string) { /*malloc a new command struct */ command_t simplecommand = (command_t)checked_malloc(sizeof(struct command)); int position = 0; /*split string into words by using strtok */ char *split_string = strtok(simple_string, " "); /*set its appropriate variables */ simplecommand->type = SIMPLE_COMMAND; simplecommand->status = 0; simplecommand->input = NULL; simplecommand->output = NULL; simplecommand->has_parent = false; /* temporary size of words array, 8 bytes to store 4 words */ size_t newsize = (size_t) (8 * sizeof(char*)); simplecommand->u.word = (char **)checked_malloc(newsize); while(split_string != NULL) { if ((position * sizeof(char*)) == newsize) {simplecommand->u.word = (char **)checked_grow_alloc(simplecommand->u.word, &newsize);} /*set the word variable in the union of the command struct to be the simple command word */ simplecommand->u.word[position] = (char *)checked_malloc(strlen(split_string) + 1); strcpy(simplecommand->u.word[position], split_string); position++; /*get the next word in the splitted string */ split_string = strtok(NULL, " "); } simplecommand->u.word[position] = '\0'; return simplecommand; }
void push_stack (stack *s, const void *src) { void *dst; if (s->len == s->max_len) { size_t temp = s->max_len * s->elemsize; s->elements = checked_grow_alloc(s->elements, &temp); s->max_len = temp / s->elemsize; } dst = (char *)s->elements + s->len * s->elemsize; memcpy(dst, src, s->elemsize); s->len++; }
int add_dep_to_graph(dependency_graph_t g, dependency_node_t n, int arr) { if(arr == 0) { if (g->no_dep_mem<(sizeof(dependency_node_t)* (g->no_dep_size+1))) { g->no_dep = checked_grow_alloc(g->no_dep, &(g->no_dep_mem)); } g->no_dep[g->no_dep_size] = n; g->no_dep_size++; } else if (arr == 1) { if(g->dep_mem<(sizeof(dependency_node_t)* (g->dep_size +1))) { g->dep = checked_grow_alloc(g->dep, &(g->dep_mem)); } g->dep[g->dep_size] = n; g->dep_size++; } else return -1; return 0; }
bool add_dependency (command_t c, command_t dep) { // We don't allow null commands or dependencies to be passed in if (c == NULL || dep == NULL) return false; // The two extra spaces allow us to have a NULL pointer at the end if (c->dependencies == NULL) { c->dep_alloc_size = 2; c->dependencies = checked_malloc (c->dep_alloc_size * sizeof (command_t)); } else if (c->dep_size + 1 >= c->dep_alloc_size) c->dependencies = checked_grow_alloc (c->dependencies, &(c->dep_alloc_size)); c->dependencies[c->dep_size++] = dep; c->dependencies[c->dep_size] = NULL; // This should be the case already, but let's be safe. return true; }
// Adds a command to the list of processes, ranked by parallelizability void add_command_t (command_t cmd, command_array **cmd_arr, size_t *arr_size, size_t *arr_capacity) { command_array cmd_info; cmd_info.command_tree = cmd; // Make the File Tree file_tree head = 0; get_files (cmd_info.command_tree, &head); cmd_info.files = head; // Check Size of the array, allocate more memory if needed if (*arr_capacity <= *arr_size) { size_t new_capacity = (*arr_capacity) * (sizeof (command_array)); *cmd_arr = checked_grow_alloc (*cmd_arr, &new_capacity); *arr_capacity = new_capacity / (sizeof (command_array)); } // Initialize new command_array element's command tree if (*arr_size != 0) { cmd_info.ranking = find_ranking (&cmd_info, cmd_arr, *arr_size); place_command_by_ranking (&cmd_info, cmd_arr, *arr_size); } else // The first command is always independent { cmd_info.ranking = 0; (*cmd_arr)[*arr_size] = cmd_info; } // Change Array Size (*arr_size)++; }
word get_next_word(char* buffer, int* it, int bufSize, int* lineNum) { word w; // deal with END if (*it == bufSize) { w.type = END; return w; } // remove beginning whitespace while (buffer[*it] == ' ' || buffer[*it] == '\t') { (*it)++; if (*it == bufSize) { w.type = END; return w; } } // deal with single-char tokens, ; | ( ) < > # // don't need to update string component of the word bc we don't use it char c = buffer[*it]; switch (c) { case ';': w.type = SEMICOLON; w.string = ";"; (*it) = (*it) + 1; return w; case '|': w.type = PIPE; w.string = "|"; (*it) = (*it) + 1; return w; case '(': w.type = LPARENS; w.string = "("; (*it) = (*it) + 1; return w; case ')': w.type = RPARENS; w.string = ")"; (*it) = (*it) + 1; return w; case '<': w.type = INPUT; w.string = "<"; (*it) = (*it) + 1; return w; case '>': w.type = OUTPUT; w.string = ">"; (*it) = (*it) + 1; return w; case '\n': w.type = NEWLINE; w.string = "\n"; (*lineNum) = (*lineNum) + 1; (*it) = (*it) + 1; return w; case '#': w.type = COMMENT; w.string = "#"; while (*it < bufSize && buffer[*it] != '\n') (*it) = (*it) + 1; if (*it != bufSize) { (*it) = (*it) + 1; // move past new line, point to start of next word (*lineNum) = (*lineNum) + 1; } return w; default: break; } // deal with words int wordLen = 64; w.string = (char*)checked_malloc(sizeof(char)*wordLen); // create string int stringIndex = 0; while (buffer[*it] != ' ' && buffer[*it] != '\t' && buffer[*it] != '\n' && buffer[*it] != ';' && buffer[*it] != '|' && buffer[*it] != '(' && buffer[*it] != ')' && buffer[*it] != '<' && buffer[*it] != '>' && *it != bufSize) { if (stringIndex == wordLen) { wordLen = wordLen*2; size_t size_size = sizeof(char)*wordLen; w.string = (char*)checked_grow_alloc((void*)w.string, &(size_size)); } if (!(isalpha(buffer[*it]) || isdigit(buffer[*it]) || buffer[*it]=='!' || buffer[*it]=='%' || buffer[*it]=='+' || buffer[*it]==',' || buffer[*it]=='-' || buffer[*it]=='.' || buffer[*it]=='/' || buffer[*it]==':' || buffer[*it]=='@' || buffer[*it]=='^' || buffer[*it]=='_' )) bad_error(lineNum, __LINE__); w.string[stringIndex] = buffer[*it]; (*it) = (*it) + 1; stringIndex++; } w.string[stringIndex] = '\0'; // assign special words if (strcmp(w.string, "if") == 0) { w.type = IF; w.string = "IF"; return w; } else if (strcmp(w.string, "then") == 0) { w.type = THEN; w.string = "THEN"; return w; } else if (strcmp(w.string, "else") == 0) { w.type = ELSE; w.string = "ELSE"; return w; } else if (strcmp(w.string, "fi") == 0) { w.type = FI; w.string = "FI"; return w; } else if (strcmp(w.string, "while") == 0) { w.type = WHILE; w.string = "WHILE"; return w; } else if (strcmp(w.string, "until") == 0) { w.type = UNTIL; w.string = "UNTIL"; return w; } else if (strcmp(w.string, "do") == 0) { w.type = DO; w.string = "DO"; return w; } else if (strcmp(w.string, "done") == 0) { w.type = DONE; w.string = "DONE"; return w; } else { w.type = SIMPLE; return w; } }
command_t make_simple_command(char *buffer) { if(!strlen(buffer)) syntax_error(); command_t command = checked_malloc(sizeof(struct command)); command->type = SIMPLE_COMMAND; command->status = -1; command->input = NULL; command->output = NULL; command->u.word = checked_malloc(8*sizeof(char*)); size_t word_size = 8; size_t input_size = 8;size_t output_size = 8; size_t cur_word_size; size_t index = 0; bool in_word = false; bool in_input = false; bool in_output = false; bool input = false; bool output = false; int i; for(i = 0; buffer[i]; i++) { if(buffer[i] == '<') { if(i == 0 || input || output || in_input || in_output) syntax_error(); command->input = checked_malloc(8*sizeof(char)); in_input = true; } else if(buffer[i] == '>') { if(i == 0 || output || in_output) syntax_error(); command->output = checked_malloc(8*sizeof(char)); in_input = false; in_output = true; } else if(isalnum(buffer[i]) || strchr("!%+,-./:@^_", buffer[i])) { if(in_input) { input = true; char* string = command->input; if(strlen(string) >= input_size) checked_grow_alloc(string, &input_size); string[strlen(string)] = buffer[i]; } else if(in_output) { output = true; char* string = command->output; if(strlen(string) >= output_size) checked_grow_alloc(string, &output_size); string[strlen(string)] = buffer[i]; } else if(!in_word) { if((input || output) && !in_input && !in_output) syntax_error(); if(index >= word_size) checked_grow_alloc(command->u.word, &word_size); command->u.word[index] = checked_malloc(8*sizeof(char)); cur_word_size = 8; command->u.word[index][0] = buffer[i]; in_word = true; } else if(in_word) { char *string = command->u.word[index]; if(strlen(string) >= cur_word_size) checked_grow_alloc(string, &cur_word_size); string[strlen(string)] = buffer[i]; } } else if(strchr("\t ", buffer[i])) { if(in_word) { in_word = false; index++; } else if(input && in_input) in_input = false; else if(output && in_output) in_output = false; } else if(buffer[i] == EOF) { if(index >= word_size) checked_grow_alloc(command->u.word, &word_size); return command; } else syntax_error(); } memset((void *) buffer, '\0', 1024); if(index >= word_size) checked_grow_alloc(command->u.word, &word_size); return command; }
command_stream_t make_command_stream (int (*get_next_byte) (void *), void *get_next_byte_argument) { //***************************************** // CREATE & ALLOCATE BUFFER //***************************************** int current_size = 1024; char* buffer = (char*)checked_malloc(sizeof(char)*current_size); int byte_count = 0; for(;;) { int c = get_next_byte(get_next_byte_argument); if (byte_count == current_size) { current_size = current_size*2; size_t size_size = sizeof(char)*current_size; buffer = (char*)checked_grow_alloc((void*)buffer, &(size_size)); } if (c != EOF && byte_count < current_size) { buffer[byte_count] = c; byte_count++; } else break; } //***************************************** // MAKE COMMAND STREAM OF COMMAND NODES //***************************************** int currentPos = 0; int lineNum = 1; // initialize command stream command_stream_t command_stream = checked_malloc(sizeof(struct command_stream)); // initialize first node command_node_t firstCommandNode = checked_malloc(sizeof(struct command_node)); command_stream->current_node = firstCommandNode; command_node_t currentCommandNode = command_stream->current_node; // initialize first command command_t firstCommand = checked_malloc(sizeof(struct command)); firstCommandNode->command = firstCommand; command_t currentCommand = currentCommandNode->command; while (get_command(buffer, ¤tPos, byte_count, currentCommand, &lineNum) == 1) { // create new node command_node_t newCommandNode = checked_malloc(sizeof(struct command_node)); newCommandNode->prev = currentCommandNode; currentCommandNode->next = newCommandNode; currentCommandNode = currentCommandNode->next; // create new command for that node command_t newCommand = checked_malloc(sizeof(struct command)); newCommandNode->command = newCommand; currentCommand = currentCommandNode->command; } if (currentCommandNode->prev != NULL) // couldn't add first command currentCommandNode->prev->next = NULL; else command_stream->current_node = NULL; return command_stream; }
token_stream_t convert_buffer_to_token_stream(char* buffer, size_t size) { //in this function convert buffer to the token stream, which is a linked list token_t head_token = create_token_with_type(HEAD, NULL, 0);//which created the dummy token token_t curr_token = head_token; token_t prev_token = NULL; token_stream_t head_stream = checked_malloc(sizeof(token_stream_t)); token_stream_t curr_stream = head_stream; curr_stream->head = head_token; curr_stream->tail = head_token;//now the head and tail both points to the head_token int line = 1; size_t index = 0; char c = *buffer; while(index<size) { printf("%c\n",c); if(isword(c) )//if c is word { size_t word_length = 5 ; size_t word_position = 0; char *word = (char*)checked_malloc(sizeof(word_length)); while(isword(c)) { word[word_position] = c;//assign the c to corresponding position if(word_position == word_length)//if reaches the length { word_length*=2; word = checked_grow_alloc(word,&word_length);//resize the word length } word_position++;index++;buffer++;c = *buffer;//update the char and index printf("%c\n",c); } token_t now = create_token_with_type(WORD,word,line); curr_token ->next = now; prev_token = curr_token;//assign the previous token to now curr_token = curr_token->next; curr_token->prev = prev_token; prev_token->next = curr_token; } else if(c == '\n')//if c is the new line { line++; if(curr_token->t_type ==LEFT_DERCTION||curr_token->t_type ==RIGHT_DERCTION) //LEFT direction and right direction cannot be followed by new line { error(2, 0, "Line %d: Newline cannot follow redirects.", line); return NULL; } //if the current token type is word or subshell which indicated a new command if(curr_token->t_type==WORD||curr_token->t_type==SUBSHELL) {//create a new token stream curr_stream->next = checked_malloc(sizeof(token_stream)); curr_stream = curr_stream->next; curr_stream->head = create_token_with_type(HEAD, NULL, -1); curr_token = curr_stream->head; } //else just treat is as white space index++;buffer++;c = *buffer; } else if(c == ' ' || c =='\t') { index++;buffer++;c = *buffer; //treated it as white space } else if(c == '<')//left direction { curr_token->next = create_token_with_type(LEFT_DERCTION,NULL,line); prev_token = curr_token;//assign the previous token to now curr_token = curr_token->next; curr_token->prev = prev_token; prev_token->next = curr_token; buffer++; index++; c = *buffer; } else if (c == '>') // RIGHT REDIRECT { curr_token->next = create_token_with_type(RIGHT_DERCTION, NULL, line); prev_token = curr_token;//assign the previous token to now curr_token = curr_token->next; curr_token->prev = prev_token; prev_token->next = curr_token; buffer++; index++; c = *buffer; } else if (c == ';') // SEQUENCE command { curr_token->next = create_token_with_type(SEMICOLON, NULL, line); prev_token = curr_token;//assign the previous token to now curr_token = curr_token->next; curr_token->prev = prev_token; prev_token->next = curr_token; buffer++; index++; c = *buffer; } else if (c == '&') // and { buffer++;index++;c=*buffer; //if(c!='&') // { // error(2, 0, "Line %d: Syntax error. & must be followed by &", line); // return NULL; // } if(c=='&') { curr_token->next = create_token_with_type(AND, NULL, line); prev_token = curr_token;//assign the previous token to now curr_token = curr_token->next; curr_token->prev = prev_token; prev_token->next = curr_token; buffer++; index++; c = *buffer; } else { error(2,0,"Line %d: Syntax error, && must be in pair",line); return NULL; } } else if (c == '|') // OR or PIPELINE { index++;buffer++;c=*buffer; if(c=='|') { curr_token->next = create_token_with_type(OR, NULL, line); prev_token = curr_token;//assign the previous token to now curr_token = curr_token->next; curr_token->prev = prev_token; prev_token->next = curr_token; buffer++; index++; c = *buffer; } else { curr_token->next = create_token_with_type(PIPELINE, NULL, line); prev_token = curr_token;//assign the previous token to now curr_token = curr_token->next; curr_token->prev = prev_token; prev_token->next = curr_token; //buffer++; index++; c = *buffer; } /* else { error(2, 0, "Line %d: Syntax error. | only can be followed by | or ", line); return NULL; }*/ } if (c == '(') // SUBSHELL { int subshell_line = line; int nested = 1; size_t count = 0; size_t subshell_size = 64; char* subshell = checked_malloc(subshell_size); // grab contents until subshell is closed while (nested > 0) { buffer++; index++; c = *buffer; //to examine the next char if (index == size) { error(2, 0, "Line %d: Syntax error. EOF reached before subshell was closed.", subshell_line); return NULL; } if (c == '\n') { // consume all following whitespace while (buffer[1] == ' ' || buffer[1] == '\t' || buffer[1] == '\n') { if (buffer[1] == '\n') line++; buffer++; index++; } // pass semicolon c = ';'; line++; } else if (c == '(') // count for nested subshells nested++; else if (c == ')') // close subshell { nested--; if (nested == 0) // break if outermost subshell is closed { buffer++; index++; c = *buffer; // consume last close parens break; } } // load into subshell buffer subshell[count] = c; count++; // expand subshell buffer if necessary if (count == subshell_size) { subshell_size = subshell_size * 2; subshell = checked_grow_alloc (subshell, &subshell_size); } } // create subshell token curr_token->next = create_token_with_type(SUBSHELL, subshell, subshell_line); curr_token = curr_token->next; } else if (c == ')') // CLOSE PARENS { error(2, 0, "Line %d: Syntax error. Close parens found without matching open parens.", line); return NULL; } } return head_stream; }
void time_travel_mode(command_stream_t command_stream) // time travle main function { command_t command; int line_num = 1; initialize_dependent_array(); command_list_t head = NULL; // add dependencies and stuff while ((command = read_command_stream (command_stream))) { command_list_t new_cmd = checked_malloc(sizeof(struct command_list)); new_cmd->c = command; new_cmd->file_list = NULL; new_cmd->num_of_dependent = 0; new_cmd->cmd_num = line_num; new_cmd->pid = -10; // arbitrary number that not child and parent new_cmd-> next = NULL; // if number of cmd > current array size // update it if (line_num >= current_size) { current_size *= 2; size_t resize = current_size * sizeof(int); dependent_array = checked_grow_alloc(dependent_array, &resize); } add_dependencies(command, new_cmd); /* #ifdef DEBUG if(new_cmd->file_list == NULL) printf("NULL\n"); printf("Command dependencies list: "); io_list_t cur = new_cmd->file_list; int i = 0; while(cur != NULL && i != 10) { printf("%s ", cur->name); cur = cur->next; i++; } printf("\n"); #endif */ // traverse through the graph to add dependencies command_list_t last = head; command_list_t curr = head; while(curr != NULL) { analyze_dependencies(new_cmd, curr); last = curr; curr = curr->next; } if (last == NULL) // empty list { // add head head = new_cmd; } else { last->next = new_cmd; } line_num++; } /* if (head != NULL) printf("Head outside is Cmd %d\n", head->cmd_num); int i; for( i = 0; i < INIT_SIZE; i++) { int j; for (j = 0; j < INIT_SIZE; j++) { if (dependent_array[i][j] > 0) { printf("Cmd %d requires Cmd %d\n", i, j); } } } command_list_t curr = head; while(curr != NULL) { printf("Cmd %d requires %d cmds\n", curr->cmd_num, curr->num_of_dependent); curr = curr->next; } */ // Execute time travel // TODO //printf("Head is cmd %d\n", head->cmd_num); while(head != NULL) { command_list_t curr = head; while(curr != NULL) { //printf("curr cmd is %d and num of dependency is %d\n", curr->cmd_num, curr->num_of_dependent); // If current command/node does not require other cmd to be executed before // then execute current cmd if(curr->num_of_dependent == 0 && curr->pid < 1) { pid_t pid = fork(); if (pid < 0) error(1, 0, "Fork error: %s\n", strerror(errno)); else if ( pid == 0) // child { exec_command_helper(curr->c); _exit(curr->c->status); } else if ( pid > 0) // parent then save pid and wait { curr->pid = pid; } } curr = curr->next; } int status; pid_t curr_pid = waitpid(-1, &status, 0); // parent wait for chid // Remove node from graph and update look-up table and stuff command_list_t prev = NULL; command_list_t traverse = head; while(traverse != NULL) { if(traverse->pid == curr_pid) // same pid, this node has finish executing { //printf("Remove cmd %d\n", traverse->cmd_num); // update table int i; for(i = 0; i < line_num; i++) { dependent_array[i][traverse->cmd_num] = 0; } //remove from the list if(prev == NULL) // head { head = traverse->next; } else { prev->next = traverse->next; } // update dependency number on each node command_list_t update = head; while(update != NULL) { int sum = 0; int j; for(j=0; j<line_num; j++) { sum += dependent_array[update->cmd_num][j]; } //printf("Cmd %d now requires %d cmd\n", update->cmd_num, sum); update->num_of_dependent = sum; update = update->next; } //printf("before break\n"); break; //printf("after break\n"); } prev = traverse; traverse = traverse->next; } //printf("Head is cmd %d\n", head->cmd_num); //if(head != NULL) // head = head->next; } }
/* * Use parsedFile to create a set of command structs * for each proper command in order. * Returns the number of commands found. */ int createCommandTree(char* parsedFile, int size, command_t* commands) { //Checking for Errors if(parsedFile == NULL) { error(1, 0, "Unexpected Null parsedFile"); return 0; } if(commands == NULL) { error(1, 0, "Unexpected Null commands"); return 0; } //Command Count - First command is close parentheses int numCommands = 1; //variables used to traverse through words in simple command int wordCount = -1; size_t wordCapacity = 0; int isOutput = 0; int isInput = 0; //Iterate over parsed file to create commands int i = 0; command_t temp; for(i=0; i < size; i++) { temp = (command_t)checked_malloc(sizeof(struct command)); temp->status = -1; temp->input = NULL; temp->output = NULL; temp->u.command[0] = NULL; temp->u.command[1] = NULL; temp->u.word = NULL; temp->u.subshell_command = NULL; char c = parsedFile[i]; if( c == '&') { temp->type = AND_COMMAND; commands[numCommands] = temp; numCommands++; wordCount = -1; wordCapacity = 0; isOutput = 0; isInput = 0; //skip next & i++; } else if(c == '|') { if(parsedFile[i+1] == '|') { temp->type = OR_COMMAND; //skip next | i++; } else { temp->type = PIPE_COMMAND; } commands[numCommands] = temp; numCommands++; wordCount = -1; wordCapacity = 0; isOutput = 0; isInput = 0; } else if(c == ';') { temp->type = SEQUENCE_COMMAND; commands[numCommands] = temp; numCommands++; wordCount = -1; wordCapacity = 0; isOutput = 0; isInput = 0; } else if(c == '(') { temp->type = SUBSHELL_COMMAND; commands[numCommands] = temp; numCommands++; wordCount = -1; wordCapacity = 0; isOutput = 0; isInput = 0; } else if(c == ')') { free(temp); //Point to empty command stored at the front of the array commands[numCommands] = commands[0]; numCommands++; wordCount = -1; wordCapacity = 0; isOutput = 0; isInput = 0; } else if (c == ' ') { free(temp); if(isOutput || isInput) { isOutput = 0; isInput = 0; parsedFile[i] = 0; } else if(wordCount > -1) { parsedFile[i] = 0; wordCount++; if((i+1)<size) { if( parsedFile[i+1] != '&' && parsedFile[i+1] != '|' && parsedFile[i+1] != ';' && parsedFile[i+1] != '(' && parsedFile[i+1] != ')' && parsedFile[i+1] != '>' && parsedFile[i+1] != '<' && !isspace(parsedFile[i+1])) { if(wordCount >= (int)(wordCapacity-1)) { size_t wordCapNew = wordCapacity*sizeof(char*); commands[numCommands-1]->u.word = (char**)checked_grow_alloc(commands[numCommands-1]->u.word, &wordCapNew); wordCapacity = wordCapNew/sizeof(char*); } commands[numCommands-1]->u.word[wordCount] = &(parsedFile[i+1]); commands[numCommands-1]->u.word[wordCount+1] = NULL; } } } } else if (c == '\n' || c == EOF) { free(temp); commands[numCommands] = NULL; numCommands++; wordCount = -1; wordCapacity = 0; isOutput = 0; isInput = 0; } else { if(c == '>') { free(temp); isOutput = 1; i++; while(i < size && isspace(parsedFile[i])) { i++; } if(commands[numCommands-1] == commands[0]) { int lastCommand; for(lastCommand = numCommands-2; lastCommand>0; lastCommand--){ if(commands[lastCommand]->type == SUBSHELL_COMMAND){ commands[lastCommand]->output = &parsedFile[i]; } } } else { commands[numCommands-1]->output = &parsedFile[i]; } } else if(c == '<') { free(temp); isInput = 1; i++; while(i < size && isspace(parsedFile[i])) { i++; } if(commands[numCommands-1] == commands[0]) { int lastCommand; for(lastCommand = numCommands-2; lastCommand>0; lastCommand--){ if(commands[lastCommand]->type == SUBSHELL_COMMAND){ commands[lastCommand]->input = &parsedFile[i]; } } } else { commands[numCommands-1]->input = &parsedFile[i]; } } else { if(wordCount == -1 && !isOutput && !isInput) { //initialize word temp->type = SIMPLE_COMMAND; temp->u.word = (char**)checked_malloc(sizeof(char*)*2); temp->u.word[0] = &(parsedFile[i]); temp->u.word[1] = NULL; commands[numCommands] = temp; numCommands++; wordCount = 0; wordCapacity = 2; } else { free(temp); } } } } if(commands[numCommands-1] != NULL){ commands[numCommands] = NULL; numCommands++; } return numCommands; }
command_stream_t make_command_stream (int (*get_next_byte) (void *), void *get_next_byte_argument) { size_t size = 1000; char *buf = (char*) checked_malloc(size); size_t i = 0; char c = get_next_byte(get_next_byte_argument); while(c != EOF) { if(i >= size) checked_grow_alloc(buf, &size); buf[i]=c; c = get_next_byte(get_next_byte_argument); i += sizeof(char); } buf[i] = '\0'; char* err_buf = checked_malloc(size); strcpy(err_buf, buf); //printf("%s\n", buf); // char delimiters = 'a'; char* token = strtok(buf, "\n"); size = 1000; i = 0; // printf("here\n"); command_stream_t result = checked_malloc(sizeof(command_stream_t)); result->my_commands = checked_malloc(size); result->size = 0; result->next_pos = 0; while(token != NULL) { //printf("%s\n", token); if(analyze_token(token)) { //printf("%s\n", token); result->my_commands[result->size] = process_buffer(token); //printf("Finished: %s\n", token); if(result->my_commands[result->size] == NULL) {} else if(result->my_commands[result->size]->status <= -2) { // printf("BUF: %s\n", err_buf); output_error(err_buf, token, result->my_commands[result->size]->status); } else { // print_command(result->my_commands[command_count]); result->size++; } token = strtok(NULL, "\n"); // printf("%s\n", token); } else { // printf("%s\n", token); char *temp = strtok(NULL, "\n"); //printf("NEXT TOKEN: %s\n", temp); if(temp!=NULL) { strcat(token,temp); printf("%s\n", token); } else output_error(err_buf, token,0); } } /*ONE COMMAND TESTING PURPOSES ONLY command_t e1 = process_buffer(set_of_tokens[0]); if(e1==NULL) { printf("NULL command, comment"); return result; } // printf("Word 1: %s %d\n", e1->u.word[2], strlen(e1->u.word[0])); print_command(e1); // while(e1->u.word[index] != NULL) result->my_commands[0] = e1; */ return result; }
dependency_graph_t build_graph (command_stream_t s) { dependency_graph_t ret_d; ret_d = NULL; size_t num; num = 0; size_t iter = 0; command_t comm; ret_d =checked_malloc(sizeof(struct dependency_graph)); init_graph(ret_d); char**args; size_t a_size; size_t a_mem; a_mem = (sizeof(char*)); args=checked_malloc(a_mem); int size= countNodes(s->item); char** read; size_t r_mem; size_t r_size; char** write; size_t w_mem; size_t w_size; size_t position=0; size_t innerpos = 0; for(num = 0; num < size;num++) { comm = s->cArray[num]; //each command in the array dependency_node_t n; n = checked_malloc (sizeof (struct dependency_node)); init_node(n, comm); //make a node to add to the graph while(iter < ret_d->no_dep_size || iter < ret_d->dep_size) { //if (debugmode) { printf ("I AM THERE!"); } r_size = 0; r_mem = (sizeof(char*)); read = checked_malloc(r_mem); w_mem = (sizeof(char*) * 3); w_size = 0; write = checked_malloc(w_mem); a_size = 0; size_t aMem = sizeof (char*); args = checked_malloc(aMem); //find all the arguments passed on the command line process_command(comm, args, &a_size, &aMem); process_command(comm, read, &r_size, &r_mem); process_command(comm, write, &w_size, &w_mem); //set all the node properties n->read = read; n->read_size = r_size; n->read_mem = r_mem; n->write = write; n->write_size = w_size; n->write_mem = w_mem; n->args = args; //printf("iter: %zu\n", iter); //error(1,0,"kid"); //if(comm->input!= NULL) // printf("%s\n", comm->input); //printf ("1"); //if there is a value in the output array and there is a node in the executable array //of the graph, then add a dependency to the current node and then push it to the dependancy graph if(write != NULL && iter < ret_d->no_dep_size){//printf("O\n"); while(position < w_size){ while(innerpos < ret_d->no_dep[iter]->read_size){ if(strcmp(ret_d->no_dep[iter]->read[innerpos], write[position])==0) { if (mem_need_grow (n->b4, &n->b4_size, sizeof(dependency_node_t) , n->b4_mem)) { n->b4 = checked_grow_alloc (n->b4, &(n->b4_mem)); } n->b4[n->b4_size] = ret_d->no_dep[iter]; n->b4_size +=1; } innerpos+=1; } position +=1; } } //if there is a value in the output array and there is a node in the dependancy array //of the graph, then add a dependency to the current node and then push it to the dependancy graph, because all commands //are parsed sequentially, if a dependancy occurs in the dependancy graph, then it must be added to the //dependancy graph if(write != NULL && iter < ret_d->dep_size){//printf("O\n"); while(write[position]!=NULL){//printf("O2\n"); while(ret_d->dep[iter]->read[innerpos]!=NULL){ if(strcmp(ret_d->dep[iter]->read[innerpos], write[position])==0) { n->b4[n->b4_size] = ret_d->dep[iter]; n->b4_size +=1; } innerpos+=1; } position +=1; } } //printf ("3"); //if there is a input depencdancy and there is a matching value in the dependancy graph //push the dependancy for this node if(read != NULL && iter < ret_d->dep_size){ while(read[position]!=NULL){ while(ret_d->dep[iter]->write[innerpos]!=NULL){ if(strcmp(ret_d->dep[iter]->write[innerpos], read[position])==0) { n->b4[n->b4_size] = ret_d->dep[iter]; n->b4_size +=1; } innerpos+=1; } position +=1; } } //printf ("4"); //same thing as above, but check the executable array for a dependancy if(read != NULL && iter < ret_d->no_dep_size){ while(read[position]!=NULL){ while(ret_d->no_dep[iter]->write[innerpos]!=NULL){ if(strcmp(ret_d->no_dep[iter]->write[innerpos], read[position])==0) { n->b4[n->b4_size] = ret_d->no_dep[iter]; n->b4_size +=1; } innerpos+=1; } position +=1; } } //printf ("5"); //this should do the same for the arguments parsed as command line and not strict //I/O redirection. This function checks the dependancy array of the graph if(args != NULL && iter < ret_d->dep_size){ while(args[position]!=NULL){ while(ret_d->dep[iter]->write[innerpos]!=NULL){ if(strcmp(ret_d->dep[iter]->write[innerpos], args[position])==0) { n->b4[n->b4_size] = ret_d->dep[iter]; n->b4_size +=1; } innerpos+=1; } position +=1; } } //printf ("6"); //same as above, but it checks the executable array for the graph if(args != NULL && iter < ret_d->no_dep_size){ while(args[position]!=NULL){ while(ret_d->no_dep[iter]->write[innerpos]!=NULL){ if(strcmp(ret_d->no_dep[iter]->write[innerpos], args[position])==0) { n->b4[n->b4_size] = ret_d->no_dep[iter]; n->b4_size +=1; } innerpos+=1; } position +=1; } } //printf ("6.5"); /*if(comm->input != NULL && iter < ret_d->depSize){ if(ret_d->dep[iter]->c->output == comm->input) { n->before[n->bef_size] = ret_d->dep[iter]; n->bef_size+=1; //ret_d->dep[iter]->after[ret_d->dep[iter]->aft_size] = n; //ret_d->dep[iter]->aft_size++; } }*/ //reset all the values that you used before in the loop position = 0; innerpos = 0; iter +=1; } //printf ("7"); //if at any point the bef_size of the current node has been altered so it is greater than 0, add this //node to the dependancy array for the graph if(n->b4_size > 0){//if (debugmode) printf("befsize = %zu\n", n->bef_size); add_dep_to_graph(ret_d, n, 1);} //if the node has no dependancies, then push it to the executable array of the dependancy graph else{// if (debugmode) printf("befsize = %zu\n", n->bef_size); add_dep_to_graph(ret_d, n, 0);} //reset iter for the next command that needs to be added iter = 0; //TODO: // Determine which nodes already seen depend on this one. // Look through the independent nodes. // If a match is found, add this node as a dependency // And move it to the node with dependencies list // Look through the nodes with dependencies. // If a match is found, add this node as a dependency //printf ("9"); } return ret_d; }
/* FIXME: Define the type 'struct command_stream' here. This should complete the incomplete type declaration in command.h. */ command_stream_t make_command_stream(int(*get_next_byte) (void *), void *get_next_byte_argument) { /* FIXME: Replace this with your implementation. You may need to add auxiliary functions and otherwise modify the source code. You can also use external functions defined in the GNU C Library. */ if (DEBUG) printf("291 Begin make_command_stream\n"); initStream(); size_t sizeofBuffer = 1024; char* buffer = (char*)checked_malloc(sizeofBuffer); char curr; size_t filled = 0; while ((curr = get_next_byte(get_next_byte_argument)) != EOF) { buffer[filled] = curr; filled++; if (filled == sizeofBuffer) { sizeofBuffer *= 2; buffer = (char*)checked_grow_alloc(buffer, &sizeofBuffer); } } //***For the parser: //Word int bufferWordSize = 10; int currWord = 0; //char ** wordElement; char** wordElement = checked_malloc(sizeof(char*)); wordElement[currWord] = (char*)checked_malloc(bufferWordSize); int usedWord = 0; //Input int bufferInputSize = 10; char* inputElement = (char*)checked_malloc(bufferInputSize); int usedInput = 0; //Output int bufferOutputSize = 10; char* outputElement = (char*)checked_malloc(bufferOutputSize); int usedOutput = 0; //***Initialize operator and command stacks initStacks(); if (DEBUG) printf("333 Buffer created, initStacks()\n"); int i = 0; while (i < (int)filled) { if (DEBUG) printf("on buffer %d\n", i); //***When you want to add a character*************************// int op = -1; int openCount = 0; int closedCount = 0; if (buffer[i] == '`') error(1, 0, "Line %d: %c", __LINE__, buffer[i]); if (buffer[i] == '(') { openCount = 1; closedCount = 0; int x = i; while (x < (int) filled) { x++; if (buffer[x] == '(') openCount++; if (buffer[x] == ')') closedCount++; if (closedCount == openCount) break; } if (closedCount != openCount) error(1, 0, "Line %d: Expected ')' for end of subshell", __LINE__); } if(buffer[i] == ')') { if(openCount == 0) error(1, 0, "Line %d: Expected '(' before ')'", __LINE__); } if(buffer[i] = '(') { op = numberOfOper(&buffer[i]); processOperator(op); } //Case of ' ' while (buffer[i] == ' ' && usedWord == 0) i++; if (buffer[i] == ' ' && usedWord != 0) { if (usedWord >= bufferWordSize) { bufferWordSize += 10; wordElement[currWord] = (char*)checked_realloc(wordElement[currWord], bufferWordSize); } //i++; wordElement[currWord][usedWord] = '\0'; while (buffer[i + 1] == ' ') i++; usedWord = 0; bufferWordSize = 10; currWord++; wordElement[currWord] = (char*)checked_malloc(bufferWordSize); //wordElement[currWord][usedWord] = buffer[i]; //usedWord++; } //Case of carrots //WHAT IF a<b>c>d<a....?! You're making a simple command out of a<b>c which then // must also be the word of >d<a //Case of '<' first else if (buffer[i] == '<') { int k = i; while (buffer[k-1] == ' ') { k--; if(buffer[k-1] == '\n') error(1, 0, "Line %d: Operator and word on diff lines", __LINE__); } if (wordElement[0][0] == '\0') error(1, 0, "Line %d: No command given to '<'", __LINE__); i++; while (buffer[i] != '<' && buffer[i] != '>' && buffer[i] != '&' && buffer[i] != '|' && buffer[i] != '(' && buffer[i] != ')' && buffer[i] != ';' && buffer[i] != '\n') { if (i == filled) { if (DEBUG) printf("378 Complete command, free buffer bc EOF\n"); currWord++; wordElement[currWord] = '\0'; if (usedInput == 0) inputElement = NULL; if (usedOutput == 0) outputElement = NULL; makeSimpleCommand(wordElement, inputElement, outputElement); completeCommand(); //free(buffer); return headStream; } if (buffer[i] == ' ') i++; else { if (usedInput >= bufferInputSize) { bufferInputSize += 10; inputElement = (char*)checked_realloc(inputElement, bufferInputSize); } inputElement[usedInput] = buffer[i]; usedInput++; i++; } } if (usedInput >= bufferInputSize) { bufferInputSize += 10; inputElement = (char*)checked_realloc(inputElement, bufferInputSize); } if (usedInput == 0) error(1, 0, "Line %d: No input after '<'", __LINE__); inputElement[usedInput] = '\0'; usedInput++; if (buffer[i] == '>') { i++; while (buffer[i] != '<' && buffer[i] != '>' && buffer[i] != '&' && buffer[i] != '|' && buffer[i] != '(' && buffer[i] != ')' && buffer[i] != ';' && buffer[i] != '\n') { if (i == filled) { if (DEBUG) printf("413 Complete command, free buffer at EOF\n"); currWord++; wordElement[currWord] = '\0'; if (usedInput == 0) inputElement = NULL; if (usedOutput == 0) outputElement = NULL; makeSimpleCommand(wordElement, inputElement, outputElement); completeCommand(); //free(buffer); return headStream; } if (buffer[i] == ' ') i++; else { if (usedOutput >= bufferOutputSize) { bufferOutputSize += 10; outputElement = (char*)checked_realloc(outputElement, bufferOutputSize); } outputElement[usedOutput] = buffer[i]; usedOutput++; i++; } } if (usedOutput >= bufferOutputSize) { bufferOutputSize += 10; outputElement = (char*)checked_realloc(outputElement, bufferOutputSize); } if (usedOutput == 0) error(1, 0, "Line %d: No input after '<'", __LINE__); outputElement[usedOutput] = '\0'; usedOutput++; //i--; //Check logic } i--; } /////CHECK FOR EXTRA i++!!!!! //Case of '>' first else if (buffer[i] == '>') { int k = i; while (buffer[k-1] == ' ') { k--; if(buffer[k-1] == '\n') error(1, 0, "Line %d: Operator and word on diff lines", __LINE__); } if (wordElement[0][0] == '\0') error(1, 0, "Line %d: No command given to '<'", __LINE__); i++; while (buffer[i] != '<' && buffer[i] != '>' && buffer[i] != '&' && buffer[i] != '|' && buffer[i] != '(' && buffer[i] != ')' && buffer[i] != ';' && buffer[i] != '\n') { if (i == filled) { if (DEBUG) printf("471 Complete Command, free buffer at EOF"); currWord++; wordElement[currWord] = '\0'; if (usedInput == 0) inputElement = NULL; if (usedOutput == 0) outputElement = NULL; makeSimpleCommand(wordElement, inputElement, outputElement); completeCommand(); //free(buffer); return headStream; } if (buffer[i] == ' ') i++; else { if (usedOutput >= bufferOutputSize) { bufferOutputSize += 10; outputElement = (char*)checked_realloc(outputElement, bufferOutputSize); } outputElement[usedOutput] = buffer[i]; usedOutput++; i++; } } if (usedOutput >= bufferOutputSize) { bufferOutputSize += 10; outputElement = (char*)checked_realloc(outputElement, bufferOutputSize); } if (usedOutput == 0) error(1, 0, "Line %d: No input after '<'", __LINE__); outputElement[usedOutput] = '\0'; usedOutput++; if (buffer[i] == '<') { i++; while (buffer[i] != '<' && buffer[i] != '>' && buffer[i] != '&' && buffer[i] != '|' && buffer[i] != '(' && buffer[i] != ')' && buffer[i] != ';' && buffer[i] != '\n') { if (i == filled) { if (DEBUG) printf("505 Complete Command, free buffer at EOF"); currWord++; wordElement[currWord] = '\0'; if (usedInput == 0) inputElement = NULL; if (usedOutput == 0) outputElement = NULL; makeSimpleCommand(wordElement, inputElement, outputElement); completeCommand(); //free(buffer); return headStream; } if (buffer[i] == ' ') i++; else { if (usedInput >= bufferInputSize) { bufferInputSize += 10; inputElement = (char*)checked_realloc(inputElement, bufferInputSize); } inputElement[usedInput] = buffer[i]; usedInput++; i++; } } if (usedInput >= bufferInputSize) { bufferInputSize += 10; inputElement = (char*)checked_realloc(inputElement, bufferInputSize); } if (usedInput == 0) error(1, 0, "Line %d: No input after '<'", __LINE__); inputElement[usedInput] = '\0'; usedInput++; } wordElement[currWord + 1] = '\0'; /*if (usedInput == 0) inputElement = NULL; if (usedOutput == 0) outputElement = NULL; if(DEBUG) printf("makeSimpleCommand %s\n", wordElement[0]); makeSimpleCommand(wordElement, inputElement, outputElement); bufferWordSize = 10; currWord = 0; usedWord = 0; usedInput = 0; usedOutput = 0; wordElement = (char**)checked_malloc(sizeof(char*)); wordElement[currWord] = (char*)checked_malloc(bufferWordSize); inputElement = (char*)checked_malloc(bufferInputSize); outputElement = (char*)checked_malloc(bufferOutputSize);*/ i--; } //Operators //After every operator is encountered, use makeSimpleCommand to push the command on the stack //Case of '|' else if (buffer[i] == '|') { int k = i; while (buffer[k-1] == ' ') { k--; if(buffer[k-1] == '\n') error(1, 0, "Line %d: Operator and word on diff lines", __LINE__); } if (buffer[i+1] == '|' && operatorStack == NULL) error(1, 0, "Line %d: Missing pipe for '||'", __LINE__); if (wordElement[0][0] == '\0') error(1, 0, "Line %d: Nothing for '|'", __LINE__); //if (commandStack == NULL) // error(1, 0, "Line %d: Nothing to run '|' on"); if (buffer[i + 1] == '|' && buffer[i+2] == '|') error(1, 0, "Line %d: Invalid Command, too many '|'", i); op = numberOfOper(&buffer[i]); //error(1, 0, "Line %d: Nothing to pipe", __LINE__); if (buffer[i-1] != ' ') currWord++; wordElement[currWord] = '\0'; if (usedInput == 0) inputElement = NULL; if (usedOutput == 0) outputElement = NULL; if (DEBUG) printf(" 566 makeSimpleCommand %s\n", wordElement[0]); makeSimpleCommand(wordElement, inputElement, outputElement); bufferWordSize = 10; currWord = 0; usedWord = 0; usedInput = 0; usedOutput = 0; wordElement = (char**)checked_malloc(sizeof(char*)); wordElement[currWord] = (char*)checked_malloc(bufferWordSize); inputElement = (char*)checked_malloc(bufferInputSize); outputElement = (char*)checked_malloc(bufferOutputSize); if (DEBUG) printf("577 Process operator %d\n", op); processOperator(op); if (op == 3) i++; if (buffer[i + 1] == ' ') i++; //i++; } //Case of '&' else if (buffer[i] == '&') { int k = i; while (buffer[k-1] == ' ') { k--; if(buffer[k-1] == '\n') error(1, 0, "Line %d: Operator and word on diff lines", __LINE__); } //if (buffer[i] == '&' && operatorStack == NULL) // error(1, 0, "Line %d: Missing pipe for '&&'", __LINE__); if (wordElement[0][0] == '\0') error(1, 0, "Line %d: Nothing for '|'", __LINE__); if (buffer[i + 1] == '&' && buffer[i+2] == '&') error(1, 0, "Line %d: Invalid Command, too many '&'", i); op = numberOfOper(&buffer[i]); if (buffer[i-1] != ' ') currWord++; wordElement[currWord] = '\0'; if (usedInput == 0) inputElement = NULL; if (usedOutput == 0) outputElement = NULL; if (DEBUG) printf("592 makeSimpleCommand %s\n", wordElement[0]); makeSimpleCommand(wordElement, inputElement, outputElement); bufferWordSize = 10; usedWord = 0; currWord = 0; usedInput = 0; usedOutput = 0; wordElement = (char**)checked_malloc(sizeof(char*)); wordElement[currWord] = (char*)checked_malloc(bufferWordSize); inputElement = (char*)checked_malloc(bufferInputSize); outputElement = (char*)checked_malloc(bufferOutputSize); processOperator(op); i++; if (buffer[i + 1] == ' ') i++; } //Case of ';' else if (buffer[i] == ';') { int k = i; while (buffer[k-1] == ' ') { k--; if(buffer[k-1] == '\n') error(1, 0, "Line %d: Operator and word on diff lines", __LINE__); } if(wordElement[0][0] == '\0') error(1, 0, "Line %d: Nothing before sequence", i); op = numberOfOper(&buffer[i]); currWord++; wordElement[currWord] = '\0'; if (usedInput == 0) inputElement = NULL; if (usedOutput == 0) outputElement = NULL; if (DEBUG) printf("617 makeSimpleCommand %s\n", wordElement[0]); if ((currWord = 0) || (currWord == 1)) error(1, 0, "Line %d: Nothing to run ';' on", i); makeSimpleCommand(wordElement, inputElement, outputElement); bufferWordSize = 10; usedWord = 0; currWord = 0; usedInput = 0; usedOutput = 0; wordElement = (char**)checked_malloc(sizeof(char*)); wordElement[currWord] = (char*)checked_malloc(bufferWordSize); inputElement = (char*)checked_malloc(bufferInputSize); outputElement = (char*)checked_malloc(bufferOutputSize); processOperator(op); //i++; } //Case of '\n' else if (buffer[i] == '\n' && i != 0) { /*int scChecker = i; while (buffer[i + 1] == ' ') { scChecker++; if (buffer[scChecker + 1] == ';') error(1, 0, "Line %d: Newline followed by ';'"); }*/ if (buffer[i+1] == ';') error(1, 0, "Line %d: Newline followed by ';'", i); if ((i + 1) == (int)filled) { currWord++; wordElement[currWord] = '\0'; if (usedInput == 0) inputElement = NULL; if (usedOutput == 0) outputElement = NULL; if (DEBUG) printf("654 makeSimpleCommand %s\n", wordElement[0]); makeSimpleCommand(wordElement, inputElement, outputElement); bufferWordSize = 10; currWord = 0; usedWord = 0; usedInput = 0; usedOutput = 0; wordElement = (char**)checked_malloc(sizeof(char*)); wordElement[currWord] = (char*)checked_malloc(bufferWordSize); inputElement = (char*)checked_malloc(bufferInputSize); outputElement = (char*)checked_malloc(bufferOutputSize); completeCommand(); free(buffer); return headStream; } char lastC; int back = 1; while (buffer[i - back] == ' ' && i - back >= 0) { //lastC = buffer[i - back]; back++; } lastC = buffer[i - back]; if (buffer[i + 1] == '\n') { while (buffer[i + 1] == '\n') i++; if (lastC != '|' && lastC != '&') { currWord++; wordElement[currWord] = '\0'; if (usedInput == 0) inputElement = NULL; if (usedOutput == 0) outputElement = NULL; if (DEBUG) printf("654 makeSimpleCommand %s\n", wordElement[0]); makeSimpleCommand(wordElement, inputElement, outputElement); bufferWordSize = 10; currWord = 0; usedWord = 0; usedInput = 0; usedOutput = 0; wordElement = (char**)checked_malloc(sizeof(char*)); wordElement[currWord] = (char*)checked_malloc(bufferWordSize); inputElement = (char*)checked_malloc(bufferInputSize); outputElement = (char*)checked_malloc(bufferOutputSize); completeCommand(); } } else { if (lastC == '|' || lastC == '&' || lastC == '<' || lastC || '>') { while (buffer[i + 1] == '\n') i++;//////SPIT ERROR? } else { char swap = ';'; op = numberOfOper(&swap); wordElement[currWord + 1] = '\0'; if (usedInput == 0) inputElement = NULL; if (usedOutput == 0) outputElement = NULL; if (DEBUG) printf(" 679 makeSimpleCommand %s\n", wordElement[0]); makeSimpleCommand(wordElement, inputElement, outputElement); bufferWordSize = 10; currWord = 0; usedWord = 0; usedInput = 0; usedOutput = 0; wordElement = (char**)checked_malloc(sizeof(char*)); wordElement[currWord] = (char*)checked_malloc(bufferWordSize); inputElement = (char*)checked_malloc(bufferInputSize); outputElement = (char*)checked_malloc(bufferOutputSize); processOperator(op); } } } //Case of # (comment) else if (buffer[i] == '#') { if (DEBUG) printf("698 Got a comment!\n"); while (buffer[i] != '\n') i++; } //Else else { if (buffer[i] == '\'') { if (buffer[i + 1] == 'E' && buffer[i + 2] == 'O' && buffer[i + 3] == 'F') break; } //if (buffer[i] != ' ') wordElement[currWord][usedWord] = buffer[i]; usedWord++; if (i + 1 == filled) { currWord++; wordElement[currWord] = '\0'; if (usedInput == 0) inputElement = NULL; if (usedOutput == 0) outputElement = NULL; makeSimpleCommand(wordElement, inputElement, outputElement); completeCommand(); } } i++; } free(buffer); return headStream; }
int main (int argc, char **argv) { int command_number = 1; bool print_tree = false; bool time_travel = false; program_name = argv[0]; for (;;) switch (getopt (argc, argv, "pt")) { case 'p': print_tree = true; break; case 't': time_travel = true; break; default: usage (); break; case -1: goto options_exhausted; } options_exhausted:; // There must be exactly one file argument. if (optind != argc - 1) usage (); script_name = argv[optind]; FILE *script_stream = fopen (script_name, "r"); if (! script_stream) error (1, errno, "%s: cannot open", script_name); command_stream_t command_stream = make_command_stream (get_next_byte, script_stream); command_t last_command = NULL; command_t command; if(time_travel) { size_t command_buf = 16; command_t* command_array = NULL; command_array = (command_t*) checked_malloc(command_buf*sizeof(command_t)); int command_count = 0; int i; int previous_command = 0; for (command_count = 0; (command = read_command_stream (command_stream)); command_count++) { if (command_count == (int)command_buf) command_array = (command_t*) checked_grow_alloc(command_array, &command_buf); command_array[command_count] = command; } bool dependency_matrix[command_count][command_count]; int j; int k; bool run_command; pid_t pid; int fd[command_count][2]; int retval; fd_set set; int buf; int m; int z; int read_return; for (j=0; j < command_count; j++) for (k = 0; k < command_count; k++) dependency_matrix[j][k] = false; //Iterating through all commands for (i=0; i < command_count; i++) { //Iterating through all commands preceding it for (previous_command = i-1; previous_command >= 0; previous_command--) { //Iterating through the output files of the current command for (j=0; j < command_array[i]->top_outputs_count; j++) { //Iterating through the input files of the preceding command for (k=0; k < command_array[previous_command]->top_inputs_count; k++) { if (strcmp(command_array[i]->top_outputs[j], command_array[previous_command]->top_inputs[k]) == 0) { dependency_matrix[i][previous_command] = true; break; } } //Iterating through the output files of the preceding command for (k=0; k < command_array[previous_command]->top_outputs_count; k++) { if (strcmp(command_array[i]->top_outputs[j], command_array[previous_command]->top_outputs[k]) == 0) { dependency_matrix[i][previous_command] = true; break; } } } //Iterating through the input files of the current command for (j=0; j < command_array[i]->top_inputs_count; j++) { //Iterating through the input files of the preceding command for (k=0; k < command_array[previous_command]->top_inputs_count; k++) { if (strcmp(command_array[i]->top_inputs[j], command_array[previous_command]->top_inputs[k]) == 0) { dependency_matrix[i][previous_command] = false; break; } } //Iterating through the output files of the preceding command for (k=0; k < command_array[previous_command]->top_outputs_count; k++) { if (strcmp(command_array[i]->top_inputs[j], command_array[previous_command]->top_outputs[k]) == 0) { dependency_matrix[i][previous_command] = true; break; } } } } } for(z=0; z < command_count; z++) fd[z][0] = 0; bool done = false; while(!done) { for (i=0; i < command_count; i++) { run_command = true; for (k=0; k < command_count; k++) { if (dependency_matrix[i][k]) { run_command = false; break; } } if (run_command) { dependency_matrix[i][i] = true; if (pipe(fd[i]) != 0) { fprintf(stderr, "Failed to initialize pipe\n"); exit(1); } //Child process pid = fork(); if(pid == 0) { close(fd[i][0]); execute_command (command_array[i], false); //Setup pipe for writing from child to parent m = i; // fprintf(stderr, "write#:%i\n", m); write(fd[i][1], &m, sizeof(int)); close(fd[i][1]); exit(command_array[i]->status); } //Parent Process else if (pid > 0) { close(fd[i][1]); continue; } else { fprintf(stderr, "Failed to fork\n"); exit(1); } } } FD_ZERO(&set); for(z=0; z < command_count; z++) { if(fd[z][0] != 0) { FD_SET(fd[z][0], &set); //fprintf(stderr, "set\n"); } } retval = select(FD_SETSIZE, &set, NULL, NULL, NULL); if(retval == -1) { fprintf(stderr, "Error monitoring pipes"); exit(1); } for(z=0; z < command_count; z++) { if(fd[z][0] != 0) { //fprintf(stderr, "fjieowajfoew\n"); read_return = read(fd[z][0], &buf, sizeof(int)); if(read_return > 0) { //fprintf(stderr, "Read: %i\n", buf); for(k=0; k < command_count; k++) dependency_matrix[k][buf] = false; //Set child command dependent to itself to indicate that it has already successfully executed dependency_matrix[buf][buf] = true; //close(fd[z][0]); } else if(read_return == -1) { fprintf(stderr, "Error reading\n"); exit(1); } } } for(z=0; z < command_count; z++) { if(!dependency_matrix[z][z]) break; } if(z == command_count) done = true; // FD_ZERO(&set); // FD_SET(fd[0], &set); //When this returns, data has been detected from pipe // retval = select(FD_SETSIZE, &set, NULL, NULL, NULL); // fprintf(stderr, "Select read:%i\n", retval); /* while (read(fd[0], &buf, sizeof(int)) > 0) { fprintf(stderr, "Going through while loop with buf:%i \n", buf); for(k=0; k < command_count; k++) dependency_matrix[k][buf] = false; //Set child command dependent to itself to indicate that it has already successfully executed dependency_matrix[buf][buf] = true; } fprintf(stderr, "z:%i\n", z); */ /* int read_return; while((read_return = read(fd[0], &buf, sizeof(int))) <= 0) { if (read_return == -1) { fprintf(stderr, "Error:%i\n", errno); fprintf(stderr, "Error reading\n"); exit(1); } } fprintf(stderr, "Iteration:%i\nNum_read:%i\n", z, read_return); do { fprintf(stderr, "Bufval:%i\n", buf); for(k=0; k < command_count; k++) dependency_matrix[k][buf] = false; //Set child command dependent to itself to indicate that it has already successfully executed dependency_matrix[buf][buf] = true; } while(read(fd[0], &buf, sizeof(int)) > 0); close(fd[0]); */ } for(z=0; z < command_count; z++) close(fd[z][0]); while((pid = wait(NULL))) { if(pid == -1 && errno == ECHILD) break; else if(pid == -1) { fprintf(stderr, "Error waiting on children"); exit(1); } } /* for (i = 0; i < command_count; i++) { last_command = command_array[i]; execute_command(command_array[i], false); } */ } else { while ((command = read_command_stream (command_stream))) { if (print_tree) { printf ("# %d\n", command_number++); print_command (command); } else { last_command = command; execute_command (command, time_travel); } } } return print_tree || !last_command ? 0 : command_status (last_command); }
/////////////////////////////////////////////////////////////////// //Creates the stream of tokens for use in stack processing later.// /////////////////////////////////////////////////////////////////// struct token_node_list* create_token_stream(char* input, int num_of_chars){ //Create the token node list struct token_node_list* new_token_list= malloc(sizeof(struct token_node_list)); struct token_node_list* head_of_list = new_token_list; //Make dummy token in order to avoid NULL token_type pointer struct token_node* dummy_head = add_token(new_token_list, NULL,DUMMY_HEAD); new_token_list->head = dummy_head; char char_to_sort = *input; int nested_breaker = 0; int char_num_counter = 0; while(char_num_counter < num_of_chars){ if(char_to_sort == '\000'){ return head_of_list; } //Check to see if word if(isWord(char_to_sort)){ //If so, store the word in its own token size_t size = 8; char* w = checked_malloc(size); size_t word_index = 0; do{ w[word_index] = char_to_sort; word_index++; if(word_index == size){ size = size*2; w = checked_grow_alloc(w, &size); } char_num_counter++; //increment index input++; //increment stream pointer char_to_sort = *input; }while(isWord(char_to_sort) && char_num_counter < num_of_chars); new_token_list->cur_node = add_token(new_token_list, w, WORD); } //Handle useless white space else if(char_to_sort == ' ' || char_to_sort == '\t'){ char_num_counter++; //increment index input++; //increment stream pointer char_to_sort = *input; } //Check for subshell else if( char_to_sort == '('){ //TODO int num_pairs = 1; int open_pars = 1; int close_pars = 0; int parens_valid = 0; int index = 0; int buf_size = 10; //random low num for most purposes char *ss_buf = malloc(buf_size* sizeof(char)); if(ss_buf == NULL) fprintf(stderr, "\n Error allocating memory for subshell parse.\n"); while(num_pairs>0){ char_num_counter++; //increment index input++; //increment stream pointer char_to_sort = *input; if(char_num_counter == num_of_chars){ //gone through all chars fprintf(stderr, "\nAll characters used.\n"); return NULL; } else if(char_to_sort == '('){ open_pars++; num_pairs++; } else if(char_to_sort == ')'){ //Decrease the number of pairs. close_pars++; num_pairs--; parens_valid = open_pars-close_pars; if(num_pairs == 0 && parens_valid == 0){ char_num_counter++; input++; char_to_sort = *input; break; } } else if(char_to_sort == '\n'){ if(input[1] == '\000'){ error(6, 0, "input[1] is null, so nothing after the newline."); } while(input[1] != ' ' || input[1] != '\t' || input[1] != '\n'){ //Eliminate useless characters input++; char_to_sort++; } //Spec says to substitute semicolon for \n char_to_sort = ';'; } ss_buf[index] = char_to_sort; index++; if(index == buf_size){ buf_size+=2; ss_buf = realloc(ss_buf, buf_size*sizeof(char)); if(ss_buf == NULL){ fprintf(stderr, "\n Error reallocating memory for subshell buffer.\n"); return NULL; } } if( num_pairs == 0 && parens_valid == 0) break; else if(num_pairs == 0 && parens_valid != 0){ error(2, 0, "\n Mismatched parentheses.\n"); return NULL; } } new_token_list->cur_node = add_token(new_token_list, ss_buf, SUBSHELL); } //Check for OR and PIPE else if(char_to_sort == '|'){ char_num_counter++; input++; //increment pointer char_to_sort = *input; //Check to see if the next character is also a pipe, this is an OR if(char_to_sort == '|'){ //Add a token node for OR new_token_list->cur_node = add_token(new_token_list, NULL, OR); char_num_counter++; input++; //increment pointer char_to_sort = *input; //peek at the next character }else new_token_list->cur_node = add_token(new_token_list, NULL, PIPE); } //Check for & and AND, code is same as OR case else if(char_to_sort == '&'){ char_num_counter++; input++; //increment pointer char_to_sort = *input; //peek at the next character if(char_to_sort == '&'){ //This is an and new_token_list->cur_node = add_token(new_token_list, NULL, AND); char_num_counter++; input++; //increment pointer char_to_sort = *input; //peek at the next character }else if(char_to_sort != '&'){ error(2,0, "\n Single and...error.\n"); return NULL; } } //Check for left redirect else if(char_to_sort == '<'){ new_token_list->cur_node = add_token(new_token_list, NULL, LEFT_REDIRECT); char_num_counter++; input++; //increment pointer char_to_sort = *input; //peek at the next character } //Check for right redirect else if(char_to_sort == '>'){ new_token_list->cur_node = add_token(new_token_list, NULL, RIGHT_REDIRECT); //hurwitz char_num_counter++; input++; //increment pointer char_to_sort = *input; //peek at the next character } //Handle newline else if(char_to_sort == '\n'){ if(*input++ == '\000'){ return head_of_list; break; }else *input--; switch(new_token_list->cur_node->token_type){ case LEFT_REDIRECT: case RIGHT_REDIRECT: error(2, 0, "\n Error in syntax. Redirect before newline.\n"); return NULL; break; case WORD: case SUBSHELL: if(new_token_list->cur_node->token_type != DUMMY_HEAD){ new_token_list->next = malloc(sizeof(struct token_node_list)); if(new_token_list->next == NULL){ fprintf(stderr, "\nError allocating memory for new tree in create_token_stream.\n"); return NULL; } new_token_list = new_token_list->next; if(new_token_list == NULL) fprintf(stderr, "\n new_token_list is NULL in handling newline\n"); new_token_list->head = add_token(new_token_list, NULL, DUMMY_HEAD ); new_token_list->cur_node = new_token_list->head; } break; default: break; }/* if(char_to_sort == ';'){ new_token_list->cur_node = add_token(new_token_list, NULL, SEMICOLON); }*/ char_num_counter++; input++; //increment pointer char_to_sort = *input; //peek at the next character } //Check for semicolon else if(char_to_sort == ';'){ new_token_list->cur_node = add_token(new_token_list, NULL, SEMICOLON); char_num_counter++; //increment index input++; //increment stream pointer char_to_sort = *input; } else{ error(4, 0,"\nCharacter is not a word or a special token.\n"); return NULL; //no character matches } } //Return pointer to the top of the token_stream return head_of_list; }
command_stream_t make_command_stream(int (*get_next_byte)(void *), void *get_next_byte_argument) { // read all the input size_t bufferSize = 1024; size_t read = 0; int val; char* buffer = (char*) checked_malloc(bufferSize); while ((val = get_next_byte(get_next_byte_argument)) != EOF) { buffer[read++] = val; if (read == bufferSize) { buffer = (char*) checked_grow_alloc(buffer, &bufferSize); } } if (read == bufferSize) { buffer = (char*) checked_grow_alloc(buffer, &bufferSize); } buffer[read] = 0; // lex the input token* tokens; size_t num_tokens = 0; lexer(buffer, &tokens, &num_tokens); //test_arvore_vec(tokens, num_tokens); //exit(0); // put all the tokens into a vector arvore_vec* v; init_arvore_vec(&v, num_tokens); size_t i = 0; for (; i < num_tokens; i++) { arvore a; a.type = TOKEN_AT; a.u.tok = tokens + i; append_arvore_vec(v, a); } // parse tokens into AST command_t top_cmd = parse(v); //print_command(top_cmd); // break top level sequence commands down arvore_vec* stack; init_arvore_vec(&stack, 10); arvore x; x.type = COMMAND_AT; x.u.cmd = top_cmd; append_arvore_vec(stack, x); arvore_vec* list; init_arvore_vec(&list, 10); while (stack->size > 0) { arvore pop = get_arvore_vec(stack, stack->size - 1); command_t cmd = pop.u.cmd; stack->size--; if (cmd->type == SEQUENCE_COMMAND) { arvore a; a.type = COMMAND_AT; a.u.cmd = cmd->u.command[0]; arvore b; b.type = COMMAND_AT; b.u.cmd = cmd->u.command[1]; append_arvore_vec(stack, b); append_arvore_vec(stack, a); } else { append_arvore_vec(list, pop); } } // create command stream command_stream_t cst = (command_stream_t) checked_malloc( sizeof(struct command_stream)); cst->commands = (command_t*) checked_malloc(sizeof(command_t) * list->size); for (i = 0; i < list->size; i++) cst->commands[i] = get_arvore_vec(list, i).u.cmd; cst->size = list->size; cst->iterator = 0; return cst; // debug /*char* type_names[11] = { "word", ";", "|", "&&", "||", "(", ")", "<", ">", "NL", "?" }; for (i = 0; i < num_tokens; i++) { token t = tokens[i]; if (t.type != NEWLINE_TOKEN) printf("%s\t%s\n", type_names[t.type], t.text); else printf("%s\n", type_names[t.type]); }*/ }
command_stream_t make_command_stream (int (*get_next_byte) (void *), void *get_next_byte_argument) { /* FIXME: Replace this with your implementation. You may need to add auxiliary functions and otherwise modify the source code. You can also use external functions defined in the GNU C Library. */ /* create a previous byte character to see what the previous character was */ /*char previous_byte = get_next_byte(get_next_byte_argument); */ /* create a current_byte char to look at the current byte */ char current_byte; /* create a temporary array to hold all the commands that we will even put together into a tree */ command_t temp_command = NULL; /*char buffer array to take in all the characters from the file in the beginning*/ char* char_buffer; /*index for what element in the character buffer we are currently looking at */ int buf_index = 0; /*malloc initialize size of char buffer to 16, change size of character to indicate that */ char_buffer = (char *)checked_malloc(256 * sizeof(char)); size_t size = (size_t) 256 * sizeof(char); /*for changing subshell commands*/ int* start_index = (int*) checked_malloc(sizeof(int*)); /*to create array of commands */ size_t array_size = (sizeof(command_t) * 1024); command_t* temp_array = (command_t*) checked_malloc(array_size); int temp_idx = 0; int num_cmds = 0; /*create primary array of commands*/ command_stream_t output = (command_stream_t) checked_malloc(sizeof(struct command_stream)); output->command_array = (command_t*) checked_malloc((size_t) sizeof(command_t) * 8); output->index = 0; output->size = 0; current_byte = get_next_byte(get_next_byte_argument); int placeholder; while (current_byte != EOF) { /*realloc memory */ if (buf_index * sizeof(char) == size) {char_buffer = (char *) checked_grow_alloc(char_buffer, &size);} char_buffer[buf_index] = current_byte; buf_index++ ; current_byte = get_next_byte(get_next_byte_argument); } char_buffer[buf_index] = current_byte; /* set buf_index back to 0 once we are done reading */ buf_index = 0; /* keep track of line for return error */ int line_num = 1; /* create variable to check if we are in a subshell or not */ int open_bracket = 0; char current_buffer = char_buffer[buf_index]; /* checked the bytes in the command buffer we have just created one by one to create commands */ while (current_buffer != EOF) { /* check correct use of paranthesis */ /* store what we are currently looking at in the buffer into a char*/ /* ignore white spaces, tabs, and comment symbol */ while((current_buffer == ' ') || (current_buffer == '\t') || (current_buffer == '#')) { /* if comment, ignore until newline */ if(current_buffer == '#') { if (buf_index >0) { if (char_buffer[buf_index-1] != ' ' && char_buffer[buf_index-1] != '\n') { error(1, 0, "invalid character before #"); } } while(current_buffer != '\n') {buf_index++; current_buffer = char_buffer[buf_index];} } else {buf_index++; current_buffer = char_buffer[buf_index];} } if (check_for_simple(current_buffer) == 1) { /* put code to retrieve following simple command, and put it into a simple command struct */ temp_command = retrieve_simple_command(char_buffer, &buf_index); } else if (check_for_special_token(current_buffer) == 1) { /* check to see which special token the character currently is and put the command into the proper special command struct" */ if(current_buffer == '&') { if (temp_idx > 0) { if(temp_array[temp_idx-1]->type != SIMPLE_COMMAND && temp_array[temp_idx-1]->type != RIGHT_PAREN) { error(1,0, "Two consecutive special commands in line: %i",line_num); } } buf_index++; current_buffer = char_buffer[buf_index]; /* check if AND_COMMAND is valid */ if(current_buffer == '&') { placeholder = buf_index; buf_index++; current_buffer = char_buffer[buf_index]; while(current_buffer == ' ' || current_buffer == '\n' || current_buffer == '\t' || current_buffer == '#') { /* if comment, ignore until newline */ if(current_buffer == '#') { if (buf_index >0) { if (char_buffer[buf_index-1] != ' ' && char_buffer[buf_index-1] != '\n') { error(1, 0, "invalid character before #"); } } while(current_buffer != '\n') {buf_index++; current_buffer = char_buffer[buf_index];} } buf_index++; current_buffer = char_buffer[buf_index]; } if(current_buffer == '(' || check_for_simple(current_buffer) == 1) { temp_command = make_special_command(AND_COMMAND); buf_index = placeholder; current_buffer = char_buffer[buf_index]; } else { error(1,0, "Invalid token after '&' in line: %i",line_num); } } /*also check if next command in array of commands is a simple command or a LEFT PAREN */ /* add and command to array of commands */ } else if(current_buffer == '|') { if (temp_idx > 0) { if(temp_array[temp_idx-1]->type != SIMPLE_COMMAND && temp_array[temp_idx-1]->type != RIGHT_PAREN) { error(1,0, "Two consecutive special commands in line: %i",line_num); } } /* check if OR_COMMAND or PIPE_COMMAND is valid */ buf_index++; current_buffer = char_buffer[buf_index]; if(current_buffer == '|') { placeholder = buf_index; buf_index++; current_buffer = char_buffer[buf_index]; while(current_buffer == ' ' || current_buffer == '\n' || current_buffer == '\t' || current_buffer == '#') { /* if comment, ignore until newline */ if(current_buffer == '#') { if (buf_index >0) { if (char_buffer[buf_index-1] != ' ' && char_buffer[buf_index-1] != '\n') { error(1, 0, "invalid character before #"); } } while(current_buffer != '\n') {buf_index++; current_buffer = char_buffer[buf_index];} } buf_index++; current_buffer = char_buffer[buf_index]; } if(current_buffer == '(' || check_for_simple(current_buffer) == 1) { temp_command = make_special_command(OR_COMMAND); buf_index = placeholder; current_buffer = char_buffer[buf_index]; } else { error(1, 0, "invalid token after '||'"); } buf_index = placeholder; current_buffer = char_buffer[buf_index]; } else if(current_buffer == ' ' || current_buffer == '\n' || current_buffer == '\t' || current_buffer == '(' || check_for_simple(current_buffer) == 1) { placeholder = buf_index-1; while(current_buffer == ' ' || current_buffer == '\n' || current_buffer == '\t' || current_buffer == '#') { /* if comment, ignore until newline */ if(current_buffer == '#') { if (buf_index >0) { if (char_buffer[buf_index-1] != ' ' && char_buffer[buf_index-1] != '\n') { error(1, 0, "invalid character before #"); } } while(current_buffer != '\n') {buf_index++; current_buffer = char_buffer[buf_index];} } buf_index++; current_buffer = char_buffer[buf_index]; } if(current_buffer == '(' || check_for_simple(current_buffer) == 1) { temp_command = make_special_command(PIPE_COMMAND); buf_index = placeholder; current_buffer = char_buffer[buf_index]; } else { error(1, 0, "invalid token after '||'"); } buf_index = placeholder; current_buffer = char_buffer[buf_index]; } } else if(current_buffer == '(') { open_bracket++; placeholder = buf_index; buf_index++; current_buffer = char_buffer[buf_index]; while (current_buffer == ' ' || current_buffer == '\n' || current_buffer == '\t' || current_buffer == '#') { /* if comment, ignore until newline */ if(current_buffer == '#') { if (buf_index >0) { if (char_buffer[buf_index-1] != ' ' && char_buffer[buf_index-1] != '\n') { error(1, 0, "invalid character before #"); } } while(current_buffer != '\n') {buf_index++; current_buffer = char_buffer[buf_index];} } buf_index++; current_buffer = char_buffer[buf_index]; } if(check_for_simple(current_buffer) == 1) { temp_command = make_special_command(LEFT_PAREN); } else { error(1,0, "Invalid token after '(' in line: %i",line_num); } buf_index = placeholder; current_buffer = char_buffer[buf_index]; } else if(current_buffer == ')') { open_bracket--; if(open_bracket < 0) { error(1,0, "')' cannot precede '(' in line: %i",line_num); } temp_command = make_special_command(RIGHT_PAREN); } else if(current_buffer == '<') { if (temp_idx >= 2) { if (temp_array[temp_idx -2]->type == GREATER_THAN) {error(1,0, "Invalid token after '<' in line: %i",line_num);} } placeholder = buf_index; buf_index++; current_buffer = char_buffer[buf_index]; while(current_buffer == ' ' || current_buffer == '\t') { buf_index++; current_buffer = char_buffer[buf_index]; } if (check_for_simple(current_buffer)) { temp_command = make_special_command(LESS_THAN); buf_index = placeholder; current_buffer = char_buffer[buf_index]; } else { error(1,0, "Invalid token after '<' in line: %i",line_num);} } else if(current_buffer == '>') { placeholder = buf_index; buf_index++; current_buffer = char_buffer[buf_index]; while(current_buffer == ' ' || current_buffer == '\t') { buf_index++; current_buffer = char_buffer[buf_index]; } if (check_for_simple(current_buffer)) { temp_command = make_special_command(GREATER_THAN); buf_index = placeholder; current_buffer = char_buffer[buf_index]; } else { error(1,0, "Invalid token after '>' in line: %i",line_num); } } else if(current_buffer == ';' && open_bracket > 0 && temp_idx != 0) { placeholder = buf_index; buf_index++; current_buffer = char_buffer[buf_index]; while (current_buffer == ' ' || current_buffer== '\n' || current_buffer == '\t' || current_buffer == '#') { if (current_buffer == '#') { if (buf_index >0) { if (char_buffer[buf_index-1] != ' ' && char_buffer[buf_index-1] != '\n') { error(1, 0, "invalid character before #"); } } while(current_buffer != '\n') {buf_index++; current_buffer = char_buffer[buf_index];} } buf_index++; current_buffer = char_buffer[buf_index]; } if( check_for_simple(current_buffer) == 1) { temp_command = make_special_command(SEQUENCE_COMMAND); buf_index = placeholder; current_buffer = char_buffer[buf_index]; } else if (current_buffer == '(') { temp_command = make_special_command(SEQUENCE_COMMAND); buf_index = placeholder; current_buffer = char_buffer[buf_index]; } else if (current_buffer == ')') { buf_index = placeholder; current_buffer = char_buffer[buf_index]; } else { error(1,0, "Invalid token after ';' in line: %i",line_num); } } else if(current_buffer == ';' && temp_idx == 0) {error(1,0, "Invalid token in line: %i",line_num);} } else if (current_buffer == '#') { if(buf_index >0) { if (char_buffer[buf_index-1] != ' ') {error(1,0, "Invalid token in line: %i",line_num);} } while(current_buffer != '\n') {buf_index++; current_buffer = char_buffer[buf_index];} } else if (current_buffer != '\n' && current_buffer != EOF) {error(1,0, "Invalid token in line: %i",line_num);} /*check if we are at a newline and we are not in a subshell command */ if(((current_buffer == '\n') || (current_buffer == ';')) && (temp_idx != 0)) { if (open_bracket == 0) { if (temp_array[temp_idx-1]->type == SIMPLE_COMMAND|| temp_array[temp_idx-1]->type == RIGHT_PAREN) { output->command_array[output->size] = make_tree(temp_array, num_cmds, start_index, 0); output->size++; *start_index = 0; free(temp_array); array_size = (size_t) (sizeof(command_t) * 1024); temp_array = (command_t*) checked_malloc(array_size); temp_idx = 0; num_cmds = 0; } } else if (open_bracket>0) { if (current_buffer == '\n') { if (temp_idx > 0) { if (temp_array[temp_idx-1]->type == SIMPLE_COMMAND) { placeholder = buf_index; buf_index++; current_buffer = char_buffer[buf_index]; while (current_buffer == ' ' || current_buffer == '\n') { buf_index++; current_buffer = char_buffer[buf_index]; } if (current_buffer == '(' || check_for_simple(current_buffer)) { temp_command = make_special_command(SEQUENCE_COMMAND); /*check if we need to resize */ if ((temp_idx * sizeof(command_t)) == array_size) temp_array = (command_t*) checked_grow_alloc(temp_array, &array_size); temp_array[temp_idx] = temp_command; temp_idx++; num_cmds++; } buf_index = placeholder; current_buffer = char_buffer[buf_index]; } } /* else do nothing */ } else if (current_buffer == ';') { if (temp_idx > 0) { if (temp_command->type == SEQUENCE_COMMAND) { if (temp_array[temp_idx-1]->type == SIMPLE_COMMAND) { /*check if we need to resize */ if ((temp_idx * sizeof(command_t)) == array_size) temp_array = (command_t*) checked_grow_alloc(temp_array, &array_size); temp_array[temp_idx] = temp_command; temp_idx++; num_cmds++; } } } } } } /*add command to temporary command array */ if (current_buffer != '\n' && current_buffer != ';' && current_buffer != EOF) { if(temp_idx == 0) { if(temp_command->type != SIMPLE_COMMAND && temp_command->type != LEFT_PAREN) { error(1,0, "The first command must be a simple command or open parenthesis in line: %i",line_num-1); } } /*check if we need to resize */ if ((temp_idx * sizeof(command_t)) == array_size) temp_array = (command_t*) checked_grow_alloc(temp_array, &array_size); temp_array[temp_idx] = temp_command; temp_idx++; num_cmds++; } buf_index++; current_buffer = char_buffer[buf_index]; if((current_buffer == EOF) && (temp_idx != 0)) { if (open_bracket > 0) { error(1,0, "Unclosed parenthesis in line: %i",line_num-1);} if (temp_idx > 0) { if (temp_array[temp_idx-1]->type != SIMPLE_COMMAND && temp_array[temp_idx-1]->type != RIGHT_PAREN) { error(1, 0, "last command is not a simple command or right paren"); } } output->command_array[output->size] = make_tree(temp_array, num_cmds, start_index, 0); output->size++; *start_index = 0; free(temp_array); } } /* previous byte becomes current byte */ /*previous_byte = current_byte;*/ return output; }
char* get_executable_path (char* bin_name) { if(bin_name == NULL) return NULL; // Check if this is a valid absolute price if (file_exists (bin_name)) return bin_name; // First, find the current working directory char *cwd = getcwd (NULL, 0); // Does it exist relative to the current directory? char *path = checked_malloc (sizeof(char) * (strlen(cwd) + strlen(bin_name) + 1 + 1)); // Add one char for '/' and one for NULL strcpy (path, cwd); strcat (path, "/"); strcat (path, bin_name); if (file_exists (path)) return path; // If not, let's try the system PATH variable and see if we have any matches there char *syspath = getenv ("PATH"); // "The application shall ensure that it does not modify the string pointed to by the getenv() function." // By definition of getenv, we copy the string and modify the copy with strtok char *syspath_copy = checked_malloc(sizeof (char) * (strlen (syspath) + 1 + 1)); // Add one char for '/' and one for NULL strcpy (syspath_copy, syspath); // Split the path char **path_elements = NULL; char *p = strtok (syspath_copy, ":"); int path_items = 0, i; while (p) { path_elements = checked_realloc (path_elements, sizeof (char*) * (path_items + 2)); path_elements[path_items] = p; path_items++; p = strtok (NULL, ":"); } path_elements[path_items] = NULL; // Make sure the last item is null for later looping // Now, let's iterate over each item in the path and see if it's a fit for (i = 0; path_elements[i] != NULL; i++) { size_t len = sizeof(char) * (strlen(bin_name) + strlen(path_elements[i]) + 1); path = checked_grow_alloc (path, &len); strcpy (path, path_elements[i]); strcat (path, "/"); strcat (path, bin_name); if (file_exists (path)) { free (path_elements); free (syspath_copy); return path; } } free (path_elements); free (syspath_copy); free (path); return NULL; // If we got this far, there's an error. }
void input_dependencies (cmd_stream_t stream) { const int INC = sizeof(int); size_t size = INC; size_t id_size = size; stream->curr = stream->tail; cmd_node_t current = stream->curr; cmd_node_t ptr; // Loop through each complete command in stream // Starts at tail of stream and goes backwards while (current != NULL) { size = INC; int* ids = checked_malloc(size*sizeof(int)); int id_index = 0; ids[0] = 0; ptr = stream->head; // Check each file dependency if (current->depends != NULL) { current->depends->curr = current->depends->head; file_node_t ptr0 = current->depends->curr; // Go through each file in current command while (ptr0 != NULL) { //printf("Going through each file in current command\n"); ptr = stream->head; // Go through each previous command while (ptr != current) { // Go through each file in this previous command if (ptr->depends != NULL) { ptr->depends->curr = ptr->depends->head; while (ptr->depends->curr != NULL) { // Found dependent file if (strcmp(ptr0->name, ptr->depends->curr->name) == 0 && (ptr->depends->curr->type == 'w' || ptr0->type == 'w')) { int j = 0; while (j < id_index) { if (ids[j] == ptr->id) break; ++j; } // If command id was not already in list, add it if (j == id_index) { ids = checked_grow_alloc(ids, &size); ids[id_index] = ptr->id; ++id_index; int y; } } ptr->depends->curr = ptr->depends->curr->next; } } ptr = ptr->next; } ptr0 = ptr0->next; } } current->depend_id = ids; // End int array with signal bit (0 can never be an id) ids[id_index] = 0; current = current->prev; } stream->curr = stream->head; }
token_stream_t char_stream_to_token_stream (char_stream_t cst) { // Initialize the new token_stream, allocating memory and setting variables token_stream_t stream = checked_malloc(sizeof(struct token_stream)); stream->head = NULL; stream->tail = NULL; // Prev_token will keep track of the previous token for syntax purposes // Initializing prev_token here token_t prev_token = checked_malloc(sizeof(struct token)); prev_token->type = NEWLINE; // Makes it easy for the first real line prev_token->string = NULL; // Start the character stream char_stream_init(cst); char ch; bool in_andorpipe_command = false; int paren_count = 0; int line_num = 1; // For error reporting // Loop through all the characters, tokenizing them and checking syntax while ((ch = char_stream_current(cst)) != EOF) { if (ch == '#') // COMMENT { if(cst->last != '\0' && cst->last != '\n' && cst->last != '\t' && cst->last != ' ') { error(1,0,"Comment Error"); } while (ch != '\n') // until you find a new line... { ch = char_stream_read(cst); // iterate through characters } } else if (ch == '\n') // NEWLINE { line_num++; switch (prev_token->type) // check if it's valid syntax { case IN: case OUT: error (1, 0, "%d: Invalid newline after previous token\n",line_num); break; case AND: case OR: case PIPE: case NEWLINE: ch = char_stream_read(cst); // keep going... break; default: { // Create the new token and add it to the token stream token_t new_token = checked_malloc(sizeof(struct token)); new_token->type = NEWLINE; new_token->string = NULL; token_stream_add(stream, new_token); // set the prev_token for syntax-checking prev_token->type = NEWLINE; prev_token->string = NULL; ch = char_stream_read(cst); } } } else if (isspace(ch)) // BLANK SPACE (not \n) { ch = char_stream_read(cst); } else if (ch == ')') // CLOSED PAREN { switch (prev_token->type) { case AND: case OR: case PIPE: case IN: case OUT: case OPEN_PAREN: error (1, 0, "%d: Invalid ')' after previous token\n", line_num); break; default: { // Create the new token and add it to the token stream token_t new_token = checked_malloc(sizeof(struct token)); new_token->type = CLOSE_PAREN; new_token->string = NULL; token_stream_add(stream, new_token); // set the prev_token for syntax-checking prev_token->type = CLOSE_PAREN; prev_token->string = NULL; ch = char_stream_read(cst); paren_count--; } } } else if (ch == '(') // OPEN PAREN { switch (prev_token->type) { case WORD: case IN: case OUT: case CLOSE_PAREN: error (1, 0, "%d: Invalid '(' after previous token\n", line_num); break; default: { // Create the new token and add it to the token stream token_t new_token = checked_malloc(sizeof(struct token)); new_token->type = OPEN_PAREN; new_token->string = NULL; token_stream_add(stream, new_token); // set the prev_token for syntax-checking prev_token->type = OPEN_PAREN; prev_token->string = NULL; ch = char_stream_read(cst); paren_count++; in_andorpipe_command = false; // printf("%i: in_andorpipe_command set to FALSE\n", line_num); } } } else if (ch == '&') // AND { ch = char_stream_read(cst); // Check to see if & or && if (ch == '&') { switch (prev_token->type) { case WORD: case CLOSE_PAREN: { // Create the new token and add it to the token stream token_t new_token = checked_malloc(sizeof(struct token)); new_token->type = AND; new_token->string = NULL; token_stream_add(stream, new_token); // set the prev_token for syntax-checking prev_token->type = AND; prev_token->string = NULL; ch = char_stream_read(cst); in_andorpipe_command = true; // printf("%i: in_andorpipe_command set to TRUE\n", line_num); break; } default: error (1, 0, "%d: Invalid '&&' after previous token\n", line_num); } } else { error (1, 0, "%d: Invalid token: & must be followed by &\n", line_num); } } else if (ch == '|') { ch = char_stream_read(cst); switch (prev_token->type) { case WORD: case CLOSE_PAREN: if (ch == '|') { // Create the new token and add it to the token stream token_t new_token = checked_malloc (sizeof (struct token)); new_token->type = OR; new_token->string = NULL; token_stream_add(stream, new_token); // set the prev_token for syntax-checking prev_token->type = OR; prev_token->string = NULL; ch = char_stream_read(cst); in_andorpipe_command = true; // printf("%i: in_andorpipe_command set to TRUE\n", line_num); } else { // Create the new token and add it to the token stream token_t new_token = checked_malloc (sizeof(struct token)); new_token->type = PIPE; new_token->string = NULL; // set the prev_token for syntax-checking token_stream_add(stream, new_token); prev_token->type = PIPE; prev_token->string = NULL; in_andorpipe_command = true; // printf("%i: in_andorpipe_command set to TRUE\n", line_num); } break; default: error (1, 0, "%d: Invalid '|' or '||' after previous token\n", line_num); } } else if (ch == ';') { switch (prev_token->type) { case WORD: case CLOSE_PAREN: { // Create the new token and add it to the token stream token_t new_token = checked_malloc (sizeof (struct token)); new_token->type = SEQ; new_token->string = NULL; token_stream_add(stream, new_token); // set the prev_token for syntax-checking prev_token->type = SEQ; prev_token->string = NULL; ch = char_stream_read(cst); break; } default: error (1, 0, "%d: Invalid ';' after previous token\n", line_num); } } else if (ch == '<') { switch (prev_token->type) { case WORD: case CLOSE_PAREN: { // Create the new token and add it to the token stream token_t new_token = checked_malloc (sizeof (struct token)); new_token->type = IN; new_token->string = NULL; token_stream_add(stream, new_token); // set the prev_token for syntax-checking prev_token->type = IN; prev_token->string = NULL; ch = char_stream_read(cst); break; } default: error (1, 0, "%d: Invalid '<' after previous token\n", line_num); } } else if (ch == '>') { switch (prev_token->type) { case WORD: case CLOSE_PAREN: { // Create the new token and add it to the token stream token_t new_token = checked_malloc (sizeof (struct token)); new_token->type = OUT; new_token->string = NULL; token_stream_add(stream, new_token); // set the prev_token for syntax-checking prev_token->type = OUT; prev_token->string = NULL; ch = char_stream_read(cst); break; } default: error (1, 0, "%d: Invalid '>' after previous token\n", line_num); } } else { if (prev_token->type == CLOSE_PAREN) error (1, 0, "%d: Invalid string after ')'\n", line_num); if (!is_regular_char(ch)) { error (1, 0, "%d: Invalid character '%c'\n", line_num, ch); } size_t count = 0; size_t max = 8; token_t new_token = checked_malloc(sizeof(struct token)); new_token->type = WORD; new_token->string = checked_malloc(max * sizeof(char)); while (is_regular_char(char_stream_current(cst))) { if (count + 1 >= max) checked_grow_alloc(new_token->string, &max); new_token->string[count++] = char_stream_current(cst); ch = char_stream_read(cst); } new_token->string[count] = '\0'; // end the string token_stream_add(stream, new_token); prev_token->type = WORD; prev_token->string = NULL; in_andorpipe_command = false; // printf("%i: in_andorpipe_command set to FALSE\n", line_num); } } if (in_andorpipe_command) error (1, 0, "EOF: Reached end of file without correct number of commands (and, or, pipe)\n"); if (paren_count) error (1, 0, "EOF: Incorrect number of parentheses\n"); //print_tokens(stream); return stream; }
void redirect_commands(command_t symb, command_t command_input, command_t command_output) { size_t input_size= 32 * sizeof(char); int index = 0; command_input->input = (char *) checked_malloc(32 * sizeof(char)); command_input->input[0] = '\0'; size_t output_size= 32 * sizeof(char); command_output->output = (char *) checked_malloc(32 * sizeof(char)); command_output->output[0] = '\0'; char* nothing = (char*) checked_malloc(sizeof(char*)); nothing[0] = '\0'; if (symb-> type == GREATER_THAN) { /*if (command_output->output != NULL) { error(1,0, "Invalid token for output in line: 0 ");} */ if (command_input->u.word[index] != NULL) { if (sizeof(command_input->u.word[index]) >= output_size) {command_output->output = (char*) checked_grow_alloc(command_output->output, &output_size);} strcat(command_output->output, command_input->u.word[index]); index++; } } index = 0; if (symb-> type == LESS_THAN) { /*if (command_input->input != NULL) { error(1,0, "Invalid token for input in line: 0");} */ if (command_output->u.word[index] != NULL) { if (sizeof(command_output->u.word[index]) >= input_size) {command_input->input = (char*) checked_grow_alloc(command_input->input, &input_size);} strcat(command_input->input, command_output->u.word[index]); index++; } } if (symb->type == LESS_THAN) { symb->has_parent = 1; command_output->has_parent = 1; } if (symb->type == GREATER_THAN) { symb->has_parent = 1; command_input->has_parent = 1; } }
/* * Fill parseFile with valid character array input * Remove all white space and comments * Return the size of the array */ int parseFile(int (*get_next_byte) (void *), void *get_next_byte_argument, char* parsedFile) { int size = 0; size_t capacity = 256; //Allocate space in parsedFile if(!parsedFile) { error(1, 0, "Unexpected Null parsedFile"); return 0; } //to hold next character char c; //For parantheses correctness int parenCount = 0; //Used to remove comments int isComment = 0; //Used to check for valid redirection int findSingleWord = 0; int singleWordStarted = 0; int foundLessThan = 0; int foundSingleWord = 0; while( (c = get_next_byte(get_next_byte_argument)) && c != 0 && !feof(get_next_byte_argument)) { //printf("DEBUG: parseFile: checking %c\n", c); // If the beginning of a comment is reached // set the comment flag to one and continue // through the loop if(c == '#') { isComment = 1; continue; } // If comment flag is set and the current character is not // a new line, then skip character and continue loop // Otherwise, if it is a new line, unset the comment flag if(isComment && c != '\n'){ continue; }else if(isComment){ isComment = 0; } // If character is a new line, check if it is an // extra or arbitrary new line. If it is, then // remove it. Otherwise, if its any other arbitrary // white space, also remove it. If not a white space, // then check grammar. if(c == '\n') { int parsePointer = size-1; if(size == 0 || parsedFile[parsePointer] == '\n') { continue; } if(parsedFile[parsePointer] == ' ') { if(parsePointer-1 >= 0){ if(parsedFile[parsePointer-1] == '&' || parsedFile[parsePointer-1] == '|' || parsedFile[parsePointer-1] == ';' ) { continue; } } parsedFile[parsePointer] = '\n'; continue; } if(parsedFile[parsePointer] == '&' || parsedFile[parsePointer] == '|' || parsedFile[parsePointer] == ';'){ continue; } } else if(isspace(c)) { if(c != ' ') { c = ' '; } if(size == 0 || parsedFile[size-1] == ' ' || parsedFile[size-1] == '\n') { continue; } } else { if(!isProperGrammar(parsedFile, size, &parenCount, c)) { error (1, 0, "Improper Syntax in File: bad grammar"); } } // If an I/O flag has been set to find // single file name, then check for valid // file name. Otherwise check if current character is // I/O character if(findSingleWord) { if(foundSingleWord) { if( c == '|' || c== '&' || c == ';' || c == '(' || c == '\n') { findSingleWord = 0; foundSingleWord = 0; singleWordStarted = 0; foundLessThan = 0; } else if(c == '>' && foundLessThan) { foundLessThan = 0; findSingleWord = 1; foundSingleWord = 0; singleWordStarted = 0; } else if(isspace(c)) { //do nothing } else { error (1, 0, "Improper Syntax in File: Improper Redirect"); return 0; } } else if(singleWordStarted) { if( c== '(' || c== '<') { error (1, 0, "Improper Syntax in File: Improper Redirect"); return 0; } else if( c == '|' || c== '&' || c == ';' || c == '\n') { findSingleWord = 0; foundSingleWord = 0; singleWordStarted = 0; foundLessThan = 0; } else if(isspace(c)) { foundSingleWord = 1; } else if( c == '>' && foundLessThan ) { findSingleWord = 1; singleWordStarted = 0; foundLessThan = 0; foundSingleWord = 0; } else if(c == '>') { error (1, 0, "Improper Syntax in File: Improper Redirect"); return 0; } } else if( c == '|' || c== '&' || c == ';' || c == '(' || c == '>' || c == '<' || c == '\n') { error (1, 0, "Improper Syntax in File: Improper Redirect"); return 0; } else if(isspace(c)) { //do nothing } else { singleWordStarted = 1; } } else if(c == '<') { findSingleWord = 1; foundLessThan = 1; foundSingleWord = 0; singleWordStarted = 0; } else if(c == '>') { findSingleWord = 1; foundLessThan = 0; foundSingleWord = 0; singleWordStarted = 0; } if(!(size < (signed int)capacity)) { parsedFile = (char*)checked_grow_alloc((void*)parsedFile, &capacity); } // Remove any extra white space before // New lines and close parentheses if(c == '>' || c == '\n') { int parsePointer = size-1; while(parsePointer >= 0) { if(isspace(parsedFile[parsePointer])) { size--; } else { break; } parsePointer--; } } // Add space before any special characters if(size > 0) { if(c == ')' || c == ';' || c == '(' || c == '\n' || c == '>' || c == '<' ) { if(parsedFile[size-1] != ' ') { parsedFile[size] = ' '; size++; } } else if( c == '&' || c == '|') { if(parsedFile[size-1] != ' ' && parsedFile[size-1] != c) { parsedFile[size] = ' '; size++; } } if(!(size < (signed int)capacity)) { parsedFile = (char*)checked_grow_alloc((void*)parsedFile, &capacity); } } //Add Valid Character to Array parsedFile[size] = c; //Increment character count size++; } //Check if file ended properly if(parsedFile[size-1] != ';' && parsedFile[size-1]!='\n' && !isProperGrammar(parsedFile, size, &parenCount, ';')) { error (1, 0, "Improper Syntax in File: File terminated incorrectly"); } //add end of file if(!(size < (signed int)capacity)) { parsedFile = (char*)checked_grow_alloc((void*)parsedFile, &capacity); } //Add Null Character to End of Array parsedFile[size] = '\0'; //size++; if(parenCount > 0) { error (1, 0, "Improper Syntax in File: Unclosed Parentheses"); return 0; } //printf("%s\n", parsedFile); return size; }