2014-02-14 4 views
0

Я работаю над проектом, в котором я должен написать командную оболочку для linux в C. До сих пор он работает для команд без ввода (т. Е. Оболочка будет запускать «дату», команда и команда «ls».)аргументы команды execvp и чтения

Однако команды, требующие ввода, кажутся, что он считывает каждый вход как отдельную команду. Например, для команды:

% gcc -o testFile testFile.c 

Кажется, если оболочка работает GCC как свою собственную команду, то -o, то TestFile и testfile.c, когда следует принимать GCC, как команда, с другие три записи в качестве входных данных.

Я не понимаю, что происходит в коде - и это, вероятно, происходит из-за непонимания функции execvp (я читал об этом из нескольких источников, и я до сих пор не думаю, что понимаю). Я думал, что сделал !).

Вызов execvp выполняется в функции.

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

#define MAX_ARGUMENTS 10 


void parseLine(char *command, char **args) { 

const char split = '\0'; 
int i; 
char *ptrToken; 

while(*command != '\0') { 
    while ((*command == '\n') || (*command == '\t') 
     || (*command == ' ')) { 
     *(command++) = '\0'; 
     } // end 'while' 
    *args++ = command; 
    printf("%s\n", command); 
    while ((*command != '\n') && (*command != '\t') 
     && (*command != '\0') && (*command != ' ')) { 
     command++; 
     } // end 'while' 

    } // end 'while' 
*args = '\0'; 
} // end parseLine 

void execute(char **arrayOfPtrs) { 
/* 
CURRENT BUG: 
The function is taking the array of pointers, and executing each 
input from the array seperately. 

The execvp function is being misused. 
*/ 
pid_t pid; 
int waitStatus; 

switch (pid = fork()) { 
    case 0: // Child process 
     if (execvp(arrayOfPtrs[0], arrayOfPtrs) < 0) { 
      perror("THE COMMAND FAILED TO EXECUTE!"); 
      break; 

      } // end 'if 

    case -1: // Fork failed 
     perror("THE PROCESS FAILED TO FORK"); 
     break; 

    default: // Parent process 
     while ((wait(&waitStatus) != pid)) {}; 
     break; 
} // end 'switch' 
return; 
} // end 'execute 

void clearPointerArray(char **args){ 

while (*args != NULL) { 
    *(args++) = NULL; 
} 
} 


int main() { 

int i; 
char command[MAX_STRING_LENGTH]; // unparsed command 
pid_t pid; 
char *args[MAX_ARGUMENTS]; // Argument vector. 


while(1) { 
    clearPointerArray(args); 
    printf("%s", "TimsShell--> "); 
    scanf("%s", command); 

    parseLine(command, args); 

    if ((strcmp(args[0], "exit") == 0) || (strcmp(args[0], "quit") == 0)) { 
     printf("%s\n", "Goodbye!"); 
     return 0; 
    } 

    execute(args); 

    }// while loop 
return 0; 

} // main 

А вот некоторые выходы из командной строки:

% gcc -o mainShell mainShell.c 
% ./mainShell 
TimsShell--> date 
date 
Fri Feb 14 15:50:28 EST 2014 
TimsShell--> ls 
ls 
change.log  doLocalConf.xml license.txt notepad++.exe session.xml    testFile.c 
commandStorage.c functionList.xml localization plugins  shortcuts.xml   themes 
config.model.xml langs.model.xml mainShell  readme.txt  stylers.model.xml updater 
config.xml  langs.xml  mainShell.c SciLexer.dll  stylers.xml   user.manual 
TimsShell--> gcc -o testFile testFile.c 
gcc 
gcc: fatal error: no input files 
compilation terminated. 
TimsShell--> -o 
THE COMMAND FAILED TO EXECUTE!: No such file or directory 
TimsShell--> testFile 
THE COMMAND FAILED TO EXECUTE!: No such file or directory 
TimsShell--> testFile.c 
: not found 2: testFile.c: 
testFile.c: 3: testFile.c: Syntax error: "(" unexpected 
TimsShell--> ^C 
+0

Есть ли причина, что вы лечения '', '\ n' и' \ T' специально, а не вести себя как реальная оболочка будет и позволяет любому символу в 'IFS' действовать как разделитель (с' \ n \ t 'в качестве значения IFS по умолчанию)? Я бы сказал, что то, как вы это делаете, на самом деле делает код сложнее, чем правильное поведение. –

ответ

1

Обратитесь к справочной странице для зсапа почему это происходит. Проблема в вашем формате строки:

% s

Соответствует последовательности без пробельных символов; следующий указатель должен быть указателем на массив символов, который достаточно длинный, чтобы удерживать входную последовательность и завершающий нулевой байт ('\ 0'), который автоматически добавляется . Строка ввода останавливается в белом пространстве или в максимальной ширине поля , в зависимости от того, что наступит раньше.

Попробуйте вместо этого:

scanf("%[^\n]s", command); 
getchar(); 

или

scanf(" %[^\n]s", command); 
+1

Или даже лучше, используйте 'fgets()'. –

+0

scanf ("% [^ \ n] s", a) не работает - он просто продолжает повторять команду снова и снова. Для fgets() у меня нет файла для извлечения - я просто хочу извлечь пользовательский ввод. – newalchemy

+1

@newalchemy: Используйте 'fgets (команда, MAX_STRING_LENGTH, stdin);'. Использование 'scanf()' здесь в любом случае небезопасно, поскольку вы не устанавливаете ограничение на длину ввода, но вы все равно пытаетесь сохранить все это в 'command'. –

Смежные вопросы