2011-12-08 21 views

Trả lời

6

execvpthay thế quá trình hoạt động hiện tại trong bộ nhớ. Không có "đánh bắt" đầu ra.

Tôi nghi ngờ bạn đang cố gắng chạy một quy trình bên ngoài từ một quy trình hiện có và phân tích đầu ra của nó. Bạn cần sử dụng popen() để thực hiện fork() rồi exec(), trả lại FILE * để đọc (sẽ là stdout của quá trình bạn vừa chạy).

1

Xem tài liệu của popen, tôi nghĩ đó chính xác là những gì bạn cần.

1

Như những người khác đã nói, popen là những gì bạn muốn sử dụng. Một cái gì đó như thế này ...

#include <iomanip> 
#include <iostream> 

using namespace std; 

const int MAX_BUFFER = 255; 

int main() 
{ 
     string cmd; 
     cout << "enter cmd: "; 
     cin >> cmd; 
     cout << endl << "running " << cmd << "…" << endl; 


     string stdout; 
     char buffer[MAX_BUFFER]; 
     FILE *stream = popen(cmd.c_str(), "r"); 
     while (fgets(buffer, MAX_BUFFER, stream) != NULL) 
     stdout.append(buffer); 
     pclose(stream); 


     cout << endl << "output: " << endl << stdout << endl; 
} 
+0

cũng sẽ hoạt động với đối số? – topherg

+0

Vâng, cin sẽ làm giảm các đối số nhưng nếu bạn thu nhỏ chúng đúng cách, bạn có thể xử lý một thứ gì đó "ls -latr". – Ternary

4

tôi mất lòng tin popen/pclose, như tôi đã làm việc trên quá nhiều hệ thống nơi SIGCHLD đã được xử lý hơi khác nhau. Và tôi không tin tưởng việc phân tích cú pháp sh -shell được sử dụng bởi popen, vì tôi hiếm khi sử dụng nó.

Ngắn 22 tuổi O'Reilly cuốn sách Using C on the UNIX System, by Dave Curry vẫn là một rất tài liệu tham khảo tốt cho loại công cụ này.

Dù sao, đây là một số mã. Nó hơi dài, vì nó phân tích chuỗi mẫu "/bin/ls /etc" thành mảng {"/bin/ls", "/etc", 0}. Nhưng tôi thấy việc sử dụng định dạng chuỗi dễ dàng hơn ngắn hơn 98% thời gian, mặc dù ví dụ này tuân theo điều đó.

Mã này tạo danh sách /etc. Bạn cần phải thay đổi một số nội dung như ví dụ: NUMBER() giống với XtNumber(). Và bạn sẽ cần phải quyết định xem nó có phù hợp với việc xử lý của bạn là SIGCHLD hay không.

int main(void) { // list the files in /etc 
    char buf[100]; 
    FILE *fp; 
    int pid = spawnfp("/bin/ls /etc", &fp); 
    while (fgets(buf, sizeof buf, fp)) 
     printf("%s", buf); 
    fclose(fp);     // pclose() replacement 
    kill(pid, SIGKILL);   // pclose() replacement 
    return 0; 
} 

Các thủ tục con ở đây là:

static int spawnpipe(const char *argv[], int *fd) // popen() replacement 
{ 
    int pid; 
    int pipe_fds[2]; 

    if (pipe(pipe_fds) < 0) 
     FatalError("pipe"); 

    switch ((pid = fork())) 
    { 
     case -1: 
     FatalError("fork"); 
     case 0:      // child 
     close(1); 
     close(2); 
     dup(pipe_fds[0]); 
     dup(pipe_fds[1]); 
     close(pipe_fds[0]); 
     close(pipe_fds[1]); 

     execv(argv[0], (char * const *)argv); 
     perror("execv"); 
     _exit(EXIT_FAILURE); // sic, not exit() 
     default: 
     *fd = pipe_fds[0]; 
     close(pipe_fds[1]); 
     return pid; 
    } 
} 

này chuyển đổi một chuỗi ascii vào một danh sách argv, mà có lẽ là vô ích cho bạn:

Bool convertStringToArgvList(char *p, const char **argv, int maxNumArgs) 
{ 
    // Break up a string into tokens, on spaces, except that quoted bits, 
    // with single-quotes, are kept together, without the quotes. Such 
    // single-quotes cannot be escaped. A double-quote is just an ordinary char. 
    // This is a *very* basic parsing, but ok for pre-programmed strings. 
    int cnt = 0; 
    while (*p) 
    { 
     while (*p && *p <= ' ') // skip spaces 
     p++; 
     if (*p == '\'')   // single-quote block 
     { 
     if (cnt < maxNumArgs) 
      argv[cnt++] = ++p; // drop quote 
     while (*p && *p != '\'') 
      p++; 
     } 
     else if (*p)    // simple space-delineated token 
     { 
     if (cnt < maxNumArgs) 
      argv[cnt++] = p; 
     while (*p > ' ') 
      p++; 
     } 
     if (*p) 
     *p++ = 0;    // nul-terminate 
    } 
    if (cnt < maxNumArgs) 
     argv[cnt++] = 0; 
    return cnt <= maxNumArgs;  // check for too many tokens (unlikely) 
} 

này chuyển chuỗi lập luận để tokens và quan trọng hơn, số fd đến số fp, vì OP đã yêu cầu stdout:

int spawnfp(const char *command, FILE **fpp) 
{ 
    const char *argv[100]; 
    int fd, pid; 
    if (!convertStringToArgvList(strdupa(command), argv, NUMBER(argv))) 
     FatalError("spawnfp"); 
    pid = spawnpipe(argv, &fd); 
    *fpp = fdopen(fd, "r"); 
    return pid; 
} 
Các vấn đề liên quan