自定义简单Shell中的错误’ls’命令行为教程
我遇到的问题似乎只是从我的知识中消失了.我正在编写一个简单的shell来学习一些用于Unisys实习的系统编程.在我的shell中,似乎我正在尝试的所有命令都在ls之外工作,甚至现在发现了wc命令. ls和wc在我自己输入时工作,但如果我给它参数,它将无法工作并给我一个错误说没有这样的文件或目录.
这是我的代码:
#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(问题)
$$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
哪个 – 哪个
$$which -a which
Token #1: which
Token #2: a
Token #3: which
/usr/bin/which
甚至最后是男人
GETLINE(3) BSD Library Functions Manual GETLINE(3)
NAME
getdelim, getline -- get a line from a stream
LIBRARY
Standard C Library (libc, -lc)
.
.
.
任何人都可以帮我指出我遇到这个问题的原因吗?
解决方法:
您在DELIMS宏中添加了“ – ”作为单词分隔符.
删除它应该可以解决您的问题.
顺便说一下,它可能最好避免宏,你可以轻松地做到这一点.在这里,我会使用const char * delims来存储分隔符.我通常发现更容易声明一个接近其使用位置的变量 – 我认为这样可以更容易地发现错误并阅读代码.