2016-04-24 184 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