如何从在 C 中存储 shell 脚本输出的指针获取多个字符串?
How to get multiple strings from pointer that stores the output of a shell script in C?
我正在尝试使用命名管道 (fifo) 在 C 语言中编写代码,客户端在其中询问有关目录的信息。
服务器检查目录是否存在,并发回目录的大小、文件和子目录的数量。
请求还可以指定获取文件名和子目录名。
客户端获取目录名称作为参数,也是 -d
选项的规范。
服务器执行 shell 脚本以解决问题。
我已经问了一个关于这个主题的问题并且对代码进行了一些改进,但仍然无法正确运行。
这是问题的 link: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
需要修改什么才能获得完整的输出?
问题出在server.c内的第52行。
您正在使用 fgets()
将输出复制到 msg.spec
。
但是 fgets()
在换行符 ('\n') 处停止输入。
因此,您只会看到一个结果。
要克服这个问题,您可以这样做:
char str[100]; // arbitrary length
while(fgets(str, MAXLEN, g))
{
strcat(msg.spec, str);
}
这会在每次迭代中不断获取输入并将每一行连接到之前的输出。
我正在尝试使用命名管道 (fifo) 在 C 语言中编写代码,客户端在其中询问有关目录的信息。
服务器检查目录是否存在,并发回目录的大小、文件和子目录的数量。 请求还可以指定获取文件名和子目录名。
客户端获取目录名称作为参数,也是 -d
选项的规范。
服务器执行 shell 脚本以解决问题。
我已经问了一个关于这个主题的问题并且对代码进行了一些改进,但仍然无法正确运行。
这是问题的 link: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
需要修改什么才能获得完整的输出?
问题出在server.c内的第52行。
您正在使用 fgets()
将输出复制到 msg.spec
。
但是 fgets()
在换行符 ('\n') 处停止输入。
因此,您只会看到一个结果。
要克服这个问题,您可以这样做:
char str[100]; // arbitrary length
while(fgets(str, MAXLEN, g))
{
strcat(msg.spec, str);
}
这会在每次迭代中不断获取输入并将每一行连接到之前的输出。