APUE-练手项目-交互式shell-转移表-第三版

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

posted @ 2022-11-22 04:09  steve的miao  阅读(31)  评论(0编辑  收藏  举报