+ All Categories
Home > Documents > ReporteProyecto2

ReporteProyecto2

Date post: 29-Dec-2015
Category:
Upload: omar-munoz
View: 24 times
Download: 0 times
Share this document with a friend
Description:
Proyecto de shell en linuxOS Silberchatz
Popular Tags:
13
Project-UNIX Shell and History Feature This project consists of modifying a C program which serves as a shell interface that accepts user commands and then executes each command in a separate process. A shell interface provides the user a prompt after which the next command is entered. Ilustración 1 Executing the program Ilustración 2 Executing gedit command, waits for the child process to terminate UNIX shells typically also allow the child process to run in the background-or concurrentyl-as well by specifying the ampesand (&) at the end of the command. Example: Ilustración 3 Executing gedit command, running parallel background
Transcript
Page 1: ReporteProyecto2

Project-UNIX Shell and History Feature

This project consists of modifying a C program which serves as a shell interface that accepts user commands and then executes each command in a separate process. A shell interface provides the user a prompt after which the next command is entered.

Ilustración 1 Executing the program

Ilustración 2 Executing gedit command, waits for the child process to terminate

UNIX shells typically also allow the child process to run in the background-or concurrentyl-as well by specifying the ampesand (&) at the end of the command. Example:

Ilustración 3 Executing gedit command, running parallel background

This program is terminated when the user enters <Control><D> and setup() theb invokes exit().

The contents of the command entered by the user is loaded into the args array.

Page 2: ReporteProyecto2

Ilustración 4 Executing commands with different parameters

Creating a History Feature

This code also provides a history feature that allows the user access up to the 10 most recently entered commands. These commands will be numbered starting at 1 and will continue to grow larger even past 10, e.g. if the user has entered 35 commands, the 10 most recent commands sholud be numbered 26 to 35. The user will be able to list these commands when he/she presses <Control><C>, which is the SIGINT signal. When the user presses that command, the signal handler will output a list of the most recent 10 commands.

Page 3: ReporteProyecto2

Ilustración 5 Pressing CTR + C to show the command history

Ilustración 6 Executing echoes

Page 4: ReporteProyecto2

Ilustración 7 The history is updated. Only 10 commands are stored

With the list, the user can run any of the previous 10 commands by entering r x where 'x' is the first letter of that command. If more than one command starts with 'x', execute the most recent one.

Ilustración 8 Executing "r e", searching the last command with initial the letter e

Page 5: ReporteProyecto2

Ilustración 9 Executing "r l", searching the last command with initial letter 'l'

Also, the user should be able to run the most recent command again by just entering 'r'. Any command that is executed in this fashion will be echoed on the user's screen and the command is also placed in the history buffer as the next command.

Ilustración 10 Executing "r", executing the last command used

Page 6: ReporteProyecto2

Ilustración 11 History is updated whe 'r' is executed and adds the command executed

If he user attempts to use this history facility to run a command and the command is detected to be erroneous, an error message should be given to the user and the command not entered in the history list, and the execvp() will not be called

Ilustración 12 Control of errors in the history

Page 7: ReporteProyecto2

Código del proyecto

#include <stdio.h>#include <signal.h>#include <unistd.h>#include <stdlib.h>#include <errno.h>#include <sys/types.h>#include <string.h>#include <ctype.h>

#define MAX_COMMANDS 10 /* size of history */#define MAX_LINE 80#define BUFFER_SIZE 50

char history[MAX_COMMANDS][MAX_LINE];char display_history[MAX_COMMANDS][MAX_LINE];static char buffer[BUFFER_SIZE];int ctrC = 0;

int command_count = 0;

void addtohistory(char inputBuffer[]) { int i = 0; int limit_history = 0; if (command_count >= 9) { limit_history = 9; } else { limit_history = command_count; } //shift all other commands in history[] if (command_count > 0) { for (i = limit_history; i > 0; i--) { /** * quitar este comentario para ver como va recorriendo los comandos printf("Copia [%d] %s a [%d] %s\n", i - 1, display_history[i - 1], i, display_history[i]); */ strcpy(history[i], history[i - 1]); strcpy(display_history[i], display_history[i - 1]); } } // add the command to beggining strcpy(history[0], inputBuffer); // add the display-style command to beginning history i = 0; while (inputBuffer[i] != '\n' && inputBuffer[i] != '\0') { display_history[0][i] = inputBuffer[i]; i++; } display_history[0][i] = '\0'; //make a C string

Page 8: ReporteProyecto2

++command_count;

return;}

