簡體   English   中英

用C編寫的Shell僅執行一次

[英]Shell written in C executes only one time

我被要求用C語言為外殼編寫代碼,該代碼將執行lspwdls -lls -l -lals -l /tmp等命令,而無需使用管道。

這是它的行為。

  1. 無論輸入多少次,嘗試單字命令都可以完美工作(例如lspwdpstreepstime )。

  2. 嘗試使用帶有選項的命令僅在第一次時有效,然后每次重新鍵入命令時都會收到“找不到命令”。 (例如ls -l )。

  3. 如果它是我在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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM