2015-11-26 55 views
4

我遇到了一个似乎超出我的知识范围的问题。我正在写一个简单的shell来学习Unisys提供的实习系统编程。在我的shell中,似乎除了ls之外,我尝试的所有命令都在工作,甚至现在发现了wc命令。 lswc当我自己输入时会起作用,但是如果我给出它的参数,它将失效并给我一个错误,说No such file or directory自定义简单shell中的'ls'命令行为不正确

这里是我的代码:

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

#define BUF_SIZE 1024 
#define DELIMS " -\r\t\n" 

/**************************************************************** 
* Capture input from the user. Returns the input from the 
* standard input file descriptor. 
***************************************************************/ 
char * getInput (char **buffer, size_t buflen) 
{ 
    size_t bufsize = BUF_SIZE; 
    *buffer = malloc(sizeof(char) * bufsize + 1); // allocate space for the buffer 

    if (!*buffer) 
    { 
     fprintf(stderr, "Shell: buffer allocation error\n"); 
     exit(EXIT_FAILURE); 
    } 

    printf("$$ "); 

    fflush(NULL); 

    int bytesRead = getline(&(*buffer), &bufsize, stdin); 
    if (bytesRead < 0) 
    { 
     printf("Getline error\n"); 
     exit(EXIT_FAILURE); 
    } 

    return *buffer; // Not capturing return value right now 
} 

/**************************************************************** 
* Tokenize the buffer input from stdin 
***************************************************************/ 
char ** splitLine(char *line) 
{ 
    int bufsize = BUF_SIZE; 
    int pos = 0; 
    char **tokens = malloc (sizeof(char) * BUF_SIZE + 1); 
    char *token; 

    if (!tokens) 
    { 
     fprintf(stderr, "Shell: buffer allocation error\n"); 
     exit(EXIT_FAILURE); 
    } 

    /* Tokenize the line */ 
    token = strtok(line, DELIMS); 
    while (token != NULL) 
    { 
     tokens[pos] = token; 
     pos++; 
     if (pos > bufsize) 
     { 
      bufsize += BUF_SIZE; 
      tokens = realloc(tokens, bufsize * sizeof(char) + 1); 
      if (!tokens) 
      { 
       fprintf(stderr, "Shell: buffer allocation error\n"); 
       exit(EXIT_FAILURE); 
      } 
     } 
     token = strtok(NULL, DELIMS); // continue grabbing tokens 
    } 

    tokens[pos] = NULL; 
    return tokens; 
} 

/**************************************************************** 
* Main function 
***************************************************************/ 
int main (int argc, char **argv) 
{ 
    char *buf;  // buffer to hold user input from standard input stream. 
    pid_t pid;   // Parent id of the current process 
    int status; 

    /* Loop while the user is getting input */ 
    while (getInput(&buf, sizeof(buf))) 
    { 
     char **args = splitLine(buf); 
     int i = 0; 

     /* Print tokens just to check if we are processing them correctly */ 
     while (1) 
     { 
      char *token = args[i++]; 
      if (token != NULL) 
       printf("Token #%d: %s\n", i, token); 
      else 
       break; 
     } 

     fflush(NULL); 

     /* Fork and execute command in the shell */ 
     pid = fork(); 
     switch(pid) 
     { 
      case -1: 
      { 
       /* Failed to fork */ 
       fprintf(stderr, "Shell cannot fork: %s\n", strerror(errno)); 
       continue; 
      } 
      case 0: 
      { 
       /* Child so run the command */ 
       execvp(args[0], args);  // Should not ever return otherwise there was an error 
       fprintf(stderr, "Shell: couldn't execute %s: %s\n ", buf, strerror(errno)); 
       exit(EX_DATAERR); 
      } 
     } 

     /* Suspend execution of calling process until receiving a status message from the child process 
      or a signal is received. On return of waitpid, status contains the termination 
      information about the process that exited. The pid parameter specifies the set of child 
      process for which to wait for */ 
     if ((pid = waitpid(pid, &status, 0) < 0)) 
     { 
      fprintf(stderr, "Shell: waitpid error: %s\n", strerror(errno)); 
     } 

     free(args); 
    } 

    free(buf); 

    exit(EX_OK); 
} 

例如,我试图与输出以下命令:

LS -la(问题)

$$ ls -la 
Token #1: ls 
Token #2: la 
ls: la: No such file or directory 
$$ 

WC -l(THE ISSUE)

$$ wc -l 
Token #1: wc 
Token #2: l 
wc: l: open: No such file or directory 

LS

$$ ls 
Token #1: ls 
Makefile driver  driver.dSYM main.c  main.o 
$$ 

PS -La

$$ ps -la 
Token #1: ps 
Token #2: la 
    UID PID PPID CPU PRI NI  VSZ RSS WCHAN STAT TT  TIME COMMAND 
    0 2843 2405 0 31 0 2471528  8 -  Us s000 0:00.08 login 
    501 2845 2843 0 31 0 2463080 1268 -  S s000 0:01.08 -bash 
    501 4549 2845 0 31 0 2454268 716 -  S+ s000 0:00.01 ./driv 
    0 4570 4549 0 31 0 2435020 932 -  R+ s000 0:00.00 ps la 
$$ 

其中该

$$ which which 
Token #1: which 
Token #2: which 
/usr/bin/which 

WHI CH -a这

$$ which -a which 
Token #1: which 
Token #2: a 
Token #3: which 
/usr/bin/which 

,甚至最后男人函数getline

GETLINE(3)    BSD Library Functions Manual    GETLINE(3) 

NAME 
    getdelim, getline -- get a line from a stream 

LIBRARY 
    Standard C Library (libc, -lc) 
. 
. 
. 

任何人可以帮我指出来,为什么我有这个问题?

+2

只要看看你的输出,就会失去命令行选项中的'-',所以在第一个例子中,你有效地做了一个'ls la',它会在bash中给出相同的错误。 'ps'的工作原理是因为'ps'在没有'-'的情况下需要一些选项。 – blm

+0

对于@blm所说的,你有'#define DELIMS“ - \ r \ t \ n”',并且你用'strtok()'来使用它。从分隔符列表中删除短划线。 –

回答

3

您在DELIMS宏中添加了“ - ”作为单词分隔符。

删除它应该可以解决您的问题。

顺便说一句,它可能是最好的避免宏,你可以轻松地做到这一点。在这里,我会用const char* delims来存储分隔符。我通常会发现将变量声明为接近它的用处更容易 - 我认为这样可以更容易地发现错误并读取代码。

+0

OOPS!对于那个家伙感到抱歉。我很愚蠢哈哈。这解决了这个问题。非常感谢您为我指出这一点。天哪,对不起,浪费你的时间家伙:( –