2013-05-05 84 views
0

我爲它寫了一些C代碼,使用popen得到「ls -la」命令的結果並將結果寫入C中。代碼如下所示:使用popen(「ls -la」)會產生奇怪的結果

unsigned int ls(char *destination, const char *username, const char *relative_path) 
{ 
printf("LS IMP\n"); 
//if(!username || !relative_path) return -1; 
FILE *ls_pipe = NULL; 
unsigned long ls_pipe_size = -1; 

const char ls_command[] = "ls -la "; 
char ls_path[255] = "/home/"; 
char ls_full_command[255]; 

char buffer[255]; 
bzero(buffer, 255); 

char *entries = NULL; 

bzero(ls_full_command, 255); 

strcat(ls_path, username); 
strcat(ls_path, relative_path); 

strcat(ls_full_command, ls_command); 
strcat(ls_full_command, ls_path); 

printf("AFTER CATS\n"); 
ls_pipe = popen(ls_full_command, "r"); 

if(ls_pipe == NULL) return -1; 

printf("Pipe ok!"); 

fseek(ls_pipe, 0, SEEK_END); 
ls_pipe_size = ftell(ls_pipe); 
rewind(ls_pipe); 

printf("Filesize: %lu\n", ls_pipe_size); 

int i; 

for(i = 0; i < 100; i++) 
{ 
    fread(buffer, 1, 255, ls_pipe); 

    printf("%s", buffer); 
} 

//entries = (char*) malloc(sizeof(char) * ls_pipe_size); 
//if(entries == NULL) return -1; 
printf("Entries ok!\n"); 

//if(ls_pipe_size != fread(destination, sizeof(char), ls_pipe_size, ls_pipe)) return -1; 

fclose(ls_pipe); 
return strlen(destination); 

} 

的問題是管道的大小是巨大的(?),並在適當的結果後,三個項目開始出現不停地換類似於無窮大的結果。

有沒有什麼方法可以在不知道結果行的確切數量的情況下使用類似wc -l的另一個popen?

感謝

P.S有代碼的一些修改當我試圖測試什麼錯和的malloc沒有因爲管道的瘋狂大小的工作。

+1

fread不會添加空,因此%s是錯誤的。 – stark 2013-05-05 21:55:01

+0

是的,我知道,這是更多的調試代碼。問題是我不知道把'\ 0'放在哪裏,因爲在正確的結果之後我得到了垃圾,所以我不知道結果和垃圾開始的位置。 – 2013-05-05 21:57:11

+1

您沒有檢查fseek正在返回的EBADF。 – stark 2013-05-05 21:59:51

回答

1

你不能在管道上尋找。您從ftell()獲得的任何價值都不重要或錯誤。由於無法在管道上尋找,因此無法倒回管道。您只能從管道讀取一次數據。

因此,您需要重新設計代碼來讀取不確定數量的數據。

下面是一些合理的工作代碼 - 但我需要使它適應Mac OS X和我的機器,所以不是/home/它使用/Users/,並調用ls()使用我的用戶名。該代碼可以正確處理緩存中充滿不以null結尾的數據(爲我的bin目錄列出大約570行輸出)。我已將界面保留爲ls,儘管它幾乎不使用destination,並且返回destination的長度與其所做的操作無關。它還使用pclose()關閉管道。使用pclose()可以避免讓殭屍離開並返回fclose()不會執行的程序的退出狀態。

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

static unsigned int ls(char *destination, const char *username, const char *relative_path) 
{ 
    printf("LS IMP\n"); 
    assert(destination != 0 && username != 0 && relative_path != 0); 
    const char ls_command[] = "ls -la "; 
    char ls_path[255] = "/Users/"; 
    char ls_full_command[255]; 

    snprintf(ls_full_command, sizeof(ls_full_command), "%s %s%s/%s", 
      ls_command, ls_path, username, relative_path); 

    FILE *ls_pipe = popen(ls_full_command, "r"); 

    if (ls_pipe == NULL) 
     return -1; 

    printf("Pipe ok!\n"); 

    char buffer[255]; 
    int nbytes; 
    while ((nbytes = fread(buffer, 1, 255, ls_pipe)) > 0) 
     printf("%.*s", nbytes, buffer); 
    putchar('\n'); 

    printf("Entries ok!\n"); 
    pclose(ls_pipe); 
    return strlen(destination); 
} 

int main(void) 
{ 
    unsigned int length = ls("/", "jleffler", "bin"); 
    printf("ls() returned %u\n", length); 
    return(0); 
} 
相關問題