首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使用execvp()执行命令

如何使用execvp()执行命令
EN

Stack Overflow用户
提问于 2018-03-06 10:51:19
回答 2查看 6.7K关注 0票数 0

因此,我正在尝试为我的学校项目创建一个自定义的shell。我的方法是创建子进程,并让该进程使用我的教授在课堂上简要提到的execvp()函数执行命令。这是我的代码,一如既往,任何帮助都是非常感谢的。

代码语言:javascript
复制
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>

#define MAX_LINE 80



int main(int argc, char *argv[])
{
    char *input = (char*)malloc(MAX_LINE*sizeof(char)); 
    int should_run = 1;

    while(should_run){
        printf("osh>");
        fflush(stdout);

        pid_t pid;
        pid = fork();
        if(pid < 0){
            printf("error with creating chiled process");
            return 0;
        }

        if(pid == 0){
            fgets(input, MAX_LINE, stdin);
            char *token = strtok(input," ");

            if(execvp(token[0], token) < 0){
                printf("Error in execution.");
                return(0);
            }
            //should_run = 0;
        }
        waitpid(pid, 1, 0);

    }
    return 0;
}
EN

回答 2

Stack Overflow用户

发布于 2018-03-06 10:57:11

execvp的原型是

代码语言:javascript
复制
int execvp(const char *file, char *const argv[]);

它需要一个指向char的指针作为第一个参数,以及一个指向char*数组的NULL-terminated指针。您传递的是完全错误的参数。

您将传递一个char作为第一个参数,传递一个char*作为第二个参数。

请改用execlp

代码语言:javascript
复制
int execlp(const char *file, const char *arg, ...
              /* (char  *) NULL */);

所以

代码语言:javascript
复制
char *token = strtok(input," \n");

if(token == NULL)
{
    fprintf(stderr, "only delimiters in line\n");
    exit(1);
}

if(execlp(token, token, NULL) < 0){
    fprintf(stderr, "Error in execution: %s\n", strerror(errno));
    exit(1);
}

此外,UNIX中的约定是将错误消息打印到stderr,出现错误的进程的退出状态应该不是0。

票数 1
EN

Stack Overflow用户

发布于 2018-03-06 18:31:36

正如巴勃罗所说,您正在向execvp()传递错误的参数。您可以考虑自己编写一个函数(char **strsplit(char *str, char delim)),该函数接受一个字符串并将其拆分成更小的片段,返回一个字符串数组。

另外,不要忽视编译器的警告,它们会告诉你很多事情,我建议你用gcc -Wall -Wextra -Werror编译,这样你的程序中几乎所有可能的错误都会被发现。

我之所以告诉你这一点,是因为waitpid()将指向整数的指针作为第二个参数,以获取派生程序的状态更新。有了这个状态,你就可以知道程序是如何退出的(正常,segf,总线错误...),如果出了问题,你可以用它来打印一个错误。

你可以考虑使用execv() (我知道我离题了,但是你可以从中学到有用的东西),然后自己找到正确的可执行文件。

代码语言:javascript
复制
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <dirent.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/stat.h>

#define MAX_LINE 255

char    **strsplit(char *str, char delim);
char    *strjoin(char const *s1, char const *s2);


int         isexec(char *path)
{
    struct stat buf;

    lstat(path, &buf);
    if (S_ISREG(buf.st_mode) && (S_IXUSR & buf.st_mode))
        return (1);
    return (0);
}

static char     *find_exec_readdir(char *paths, char *cmd)
{
    DIR             *dir;
    struct dirent   *dirent;
    char            *exec;

    exec = NULL;
    if ((dir = opendir(paths)) != NULL)
    {
        while ((dirent = readdir(dir)) != NULL)
        {
            if (!strcmp(dirent->d_name, cmd))
            {
                exec = strdup(dirent->d_name);
                break ;
            }
        }
        if (closedir(dir))
            dprintf(2, "Failed closing dir.\n");
    }
    return (exec);
}

char    *find_exec(char *cmd, char **paths)
{
    char            *exec;
    char            *path;
    char            *tmp;
    int             i;

    i = -1;
    exec = NULL;
    path = NULL;
    if ((cmd[0] == '.' || cmd[0] == '/'))
    {
        if (isexec(cmd))
            return (strdup(cmd));
        return (NULL);
    }
    while (paths[++i])
        if ((exec = find_exec_readdir(paths[i], cmd)) != NULL)
        {
            tmp = strjoin(paths[i], "/");
            path = strjoin(tmp, exec);
            free(tmp);
            free(exec);
            break ;
        }
    return (path);
}

int handle_return_status(int status)
{
    int         sig;
    int         i;

    if (!WIFEXITED(status) && WIFSIGNALED(status))
    {
        sig = WTERMSIG(status);
        i = -1;
        while (++i <= 13)
        {
            if (print_signal_error(sig))
            {
                return (-1);
            }
        }
        dprintf(2, "Process terminated with unknown signal: %d\n", sig, NULL);
        return (-1);
    }
    return (0);
}


int main(int argc, char *argv[])
{
    char    *input = NULL; 
    char    **command = NULL;
    int     should_run = 1;
    int     status = 0;


    (void)argc;
    (void)argv;
    if ((input = (char*)malloc(MAX_LINE*sizeof(char))) == NULL)
        return (dprintf(2, "Failed to malloc, abort.\n"));
    while(should_run){
        printf("osh> ");
        fflush(stdout);

        pid_t pid;
        pid = fork();
        if(pid < 0)
            return (dprintf(2, "error with creating chiled process\n"));

        if(pid == 0){
            fgets(input, MAX_LINE, stdin);
            command = strsplit(input, ' ');
            command[0] = find_exec(command[0], strsplit(getenv("PATH"), ':'));

            if(execv(command[0], &command[1]) < 0)
                return (dprintf(2, "Error in execution.\n"));
            //should_run = 0;
        }
        waitpid(pid, &status, 0);
        handle_ret_status(status);

    }
    return 0;
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/49122665

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档