execve()和execvp()忽略了第一个参数

时间:2015-08-09 00:13:53

标签: c shell exec fork execvp

这是作业。

我的代码:

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

int main(void){

int run=1;

while (run) {
    int perror;
    pid_t pid;
    char in[1536];
    char para[512]="/bin/";
    char *argv[512];

printf("%s..: %s","\x1B[31m","\x1B[37m");
    fgets(in,1530,stdin);
    char *com = strtok (in," \t\r\n");
    char *c2=com;

    strcat (para,com); 
    strcat (para,"\0");

    int i=0;
    while (com != NULL){
        com = strtok (NULL, " \n\r\t");
        if (com!=NULL){
            argv[i]=com;
            i++;
        }
    }

    argv[i]="\0";

    if (strcmp(c2, "exit") == 0|strcmp(c2, "quit") == 0){
        run=0;
    }

    else{ 
        if ((pid=fork())==0){ //Child
            execvp(para,argv);
        }
        else{ //Parent
            waitpid(pid,&perror,0);
        }
    }
}
return 0;
}

lspwd之类的命令在没有参数的情况下完美地工作,但是当我尝试使用参数时,第一个参数被忽略。以下示例输出。

$ make
$ ./A1T2
..: ls
A1T2  main.c  main.c~  main.c++~  main.c.old  Makefile  Makefile~
..: pwd
/home/kevin/Documents/COS-222/Assignments/Assignment-1/Task-2
..: mkdir one
one: cannot create directory ‘’: No such file or directory
..: mkdir one two
one: cannot create directory ‘’: No such file or directory
..: ls
: cannot access : No such file or directory
two:
..: exit
kevin@Kevin-MATE:~/Documents/COS-222/Assignments/Assignment-1/Task-2$ make
./A1T2
..: ls
A1T2  main.c  main.c~  main.c++~  main.c.old  Makefile  Makefile~  two
..: echo hello world
world 
..: exit
$

3 个答案:

答案 0 :(得分:2)

注意:execvp()的第一个参数不是字符串,而是指向字符串的指针,就像argv []数组中的所有条目一样,argv []数组以NULL的最终条目终止,而不是'\ 0'

以下代码:

compiles cleanly, 
performs the desired function.

用户输入的'ls'行将打印当前目录中的所有文件名。

用户输入的'ls -la'行将打印当前目录中所有文件名的长版本。

但是,输入'ls *'行的用户将失败,并显示有关未找到文件的消息。 I.E. 'glob'ing没有被执行。

#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>

enum
{
    MAX_PARAMETERS = 512,
    MAX_PGM_NAME_LEN = 512,
    MAX_USER_INPUT_LEN =1563
};

int main(void)
{

    int run=1;

    while (run)
    {
        int status;
        pid_t pid;
        char in[MAX_USER_INPUT_LEN];
        char para[MAX_PGM_NAME_LEN]="/bin/";
        char *argv[MAX_PARAMETERS] = {'\0'};
        int i = 1; // index into argv[] list

        // change some terminal screen characteristic
        printf("%s..: %s","\x1B[31m","\x1B[37m");

        printf( "enter program name to be executed and any parameters\n separated by space, tab or newline\n");
        fgets(in,MAX_USER_INPUT_LEN,stdin);

        char *pgmName = strtok (in," \t\r\n");
        if( NULL == pgmName )
        { // then strtok failed
            perror( "strtok failed" );
            exit( EXIT_FAILURE );
        }

        // implied else, strtok successful

        printf( "program to execute: %s\n", pgmName);
        char *c2=pgmName;

        strcat( para, pgmName);
        argv[0] = para;
        printf( "argv[0] = %s\n", argv[0]);

        char * parameter = NULL;
        while (NULL != (parameter = strtok(NULL, " \n\r\t") ) )
        {
            printf( "argv[%d] = %s\n", i, parameter);
            argv[i]=parameter;
            i++;
        }

        argv[i]=NULL; // terminate the parameter list

        if ( (strcmp(c2, "exit") == 0) | (strcmp(c2, "quit") == 0) )
        {
            run=0;
        }

        else
        {
            pid=fork();
            if (-1 == pid)
            { // then fork failed
                perror( "fork() failed");
                exit( EXIT_FAILURE );
            }

            // implied else, fork successful

            if( 0 == pid)
            { //Child
                execvp(para,argv);
                exit( EXIT_FAILURE ); // should never get here
            }
            else
            { //Parent
                waitpid(pid,&status,0);
            }
        }
    }
    return 0;
}

答案 1 :(得分:1)

params放入argv[0]并将所有内容移至argv并致电:

execvp (argv[0], argv);

答案 2 :(得分:0)

我建议您使用main(argc, argv)接收用于启动代码的命令行参数,然后调用execvp(argv[1], &argv[1]);

这将简单地传递您在启动代码时在命令行上提供的所需参数,因此,如果您使用...启动代码

yourcode ls -l -b

execvp()方法会收到&#34; ls&#34;作为第一个参数和&#34; -l&#34;和&#34; -b&#34;作为附加参数。

请记住,不要重复代码,并始终提供评论。