简体   繁体   English

在虚拟外壳中处理CTRL-C

[英]Handling CTRL-C in dummy shell

I'm writing a dummy shell that should not terminate when the user types ctrl-C but should just generate a new prompt line. 我正在编写一个虚拟外壳,当用户键入ctrl-C时该外壳不应终止,而应仅生成一个新的提示行。 Currently, my shell does not terminate when I type ctrl-C but it still does not print the new prompt line. 当前,当我键入ctrl-C时,我的外壳并没有终止,但是它仍然不显示新的提示行。 Do you know why this is the case and how I can fix this? 您知道为什么会这样吗,我该如何解决?

My code is below: 我的代码如下:

#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;
}

but what would I pass through fflush()? 但是我将通过fflush()通过什么呢?

It would be 这将是

    fflush(stdout);

- but that is not needed because of the fgets(buffer, BUFFER_SIZE, stdin) . -但这不是必需的,因为有fgets(buffer, BUFFER_SIZE, stdin)

Output streams that refer to terminal devices are always line buffered by default; 默认情况下,引用终端设备的输出流始终是行缓冲的。 pending output to such streams is written automatically whenever an input stream that refers to a terminal device is read. 每当读取指向终端设备的输入流时,这些流的未决输出都会自动写入。

(See man stdio .) (请参阅man stdio 。)

I'm assuming you want the interrupt handler to jump into the while loop in your main function, instead of printing "\\>" . 我假设您希望中断处理程序跳入main函数的while循环中,而不是打印"\\>"

You can use sigsetjmp and siglongjmp for this. 您可以sigsetjmp使用sigsetjmpsiglongjmp You might want to take at [1] for an example. 您可能想以[1]为例。

#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);
}

This was adapted from [2]. 改编自[2]。 If you use sigaction() , sigprocmask() , or sigsuspend() you need to use the siglongjmp and sigsetjmp functions, respectively [3]. 如果使用sigaction()sigprocmask()sigsuspend() ,则需要分别使用siglongjmpsigsetjmp函数[3]。

Sources : 资料来源

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM