如何从在 C 中存储 shell 脚本输出的指针获取多个字符串?
Posted
技术标签:
【中文标题】如何从在 C 中存储 shell 脚本输出的指针获取多个字符串?【英文标题】:How to get multiple strings from pointer that stores the output of a shell script in C? 【发布时间】:2020-05-24 18:20:05 【问题描述】:我正在尝试使用命名管道 (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
为了获得完整的输出需要修改什么?
【问题讨论】:
【参考方案1】:问题出在 server.c 中的第 52 行。
您正在使用fgets()
将输出复制到msg.spec
。
但是fgets()
停止在换行符('\n')处接受输入。
因此,您只会看到一个结果。
要克服这个问题,您可以执行以下操作:
char str[100]; // arbitrary length
while(fgets(str, MAXLEN, g))
strcat(msg.spec, str);
这会在每次迭代中不断获取输入,并将每一行连接到前一个输出。
【讨论】:
谢谢。同时我想通了:D以上是关于如何从在 C 中存储 shell 脚本输出的指针获取多个字符串?的主要内容,如果未能解决你的问题,请参考以下文章