0

我的功能有问题system()

我需要实现一个简单的 bash,我项目的模块之一是允许用户键入一些 bash 命令来执行它。

高于我实际上正在做的事情:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// similar to gets
int reads(char* str)
{
#ifndef WIN32
    fflush(stdout);
    strcpy(str,GetServiceLine());
#else
    gets(str);
#endif

    return 1;
}

int main(void) {
    char str[100];

        while(strcmp(str, "exit")) {
            printf("\nNote: type \"exit\" to return menu\n");
            printf("MyBash$ ");
            reads(str);

            system(str);
        }

    return 0;
}

我的问题是像ping.

当我在我的 PC 上运行此代码并尝试执行ping合法命令时IP它工作正常,我可以使用 停止ping进程CTRL+C,但是当我以相同的方式在目标上运行它时,我无法使用CTRL+C并且我的进程始终保持在system()称呼。

有人可以帮助我吗?

注意:我阅读了这篇关于如何使用 CTRL+C 来破坏系统功能的帖子。我尝试了这个建议,但没有奏效。

谢谢。

4

3 回答 3

1

既然你还没有尝试过,我会把它扔在这里作为建议。您始终可以安装信号处理程序来捕获您感兴趣的信号。

这是一个使用(主要)您的代码的快速示例,它演示了它是如何完成的:

#include <signal.h>
#include <stdio.h> 
#include <stdlib.h> 
#include <string.h>   

void intHandler(int dummy) 
{
    exit(1);   // Do whatever you want here to handle it...
}

int main(void) 
{
    char str[100];
    signal(SIGINT, intHandler);   
    signal(SIGKILL, intHandler);
    while(strcmp(str, "exit")) {
       printf("\nNote: type \"exit\" to return menu\n");
       printf("MyBash$ ");
       gets(str);
       system(str);
    }      
    return 0; 
} 

我可以用这个来捕捉 ctrl+C,但我不确定它是否是你要找的。

于 2012-10-10T19:27:14.127 回答
1

在上面的评论之后,我只是想解释为什么你不能以一种优雅的方式控制它(尽管在评论中建议了一些技巧)。

如果您分叉了一个子进程,然后在子进程上调用 exec 以执行作为参数传递给 exec 的二进制文件,系统命令的行为将完全一致。

system() 函数应忽略 SIGINT 和 SIGQUIT 信号,并应阻止 SIGCHLD 信号,同时等待命令终止。如果这可能导致应用程序错过可能会杀死它的信号,那么应用程序应该检查 system() 的返回值并采取任何适当的措施。

请记住,这是非常特定于操作系统的行为,并且没有这样的标准。

Linux中的system()函数调用

内部 ping 实用程序将在 icmp 上运行并等待,直到收到来自其他节点的响应。

您可能会按照另一个答案中的建议编写信号处理程序并调用 killpid() 但它会被阻止,直到对 system() 的调用返回。这在函数的规范中有所说明。因此,您可能能够终止,但只有在呼叫返回之后。:)

于 2012-10-10T19:36:59.820 回答
0

在用于解决我的问题的代码下方。我不知道是否是更好的解决方案,但在这种情况下解决了我的问题。

#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// similar to gets
int reads(char* str)
{
#ifndef WIN32
    fflush(stdout);
    strcpy(str,GetServiceLine());
#else
    gets(str);
#endif

    return 1;
}

void getCommandName(char input[], char output[])
{
    int count=0;

    while (input[count] != NULL && input[count] != ' ' && input[count] != '\0') {
        output[count] = input[count];
        count++;
    }
}

int killLastCommand(int pid)
{
    char commandKill[30];

    memset(commandKill, 0, 30);

    sprintf(commandKill, "kill -9 %d", pid);
    return(!system(commandKill));
}

int main(void) {
    FILE *fp; //Will be used with popen()
    char str[100];
    char lastCommandName[50];
    char pidofCommand[50];
    char strLastPIDCommand[10];
    int lastPIDCommand=0;

    memset (str, 0, 100);

        while(strcmp(str, "exit")) {
        if (lastPIDCommand == 0) {
            memset (lastCommandName, 0, 50); //Clean lastCommandName array
            memset (pidofCommand, 0, 50); //Clean pidofCommand array
            memset (strLastPIDCommand, 0, 10); //Clean strLastPIDCommand array

            printf("\n\nNote: type \"exit\" to return menu\n");
            printf("MyBash$ ");
                reads(str);

            if (strcmp(str, "exit")) {
                    sprintf(str, "%s &", str);
            }

            getCommandName(str, lastCommandName);

            system(str);
            sleep(1); //Sleep to guarantee than command will end

            sprintf(pidofCommand, "pidof %s", lastCommandName); 

            //Saving PID
            fp = popen(pidofCommand, "r");

            if (fp) {
                fgets(strLastPIDCommand, 10, fp);
                lastPIDCommand = atoi(strLastPIDCommand);
            } else {
                //Handle error
            }
            pclose(fp);

printf("commandName = %s\r\n", lastCommandName);
printf("pid = %d\r\n", lastPIDCommand);
        } else {
            printf("\n\nYou have a command running, press 'kill' to stop it before to type another command\n");
            printf("EITVBash$ \n\n");
            reads(str);

//          if (str[0] == 0x03) { //CTRL+C hexa code
            if (!strcmp(str, "kill")) {
                if (killLastCommand(lastPIDCommand)) {
                    lastPIDCommand = 0;
                }
            }
        }
    }

    return 0;
}

我的实现可能不干净,但我对 c 没有太多经验。

谢谢大家。

于 2012-10-11T14:15:29.857 回答