【发布时间】:2012-09-23 11:06:54
【问题描述】:
我正在制作一个简单的外壳。它还需要能够逐行读取文本文件。这是我的代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/stat.h>
// Exit when called, with messages
void my_exit() {
printf("Bye!\n");
exit(0);
}
int main(void) {
setvbuf(stdout, NULL, _IONBF, 0);
// Char array to store the input
char buff[1024];
// For the fork
int fid;
// Get all the environment variables
char dir[50];
getcwd(dir,50);
char *user = getenv("USER");
char *host = getenv("HOST");
// Issue the prompt here.
printf("%s@%s:%s> ", user, host, dir);
// If not EOF, then do stuff!
while (fgets(buff, 1024, stdin) != NULL) {
// Get rid of the new line character at the end
// We will need more of these for special slash cases
int i = strlen(buff) - 1;
if (buff[i] == '\n') {
buff[i] = 0;
}
// If the text says 'exit', then exit
if (!strcmp(buff,"exit")) {
my_exit();
}
// Start forking!
fid = fork();
// If fid == 0, then we have the child!
if (fid == 0) {
// To keep track of the number of arguments in the buff
int nargs = 0;
// This is a messy function we'll have to change. For now,
// it just counts the number of spaces in the buff and adds
// one. So (ls -a -l) = 3. AKA 2 spaces + 1. Really in the
// end, we should be counting the number of chunks in between
// the spaces.
for (int i = 0; buff[i] != '\0'; i++) {
if (buff[i] == ' ') nargs ++;
}
// Allocate the space for an array of pointers to args the
// size of the number of args, plus one for the NULL pointer.
char **args = malloc((sizeof(char*)*(nargs + 2)));
// Set the last element to NULL
args[nargs+1] = NULL;
// Split string into tokens by space
char *temp = strtok (buff," ");
// Copy each token into the array of args
for (int i = 0; temp != NULL; i++) {
args[i] = malloc (strlen(temp) + 1);
strcpy(args[i], temp);
temp = strtok (NULL, " ");
}
// Run the arguments with execvp
if (execvp(args[0], args)) {
my_exit();
}
}
// If fid !=0 then we still have the parent... Need to
// add specific errors.
else {
wait(NULL);
}
// Issue the prompt again.
printf("%s@%s:%s> ", user, host, dir);
}
// If fgets == NULL, then exit!
my_exit();
return 0;
}
当我将它作为 shell 单独运行时,它运行良好。当我运行 ./myshell
commands.txt 是:
ls -l -a
pwd
ls
但是输出是:
>Bye!
>Bye!
>Bye!
>Bye!
>Bye!
>Bye!>Bye!
>Bye!
>Bye!
>Bye!
甚至不运行我的命令。有任何想法吗?我认为我的 while 循环非常简单。
【问题讨论】:
-
尝试在 my_exit() 中打印进程的 PID,看看谁在打印什么。
-
您至少需要在打印提示后刷新输出,以便它出现在相对于命令输出的正确位置。
-
打印出 PID,除了最后一个 19147 之外,我得到所有 0(每个 Bye!)
-
一些与您的问题无关的cmets。如果您不使用
argc和argv,只需声明int main(void)。对user和host的分配进行强制转换是多余的,分配可能是初始化:char *user = getenv("USER"); char *host = getenv("HOST"); -
请不要破坏您的问题。在你得到一些答案或 cmets 之前,改变事情是可以的;即使您有一些 cmets,也可以进行更改。然而,一旦你开始得到答案,你就必须更加小心地做出改变。对于那些通过删除他们回答时可见的 90% 代码来帮助您完全使他们的回答无效的人来说,这是不公平的。
标签: c while-loop fgets