c - C写的shell只执行一次

标签 c linux shell pipe

我被要求用 C 为 shell 编写代码,它将执行如下命令 ls, pwd, ls -l, ls -l -la, ls -l/tmp 等,没有管道。

这是它的行为方式。

  1. 尝试单个单词命令效果很好(例如 lspwdpstreepstime),无论我输入多少次。

  2. 仅在第一次尝试带选项的命令时有效,然后我每次重新输入时都会收到“找不到命令”的提示。 (例如 ls -l)。

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

相关文章:

c - 如何使用 C 中的指针将数组 (1D) 传递给函数?

c - 指针类型转换为不同的数据类型

c++ - 定义结构并用作参数

linux - 在 64 位系统上使用 gcc -m32 编译应用程序

linux - ENV_VAR=${sh_var} 在 sh 脚本中设置

linux - 语法错误: unexpected end of file when sourcing a file in bash

c - 将结构体的地址分配给指针

linux - 使用 Bash 跳过文件中的第一个匹配项

java - 32 位 Linux (Xubuntu 14.04) 上的 MATLAB 2013 安装

python - bash:根据安装的 python 版本执行不同的操作