我的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
等命令。
当我在我的电脑上运行此代码并尝试执行合法ping
的{{1}}命令时,它可以正常工作,我可以使用IP
停止ping
进程,但当我以同样的方式在我的目标上运行它时,我无法使用CTRL+C
,我的进程始终保持CTRL+C
电话。
有人可以帮助我吗?
注意:我阅读this post有关如何使用CTRL + C来破坏系统功能的信息。我尝试了这个建议,但没有用。
感谢。
答案 0 :(得分:1)
既然你还没有尝试过,我会把它作为建议扔在这里。您始终可以install a signal handler来捕捉您感兴趣的信号。
这是一个使用(主要)代码的快速示例,演示了如何完成:
#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,但我不确定它是否是您正在寻找的。 p>
答案 1 :(得分:1)
在上述评论之后,我只想解释为什么你无法以优雅的方式控制它(虽然在评论中建议了一些黑客攻击)。
如果你分叉了一个子进程,然后在子进程上调用了exec来执行传递给exec作为参数的二进制文件,那么系统命令将会完全正常运行。
system()函数应忽略SIGINT和SIGQUIT信号,并在等待命令终止时阻止SIGCHLD信号。如果这可能导致应用程序错过可能导致它被杀死的信号,那么应用程序应检查system()的返回值并采取适当的任何操作。
请记住,这是特定于操作系统的行为,并且没有这样的标准。
system() function call in Linux
内部ping实用程序将在icmp上运行并等待,直到从另一个节点收到响应。
您可能会按照另一个答案中的建议编写一个信号处理程序并调用killpid()但它会被阻塞,直到对system()的调用返回为止。这在功能的规格中说明。所以你可以终止,但只能在通话结束后才能终止。 :)
答案 2 :(得分: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没有太多经验。
谢谢大家。