2016-09-16 4 views
1

Я пытаюсь сделать крошечную оболочку. Моя проблема в том, что когда я звоню execvp() - я получаю ошибки. Например, когда я печатаю ls -l, он возвращает ls: invalid option -- 'execvp() не работает в моей оболочке

Может кто-нибудь, пожалуйста, помочь мне понять, почему я получаю эту ошибку? Для моего кода функция split split получает вход пользователя и разбивает их на отдельные команды. Отдельные команды разделяются символом ;.

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

#define MAX_CHARACTERS 512 
#define HISTORY_SIZE 10 

int commandSplit(char *c, char *a[], int t[]) { 

int count = 0; 
int total = 0; 
char *temp[MAX_CHARACTERS]; 
char *readCommands = strtok(c, ";"); 
while(readCommands != NULL) { 
    printf("Reading full command: %s\n", readCommands); 
    temp[count] = readCommands; 
    count++; 
    readCommands = strtok(NULL, ";"); 
} 
printf("Done reading full commands\n"); 
for(int i = 0; i < count; i++) { 
    char *read = strtok(temp[i], " "); 
    int track = 0; 
    while(read != NULL) { 
     printf("Reading individual command: %s\n", read); 
     a[total] = read; 
     track++; 
     total++; 
     read = strtok(NULL, " "); 
    } 
    t[i] = track; 
} 

return count; 
} 

int main() { 

int exitProgram = 0; 
char *args[MAX_CHARACTERS]; 

while(!exitProgram) { 

char *commands = (char *)(malloc(MAX_CHARACTERS*sizeof(char))); 
int tracker[MAX_CHARACTERS]; 
int numOfCommands = 0; 
printf("tinyshell> "); 
fgets(commands, MAX_CHARACTERS, stdin); 

if(strlen(commands) == 0) continue; 

numOfCommands = commandSplit(commands, args, tracker); 
printf("There are %i commands!\n", numOfCommands); 

if(strcmp(args[0], "exit") == 0) { 
    printf("Exiting\n"); 
    exitProgram = 1; 
    continue; 
} 

int l = 0; 
for(int i = 0; i < numOfCommands; i++) { 
    int status; 
    char *holder[tracker[i]+1]; 
    for(int j = 0; j < tracker[i]; j++) { 
     holder[j] = args[l]; 
     printf("Assiging holder:%s\n", holder[j]); 
     l++; 
    } 
    holder[tracker[i]] = NULL; 
    printf("What is holder? \n"); 
    for(int o = 0; o < tracker[i]; o++) printf("%s", holder[o]); 
    pid_t p = fork(); 
    pid_t waiting; 
    if(p == 0) { 
    printf("I am in child process\n"); 
    execvp(holder[0], holder); 

    fprintf(stderr, "Child process could not execvp!\n"); 
    exit(1); 
    } 
    else { 
     if(p < 0) { 
      fprintf(stderr, "Fork FAILED!\n"); 
     } 
     else { 
      waiting = wait(&status); 
      printf("Child %d, status %d\n", waiting, status); 
     } 
    } 
    for(int i = 0; i < numOfCommands; i++) { 
     args[i] = NULL; 
    } 
} 

} 

return 0; 

} 
+0

Вы уверены, что 'holder' правильно прекращено? Если вы выполните код в строке в отладчике, он будет вести себя так, как вы ожидаете? Все переменные значения, как вы ожидаете? –

+0

, показывающий вывод 'for (int o = 0; o

ответ

2

Ваша проблема в том, что fgets()also reads the newline character. В результате последний аргумент массива аргументов execvp() содержит новую строку, в результате чего ls жалуется на непризнанный аргумент: то, что вы фактически передаете на ls, равно -l\n; то, что вам нужно передать, это просто -l без новой строки.

Попробуйте добавить этот код после вызова fgets обрезать входной буфер:

int len; 
len = strlen(commands); 
if (len > 0 && commands[len-1] == '\n') { 
    commands[len-1] = '\0'; 
} 
+0

Большое вам спасибо. Я сводил меня с ума, пытаясь понять, что случилось. – David

+0

У меня, похоже, возникает другая проблема. Когда я вхожу в «ls -l; ls», он выполняет обе команды в порядке. Однако, если я нахожу «ls; ls -l», он выполняет первую команду правильно, но «ls -l» не перечисляет каталоги, но, похоже, не вызывает ошибки. Я просто получаю пару нулевых операторов на своем экране. – David

+2

@ Давид пытается использовать отладчик для отслеживания кода и поиска проблемы. – kfx