[英]Shell written in C executes only one time
我被要求用C語言為外殼編寫代碼,該代碼將執行ls
, pwd
, ls -l
, ls -l -la
, ls -l /tmp
等命令,而無需使用管道。
這是它的行為。
無論輸入多少次,嘗試單字命令都可以完美工作(例如ls
, pwd
, pstree
, ps
, time
)。
嘗試使用帶有選項的命令僅在第一次時有效,然后每次重新鍵入命令時都會收到“找不到命令”。 (例如ls -l
)。
如果它是我在shell上鍵入的第一條命令(例如ls -l /tmp
),則嘗試使用帶有選項和路徑的命令是可行的,並且如果它是第一條命令,則可以執行任意多次。 如果我先輸入ls
,然后輸入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;
}
事實是,我設法使其運行了許多次(請參見此處 ),但是由於我開始使結構和變量成為全局變量,因此在main()
添加了函數而不是整個代碼,看來僅第一次運行,然后除了exit
外不執行其他命令。
事實證明,您的execute函數中的word數組包含一個奇怪的字符,但長度為零,您需要進行一些更改! 如下更新您的執行功能
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
發現錯誤。 我應該在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;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.