頭文件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*