I'm writing a small shell in C as an exercis to learn about linux and C. Now I can execute custom commands and the exit command, but I can't execute a builtin CD command since I don't know how to split it in two part (the cd command and the name of the directory to CD to).
我正在用C语言编写一个小shell来学习linux和C.现在我可以执行自定义命令和exit命令,但我不能执行内置CD命令,因为我不知道如何拆分它分两部分(cd命令和CD到目录的名称)。
The desired functionality is that my program should accept the cd command with a parameter that is the directory. I can do it with command-line arguments but I don't know how to do it in its current form. How can it be done?
所需的功能是我的程序应该接受带有作为目录的参数的cd命令。我可以用命令行参数来做,但我不知道如何以当前的形式做到这一点。如何做呢?
#include <sys/stat.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <dirent.h>
#include <errno.h>
#include <stdarg.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>
#define BUFFER_LEN 1024
#define BUFFERSIZE 1024
int mystrcmp(char const *, char const *);
void err_syserr(char *fmt, ...)
{
int errnum = errno;
va_list args;
va_start(args, fmt);
vfprintf(stderr, fmt, args);
va_end(args);
if (errnum != 0)
fprintf(stderr, "(%d: %s)\n", errnum, strerror(errnum));
exit(EXIT_FAILURE);
}
int main() {
char line[BUFFER_LEN];
char* argv[100];
char* path= "/bin/";
char progpath[20];
int argc;
size_t length;
char *token;
int i=0;
int pid;
while(1) {
i = 0;
printf("miniShell>> ");
if(!fgets(line, BUFFER_LEN, stdin)) {
break;
}
length = strlen(line);
if (line[length - 1] == '\n') {
line[length - 1] = '\0';
}
if(strcmp(line, "exit")==0) {
break;
}
if(strcmp(line, "cd")==0) {
/*printf("change directory to %s\n", argv[2]);
chdir(argv[2]);*/
}
token = strtok(line," ");
while(token!=NULL) {
argv[i]=token;
token = strtok(NULL," ");
i++;
}
argv[i]=NULL;
argc=i;
for(i=0; i<argc; i++) {
printf("%s\n", argv[i]);
}
strcpy(progpath, path);
strcat(progpath, argv[0]);
for(i=0; i<strlen(progpath); i++) {
if(progpath[i]=='\n') {
progpath[i]='\0';
}
}
pid= fork();
if(pid==0) {
execvp(progpath,argv);
fprintf(stderr, "Child process could not do execvp\n");
} else {
wait(NULL);
printf("Child exited\n");
}
}
return (0);
}
int mystrcmp(char const *p, char const *q)
{
int i = 0;
for(i = 0; q[i]; i++)
{
if(p[i] != q[i])
return -1;
}
return 0;
}
int cd(char *pth) {
char path[BUFFERSIZE];
char cwd[BUFFERSIZE];
char * return_value;
int other_return;
strcpy(path,pth);
if(pth[0] != '/')
{
return_value = getcwd(cwd,sizeof(cwd));
strcat(cwd,"/");
strcat(cwd,path);
other_return = chdir(cwd);
} else {
other_return = chdir(pth);
}
printf("Spawned foreground process: %d\n", getpid());
return 0;
}
2 个解决方案
#1
2
Use strpbrk
or strsep
to split your input into white-space separated tokens, then use strcmp on the first one and use the remaining ones as arguments.
使用strpbrk或strsep将输入拆分为空格分隔的标记,然后在第一个使用strcmp并使用其余的作为参数。
This answer to a related question has an example, and here are some notes on portability.
这个相关问题的答案有一个例子,这里有一些关于可移植性的注释。
#2
0
I'd suggest to parse your argument with the getopt
function from unistd
library. It's covered in this question too.
我建议用unistd库中的getopt函数解析你的参数。它也包含在这个问题中。
Here is the documentation for getopt
command.
这是getopt命令的文档。
#1
2
Use strpbrk
or strsep
to split your input into white-space separated tokens, then use strcmp on the first one and use the remaining ones as arguments.
使用strpbrk或strsep将输入拆分为空格分隔的标记,然后在第一个使用strcmp并使用其余的作为参数。
This answer to a related question has an example, and here are some notes on portability.
这个相关问题的答案有一个例子,这里有一些关于可移植性的注释。
#2
0
I'd suggest to parse your argument with the getopt
function from unistd
library. It's covered in this question too.
我建议用unistd库中的getopt函数解析你的参数。它也包含在这个问题中。
Here is the documentation for getopt
command.
这是getopt命令的文档。