OS之子进程简单模拟shell解释环境(再次)
2016-01-12 17:22
453 查看
(1)当输入一条指令后,将指令拆分成独立的符号;
(2)如果指令的最后一个符号是’&’,则(4)子进程执行指令的时候,父进程将不会wait()子进程执行完毕,继续接收下一条指令进行解释;
(3)History指令由主程序使用循环队列进行维护,最多只记录10条历史指令;'!!'执行最近执行过的指令,'! + 数字'执行对应的历史指令;
(4)如果是非history指令,fork()一个子进程,调用execvp()进行解释执行;
一、主程序
二、history队列维护头文件
三、history队列维护实现
四、源代码
http://download.csdn.net/detail/qq123386926/9401186
(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 ); int main( 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; } int stoken_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; } void child_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 512 typedef 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" int history_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_RECORD history_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; } int history_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_RECORD history_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_RECORD history_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_RECORD history_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; } int history_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; } int history_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
相关文章推荐
- bash脚本编程 条件判断 二
- linux shell中 "" '' ``的区别
- shell中大于、等于、小于
- jdbc与 Beanshell PostProcessor 对多条结果的处理
- .bashrc 文件中增加头文件路径和库文路径
- Linux shell 学习
- shell判断文件是否有变化
- xshell密钥登录和密钥登录注意
- Linux shell下的颜色含义
- linux shell 快捷键
- ls -bash: ls: command not found (大多数命令不灵)
- echo命令写shell
- bash脚本编程 变量 一
- 搭建spark cluster过程中 scp传送文件 文件权限管理 磁盘及文件使用情况
- shell 编程语法总结(I/O 逻辑控制结构)
- linux 新建用户后无法用shell登录
- shell---practice2
- Linux系统下Python调用系统Shell的方法
- Bash shell编程<六>:处理用户输入
- Android shell脚本的使用