/* the signal handler function */void handle_SIGINT() { int i, upper; //write(STDOUT_FILENO,buffer,strlen(buffer)); if (command_count < MAX_COMMANDS){ upper = command_count; } else { upper = MAX_COMMANDS; } //Desplegar 10 comandos recientes en pantalla printf("\n---Command History---\n"); for (i = 0; i < upper; i++) { printf("%d \t %s\n", command_count - i, display_history[i]); }

ctrC = 1; /* flag so it doesn't add command to history */ //exit(0); /* exits program */}

/** setup() reads in the next command line, separating it intodistinct tokens using whitespace as delimiters.setup() modifies the args parameter so that it holds pointersto the null-terminated strings that are the tokens in the mostrecent user command line as well as a NULL pointer, indicatingthe end of the argument list, which comes after the stringpointers that have been assigned to args. */

void setup(char inputBuffer[], char *args[], int *background){ int length; /* # of characters in the command line */ int i; /* loop index for accessing inputBuffer array */ int start; /* index where beginning of next command parameter is */ int ct; /* index of where to place the next parameter into args[] */ char command_firstl; /* first letter of command */ ct = 0; /* read what the user enters on the command line */ length = read(STDIN_FILENO, inputBuffer, MAX_LINE); //printf("First size: %zu\n",strlen(inputBuffer));//QUITAR //printf("length: %d\n",length); start = -1;

if(length == 0) exit(0); /* ^d was entered, end of user command stream */ if(length < 0){ //perror("error reading the command"); //exit(-1); /* terminate with error code of -1 */ }

Page 9: ReporteProyecto2

/** * Check if they are using history */ if (inputBuffer[0] == 'r') { //printf("\nI received R\n"); if (command_count == 0) { printf("No history\n"); //return 1; } else if (inputBuffer[1] == '\n') { // restore the previous command int index = 0; strcpy(inputBuffer, history[index]); //echoes command on screen printf("COMMAND -> %s\n", display_history[0]); length = strlen(inputBuffer) + 1; } else if (inputBuffer[1] == ' ') { /* checks for r followed by a letter */ if (isalpha(inputBuffer[2])) { /* If is letter (alphabetic) */ int i = 0; for (i = 0; i < 10; i++) { command_firstl = history[i][0]; /* extract first letter of command in history */ if (command_firstl == inputBuffer[2]) { strcpy(inputBuffer, history[i]); //echoes command on screen printf("COMMAND -> %s\n", display_history[i]); length = strlen(inputBuffer) + 1; break; } } if (i >= 10) { /* didn't match any beggining letter */ strcpy(inputBuffer, "echo No hay comandos que comiencen con esa letra\n"); length = strlen(inputBuffer) + 1; ctrC = 1; /* don't add to history */ } } else { printf("Error, ingrese la primera letra del comando\n"); } } else { printf("Error, deje un espacio entre letras\n"); } } ctrC ? ctrC = 0 : addtohistory(inputBuffer);

/* examine every character in the inputBuffer */ for(i = 0; i < length; i++){ switch(inputBuffer[i]){ case ' ': case '\t': /* argument separators */ if(start != -1){

Page 10: ReporteProyecto2

/* set up pointer at beggining of command or command option */ args[ct] = &inputBuffer[start]; ct++; /* increase counter */ } inputBuffer[i] = '\0'; /* add a null char; make a C string*/ start = -1; break; case '\n': /* should be the final char examined */ if(start != -1){ args[ct] = &inputBuffer[start]; ct++; } inputBuffer[i] = '\0'; args[ct] = NULL; /* no more arguments to this command */ break; default : /* some other character */ if(start == -1) start = i; if(inputBuffer[i] == '&'){ *background = 1; inputBuffer[i] = '\0'; } } } args[ct] = NULL; /* just in case the input line was > 80*/}

int main(void){ char inputBuffer[MAX_LINE]; /* buffer to hold command entered */ int background; /* equals 1 if a command is followed by '&' */ char *args[MAX_LINE/1]; /* command line (of 80) has max of 40 arguments */ /*code made by CREW ISD*/ int ppid,pid; /*code made by CREW ISD*/

/* set up the signal handler */ struct sigaction handler; handler.sa_handler = handle_SIGINT; handler.sa_flags = 0; sigemptyset(&handler.sa_mask); sigaction(SIGINT, &handler, NULL);

strcpy(buffer,"Caught <ctrl><c>\n");

while(1){ background = 0; ppid = getpid(); //printf("Parent: %d\n",ppid); printf("COMMAND -> ");

Page 11: ReporteProyecto2

fflush(stdout); /* setup() calls exit() when Control-D is entered */ setup(inputBuffer, args, &background); /** code made by CREW ISD */ pid = fork(); if(pid == 0){ //Child process execvp(args[0],args); if (inputBuffer[0] != 'r') { //No imprime error pues r es válido printf("Error: Unknown command, please try again\n"); exit(-1); } } else { if(background == 0){ //wait(NULL); //printf("\nWaiting for the child: %d to terminate",pid); wait(NULL); //printf("\nEND WAITING\n"); //printf("Child: %d\n",pid); }else{ //exit(0); printf("\nbackg = 1, running child: %d in parallel with parent: %d\n", pid, ppid); //printf("Printing contents: %c\n",*args[0]); } } /** code made by CREW ISD */ /* printf(args[0]); printf(args[1]); printf("%d\n",background); */ /** the steps are: (1) fork a child process using fork() (2) the child process will invoke execvp() (3) if background == 1, the parent will wait, otherwise it will invoke the setup() function again. */ }}