将输入文件功能添加到Unix Shell

时间:2016-05-04 17:37:41

标签: c shell unix

我创建了一个名为myShell.c的文件,我在其中实现了一个Unix shell。我已经添加了使用命令 mysh> L>将输出重定向到文件的功能。 DIR.TXT 即可。我想要添加一个类似的功能,其中shell可以通过使用诸如 mysh> R>之类的命令从输入文件(例如'instr.txt')读取命令。 instr.txt 但需要帮助解决这个问题。我已经在代码中创建了将在下面使用的变量( redirectInputArg )。关于如何解决这个问题的任何建议?以下是我的代码:

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <string.h>
#include <unistd.h>
#include <string.h>
#include <ctype.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <errno.h>
#include "clock.h"

#define MAXLINE 100
int timeout;
double currentCycles;
double MHZ;

//
// Signal handler
//
void sighandler(int signo)
{
  switch(signo)
  {
    case SIGINT:
      printf("\n\n*** Caught SIGINT signal ***\n\n");
      currentCycles = get_counter(); // get current counter value
      printf("Elapsed Time: %f seconds.\n", currentCycles/MHZ/1.0E6);
      start_counter(); // reset the counter
      printf("mysh>");
      fflush(stdout);
      break;
    case SIGALRM:
      printf("\n\n*** Alarm caught ***\n\n");
      printf("mysh>");
      fflush(stdout);
      break;
    case SIGTERM:
      printf("\n\n*** So you think you can kill me, try again ***\n\n");
      printf("mysh>");
      fflush(stdout);
      break;
    default:
      printf("\n\n*** Caught unexpected signal number %d ***\n\n", signo);
      printf("mysh>");
      fflush(stdout);
      break;
  }
  return;
}

//
// Display options
//
void options()
{
  printf("\n  OPTIONS:\n");
  printf("------------------------------------------\n");
  printf("  A <sec> = Alarm <sec> seconds\n");
  printf("  P = Process Status Tree (ps --forest)\n");
  printf("  W = Who is logged in and count (who -q)\n");
  printf("  F = Fortune cookie (fortune)\n");
  printf("  L [dir] = Directory listing (ls -l [ dir ])\n");
  printf("  M [fname] = Display file or stdin by page (more [fname])\n");
  printf("  S = Start or restart timer \n");
  printf("  E = Elapsed time \n");
  printf("  I <num> = Ignore signal number <num>\n");
  printf("  C <num> = Catch signal number <num>\n");
  printf("  D <num> = Default action for signal <num>\n");
  printf("  R = Reverse text\n");
  printf("  H = Help\n");
  printf("  Q = Quit\n");
  printf("------------------------------------------\n");
  fflush(stdout);
  return;
}

//
// Main fetch and evaluate routine
//
int main()
{
  int retval;
  int status;
  char cmd[MAXLINE+1] = " ";
  char fname[MAXLINE];
  char *cptr[10];
  int count=0;
  const char delim[4] = " \n\t";
  int seconds;
  int signum;
  int redirectOutputArg = 0;
  int redirectInputArg = 0;
  int i, fd_out;
  mode_t mode = 0644; // S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;

  // invoke signal hander, sighandler, when some signals are received
  signal(SIGINT, sighandler);
  signal(SIGALRM, sighandler);
  signal(SIGTERM, sighandler);

  // determine system clock rate
  MHZ = mhz(0);

  while((strncmp(cmd,"Q",1)!=0)&&(strncmp(cmd,"q",1)!=0))
  {
    redirectOutputArg = 0;
    redirectInputArg = 0;
    printf("\nmysh>");
    fflush(stdout);
    memset(cmd,0,MAXLINE+1);
    if ((fgets(cmd, MAXLINE, stdin) == NULL) && ferror(stdin))
    {
      perror("fgets error");
      exit(1);
    }
    // Grab tokens from command entered
    cptr[0] = strtok(cmd, delim);
    count=1;
    while((count<10)&&((cptr[count]=strtok(NULL,delim))!=NULL))
      count++;
    for (i=0; i<count; i++)
        printf("Argument %d: %s\n", i, cptr[i]);

    for (i=2; i<count; i++)
    {
      if (strncmp(cptr[i-1],">",1)==0)
        redirectOutputArg = i;
    }
    if (redirectOutputArg > 0)
        printf("Redirect output arg: %d = %s\n",
        redirectOutputArg, cptr[redirectOutputArg]);
    fflush(stdout);

    if (feof(stdin)) // Ctrl-D -- end-of-input
    {
  exit(0);
}

switch((char)(*cptr[0]))
{
  case 'P': case 'W': case 'F': case 'L': case 'R': case 'M':
  case 'p': case 'w': case 'f': case 'l': case 'r': case 'm':
    retval = fork(); // fork off a child to do the work.
    if (retval==0)
    {
      if (redirectInputArg > 0)
      {

      }
      if (redirectOutputArg > 0)
      {
        sprintf(fname,"%s", cptr[redirectOutputArg]);
        fname[strlen(fname)]='\0';
        // redirect output to file
        fd_out = open(fname, O_RDWR | O_CREAT, mode);
        close(1);     // could also use dup2(fd_out,1);
        if (dup(fd_out)<0)
        {
            perror("Unable to dup stdout");
            exit(8);
        }
      }

      switch((char)(*cptr[0]))
      {
        case 'P': case 'p':
                  execl("/bin/ps","ps","--forest",(char *) NULL);
                  exit(1); // just in case it didn't work :-)
                  break;
        case 'W': case 'w':
                  execl("/usr/bin/who","who","-q",(char *) NULL);
                  exit(2);
                  break;
        case 'F': case 'f':
                  execl("/usr/bin/fortune","fortune",(char *) NULL);
                  exit(3);
        case 'L': case 'l':
                  if ((cptr[1]!=NULL)&&(strncmp(cptr[1],">",1)!=0))
                  {
                    execl("/bin/ls","ls", "-l",(char *)cptr[1],(char *) NULL);
                  }
                  else
                    execl("/bin/ls","ls","-l",(char *) NULL);
                  exit(4);
                  break;
        case 'R': case 'r':
                  execl("/usr/bin/rev", "rev",(char *) NULL);
                  exit(5);
        case 'M': case 'm':
                  exit(6);
                  break;
        default:  printf("Invalid user input, try again.\n");
                  exit(7);
                  break;
      }
      return 0; // child should always exit...
    }
    else
    {
      retval = wait(&status); // parent shell waits for child to exit
    }
    break;

  case 'A': case 'a': seconds = atoi(cptr[1]);
            alarm(seconds);
            break;
  case 'S': case 's': start_counter(); // reset the counter
            break;
  case 'E': case 'e': currentCycles = get_counter();
            printf("Elapsed Time: %f seconds.\n", currentCycles/MHZ/1.0E6);
            break;
  case 'I': case 'i': signum = atoi(cptr[1]);
            signal(signum,SIG_IGN);
            break;
  case 'C': case 'c': signum = atoi(cptr[1]);
            signal(signum,sighandler);
            break;
  case 'D': case 'd': signum = atoi(cptr[1]);
            signal(signum,SIG_DFL);
            break;
  case 'H': case 'h': options();
            break;
  case 'Q': case 'q': // do nothing
            break;
  default:  printf("Invalid user input, try again.\n");
            break;
    }
  }
  return 0;
}

0 个答案:

没有答案