请实现一个终端的功能,注意需要带有cd功能
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <pthread.h>
#include <semaphore.h>
#include <wait.h>
#include <signal.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/msg.h>
#include <sys/shm.h>
#include <sys/un.h>
typedef struct sockaddr_in addr_in_t;
typedef struct sockaddr addr_t;
typedef struct sockaddr_un addr_un_t;
// 处理cd命令
void handle_cd(char **args) {
if (args[1] != NULL && args[2] != NULL) {
fprintf(stderr, "cd: 参数过多\n");
return;
}
char *target_dir = args[1];
// 如果没有参数,默认切换到HOME目录
if (target_dir == NULL) {
target_dir = getenv("HOME");
if (target_dir == NULL) {
fprintf(stderr, "cd: 未设置HOME环境变量\n");
return;
}
}
// 执行目录切换
if (chdir(target_dir) != 0) {
perror("cd");
}
}
// 信号处理函数
void signal_handler(int signum) {
if (signum == SIGINT) {
printf("\n");
rl_replace_line("", 0); // 清空当前输入行
rl_redisplay(); // 重新显示提示符
}
}
int main() {
char *input;
char *args[MAX_ARGS];
char cwd[1024];
// 设置信号处理函数
signal(SIGINT, signal_handler);
while (1) {
// 获取并显示当前工作目录
if (getcwd(cwd, sizeof(cwd)) != NULL) {
printf("\033[1;32m%s\033[0m$ ", cwd); // 绿色提示符
} else {
perror("getcwd");
exit(EXIT_FAILURE);
}
// 读取用户输入
input = readline("");
if (input == NULL) {
printf("\n");
break; // 处理Ctrl+D
}
// 添加到历史记录
add_history(input);
// 移除换行符
input[strcspn(input, "\n")] = '\0';
// 解析命令参数
int i = 0;
char *token = strtok(input, " ");
while (token != NULL && i < MAX_ARGS - 1) {
args[i++] = token;
token = strtok(NULL, " ");
}
args[i] = NULL;
// 处理空输入
if (i == 0) {
free(input);
continue;
}
// 内置命令处理
if (strcmp(args[0], "cd") == 0) {
handle_cd(args);
} else if (strcmp(args[0], "exit") == 0) {
free(input);
break;
} else {
// 外部命令处理
pid_t pid = fork();
if (pid == 0) {
// 子进程执行命令
execvp(args[0], args);
perror("execvp");
exit(EXIT_FAILURE);
} else if (pid < 0) {
perror("fork");
} else {
// 父进程等待子进程
int status;
waitpid(pid, &status, 0);
}
}
free(input);
}
return 0;
}