Двойной указатель в качестве аргумента для execvp () - PullRequest
0 голосов
/ 12 января 2019

Я пытаюсь выполнить execvp(), используя собственный **tokens двойной указатель в качестве ввода вместо argv[] в назначении "создать собственную оболочку", например:

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

int main(){
    char *token;
    char **tokens = malloc(sizeof(char*)*512); //512 is for the maximum input-command length
    char *command=malloc(sizeof(char)*512);
    int i = 0;
    pid_t child_pid;
    int status;
    //***********take input from user*************************************
    fgets(command,512,stdin);

    //***********parse input*********************************************
    token = strtok(command," \t");

    while( token != NULL ) {

        tokens[i]=token;
        i ++;
        token = strtok(NULL, " \t");

    }
    child_pid = fork();

    if(child_pid == 0) {
        /* This is done by the child process. */
        execvp(tokens[0], tokens);
    } else {
        waitpid(child_pid, &status, WUNTRACED);
    }
}

Проблема определенно в этой строке:

execvp(tokens[0], tokens);

и я просто не могу понять, почему его нельзя выполнить и распечатать на моем stdout. Я пробовал это:

execvp("ls", tokens);

и все работает просто отлично. И это:

printf("%s\n", tokens[0]);

с выходным значением (в соответствии с тестовым входом: ls):

Ls

Ответы [ 2 ]

0 голосов
/ 12 января 2019

У вас есть несколько проблем в вашем коде, в том числе:

  1. Массив указателей аргументов, переданных в execvp(), должен заканчиваться нулевым указателем. Вы не гарантируете, что.

  2. Строка, полученная через fgets, будет включать все символы вплоть до новой строки, включая буфер, если буфер достаточно велик, чтобы вместить его. Вы не включаете символ новой строки в символы разделителя токенов, поэтому для команды из одного слова ls команда, переданная в execvp(), эквивалентна "ls\n", , а не "ls". Маловероятно (но не невозможно), что ls\n является доступной командой на вашем компьютере.

  3. Вы не проверяете возвращаемое значение execvp() или каких-либо других ваших функций, а также не обрабатываете никаких ошибок. execvp() отличается тем, что возвращает только в случае ошибки, но вы могли бы избежать путаницы, если бы обработали этот случай, выдав сообщение об ошибке.

После того, как я исправлю первые два из них, ваша программа успешно выполнит для меня команду "ls".

0 голосов
/ 12 января 2019

Вам нужно выделить память с помощью sizeof(char *).

char **tokens = malloc(sizeof(char *)*512);
                                   ^^----------->Size of char pointer

На данный момент вы выделяете sizeof(char), вызывая неопределенное поведение.


Также рассмотрите первый комментарий, на который указывает @ n.m

...