简体   繁体   English

如何从存储 C 中 shell 脚本的 output 的指针获取多个字符串?

[英]How to get multiple strings from pointer that stores the output of a shell script in C?

I am trying to write a code in C with named pipes (fifo), where the client is asking for information about a directory.我正在尝试使用命名管道(fifo)在 C 中编写代码,其中客户端正在询问有关目录的信息。

The server checks for the existence of the directory, and sends back the size of the directory, and the number of files and subdirectories.服务器检查目录是否存在,并返回目录的大小以及文件和子目录的数量。 The request can also specify to get the name of the files and subdirectories.该请求还可以指定获取文件和子目录的名称。

The client gets the name of the directory as an argument, also the specification by -d option.客户端获取目录的名称作为参数,也是-d选项的规范。 The server executes a shell script in order to solve the problem.服务器执行 shell 脚本以解决问题。

I already asked a question about this topic and got some improvements in the code, but still can't get it running correctly.我已经问过一个关于这个主题的问题,并且对代码进行了一些改进,但仍然无法使其正常运行。

Here is the link to the question: How to pass multiple arguments to client (fifo)?这是问题的链接: 如何将多个 arguments 传递给客户端(fifo)?

My problem is now that the server prints out only one file name instead of all filenames and subdirectories inside the directory that was given as an argument to the client.我现在的问题是服务器只打印出一个文件名,而不是作为参数提供给客户端的目录中的所有文件名和子目录。

Here is the modified server code:这是修改后的服务器代码:

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include "header.h"

int f;
Message msg;

int main() {
    if (mkfifo(FIFONAME, S_IFIFO | 0666) < 0) { /*Creating server fifo*/
        perror("Failed creating own fifo");
        printf("Server: Failed creating fifo_%d file\n", getpid());
        unlink(FIFONAME);
        exit(1);
    }

    if ((f = open(FIFONAME, O_RDONLY)) < 0) {
        perror("Failed opening fifo");
        unlink(FIFONAME);
        exit(1);
    }       

    printf("Server is working\n");
    while (1) { /*Infinite loop, waiting for client requests*/
        if ((read(f, &msg, sizeof(msg)))) {
            if (strcmp(msg.dir, "exit") == 0) {
                close(f);
                unlink(FIFONAME);
                exit(1);
            }

            switch (fork()) {
              case -1: {
                perror("Fork error\n");
                exit(1);
              }

              case 0: {
                char command[MAXLEN];
                sprintf(command,"./shell.sh %s %s", msg.dir, msg.spec);
                FILE *g;
                if ((g = popen(command, "r")) == NULL) {
                    perror("Popen error");
                    exit(1);
                }

                fgets(msg.dir, MAXLEN, g);
                fgets(msg.spec, MAXLEN, g);
                char result[MAXLEN];
                sprintf(result, "fifo_%d", msg.pid);
                msg.pid = getpid();
                int op;
                op = open(result, O_WRONLY);
                write(op, &msg, sizeof(msg));
                close(op);
                exit(0);
              }
            }
        }
    }
    return 0;
}

And the client code:和客户端代码:

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include "header.h"

int f, fc;
Message msg;
char fifoname[MAXLEN];

int main(int argc, char *argv[]) {
    if (argc == 1) {
        printf("Usage: %s directory name\n",argv[0]);
        exit(1);
    }
    sprintf(fifoname, "fifo_%d", getpid());
    if (strcmp(argv[1], "0"))
        if (mkfifo(fifoname, S_IFIFO | 0666) < 0) { /*Creating own FIFO file for result*/
            perror("Failed creating own clientfifo");
            printf("Client error: Failed creating fifo_%d file\n", getpid());
            exit(2);
        }

    if ((f = open(FIFONAME, O_WRONLY)) < 0) { /*Opening serverfifo for writing*/
        perror("Failed connecting to server");
        exit(3);
    }

    strcpy(msg.dir, argv[1]);
    strcpy(msg.spec, argv[2]); 
    msg.pid = getpid();
    write(f, &msg, sizeof(msg));

    if (strcmp(argv[1], "exit")) { /* The client is not expecting any result 
                                      because the server stopped*/
        if ((fc = open(fifoname, O_RDONLY)) < 0) { /*Opening own fifo for reading*/
            perror("Failed opening own fifo");
            printf("Client error: Failed opening own %s file\n", fifoname);
            exit(4);        
        }
        read(fc, &msg, sizeof(msg));
        printf("Client %d, received: %s%s\n", getpid(), msg.dir, msg.spec);
        close(fc);
    }

    unlink(fifoname);
    close(f);
    exit(0);
}

The common header file:常见的header文件:

#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <stdlib.h>

#define FIFONAME "server_fifo"
#define MAXLEN 1000

typedef struct {
    int pid; /*folyamat azonositoja*/
    char dir[MAXLEN];
    char spec[MAXLEN];
} Message;

And the output I get is:我得到的 output 是:

-bash-4.1$ ./client dir -d
Client 42723, received: 16K,2 directories, 2 files
a

While it should look like this:虽然它应该看起来像这样:

-bash-4.1$ ./client dir -d
Client 42723, received: 16K,2 directories, 2 files
a
b
dir1
dir2

What needs to be modified in order to get the full output?为了获得完整的 output,需要修改什么?

The problem is at line 52 inside server.c.问题出在 server.c 内的第 52 行。
You are using fgets() to copy the output to msg.spec .您正在使用fgets()将 output 复制到msg.spec But fgets() stops taking input at newline charater ('\n').但是fgets()停止在换行符('\n')处接受输入。
Hence you only see one result.因此,您只会看到一个结果。

To overcome this, you can do something like:为了克服这个问题,您可以执行以下操作:

char str[100]; // arbitrary length
while(fgets(str, MAXLEN, g))
{
     strcat(msg.spec, str);
}

This keeps taking input every iteration and concatenates each line to previous output.这会在每次迭代中不断获取输入,并将每一行连接到之前的 output。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM