首先是代码。
Shell.c:
/** @file shell.c */
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include "log.h"
/**
* Starting point for shell.
*/
int main() {
log_t *Log = malloc(sizeof(log_t));
log_init (Log);
log_t *temp;
pid_t pid = getpid(); //get current process id
char cwd[256]; //allocate array to receive the cwd
size_t cwd_size = sizeof(cwd); //gets the size of cwd
char *input_line = NULL;
size_t line_size = 0;
ssize_t line_ct;
for(;;)
{
getcwd(cwd, cwd_size); //now we actually get the current working directory
printf("(pid=%d)%s$ ", pid, cwd);
line_ct = getline(&input_line, &line_size, stdin);
if (line_ct <= 0)
{
printf("\n");
break;
}
input_line[--line_ct] = '\0'; // remove trailing newline
if (strcmp(input_line, "exit")==0)
{
break;
}
if (strncmp(input_line, "cd ", 3) == 0)
{
chdir(input_line + 3);
log_t *new_entry = malloc(sizeof(log_t));
log_init (new_entry);
log_t *temp = find_last(Log);
if (temp == NULL)
{
log_push(Log, input_line);
}
else
{
log_push(new_entry, input_line);
temp->next = new_entry;
}
continue;
}
if (strncmp(input_line, "!#", 2) == 0)
{
log_print(Log);
continue;
}
}
return 0;
}
log.h:
/** @file log.h */
#ifndef __LOG_H_
#define __LOG_H_
typedef struct _log_t {
char *user_input;
struct _log_t *next;
} log_t;
void log_init(log_t *l);
void log_destroy(log_t* l);
void log_push(log_t* l, char *item);
void log_print(log_t *l);
char *log_search(log_t* l, const char *prefix);
log_t *find_last(log_t *first);
#endif
log.c:
/** @file log.c */
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "log.h"
/**
* Initializes the log.
*
* You may assuem that:
* - This function will only be called once per instance of log_t.
* - This function will be the first function called per instance of log_t.
* - All pointers will be valid, non-NULL pointer.
*
* @returns
* The initialized log structure.
*/
void log_init(log_t *l) {
l->user_input = NULL;
l->next = NULL;
}
/**
* Frees all internal memory associated with the log.
*
* You may assume that:
* - This function will be called once per instance of log_t.
* - This funciton will be the last function called per instance of log_t.
* - All pointers will be valid, non-NULL pointer.
*
* @param l
* Pointer to the log data structure to be destoryed.
*/
void log_destroy(log_t* l) {
}
/**
* Push an item to the log stack.
*
*
* You may assume that:
* - All pointers will be valid, non-NULL pointer.
*
* @param l
* Pointer to the log data structure.
* @param item
* Pointer to a string to be added to the log.
*/
void log_push(log_t* l, char *item) {
l->user_input = item;
l->next = NULL;
}
/**
* Preforms a newest-to-oldest search of log entries for an entry matching a
* given prefix.
*
* This search starts with the most recent entry in the log and
* compares each entry to determine if the query is a prefix of the log entry.
* Upon reaching a match, a pointer to that element is returned. If no match
* is found, a NULL pointer is returned.
*
*
* You may assume that:
* - All pointers will be valid, non-NULL pointer.
*
* @param l
* Pointer to the log data structure.
* @param prefix
* The prefix to test each entry in the log for a match.
*
* @returns
* The newest entry in the log whose string matches the specified prefix.
* If no strings has the specified prefix, NULL is returned.
*/
char *log_search(log_t* l, const char *prefix) {
return NULL;
}
void log_print(log_t* l)
{
log_t *temp1 = l;
while(temp1 != NULL && temp1->user_input != NULL)
{
//printf("%s\n", temp1->user_input);
printf("%p %p %s\n", temp1, temp1->user_input, temp1->user_input);
temp1 = temp1->next;
}
}
log_t *find_last(log_t *first)
{
log_t *temp = first;
if(temp == NULL || temp->user_input == NULL)
{
return NULL;
}
while(temp->next != NULL)
{
temp = temp->next;
}
return temp;
}
所以我正在尝试创建自己的shell。我正在使用链接列表来创建用户输入的日志。测试我工作的唯一功能 - cd(目录)。然后使用!#,它应该打印用户输入的列表。它使用log的log_print函数
但是出了点问题。日志* user-&gt;输入成员用'!#'填充。他们都共享相同的地址:
collin@ubuntu:~/Desktop/mp3$ ./shell
(pid=14683)/home/collin/Desktop/mp3$ cd test1
(pid=14683)/home/collin/Desktop/mp3$ cd test2
(pid=14683)/home/collin/Desktop/mp3$ cd test3
(pid=14683)/home/collin/Desktop/mp3$ cd test4
(pid=14683)/home/collin/Desktop/mp3$ !#
0x8bbf008 0x8bbf018 !#
0x8bbf0a8 0x8bbf018 !#
0x8bbf0b8 0x8bbf018 !#
0x8bbf0c8 0x8bbf018 !#
(pid=14683)/home/collin/Desktop/mp3$
这里发生了什么?这真的很奇怪
答案 0 :(得分:3)
您没有复制字符串。您只需将输入缓冲区推入日志中,但该缓冲区会不断被覆盖。尝试:
void log_push(log_t* l, char *item) {
l->user_input = strdup(item);
l->next = NULL;
}
请注意,当您从日志中删除条目时,您需要稍后使用free
清理内存。
答案 1 :(得分:2)
您正在使用char指针作为log_push函数的数据
void log_push(log_t* l, char *item) {
l->user_input = item;
l->next = NULL;
}
它只是一个指针,当内容改变时,指针显示改变的内容,即最后一个。指针只显示“input_line”!
尝试生成另一个内存区域或使用strdup作为“paddy”声明。
void log_push(log_t* l, const char* item) {
l->user_input = (char *) malloc(sizeof(char) * strlen(item));
strncpy(item, strlen(item), l->user_input);
....
..
//or use
t->user_input = strdup(item);
....
}