无法 运行 ./program with exec and makeargv in c
Unable to run ./program with exec and makeargv in c
所以首先,这个程序有两个主要部分。第一个使用 fgets 从命令行获取输入,然后使用名为 makeargv 的函数创建一个 argv 数组。第二,获取 argv 数组并使用 execvp 运行s 它。我遇到的问题是该程序只会 运行 系统程序,例如 "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;
}
编辑:
将 fprintf 替换为 perror。
if(execvp(myargv[0], &myargv[0]) == -1){ // Here is where the error keeps appearing
fprintf(stderr, "Error: Failed to execute command!\n");
return 1;
}
if(execvp(myargv[0], &myargv[0]) == -1){ // Here is where the error keeps appearing
perror("Error: Failed to execute command!\n");
return 1;
}
我现在遇到 "No such file or directory" 错误。
已修复:
makeargv
程序使用 "\t"
作为分隔符而不是 " "
,因此它没有正确创建数组。
变化中:
char delim[] = "\t";
收件人:
char delim[] = " ";
解决了问题。
有两种执行类型:
- 首先需要一个路径作为环境PATH,其中包含一个位置(find sys executables)
- 以及其他人如何获取真实文件位置。
Form the man page (https://linux.die.net/man/3/exec):
The execlp(), execvp(), and execvpe() functions duplicate the actions of the shell in searching for an executable file if the specified filename does not contain a slash (/) character.
所以这意味着你需要使用一个绝对位置,总是以 / 开头。
您可以使用 getwd() 和 strcat() 连接两个字符串。
对于 execvp:
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);
对于evecv:
int execv(const char *path, char *const argv[]);
有问题,需要系统PATH。如果您不知道它是什么,请在 bash 中输入 "echo $PATH"。它是一个目录列表,系统可以在其中找到二进制文件,例如“/bin”中的 "ls",并与“:”连接作为分隔符。我找到了确切的定义 here.
为了您的 makeargv:
我不明白你为什么要尊重它并把地址放在后面。
execvp(myargv[0], &myargv[0])
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);
祝你好运!
所以首先,这个程序有两个主要部分。第一个使用 fgets 从命令行获取输入,然后使用名为 makeargv 的函数创建一个 argv 数组。第二,获取 argv 数组并使用 execvp 运行s 它。我遇到的问题是该程序只会 运行 系统程序,例如 "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;
}
编辑:
将 fprintf 替换为 perror。
if(execvp(myargv[0], &myargv[0]) == -1){ // Here is where the error keeps appearing
fprintf(stderr, "Error: Failed to execute command!\n");
return 1;
}
if(execvp(myargv[0], &myargv[0]) == -1){ // Here is where the error keeps appearing
perror("Error: Failed to execute command!\n");
return 1;
}
我现在遇到 "No such file or directory" 错误。
已修复:
makeargv
程序使用 "\t"
作为分隔符而不是 " "
,因此它没有正确创建数组。
变化中:
char delim[] = "\t";
收件人:
char delim[] = " ";
解决了问题。
有两种执行类型:
- 首先需要一个路径作为环境PATH,其中包含一个位置(find sys executables)
- 以及其他人如何获取真实文件位置。
Form the man page (https://linux.die.net/man/3/exec):
The execlp(), execvp(), and execvpe() functions duplicate the actions of the shell in searching for an executable file if the specified filename does not contain a slash (/) character.
所以这意味着你需要使用一个绝对位置,总是以 / 开头。
您可以使用 getwd() 和 strcat() 连接两个字符串。
对于 execvp:
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);
对于evecv:
int execv(const char *path, char *const argv[]);
有问题,需要系统PATH。如果您不知道它是什么,请在 bash 中输入 "echo $PATH"。它是一个目录列表,系统可以在其中找到二进制文件,例如“/bin”中的 "ls",并与“:”连接作为分隔符。我找到了确切的定义 here.
为了您的 makeargv:
我不明白你为什么要尊重它并把地址放在后面。
execvp(myargv[0], &myargv[0])
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);
祝你好运!