我被要求用 C 为 shell 编写代码,它将执行如下命令
ls
, pwd
, ls -l
, ls -l -la
, ls -l/tmp
等,没有管道。
这是它的行为方式。
尝试单个单词命令效果很好(例如
ls
、pwd
、pstree
、ps
、time
),无论我输入多少次。仅在第一次尝试带选项的命令时有效,然后我每次重新输入时都会收到“找不到命令”的提示。 (例如
ls -l
)。如果它是我在 shell 上键入的第一个命令(例如
ls -l/tmp
)并且执行了我想要的次数,那么尝试一个带有选项和路径的命令是有效的,如果它是第一个命令。如果我先输入ls
,然后输入ls -l/tmp
,我会得到一个命令未找到。
这是我的UPDATED代码(不小):
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#define N 1000 // array size
#define TRUE 1
#define FALSE 0
typedef bool;
struct Buffer // used to store search_path because of strcat erros with simple array
{
char cache1[N];
}buffer[N];
struct Directories // Storing the directories
{
char dir[N];
}directories[N];
struct Words // Storing the 2 words entered
{
char w[N];
}words[N];
char options[N] = {0}; // store all -x options here e.g -la -l -l -a
int path_count = 0; // # of directories in $PATH
bool terminate = TRUE; // bool variable to check for program termination
char input[N] = {0}; // our input command
char file[N] = {0};
int words_typed = 0; // # of words typed.
int options_count = 1,i; // # of options in options table
int dir_count = 0; // # of directories
int word_processed; // which word we are currently in
int cursor; // cursor position in each word
int length; // # of characters typed.
int main()
{
char *search_path = {0}; // What $ PATH returns
search_path = strtok(getenv("PATH"),":");
while (search_path!=NULL) // path scanning method
{
strcat(buffer[path_count].cache1,search_path); // buffer.cache1 = search_path
strcat(buffer[path_count].cache1,"/"); // buffer.cache1 = search_path/
path_count++;
search_path = strtok(NULL,":"); // Start scanning next path
}
while(terminate)
{
func_body();
}
return 0;
}
int func_body ()
{
do
{
printf("$"); // $ before each input command
gets(input); // get input from user
} while(strcmp(input,"") == 0); // printf $ every time user presses ENTER
bool statement = (strcmp(input,"exit") == 0 );
if (statement) // if user entered "exit"
terminate = FALSE; // while(0) terminates program
else if (!statement) // if we dont want to exit,...
{
length = strlen(input); // # of characters typed.
if (input[0] != ' ') // Procedure of finding how many words the user has typed
words_typed+=1; // If the first character is not the 'space' key then it is a word,so the words_typed becomes 1
i=1;
while (i<length)
{
if ((input[i-1] == ' ') && (input[i] != ' '))
words_typed+=1; // If the current character is not the 'space key' and the previous is, then we have a new word
i+=1;
}
func_words();
func_directories();
func_command();
}
return 0;
}
int func_words()
{
i=0;
while (i<words_typed)
{
for (cursor=0; cursor<N; cursor++)
{
words[i].w[cursor] = '\0'; // initialize the array
}
i+=1;
}
word_processed = 0;
cursor = 0;
if (input[0] != ' ') // If the first character is not the 'space' key
{
words[word_processed].w[cursor]=input[cursor]; // We input the first character of the first word in the struct
cursor+=1;
}
else
word_processed = -1; // If the first character is indeed the 'space' key then h is downgraded to -1 because if doesn't it will cause problems
i=1;
while (i<length) // Counter i contains where we are on the command given by the user.For example on the string 'ls -l' character 's' is on number 1
{
if ((input[i] != ' ') && (input[i-1] == ' '))
{
word_processed+=1;
cursor = 0; // begin the procedure for the other word of the string
}
if (input[i] != ' ') // If the first character is not the 'space' key
words[word_processed].w[cursor] = input[i]; // We input the first character of the first word in the struct
cursor+=1;
i+=1;
}
return 0;
}
int func_directories()
{
i=0;
do
{
for (cursor=0; cursor<N; cursor++)
{
directories[i].dir[cursor] ='\0'; // initialize the array
}
i+=1;
}while(i<words_typed);
i=1;
do
{
if (words[i].w[0] == '-') // if user pressed '-'
{
for (cursor=1; cursor<strlen(words[i].w); cursor++)
{
options[options_count] = words[i].w[cursor]; // counting the times user pressed and store characters after '-' option
options_count+=1;
}
options[0]='-';
}
else // in case we dont have a -x command
{
for (cursor=0; cursor<strlen(words[i].w); cursor++)
{
directories[dir_count].dir[cursor]=words[i].w[cursor];
}
dir_count+=1;
}
i+=1;
}while(i<words_typed);
return 0;
}
int func_command()
{
pid_t pid;
int temp = dir_count;
i = 0;
do // wont work with while loop
{
strcpy(file,directories[i].dir); // file = directory
if (words_typed == 1) // if 1 word is typed eg. ls
execute(words[0].w,NULL,NULL); // only 1 argument needed
else if ((options[1] != ' ') && (temp == 0)) // if user enter command x -x e.g ls -l
execute(words[0].w,options,NULL); // options has all the -x options user typed e.g -l -l -a
else if ((options[1] == ' ') && (temp != 0)) // if user enter command x -x /directory e.g ls -l /tmp
execute(words[0].w,file,NULL);
else
execute(words[0].w,options,file); // most complex command
dir_count-=1;
i+=1;
}while (dir_count > 0);
words_typed=0;
return 0;
}
int execute(char first_word[],char all_array[],char words[])
{
int counter,status;
pid_t pid;
for (counter=0;counter<path_count;counter++)
{
char command_path[N] = {0};
strcat(command_path,buffer[counter].cache1); // command_path = search_path
strcat(command_path,first_word); // command_path = search_path/command
if(fopen(command_path,"r") != NULL)
{
pid = fork();
if (pid==0) // child process
execlp(command_path,first_word,all_array,words,NULL);
if (pid>0) // parent process
waitpid(pid,&status,0);
// if pid < 0 -> error
}
}
return 0;
}
问题是我设法让它运行了我想要的次数(参见 here ),但是自从我开始将结构和变量设为全局变量后,在 中添加了函数而不是整个代码main()
,好像只运行了第一次,然后除了exit
之外没有执行其他命令。
最佳答案
事实证明,您在 execute 函数中的 words 数组包含一个奇怪的字符,但它的长度为零,您需要进行一些更改!如下更新您的执行函数
int execute(char first_word[],char all_array[],char wrds[])
{
int counter,status;
pid_t pid;
for (counter=0;counter<path_count;counter++)
{
char command_path[N] = {0};
strcat(command_path,buffer[counter].cache1); // command_path = search_path
strcat(command_path,first_word); // command_path = search_path/command
//printf("%s\n",command_path);
if(fopen(command_path,"r") != NULL)
{
pid = vfork();
if (pid==0){ // child process
//printf("%s\n",command_path);
if(wrds!=NULL){
if(strlen(wrds)==0){wrds=NULL;}}
execlp(command_path,first_word,all_array,wrds,NULL);}
if (pid>0) // parent process
waitpid(pid,&status,0);
// if pid < 0 -> error
}
}
return 0;
}
每次用户输入新命令时,您都需要在第二个 do-while 循环中的 func_directories() 方法中将 options_count 更新为 1
if (words[i].w[0] == '-') // if user pressed '-'
{//line 165
options_count=1;
//rest of the code
关于c - C写的shell只执行一次,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33971264/