【发布时间】:2017-09-22 22:37:20
【问题描述】:
我正在阅读 Silberschatz、Galvin 和 Gagne 的操作系统概念第 9 版。我已经进入第 3 章的第一个项目,他们要求我们创建一个 UNIX Shell 和历史特性。我已经创建了其中的一些,历史记录和我相信的大多数 shell 命令(密码、日期、cal 等)都可以工作 - 我现在正在尝试将 cd 添加到列表中,当我得到 Segmentation fault (core dumped) 时我在我的外壳中使用cd。我觉得这实现起来并不难,你只要把pwd 和你要去的地方换掉就行了。这是我的代码:
//Enter command 'history' for history feature and CTRL - c to exit the 'osh>' shell
/*Header files */
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <wait.h>
#define MAX_LINE 80 /* The maximum length of a command */
#define BUFFER_SIZE 50
#define buffer "\n\Shell Command History:\n"
//declarations
char history[10][BUFFER_SIZE]; //history array to store history commands
int count = 0;
char *gdir, *dir, *to;
//function to display the history of commands
void displayHistory() {
printf("Shell command history:\n");
int i;
int j = 0;
int histCount = count;
//loop for iterating through commands
for (i = 0; i<10;i++) {
//command index
printf("%d. ", histCount);
while (history[i][j] != '\n' && history[i][j] != '\0') {
//printing command
printf("%c", history[i][j]);
j++;
}
printf("\n");
j = 0;
histCount--;
if (histCount == 0)
break;
}
printf("\n");
}
//Fuction to get the command from shell, tokenize it and set the args parameter
int formatCommand(char inputBuffer[], char *args[],int *flag) {
int length; // # of chars in command line
int i; // loop index for inputBuffer
int start; // index of beginning of next command
int ct = 0; // index of where to place the next parameter into args[]
int hist;
//read user input on command line and checking whether the command is !! or !n
length = read(STDIN_FILENO, inputBuffer, MAX_LINE);
start = -1;
if (length == 0)
exit(0); //end of command
if (length < 0) {
printf("Command not read\n");
exit(-1); //terminate
}
//examine each character
for (i=0;i<length;i++) {
switch (inputBuffer[i]) {
case ' ':
case '\t' : // to seperate arguments
if(start != -1) {
args[ct] = &inputBuffer[start];
ct++;
}
inputBuffer[i] = '\0'; // add a null char at the end
start = -1;
break;
case '\n': //final char
if (start != -1) {
args[ct] = &inputBuffer[start];
ct++;
}
inputBuffer[i] = '\0';
args[ct] = NULL; // no more args
break;
default :
if (start == -1)
start = i;
if (inputBuffer[i] == '&') {
*flag = 1; //this flag is the differentiate whether the child process is invoked in background
inputBuffer[i] = '\0';
}
}
}
args[ct] = NULL; //if the input line was > 80
if(strcmp(args[0],"history")==0) {
if(count>0) {
displayHistory();
} else {
printf("\nNo Commands in the history\n");
}
return -1;
} else if (args[0][0]-'!' ==0) {
int x = args[0][1]- '0';
int z = args[0][2]- '0';
if(x>count) { // second letter check
printf("\nNo Such Command in the history\n");
strcpy(inputBuffer,"Wrong command");
} else if (z!=-48) { // third letter check
printf("\nNo Such Command in the history. Enter <=!9 (buffer size is 10 along with current command)\n");
strcpy(inputBuffer,"Wrong command");
} else {
if(x==-15) {
strcpy(inputBuffer,history[0]); // this will be your 10 th(last) command
} else if(x==0) { //Checking for '!0'
printf("Enter proper command");
strcpy(inputBuffer,"Wrong command");
} else if(x>=1) { //Checking for '!n', n >=1
strcpy(inputBuffer,history[count-x]);
}
}
}
for (i = 9;i>0; i--) //Moving the history elements one step higher
strcpy(history[i], history[i-1]);
strcpy(history[0],inputBuffer); //Updating the history array with input buffer
count++;
if(count>10) {
count=10;
}
}
int main(void) {
char inputBuffer[MAX_LINE]; /* buffer to hold the input command */
int flag; // equals 1 if a command is followed by "&"
char *args[MAX_LINE/2 + 1];/* max arguments */
int should_run =1;
pid_t pid,tpid;
int i;
while (should_run) { //infinite loop for shell prompt
flag = 0; //flag =0 by default
printf("osh>");
fflush(stdout);
if(-1!=formatCommand(inputBuffer,args,&flag)) { // get next command
pid = fork();
if (!strcmp(args[0], "cd")) {
gdir = getcwd(inputBuffer, sizeof(inputBuffer));
dir = strcat(gdir, "/");
to = strcat(dir, args[1]);
chdir(to);
continue;
}
if (pid < 0) { // if pid is less than 0, forking fails
printf("Fork failed.\n");
exit (1);
} else if (pid == 0) { //if pid == 0
//command not executed
if (execvp(args[0], args) == -1) {
printf("Error executing command\n");
}
} else {
// if flag == 0, the parent will wait,
// otherwise returns to the formatCommand() function.
i++;
if (flag == 0) {
i++;
wait(NULL);
}
}
}
}
}
我还对如何添加批处理以便我可以使用我的 shell 运行脚本感到困惑。我有文件:script.sh,里面有代码:
pwd
cal
date
理想情况下,当我输入我的 shell ./script.sh 时,它会(或者我想我想要它)运行脚本文件,但目前只是得到错误,因为我还没有实现它。如果有人可以帮助我解决这两件事,我将不胜感激!
【问题讨论】: