我创建了一个名为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;
}