在虚拟外壳中处理CTRL-C [英] Handling CTRL-C in dummy shell

查看:121
本文介绍了在虚拟外壳中处理CTRL-C的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在编写一个虚拟外壳程序,该外壳程序在用户键入ctrl-C时不应终止,而应仅生成一个新的提示行.当前,当我键入ctrl-C时,我的外壳并没有终止,但是它仍然不打印新的提示行.您知道为什么会这样吗,我该如何解决?

I'm writing a dummy shell that should not terminate when the user types ctrl-C but should just generate a new prompt line. Currently, my shell does not terminate when I type ctrl-C but it still does not print the new prompt line. Do you know why this is the case and how I can fix this?

我的代码如下:

#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <sys/wait.h>
#include <signal.h>
#define BUFFER_SIZE 1<<16
#define ARRAY_SIZE 1<<16

void INThandler(int);
static void parseCmdArgs(char *buffer, char** cmdArgs, 
                size_t cmdArgsSize, size_t *nargs)
{
    char *bufCmdArgs[cmdArgsSize]; 
    char **temp;
    char *buf;
    size_t n, p;

    cmdArgs[0] = buf = bufCmdArgs[0] = buffer;  

    for(temp=bufCmdArgs; (*temp=strsep(&buf, " \n\t")) != NULL ;){
        if ((*temp != '\0') && (++temp >= &bufCmdArgs[cmdArgsSize]))
            break;
    }

    for (p=n=0; bufCmdArgs[n]!=NULL; n++){
        if(strlen(bufCmdArgs[n])>0)
            cmdArgs[p++]=bufCmdArgs[n];
    }

    *nargs=p;
    cmdArgs[p]=NULL;
}

void INThandler(int sig)
{
  printf("\n> ");
  signal(sig, SIG_IGN);
  }
int main(void)
{
    char buffer[BUFFER_SIZE];
    char *args[ARRAY_SIZE];
    int retStatus;
    size_t nargs;
    pid_t pid;


    printf("$dummyshell\n");
    signal(SIGINT, INThandler);
    while(1){

        printf("> ");
        fgets(buffer, BUFFER_SIZE, stdin);
        parseCmdArgs(buffer, args, ARRAY_SIZE, &nargs); 


        if (nargs==0)
            continue;

        if (!strcmp(args[0], "help"))
        {
            printf("cat                    cd (absolute path references only\n");
            printf("exit\n");
            printf("help                   history\n");
            printf("jobs                   kill\n");
            printf("ls                     more\n");
            printf("ps                     pwd\n");
            continue;
        }

        if (!strcmp(args[0], "exit" ))
            exit(0);

    pid = fork();

        if (pid){      
            wait(&retStatus);
        }

        else {
            if( execvp(args[0], args)) {
          fprintf(stderr, "%s\n", strerror(errno));
                exit(127);
            }
        }
    /*  pid = fork();
    if (pid == 0)
      setpgrp();
    else if (pid)
      pid = wait(&retStatus);
    else {
      if (execvp(args[0], args)){
        fprintf(stderr, "%s\n", strerror(errno));
        exit(127);
      }
      }*/


    }    
    return 0;
}

推荐答案

我假设您希望中断处理程序跳转到main函数的while循环中,而不是打印"\>".

I'm assuming you want the interrupt handler to jump into the while loop in your main function, instead of printing "\>".

您可以为此使用sigsetjmpsiglongjmp.您可能想以[1]为例.

You can use sigsetjmp and siglongjmp for this. You might want to take at [1] for an example.

#include  <stdio.h>
#include  <signal.h>
#include  <setjmp.h>

jmp_buf  JumpBuffer;
void     INThandler(int);

void  main(void)
{
     signal(SIGINT, INThandler);
     while (1) {
          if (setjmp(JumpBuffer) == 0) {
             printf(">");
             /*...*/
          }
     }
}

void  INThandler(int  sig)
{
     signal(sig, SIG_IGN);
     signal(SIGINT, INThandler);
     longjmp(JumpBuffer, 1);
}

此内容改编自[2].如果使用sigaction()sigprocmask()sigsuspend(),则需要分别使用siglongjmpsigsetjmp函数[3].

This was adapted from [2]. If you use sigaction(), sigprocmask(), or sigsuspend() you need to use the siglongjmp and sigsetjmp functions, respectively [3].

来源:

  • [1] https://publib.boulder.ibm.com/iseries/v5r2/ic2924/index.htm?info/apis/siglngj.htm
  • [2] http://www.csl.mtu.edu/cs4411.ck/www/NOTES/non-local-goto/sig-1.html
  • [3] sigsetjmp - The Open Group Base Specifications Issue 6 IEEE Std 1003.1, 2004 Edition

这篇关于在虚拟外壳中处理CTRL-C的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