我被要求在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
,我会收到一个找不到的命令。
这是我的更新代码(它不是一个小代码):
#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),但是因为我开始使结构和变量全局化,所以在{中添加函数而不是整个代码{1}},它似乎只是第一次运行,然后执行除main()
之外的其他命令。
答案 0 :(得分:1)
事实证明,执行函数中的单词数组包含一个奇怪的字符,但它的长度为零,您需要进行一些更改!更新您的执行功能,如下所示
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
答案 1 :(得分:0)
发现错误。我应该在func_command()
的末尾重新初始化我的所有全局变量。
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);
i=0,options[N] = '\0',words_typed = 0,options_count = 1,dir_count = 0,word_processed=0,cursor=0,str_length=0; // restore values because they are global
return 0;
}