Unix-Linux編程實踐教程——shell(2)

頭文件smsh.h

//
// Created by Jimmy on 3/23/20.
//

#ifndef WHO_SMSH_H
#define WHO_SMSH_H

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <sys/wait.h>

#define YES 1
#define NO 0
#define is_delim(x) ((x)==' '||(x)=='\t')

char * next_cmd(char *, FILE *);
char ** splitline(char *);
void freelist(char **);
void * emalloc(size_t);
void * erealloc(void *, size_t);
int execute(char **);
void fatal(char *, char *, int);
void setup();
char * newstr(char * s, int len);

#endif //WHO_SMSH_H

源文件smsh.cpp

//
// Created by Jimmy on 3/23/20.
//

#include <zconf.h>
#include "include/smsh.h"

void fatal(char * s1, char * s2, int n)
{
    fprintf(stderr, "Error: %s , %s \n", s1, s2);
    exit(n);
}

void setup()
{
    signal(SIGINT, SIG_IGN);
    signal(SIGQUIT, SIG_IGN);
}

int execute(char * argv[])
{
    int pid;
    int child_info = -1;

    if(argv[0] == NULL)
        return 0;

    if((pid = fork()) == -1)
        perror("fork");
    else if(pid == 0){
        signal(SIGINT, SIG_DFL);
        signal(SIGQUIT, SIG_DFL);
        execvp(argv[0], argv);
        perror("cannot excute command");
        exit(1);
    } else{
        if(wait(&child_info) == -1){
            perror("wait");
        }
        return child_info;
    }
}

char * next_cmd(char * prompt, FILE * fp)
{
    char * buf;
    int bufspace = 0;
    int pos = 0;
    int c;

    printf("%s", prompt);
    while((c = getc(fp)) != EOF){
        if(pos + 1 >= bufspace){
            if(bufspace == 0)
                buf = static_cast<char *>(emalloc(BUFSIZ));
            else
                buf = static_cast<char *>(erealloc(buf, bufspace + BUFSIZ));
            bufspace += BUFSIZ;
        }
        if(c == '\n')
            break;
        buf[pos++] = c;
    }

    if(c == EOF && pos == 0)
        return NULL;
    buf[pos] = '\0';
    return buf;
}

char * newstr(char * s, int len)
{
    char * rv = static_cast<char *>(emalloc(len + 1));
    rv[len] = '\0';
    strncpy(rv, s, len);
    return rv;
}

void freelist(char ** list)
{
    char **cp = list;
    while(*cp)
        free(*cp++);
    free(list);
}

void * emalloc(size_t n)
{
    void * rv;
    if((rv = malloc(n)) == NULL)
        fatal("out of mem","",1);
    return rv;
}

void * erealloc(void * p, size_t n)
{
    void * rv;
    if((rv == realloc(p,n)) == NULL)
        fatal("out of mem","",1);
    return rv;
}

char ** splitline(char * line)
{
    char ** args;
    int spots = 0;
    int bufspace = 0;
    int argnum = 0;
    char * cp = line;
    char * start;
    int len;

    if(line == NULL)
        return NULL;

    args = static_cast<char **>(emalloc(BUFSIZ));
    bufspace = BUFSIZ;
    spots = BUFSIZ/sizeof(char *);

    while (*cp != '\0')
    {
        while (is_delim(*cp))
            cp++;
        if(*cp == '\0')
            break;

        if(argnum + 1 >= spots){
            args = static_cast<char **>(erealloc(args, bufspace + BUFSIZ));
            bufspace += BUFSIZ;
            spots += (BUFSIZ/ sizeof(char *));
        }

        start = cp;
        len = 1;
        while(*++cp != '\0' && !(is_delim(*cp)))
            len++;
        args[argnum++] = newstr(start, len);
    }
    args[argnum] = NULL;
    return args;
}

主函數smsh01.cpp

//
// Created by Jimmy on 3/23/20.
//

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "include/smsh.h"

#define DFL_PROMPT ">"

int main()
{
    char * cmdline, * prompt, ** arglist;
    int result;
    void setup();
    
    prompt = DFL_PROMPT;
    setup();
    
    while( (cmdline = next_cmd(prompt, stdin)) != NULL){
        if((arglist = splitline(cmdline)) != NULL)
        {
            result = execute(arglist);
            freelist(arglist);
        }
        free(cmdline);
    }
    return 0;
}

需要注意的是,原有的代碼再gcc編譯下不會產生問題,但是自己寫的時候IDE使用的是g++的編譯器,會抱一個錯誤,出現error的原因是C++設計得比C更加安全,它不能自動地將void *轉換爲其它指針類型。代碼裏面添加了static_cast。另外關於這個錯誤就提參考文章1文章2

     invalid conversion from void* to char*
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章