2016-04-24 187 views
0
#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> 
#include <string.h> 
int main() { 
printf("Transactional Shell Command Test.\n"); 
while(1) { 
    printf("Queue:"); 
    char input[500]; 
    fgets (input, 500, stdin); 
    if(strstr(input, "qb-write")){ 
    printf("These are the commands you have queued:\n"); 
    FILE *cmd = popen("cat /home/$USER/.queueBASH_transactions", "r"); 
    char buf[256]; 
    while (fgets(buf, sizeof(buf), cmd) != 0) { 
     printf("%s\n",buf); 
    } 
    pclose(cmd); 
    } 
    system(strncat("echo ",strncat(input," >> /home/$USER/.qb_transactions",500),500)); 
    usleep(20000); 
} 

return 0; 
} 

我正在尝试为事务性shell创建一个概念,并且我将它输出到用户主目录中的文件中的每个命令。它并没有完全完成,但我一次只做一个部分。当我输入“shell”的任何输入时,它会崩溃。 Codeblocks告诉我“进程返回-1(0xFFFFFFFF)”,然后通常有关运行时的信息。我在这里做错了什么?程序返回-1(0xFFFFFFFF)

+0

不代码块没有一个集成的调试? –

+0

如何呈现特定的程序输入与崩溃可以复制? –

+0

还请注意,您对'strncat()'的特殊用法不能防止缓冲区溢出,您可能认为它有此功能。 –

回答

4

strncat追加到它的第一个参数,所以你需要传递一个可写缓冲区作为第一个参数。您正在传递一个字符串文字("echo "),这取决于您的编译器和运行时环境,可能会覆盖不可预知的内存部分,或者因为它试图写入只读内存而崩溃。

char command[500]; 
strcpy(command, "echo "); 
strncat(command, input, sizeof(command)-1-strlen(command)); 
strncat(command, " >> /home/$USER/.qb_transactions", sizeof(command)-1-strlen(command)); 
system(command); 

和其余的代码一样,我省略了错误检查,因此如果命令不适合缓冲区,命令将被截断。还请注意,对strncat的重复调用效率不高,因为它们涉及遍历字符串多次以确定其结束;使用返回值并跟踪剩余的缓冲区大小会更有效,但我将此作为后续练习。

当然,首先调用一个shell来附加到文件是一个坏主意。如果输入包含外壳特殊字符,它们将被评估。您应该打开日志文件并直接写入。

char log_file[PATH_MAX]; 
strcpy(log_file, getenv("HOME")); 
strncat(log_file, "/.qb_transactions", PATH_MAX-1-strlen(log_file)); 
FILE *log_file = fopen(log_file, "a"); 
… 
while (1) { 
    … 
    fputs(cmd, log_file); 
} 
fclose(log_file); 

(再次,检查省略错误。)

+0

你对'strncat()'的建议是不恰当的,因为它不能防止缓冲区溢出,毕竟这是主要的理由, '的strcat()'。第三个参数是要复制的最大字节数,因此为了防止缓冲区溢出,该参数需要考虑目标缓冲区中字符串的原始长度。 –

+0

@JohnBollinger谢谢,修正了(我添加了一个注释,这不是一个好方法,但我不打算完全重写程序)。 – Gilles