main.c
/*
Linux API:
Function:
*/
#include "func.h"
/*********************************
主函数
*********************************/
int main(int argc, char **argv)
{
initShellCode();
for(;;)
{
argvHandler();
commandHandler();
}
exit(EXIT_SUCCESS);
}
func.c
#include "func.h"
// 函数转移表
static CommandInfo commands[] = {
// 指令,函数
{CMD_PWD, &func_pwd},
{CMD_QUIT, &func_quit},
{CMD_MKDIR, &func_mkdir},
{CMD_RMDIR, &func_rmdir},
{CMD_LS, &func_ls},
{CMD_TOUCH, &func_touch},
{CMD_RM, &func_rm},
};
// 计算表长度
int commandNum(void)
{
return sizeof(commands) / sizeof(CommandInfo);
}
/**********************
处理函数
**********************/
void commandHandler(void)
{
// 获取配置参数
CommandData *data = &gCmdData;
int i;
int cmd_bool;
int pos = INDEX_UNKNOWN;
for (i = 0; i < commandNum(); i++)
{
cmd_bool = (0 == strncmp(commands[i].command, data->cmd, strlen(commands[i].command))); // 不要 *data
if (cmd_bool)
{
pos = i;
break;
}
}
if (INDEX_UNKNOWN == pos)
{
printf("error command\n");
return;
}
commands[pos].command_func();
}
void initShellCode(void)
{
system("clear"); // puts("\033c");
}
void argvHandler(void)
{
char *token;
char command[MAX_BUF_SIZE] = {'\0'};
int cnt = 0;
int n = 0;
do
{
printf(">");
fflush(stdout);
n = scanf("%[^\n]s", gCmdData.argsV);
getchar();
}while( !n );
strcpy(command, gCmdData.argsV);
token = strtok(command, SPACE);
strcpy(gCmdData.cmd, token);
/* 继续获取其他的子字符串 */
while( token != NULL ) {
++cnt;
token = strtok(NULL, SPACE);
}
gCmdData.argsC = cnt;
}
void func_pwd(void)
{
char *path = NULL;
path = getcwd(NULL, 0);
printf("%s\n", path);
}
void func_quit(void)
{
exit(EXIT_SUCCESS);
}
void func_mkdir(void)
{
int isCreat;
char *token;
char path[MAX_BUF_SIZE] = {'\0'};
if (gCmdData.argsC != 2)
{
printf("Error mkdir\n");
return;
}
token = strtok(gCmdData.argsV, SPACE);
token = strtok(NULL, SPACE);
strcpy(path, token);
isCreat = mkdir(path, S_IRWXU | S_IWGRP | S_IWOTH);
if (isCreat < 0)
{
perror("Error mkdir");
return;
}
}
void func_rmdir(void)
{
int tmp;
char *token;
char path[MAX_BUF_SIZE] = "";
if (gCmdData.argsC != 2)
{
printf("Error rmdir\n");
return;
}
token = strtok(gCmdData.argsV, SPACE);
token = strtok(NULL, SPACE);
strcpy(path, token);
tmp = rmdir(path);
if (tmp < 0)
{
perror("Error mkdir");
return;
}
}
void func_ls(void)
{
//DIR * dir; // DIR结构体,类似FILE
/*
struct __dirstream
{
void *__fd;
char *__data;
int __entry_data;
char *__ptr;
int __entry_ptr;
size_t __allocation;
size_t __size;
__libc_lock_define (, __lock)
};
typedef struct __dirstream DIR;
*/
//struct dirent * ptr;
/*
struct dirent
{
long d_ino; // inode number 索引节点号
off_t d_off; // offset to this dirent 在目录文件中的偏移
unsigned short d_reclen; // length of this d_name 文件名长
unsigned char d_type; // the type of d_name 文件类型
char d_name [NAME_MAX+1]; // file name (null-terminated) 文件名,最长255字符
}
d : 目录-4
- : 文件-8
l : 链接文件
*/
DIR * dir;
struct dirent * ptr;
dir = opendir("./"); // 打开目录
while((ptr = readdir(dir)) != NULL) // 读取目录,struct dirent* readdir(DIR* dir_handle);
{
printf("%s ", ptr->d_name);
}
printf("\n");
//fflush(stdout);
closedir(dir); // 关闭打开的目录指针
}
void func_touch(void)
{
int fd;
char *token;
char path[MAX_BUF_SIZE] = "";
if (gCmdData.argsC != 2)
{
printf("Error mkdir\n");
return;
}
token = strtok(gCmdData.argsV, SPACE);
token = strtok(NULL, SPACE);
strcpy(path, token);
fd = open(path, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
if (fd < 0)
{
perror("Error touch");
return;
}
}
void func_rm(void)
{
int ret;
char *token;
char fileName[MAX_BUF_SIZE] = "";
if (gCmdData.argsC != 2)
{
printf("Error mkdir\n");
return;
}
token = strtok(gCmdData.argsV, SPACE);
token = strtok(NULL, SPACE);
strcpy(fileName, token);
ret = remove(fileName);
if (ret < 0)
{
perror("Error remove");
return;
}
}
func.h
#ifndef _FUNC_H_
#define _FUNC_H_
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <unistd.h> // rmdir
#include <sys/stat.h> // mode, open
#include <sys/types.h> // opendir
#include <dirent.h> // opendir
#include <fcntl.h> // open
#define MAX_BUF_SIZE 128
#define INDEX_UNKNOWN -1
#define INDEX_CMD_NUM 5
#define SPACE " "
#define ENTER "\n"
#define CMD_LS "ls"
#define CMD_MKDIR "mkdir"
#define CMD_PWD "pwd"
#define CMD_QUIT "quit"
#define CMD_RM "rm"
#define CMD_RMDIR "rmdir"
#define CMD_TOUCH "touch"
// 自定义数据类型
typedef struct
{
char cmd[MAX_BUF_SIZE];
int argsC;
char argsV[MAX_BUF_SIZE];
// ***
}CommandData;
// 自定义函数类型
typedef struct
{
char *command;
void (*command_func)(void); // 需要与子函数类型匹配
}CommandInfo;
CommandData gCmdData;
int commandNum(void);
void initShellCode(void);
void argvHandler(void);
void commandHandler(void);
void func_pwd(void);
void func_quit(void);
void func_mkdir(void);
void func_rmdir(void);
void func_ls(void);
void func_touch(void);
void func_rm(void);
#endif
Makefile
#!/bin/bash
target=shell
CC=gcc
CFLAGS=-g -Wall
$(target):main.o func.o
$(CC) -o $(target) main.o func.o $(CFLAGS)
main.o:main.c
$(CC) -c main.c
func.o:func.c
$(CC) -c func.c
.PHONY:clean # 伪目标
clean:
-rm -f $(target) # - 表示有错误不用管
-rm -f *.o