OS之子进程简单模拟shell解释环境(再次)
来源:互联网 发布:python 算法导论3 编辑:程序博客网 时间:2024/04/27 21:21
(1)当输入一条指令后,将指令拆分成独立的符号;
(2)如果指令的最后一个符号是’&’,则(4)子进程执行指令的时候,父进程将不会wait()子进程执行完毕,继续接收下一条指令进行解释;
(3)History指令由主程序使用循环队列进行维护,最多只记录10条历史指令;'!!'执行最近执行过的指令,'! + 数字'执行对应的历史指令;
(4)如果是非history指令,fork()一个子进程,调用execvp()进行解释执行;
一、主程序
/*** FILE: osh.c** NOTE: 2016-01-11 created by Jack Liu** DESC: */#include<sys/types.h>#include<sys/wait.h>#include<unistd.h>#include<signal.h>#include<stdio.h>#include<stdlib.h>#include<string.h>#include"history.h"#define MAX_HISTORY 10 /* how many stokens */int stoken_cmd_num( char *cpCmd );/* split the command into stokens */char **stoken_cmd( char *cpCmd, int *iTokenNum );/* remember the command */int do_history( char *cpCmd, PHISTORY_LIST pHistory );/* when children terminate, recycle it */void child_fun( int sig );intmain( void ){ char caCmd[ MAX_CMD ]; char **cppCmdStokens; pid_t pid; int iTokenNum; int iConcurrent; struct sigaction newSigAct, oldSigAct; HISTORY_LIST history; newSigAct.sa_handler = child_fun; if( sigaction( SIGCHLD, &newSigAct, &oldSigAct ) < 0 ) { perror( "sigaction" ); return -1; } if( history_init( &history, MAX_HISTORY ) < 0 ) { fprintf( stderr, "fail to init history list\n" ); return -1; } while( 1 ) { int i = 0; iConcurrent = 0; printf( "osh>" ); /* ** get the input command */ if( fgets( caCmd, MAX_CMD, stdin ) == NULL ) { /* the user want to exit, ctrl + D */ putchar( '\n' ); break; } if( caCmd[ strlen( caCmd ) - 1 ] == '\n' ) caCmd[ strlen( caCmd ) - 1 ] = '\0'; if( caCmd[ 0 ] == '\0' ) /* just input enter, ignore it */ continue; /* ** record the command */ if( do_history( caCmd, &history ) < 0 ) continue; /* ** split the command */ if( strcmp( caCmd, "exit" ) == 0 ) { /* the user want to exit, input exit */ break; } cppCmdStokens = stoken_cmd( caCmd, &iTokenNum ); if( cppCmdStokens == NULL ) { fprintf( stderr, "couldn't recognize: %s\n", caCmd ); continue; } /* ** fork a child to exec the command ** or ** print the history commands */ if( cppCmdStokens[ iTokenNum - 2 ][ strlen( cppCmdStokens[ iTokenNum - 2 ] ) - 1 ] == '&' ) { iConcurrent = 1; /* concurrent the command */ /* ** clear the '&' character */ cppCmdStokens[ iTokenNum - 2 ][ strlen( cppCmdStokens[ iTokenNum - 2 ] ) - 1 ] = '\0'; if( cppCmdStokens[ iTokenNum - 2 ][ 0 ] == '\0' ) { /* '&' occupy a stoken, clear the stoken */ free( cppCmdStokens[ iTokenNum - 2 ] ); cppCmdStokens[ iTokenNum - 2 ] = NULL; } } if( strcmp( cppCmdStokens[ 0 ], "history" ) == 0 ) { history_print( &history ); } else { if( ( pid = fork() ) < 0 ) { fprintf( stderr, "fail to exec: %s\n", caCmd ); continue; } else if( pid == 0 ) { /* child */ execvp( cppCmdStokens[ 0 ], cppCmdStokens ); fprintf( stderr, "fail to exec: %s\n", caCmd ); exit( -1 ); } } i = 0; /* ** clear stokens */ while( cppCmdStokens[ i ] ) free( cppCmdStokens[ i++ ] ); free( cppCmdStokens ); if( !iConcurrent ) /* wait the child to exec */ waitpid( pid, NULL, 0 ); } history_clear( &history ); return 0;}intstoken_cmd_num( char *cpCmd ){ char caTmpCmd[ MAX_CMD ]; char *cpIndex; int iNum = 0; if( cpCmd == NULL ) { fprintf( stderr, "Illegal cmd\n" ); return -1; } strncpy( caTmpCmd, cpCmd, MAX_CMD ); cpIndex = strtok( caTmpCmd, " " ); while( cpIndex ) { iNum++; cpIndex = strtok( NULL, " " ); } return iNum;}char **stoken_cmd( char *cpCmd, int *iTokenNum ){ char caTmpCmd[ MAX_CMD ]; char *cpIndex; char *cpStoken; char **cppStokens; int iNum; if( cpCmd == NULL ) { fprintf( stderr, "Illegal command line\n" ); return NULL; } strncpy( caTmpCmd, cpCmd, MAX_CMD ); if( ( iNum = stoken_cmd_num( cpCmd ) ) > 0 ) { /* ** the last element is NULL */ *iTokenNum = iNum + 1; cppStokens = malloc( sizeof( char * ) * ( iNum + 1 ) ); if( cppStokens == NULL ) { perror( "malloc" ); return NULL; } } else { fprintf( stderr, "Illegal command line\n" ); return NULL; } memset( cppStokens, 0x00, sizeof( char * ) * ( iNum + 1 ) ); /* ** begin to split */ iNum = 0; cpIndex = strtok( caTmpCmd, " " ); while( cpIndex ) { if( ( cpStoken = malloc( strlen( cpIndex ) + 1 ) ) == NULL ) { int i; for( i = 0; i < iNum; i++ ) free( cppStokens[ i ] ); free( cppStokens ); perror( "malloc" ); return NULL; } memset( cpStoken, 0x00, strlen( cpIndex ) + 1 ); strcpy( cpStoken, cpIndex ); cppStokens[ iNum++ ] = cpStoken; cpIndex = strtok( NULL, " " ); } cppStokens[ iNum ] = NULL; return cppStokens;}int do_history( char *cpCmd, PHISTORY_LIST pHistory ){ PHISTORY_RECORD pRecord; int iIndex = -1; char caTmpCmd[ MAX_CMD ] = { 0 }; if( cpCmd[ 0 ] == '!' ) { memcpy( caTmpCmd, cpCmd + 1, strlen( cpCmd ) ); /* include the NULL-terminated */ if( strcmp( caTmpCmd, "!" ) != 0 ) iIndex = atoi( caTmpCmd ); else iIndex = 1; if( iIndex <= 0 || iIndex > pHistory->iLen ) { fprintf( stderr, "no such history command\n" ); return -1; } pRecord = history_index( pHistory, iIndex ); if( pRecord == NULL ) { fprintf( stderr, "no such history command\n" ); return -1; } strcpy( cpCmd, pRecord->cpCmd ); } else { /* record the command */ pRecord = history_get_record( cpCmd ); history_pushback( pHistory, pRecord ); } return 0;}voidchild_fun( int sig ){ waitpid( -1, NULL, WNOHANG ); }
二、history队列维护头文件
/*** FILE: history.h** NOTE: 2016-01-11 created by Jack Liu** DESC: manage the historic commands up to 10*/#ifndef COM_JACKLIU_HISTORY_H#define COM_JACKLIU_HISTORY_H#define MAX_CMD 512typedef struct history_record{ char cpCmd[ MAX_CMD ]; struct history_record *prev; struct history_record *next;} HISTORY_RECORD, *PHISTORY_RECORD; typedef struct history_list{ PHISTORY_RECORD front; PHISTORY_RECORD rear; int iLen; int iMax;} HISTORY_LIST, *PHISTORY_LIST;int history_init( PHISTORY_LIST list, int iMax );PHISTORY_RECORD history_get_record( char *cpCmd );int history_pushback( PHISTORY_LIST list, PHISTORY_RECORD record ); PHISTORY_RECORD history_pop( PHISTORY_LIST list );PHISTORY_RECORD history_front( PHISTORY_LIST list );PHISTORY_RECORD history_index( PHISTORY_LIST list, int iIndex );int history_print( PHISTORY_LIST list );int history_clear( PHISTORY_LIST list );#endif
三、history队列维护实现
/*** FILE: history.c** NOTE: 2016-01-11 created by Jack Liu*/#include <stdio.h>#include <stdlib.h>#include <string.h>#include "history.h"inthistory_init( PHISTORY_LIST list, int iMax ){ if( list == NULL ) { fprintf( stderr, "history operation: init error, list argument illegal\n" ); return -1; } list->front = list->rear = NULL; list->iLen = 0; list->iMax = iMax; return 0;}PHISTORY_RECORDhistory_get_record( char *cpCmd ){ PHISTORY_RECORD pRecord; pRecord = malloc( sizeof( HISTORY_RECORD ) ); if( pRecord == NULL ) { perror( "malloc" ); return NULL; } memset( pRecord, 0x00, sizeof( HISTORY_RECORD ) ); strcpy( pRecord->cpCmd, cpCmd ); return pRecord;}inthistory_pushback( PHISTORY_LIST list, PHISTORY_RECORD pRecord ){ if( list == NULL || pRecord == NULL ) { fprintf( stderr, "illegal operation: list is empty\n" ); return -1; } if( list->rear == NULL ) { /* first record */ list->front = pRecord; pRecord->prev = pRecord->next = NULL; } else { list->rear->next = pRecord; pRecord->prev = list->rear; pRecord->next = NULL; } list->rear = pRecord; list->iLen++; if( list->iLen > list->iMax ) { PHISTORY_RECORD pToFree = list->front; list->front = list->front->next; list->front->prev = NULL; free( pToFree ); list->iLen = list->iMax; } return 0;}PHISTORY_RECORDhistory_pop( PHISTORY_LIST list ){ PHISTORY_RECORD pRecord; if( list == NULL ) { fprintf( stderr, "history operation: list is illegal\n" ); return NULL; } if( list->rear == NULL ) return NULL; /* the history list is emtpy */ pRecord = list->rear; list->rear = list->rear->prev; if( list->rear == NULL ) /* now list is empty */ list->front = NULL; else list->rear->next = NULL; return pRecord;}PHISTORY_RECORDhistory_front( PHISTORY_LIST list ){ PHISTORY_RECORD pRecord; if( list == NULL ) { fprintf( stderr, "history operation: list is illegal\n" ); return NULL; } if( list->front == NULL ) return NULL; /* history list is empty */ pRecord = list->front; list->front = list->front->next; if( list->front == NULL ) /* now list is empty */ list->rear = NULL; else list->front->prev = NULL; return pRecord;}PHISTORY_RECORDhistory_index( PHISTORY_LIST list, int iIndex ){ PHISTORY_RECORD pRecord; int i; if( list == NULL ) { fprintf( stderr, "history operation: list is illegal\n" ); return NULL; } if( list->front == NULL ) { fprintf( stderr, "history operation: list is emtpy\n" ); return NULL; } if( iIndex > list->iLen ) { fprintf( stderr, "no such history command\n" ); return NULL; } i = 1; pRecord = list->rear; while( ++i <= iIndex ) pRecord = pRecord->prev; return pRecord;}inthistory_print( PHISTORY_LIST list ){ PHISTORY_RECORD pRecord; int i; if( list == NULL ) { fprintf( stderr, "history operation: history list is empty\n" ); return -1; } i = list->iLen; pRecord = list->front; while( i > 0 ) { printf( "%02d %s\n", i--, pRecord->cpCmd ); pRecord = pRecord->next; } return 0;}inthistory_clear( PHISTORY_LIST list ){ if( list != NULL ) { PHISTORY_RECORD pRecord; while( ( pRecord = history_front( list ) ) ) free( pRecord ); } return 0;}
四、源代码
http://download.csdn.net/detail/qq123386926/9401186
0 0
- OS之子进程简单模拟shell解释环境(再次)
- OS之子进程简单模拟shell解释环境
- 1、uc/os:进程、线程、(void*)0 的简单解释
- 模拟shell进程
- 进程的简单解释
- Python实战之子进程
- Python实战之子进程
- Python利用OS模块模拟一个shell
- 【OS课程设计三】模拟进程调度
- CSU 1765 简单shell 模拟
- 【Linux】shell的简单模拟
- raw os基于VC环境的模拟
- 操作系统进程调度简单模拟
- 模拟简单进程调度实验
- [模拟] 简单的进程调度模拟
- Linux-进程环境(shell环境)
- HDOJ 1302 具体解释(简单模拟)
- 模拟shell ( 进程函数:fork(),execvp(),wait() )
- java之生成不重复的随机数
- 学习OC 问题1: 关于“ARC forbids explicit message send of release”错误
- 快排
- 【C++】Windows线程的创建、执行、互斥、同步、销毁
- intelliJ IDEA 拉取SVN数据并配置tomcat
- OS之子进程简单模拟shell解释环境(再次)
- 解决:C语言调用pcap库出现unknown types error
- php 反射机制
- 看雪论坛大神的破解游戏反调试思路
- Paths - 2
- ReactJs + BootStrap + Pager 分页
- 第3章 对象的共享
- 实现类似网易邮箱的顶部工具栏的悬停效果
- python 装饰器模式 我的理解