понимание того, почему execvp работает там, где execv не работает - PullRequest
0 голосов
/ 17 декабря 2018

Меня попросили внедрить 'мини-оболочку' в C. Я решил работать с execv, и она не работала, и когда я изменил ее на execvp, она работает!Взгляните на код (действие в tokExec function)

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


void tokExec(char command[128])
{
    // 'strtok' may look innocent, but it modifies the string, so I want a copy of the original command.
    char tokString[128];
    // 'strlen' is the lenghth without the null terminator.
    strncpy(tokString,command,strlen(command)+1);


    char* tokPtr = NULL;
    char tok[] = " ";
    int narg = 0;
    tokPtr = strtok(tokString,tok);
    char *myargs[64];

    while(tokPtr != NULL)
    {
            printf("arg %d is: %s\n",narg,tokPtr);
            myargs[narg] = tokPtr;
            narg = narg + 1;
            tokPtr = strtok(NULL,tok);
    }
    printf("Total number of arguments: %d\n",narg);

    // add the final 'NULL' element.
    myargs[narg] = NULL;

    execvp(myargs[0],myargs);
    printf("error\n");
    exit(1);
}

void normal()
{
    char command[128];
    strcpy(command,"default\0");
    printf("myShellZ > ");
    gets(command);
    while(strcmp(command,"exit") != 0)
    {
            int status;
            pid_t pid;
            if( (pid = fork()) == 0 )
            {
                    tokExec(command);
            }
            wait(&status);
            printf("myShellz > ");
            gets(command);
    }
}

void debug()
{
    // TO DO ....
    int a = 3;
}

// switching between shell modes: normal or debug.
int main(int argc, char* argv[])
{
    if(argc == 1)
            normal();
    else if(strcmp("-debug",argv[1]))
            debug();
    else
            exit(1);

    exit(0);
}

Если вместо execvp в конце tokExec я буду использовать execv, если мой вводтолько ls или ps и т. д. execv отлично, но если я добавлю аргументы к входу, например: ls -l myshell.c или evev просто ls -l или ps aux, я получу вывод error.

man едва относится к различиям между этими функциями, но утверждает, что:

Функции execv (), execvp () и execvpe () предоставляют массив указателейв строки с нулевым символом в конце, которые представляют список аргументов, доступных для новой программы.Первый аргумент, по соглашению, должен указывать на имя файла, связанное с исполняемым файлом.Массив указателей должен заканчиваться нулевым указателем.

В заключение, какая разница между execv и execvp, которые исправили мою программу в этом случае?Я знаю, что execv также работает для команд bash, так как, если я ввел команду bash без аргументов, она работает, и подпись этих двух функций идентична.Спасибо за любую помощь!

1 Ответ

0 голосов
/ 17 декабря 2018

Ответ на странице руководства.Если вы читаете раздел после той части, которую вы цитировали, она говорит о разнице

Функции execlp (), execvp () и execvpe () дублируют действия оболочки при поискеисполняемый файл, если указанное имя файла не содержит косую черту (/).Файл ищется в списке разделенных двоеточиями каталогов, указанных в переменной среды PATH.Если эта переменная не определена, по умолчанию в списке путей указан текущий каталог, за которым следует список каталогов, возвращаемый confstr (_CS_PATH).(Этот вызов confstr (3) обычно возвращает значение "/bin:/usr/bin".)

...