无法使用c中的exec和makeargv运行./program

无法使用c中的exec和makeargv运行./program,c,unix,exec,argv,C,Unix,Exec,Argv,首先,这个程序有两个主要部分。第一个使用fgets从命令行获取输入,然后使用名为makeargv的函数生成argv数组。第二,获取argv数组并使用execvp运行它。我遇到的问题是,该程序将只运行系统程序,如“ls”、“pwd”、“vim”等,但在指定目录时不会运行任何程序,如“/program”。我已经尝试过不同版本的exec,但唯一的区别是我的程序将不再运行任何命令 对于下面的程序,我删掉了所有与问题无关的代码,以避免混淆 #ifndef MAX_CANON #define MAX_CAN

首先,这个程序有两个主要部分。第一个使用fgets从命令行获取输入,然后使用名为makeargv的函数生成argv数组。第二,获取argv数组并使用execvp运行它。我遇到的问题是,该程序将只运行系统程序,如“ls”、“pwd”、“vim”等,但在指定目录时不会运行任何程序,如“/program”。我已经尝试过不同版本的exec,但唯一的区别是我的程序将不再运行任何命令

对于下面的程序,我删掉了所有与问题无关的代码,以避免混淆

#ifndef MAX_CANON
#define MAX_CANON 8192
#endif

int makeargv(const char *s, const char *delimiters, char ***argvp);

int main (int argc, char *argv[]) {
char cmd[MAX_CANON];
char delim[] = "\t";
char **myargv;



printf("Beginning program...\nEnter a command to execute:\n");
while(fgets(cmd, MAX_CANON, stdin) != NULL){    // Here's where I get input from the command line
    /* Remove newline from end of command */
    if (*(cmd + strlen(cmd) - 1) == '\n' || *(cmd + strlen(cmd) - 1) == ' ' )
        *(cmd + strlen(cmd) - 1) = 0;

    /*---- Child Code ----*/
    if((p = fork()) == 0){  
        if (makeargv(cmd, delim, &myargv) == -1) {  // Here is where I make the argv array
            fprintf(stderr, "Child failed to construct an argument array for %s\n", &cmd[0]);
            return 1;
        }

      fprintf(stderr, "Command is: %s\n", *&myargv[0]); 
        if(execvp(myargv[0], &myargv[0]) == -1){   // Here is where the error keeps appearing
            fprintf(stderr, "Error: Failed to execute command!\n");
            return 1;
        }
        return 0;
    } 
    /*---- Parent Code ----*/
这是makeargv代码

#include <errno.h>
#include <stdlib.h>
#include <string.h>

int makeargv(const char *s, const char *delimiters, char ***argvp) {
   int error;
   int i;
   int numtokens;
   const char *snew;
   char *t;

   if ((s == NULL) || (delimiters == NULL) || (argvp == NULL)) {
      errno = EINVAL;
      return -1;
   }
   *argvp = NULL;                           
   snew = s + strspn(s, delimiters);         /* snew is real start of string */
   if ((t = malloc(strlen(snew) + 1)) == NULL) 
      return -1; 
   strcpy(t, snew);               
   numtokens = 0;
   if (strtok(t, delimiters) != NULL)     /* count the number of tokens in s */
      for (numtokens = 1; strtok(NULL, delimiters) != NULL; numtokens++) ; 

                             /* create argument array for ptrs to the tokens */
   if ((*argvp = malloc((numtokens + 1)*sizeof(char *))) == NULL) {
      error = errno;
      free(t);
      errno = error;
      return -1; 
   } 
                        /* insert pointers to tokens into the argument array */
   if (numtokens == 0) 
      free(t);
   else {
      strcpy(t, snew);
      **argvp = strtok(t, delimiters);
      for (i = 1; i < numtokens; i++)
          *((*argvp) + i) = strtok(NULL, delimiters);
    } 
    *((*argvp) + numtokens) = NULL;             /* put in final NULL pointer */
    return numtokens;
}     
我现在得到一个“没有这样的文件或目录”错误

固定的:
makeargv
程序将
“\t”
用作delimeter,而不是
,因此无法正确创建数组

更改:

char delim[] = "\t";
致:


修复了该问题。

有两种类型的exec:

  • 第一个需要一个路径作为环境路径,其中包含一个位置(查找sys可执行文件的位置)
  • 以及其他如何获取真实文件位置
形成手册页():

如果指定的文件名不包含斜杠(/)字符,则execlp()、execvp()和execvpe()函数将复制shell在搜索可执行文件时的操作

这意味着您需要使用一个绝对位置,它总是以/开头

可以使用getwd()和strcat()连接这两个字符串

对于execvp:

int execvp(const char *file, char *const argv[]); // From the man (I <3 mans)
对于evecv:

int execv(const char *path, char *const argv[]);
有一个问题,它需要系统路径。如果您不知道bash中的“echo$PATH”类型是什么。这是一个目录列表,系统可以在其中找到诸如“/bin”中的“ls”之类的二进制文件,并将“:”作为sparator连接起来。我找到了确切的定义

对于您的makeargv:

我不明白你为什么尊重它,把地址记在后面

execvp(myargv[0],&myargv[0])


祝你好运

在您的第一个源代码中,以下变量是如何定义的:cmd、myargv和delim?我将它们添加到程序顶部的原始帖子中。您的代码在我的系统中工作,并将/bin/ls的本地副本添加到当前目录中。。。您能否确认您的“/program”是ELF可执行文件(而不是需要解释器的可执行脚本)?显示的代码与原型
fork()
execvp()
不符。另外,
p
是未定义的。另外,您还需要找出发生了什么错误-改为使用
peror(“错误:无法执行命令”)
打印消息!因此,我已经阅读了手册页,并使用
execvp()
execv()
尝试了系统命令、绝对路径和相对路径。第一个命令与系统命令一起工作,但仅此而已,而第二个命令对我传递的任何东西都不起作用。您知道是否需要以某种方式指定可执行文件的路径吗?例如,我一直以
/home/user/folder/../myprogram arg1 arg2
的形式给出我的程序的路径,这是
pwd
在控制台中返回的内容。感谢您的尝试,但尽管这确实有效,但这并不是我想要弄清楚的。我的makeargv程序已经可以运行了,并且构造了一个要传递给exec的argv数组,所以我想弄清楚为什么创建了这个数组,但是makeargv不适用于任何版本的exec,只要要运行的程序在当前目录中或者没有在我的路径中指定。好的,我想我发现了一个问题,请看帖子:)不幸的是,这不起作用,程序无法编译。虽然它是
execvp
的正确类型,
makeargv
不会接受它。修复了该问题!我在makeargv中使用了
“\t”
作为分隔符
,而不是
,因此我的整个程序及其参数是数组的第一个索引。整个程序现在如预期的那样工作。谢谢你的帮助!
int execvp(const char *file, char *const argv[]); // From the man (I <3 mans)
char argv[3][] = { "/bin/ls", "/", NULL};
if (execvp("/bin/ls", argv) == -1)
      return (1);
int execv(const char *path, char *const argv[]);
char **myargv; //That's we have 
char *const argv[]; //that's we need

//so you should try simply:
execvp(myargv[0], myargv);
//or if there is a cast problem
execvp(myargv[0], (char *const[])myargv);