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
原创粉丝点击