简体   繁体   中英

Code to redirect input AND output in a shell

I have created a shell program that can more or less do what the normal linux shell does. My program can redirect input OR output correctly,but not both at the same time. Any solutions online so far, haven't been useful to me.

eg

 " echo hi kenny > kenny.txt "  works

 " cat in.txt | less "      works

However,(assume in.txt is a random alphabet file)

 " sort -u < in.txt > out.txt " does not work for  both, only for the input(<).

My code is roughly as follows:

int main(int argc, char* argv[]){

 readLine();

 if (lineHasSpecialSymbols()) {
    if(hasInput()){
       inRedirection();
    }else
      outRedirection();
 }

}

Let's assume thats all needed. No pipes etc.

readLine() reads a line from the terminal and saves them in args[]

lineHasSpecialSymbols() detects the first instance of '<' or '>'and returns.

Here's the tricky part in how inRedirection() works:

void inRedirection(void) {
extractCommand("<");
int fd;
if ((pid = fork()) == -1) {
  perror("fork");
  exit(1);
}
if (pid == 0) {
  close(0);
  //open the file args2[0] and use it as standard input
  fd = open(args2[0], O_RDWR);
  execvp(args[0], args);
  perror("execv");
  exit(1);
}
if (pid != 0) {
  wait(NULL);
  printf("Done ");
  printf(args[0]);
  printf(".\n");
 }
}

outRedirection():

void outRedirection(void) {
extractCommand(">");
int fd;
if ((pid = fork()) == -1) {
  perror("fork");
  exit(1);
}
if (pid == 0) {
  close(1);
  fd = creat(args2[0], 0644);
  execvp(args[0], args);
  perror("execv");
  exit(1);
}
if (pid != 0) {
  wait(NULL);
  printf("Done ");
  printf(args[0]);
  printf(".\n");
 }
}

Finally, extractCommand():

void extractCommand(char* symbol) {
int i;
int count = 0;
for (i = 0; args[i] != NULL; i++)
  if (!strcmp(args[i], symbol)) {
     args[i] = NULL;
     while (args[i+1] != NULL) {
           args2[count] = args[i+1];
           args[i+1] = NULL;
           i++;
           count++;
     }
  }
}

Sorry, for the huge code. Here's the problem:

Let's say that I type the command :

" sort -u < in.txt > out.txt "

The code will detect the '<' and extract the command into two parts.

args[0] = "sort"   args2[0] = "in.txt"    args2[2] = "out.txt"
args[1] = "-u"     args2[1] = ">"

It will only the "sort -u < in.txt" and not the rest. My question is how can I change my code to work as an intented? Also, how can I do that for more than two commands? For example : "ls -l /home/user | sort -u | wc -l > in.txt"?

I've thought of some algorithms like making a third args (args3), but that would collide in the case of more that two commands.

I suggest you change your methods.

int outRedirection(void) {
  int i;
  int j;
  for(i = 0; args[i] != NULL; i++) {
    // Look for the >
    if(args[i][0] == '>') {
      args[i] = NULL;
      // Get the filename
      if(args[i+1] != NULL) {
    output_filename[0] = args[i+1];
      } else {
    return -1;
      }
            //For- loop to make input AND output functional
           for(j = i; args[j-1] != NULL; j++) {
                        args[j] = args[j+2];
           }
      return 1;
    }
  }
  return 0;
}

Do the same thing for input and then execute like so:

    void IOcommand(void){
    if ((pid = fork())== -1){
        perror("fork");
        exit(1);
    }if (pid == 0){

    if (input == 1)
        freopen(input_filename[0], "r", stdin);

    if (output == 1)
        freopen(output_filename[0], "w+", stdout);

        execvp(args[0],args);
        exit(-1);
 }
 if (pid != 0 ){
     wait(NULL);
     printf("Done ");
     printf(args[0]);
     printf(".\n");
 }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM