如何从将Shell脚本输出存储在C中的指针获取多个字符串?

问题描述 投票:2回答:1

我正在尝试使用命名管道(fifo)在C语言中编写代码,客户端在其中询问有关目录的信息。

服务器检查目录的存在,并发回目录的大小以及文件和子目录的数量。该请求还可以指定获取文件和子目录的名称。

客户端将目录的名称作为参数,也将由-d选项指定。服务器执行Shell脚本以解决问题。

我已经问过有关此主题的问题,并且对代码进行了一些改进,但仍然无法使其正常运行。

这里是问题的链接:How to pass multiple arguments to client (fifo)?

我的问题是,服务器仅打印出一个文件名,而不打印出作为客户端参数的目录内的所有文件名和子目录。

这是修改后的服务器代码:

#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;
}

和客户端代码:

#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);
}

公共头文件:

#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;

我得到的输出是:

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

虽然看起来应该像这样:

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

为了获得完整的输出需要修改什么?

c string bash named-pipes fifo
1个回答
1
投票

问题出在server.c内部的第52行。您正在使用fgets()将输出复制到msg.spec。但是fgets()停止接受换行符('\ n')的输入。因此,您只会看到一个结果。

要克服这一点,您可以执行以下操作:

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

这会在每次迭代时不断获取输入并将每一行连接到先前的输出。

© www.soinside.com 2019 - 2024. All rights reserved.