#include <string.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <signal.h>
#define MAX_CMD_ARG 10
#define MAX_CMD_GRP 10
const char *prompt = "myshell> ";
char* cmdgrps[MAX_CMD_GRP];
char* cmdvector[MAX_CMD_ARG];
char cmdline[BUFSIZ];
enum STAT{
NONE,
FG,
BG,
};
int status=NONE;
int pid=0;
void sigint_handler(int sign){
fputs("\n",stdout);
}
void fatal(char *str)
{
perror(str);
exit(1);
}
int makelist(char *s, const char *delimiters, char** list, int MAX_LIST)
{
if((s == NULL) || (delimiters == NULL)) return -1;
char *snew = s + strspn(s, delimiters); /* delimiters를 skip */
if((list[0] = strtok(snew, delimiters)) == NULL) return 0;
int numtokens = 1;
while(1)
{
if((list[numtokens] = strtok(NULL, delimiters)) == NULL) break;
if(numtokens == (MAX_LIST - 1)) return -1;
numtokens++;
}
return numtokens;
}
void execute_cmdgrp(char *cmdgrp)
{
int count = makelist(cmdgrp, " \t", cmdvector, MAX_CMD_ARG);
int size = strlen(cmdvector[count-1]);
if(size > 0 && cmdvector[count-1][size-1] == '&')
{
status=BG;
cmdvector[count-1][size-1] = '\0';
if(strlen(cmdvector[count-1]) == 0) cmdvector[count-1] = NULL;
}else{
status=FG;
}
//printf(cmdvector[0]);
switch(pid=fork())
{
case -1:
fatal("fork error");
break;
case 0: // child process
execvp(cmdvector[0], cmdvector);
fatal("exec error");
break;
default:
break;
}
}
void do_if_exit_cmd(const char* cmdgrp)
{
char* s = strdup(cmdgrp);
makelist(s, " \t", cmdvector, MAX_CMD_ARG);
if(strncasecmp(cmdvector[0], "exit", 4) == 0)
{
free(s);
exit(0);
}
free(s);
}
int do_if_cd_cmd(const char* cmdgrp)
{
char* s = strdup(cmdgrp);
makelist(s, " \t", cmdvector, MAX_CMD_ARG);
if(strncmp(cmdvector[0], "cd", 2) == 0)
{
chdir(cmdvector[1]);
free(s);
return 1;
}
free(s);
return 0;
}
void execute_cmdline(char* cmdline)
{
int count = makelist(cmdline, ";", cmdgrps, MAX_CMD_GRP);
if(count==0)
pid=0;
for(int i = 0; i < count; ++i)
{
do_if_exit_cmd(cmdgrps[i]);
if(do_if_cd_cmd(cmdgrps[i])) continue;
execute_cmdgrp(cmdgrps[i]);
}
}
int main(int argc, char**argv)
{
struct sigaction act;
act.sa_handler = sigint_handler;
sigaction(SIGINT, &act, NULL);
sigaction(SIGQUIT, &act, NULL);
while(1)
{
fputs(prompt, stdout);
cmdline[0]=0;
fgets(cmdline, BUFSIZ, stdin);
cmdline[strlen(cmdline) - 1] = '\0';
execute_cmdline(cmdline);
if(status==FG && pid){
int wid;
int status;
while((wid=wait(&status))!=pid && wid!=-1);
}
}
}
上面的代码是简单的概念shell 这个shell忽略了SIGINT(^ C)和SIGQUIT(^) 用g ++ {filename}
编译它问题是它在ubuntu 14.04 64bit和12.04 64bit中运行良好 但在ubuntu 12.04 32位 当我按^ C时,它会引发分段错误...
如果我更改&amp; status =&gt;这一行中的NULL'while((wid = wait(&amp; status))!= pid&amp;&amp; wid!= - 1);' 它没有错误地工作
这段代码有什么问题? 为什么剂量错误出现在某些ubuntu版本而其他人没有..
答案 0 :(得分:0)
在信号处理程序中有一些你不允许做的事情,其中之一就是调用不是异步信号安全的函数。
fputs()
中POSIX系统下的其中一个所以这个小片段:
void sigint_handler(int sign){
fputs("\n",stdout);
}
不是一个好主意。
我倾向于仅使用信号处理程序来设置可由主控制线程拾取和操作的变量,例如:
int finished = 0;
void sigint_handler(int sign){
finished = 1;
}
主程序有一个循环:
while (!finished)
doSomeWork();