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

execve() and execvp() are ignoring the first argument

这是作业。

我的代码:

#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,"[=10=]");

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

    argv[i]="[=10=]";

    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
$

params放入argv[0]并将argv中的所有内容向下移动并调用:

execvp (argv[0], argv);

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

以下代码:

compiles cleanly, 
performs the desired function.

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

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

但是,用户输入 'ls *' 行将失败,并显示有关找不到文件的消息。 IE。没有执行 '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] = {'[=11=]'};
        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;
}

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

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

yourcode ls -l -b

execvp() 方法将接收 "ls" 作为第一个参数和“-l”和“-b”作为附加参数。

记住,不要重复代码,并始终提供注释。