我看到这个代码作为如何制作一个迷你外壳的例子。但是我不知道它在做什么 - 我理解主要功能中的大多数事情,但它上面的函数初始化我真的很丢失。
任何关于shell如何工作的基础知识以及C中的一些低级函数都将非常受欢迎。
log_t Log;
void printLog(log_t *l){
log_entry_t *tmp = l->tail;
while(tmp != NULL){
printf("%s\n", tmp->value);
tmp = tmp->prev;
}
}
int countArg(char *line){
unsigned int i, count = 0;
for(i = 0; i < strlen(line); i++){
if(line[i] == ' ')
count++;
}
return count + 1;
}
char **makeargv(char *line){
char *buff;
char **retv;
unsigned int i, count, arg_num = 0;
buff = malloc((strlen(line) + 1) * sizeof(char));
strcpy(buff, line);
arg_num = countArg(buff);
retv = malloc((arg_num + 1) * sizeof(char*));
retv[arg_num] = NULL;
retv[0] = buff;
for(i = 0, count = 1; buff[i]!='\0'; i++){
if(buff[i] == ' '){
buff[i]='\0';
retv[count] = buff + i + 1;
count++;
}
}
return retv;
}
int main()
{
log_init(&Log);
char * line;
while(1){
size_t size;
char * cwd = NULL;
char * query = NULL;
char * match = NULL;
int f_exit = 0,
f_nbi=0,
f_match=0,
f_sys = 0,
f_path=0;
// print out the requested prompt
cwd = getcwd(NULL,0);
printf("$(pid=%d)%s$ ", getpid(), cwd );
free(cwd);
line = NULL;
fflush(stdout);
getline(&line, &size, stdin);
line[strlen(line)-1] = '\0';
while(1){
if(strcmp(line, "exit") == 0){
if(f_match) printf("%s matches %s\n", query, line);
f_exit = 1;
printf("Command executed by pid=%d\n",getpid());
log_destroy(&Log);
break;
}
else if(strncmp(line, "cd ", 3) == 0){
if(f_match) printf("%s matches %s\n", query, line);
printf("Command executed by pid=%d\n",getpid());
log_push(&Log, line);
if(chdir(line + 3) != 0){
printf("%s: No such file or directory\n",(line + 3));
}
break;
}
else if(strcmp(line, "!#") == 0){
if(f_match) printf("%s matches %s\n", query, line);
printf("Command executed by pid=%d\n",getpid());
printLog(&Log);
break;
}
else if(strstr(line,"!")==line){
if(f_match) printf("%s matches %s\n", query, line);
query = line+1;
match = log_search(&Log, query);
if(match==NULL){
printf("Command executed by pid=%d\n",getpid());
printf("No Match\n");
break;
}
else{
f_match = 1;
printf("Command executed by pid=%d\n",getpid());
line = malloc((strlen(match)+1)*sizeof(char));
strcpy(line, match);
continue;
}
}
else{
f_nbi = 1;
log_push(&Log,line);
if(strstr(line,"/"))
f_path = 1;
break;
}
}
if(f_exit)
break;
if(f_nbi){
pid_t pid = fork();
if(pid == 0){ //child
if(f_match){
printf("%s matches %s\n", query, line);
free(query-1);
}
printf("Command executed by pid=%d\n",getpid());
char **argv = makeargv(line);
f_sys = 0;
if(f_path)
f_sys = execv(argv[0],&argv[0]);
else
f_sys = execvp(argv[0],&argv[0]);
if(f_sys == -1)
printf("%s: not found\n",line);
free(argv[0]);
free(argv);
log_destroy(&Log);
exit(0);
}
else { //parent
waitpid(pid, NULL, WUNTRACED);
if(f_match)
free(query-1);
}
}
free(line);
line = NULL;
}
if(line != NULL){
free(line);
line = NULL;
}
return 0;
}
答案 0 :(得分:0)
printLog()
函数只是打印log_t
给定名称为typedef
的结构类型的记录链接列表中的所有数据。它从列表的尾部开始并向后工作。目前尚不清楚该列表是单链接还是双链接,但prev
通常只出现在双链表中。
countArgs()
函数是确定命令行中存在多少个参数的粗略方法。它很粗糙,因为它没有考虑引号或多个相邻的空格。然而,这些仅仅意味着它高估了论证的数量,这并不严重。它不会将制表符识别为分隔符,这对于shell来说是不常见的。
makeargv()
函数将命令行拆分为一系列空格分隔的单词,并将单词列表返回给调用函数。它有效地解析命令行,确保命令行末尾有一个空指针。同样,它是简单的,但足够。与其他两个函数相比,它的命名也不一致。