簡體   English   中英

Linux shell 分配。 Execvp 無法執行命令

[英]Linux shell assignment. Execvp failing to execute commands

我正在嘗試使用 C 為 linux 創建一個簡單的 shell。 我無法弄清楚為什么 execvp() 一直失敗。 我知道 execvp 不需要通過 arguments 傳遞路徑。 我嘗試通過 strtok 運行命令的 char 數組來遵循某人的建議。

我不斷收到 execvp 失敗:沒有這樣的文件或目錄。 我只是通過一個簡單的“ls”作為我的測試命令。

#include <string.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#define MAXARGS         20
#define CMDPROMPT       "theshell>"
#define ARGPROMPT       "Next argument: "
#define prompt(n)       printf("%s", (n) == 0 ? CMDPROMPT : ARGPROMPT);

int main(int argc, char* argv[])
{
        char arg[MAXARGS] = {0};
        int i = 0,
            should_run = 1, pid, exitstatus;

        while (should_run)
        {
                prompt(*arg);

                fgets(arg, MAXARGS, stdin);                                                                                                                 
                                                                                                                                                            
                char *arg = strtok(arg, " ");                                                                                                               
                                                                                                                                                            
                char *arg_tok[MAXARGS];                                                                                                                     
                                                                                                                                                            
                while(arg)                                                                                                                                  
                {                                                                                                                                           
                        arg_tok[i++] = arg;                                                                                                                 
                        arg = strtok(NULL, " ");                                                                                                            
                }                                                                                                                                           
                                                                                                                                                            
                pid = fork();                                                                                                                               
                                                                                                                                                            
                switch(pid)
                {
                        case -1:
                                perror("Fork Failed\n");
                                exit(1);
                        case 0:
                                execvp(arg_tok[0], arg_tok);
                                perror("execvp has failed");
                                exit(1);
                        default:
                                while( wait(&exitstatus) != pid );
                                printf("Child process exited with status %d, %d\n", exitstatus>>8, exitstatus&0377);
                }
        }
}

您有許多問題,主要在上面的評論中詳細說明。 您不會使用NULL終止指針的execvp()列表,並且您使用聲明為的arg隱藏arg

    char *arg = strtok(arg, " "); 

然后重新聲明為:

        char *arg = strtok(arg, " "); 

最后,您未能從最后一個指針指向的字符串中刪除'\n' 回想一下, fgets()讀取並在填充的緩沖區中包含'\n' 因此,只需將strtok()的分隔符列表更改為包含'\n' ,例如" \n"

總而言之,您可以這樣做:

#include <string.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/wait.h>                           /* include sys/wait.h for wait() */

#define MAXARGS         20
#define CMDPROMPT       "theshell> "            /* add space after > */
#define ARGPROMPT       "Next argument: "
#define prompt(n)       printf("%s", (n) == 0 ? CMDPROMPT : ARGPROMPT);

int main (void)
{
    char arg[MAXARGS] = "";
    int i = 0,
        should_run = 1, pid, exitstatus;

    while (should_run)
    {
        prompt (0);

        fgets (arg, MAXARGS, stdin);

        char *p = strtok (arg, " \n");           /* fix shadow of arg, included \n as delim */

        char *arg_tok[MAXARGS] = {NULL};

        while (p) {
            arg_tok[i++] = p;
            p = strtok(NULL, " \n");
        }

        pid = fork();

        switch(pid)
        {
            case -1:
                perror("Fork Failed\n");
                exit(1);
            case 0:
                execvp (arg_tok[0], arg_tok);
                perror ("execvp has failed");
                exit(1);
            default:
                while( wait(&exitstatus) != pid );
                printf ("Child process exited with status %d, %d\n",
                        exitstatus>>8, exitstatus&0377);
        }
    }
}

注意:wait()添加 header sys/wait.h

示例使用/輸出

$ ./bin/execvp_ls
theshell> ls -al fh
total 152
drwxr-xr-x  2 david david   4096 Jul  1  2018 .
drwxr-xr-x 32 david david 131072 Mar  3 15:16 ..
-rw-r--r--  1 david david    602 Jul  1  2018 Readme_ld_reqd_opts.txt
-rw-r--r--  1 david david    124 Jul  1  2018 conversion.c
-rw-r--r--  1 david david     30 Jul  1  2018 conversion.h
-rw-r--r--  1 david david    250 Jul  1  2018 convert_driver.c
Child process exited with status 0, 0
theshell> ^C

另請注意,您使用宏雖然很聰明,但通常會導致比它們解決的問題更多的問題。 簡單地編寫要顯示的提示是 go 的一種更具可讀性的方式。 雖然這里的宏使用在這里是微不足道的,但這只會隨着代碼長度和復雜性的增加而增加。

如果您還有其他問題,請仔細查看並告訴我。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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