gpt4 book ai didi

C Shell : Redirection and piping working, 但不是输入和输出重定向与 1 个或多个管道的组合

转载 作者:太空宇宙 更新时间:2023-11-03 23:40:48 25 4
gpt4 key购买 nike

我的 C shell 可以成功处理重定向(例如 ls -al > output.txt、./pre < input1.txt 等)和多个管道(即 cmd1 | cmd 2 | cmd 3)。但是,当我尝试与管道一起进行输入和输出重定向时,我的代码不起作用,例如 ./pre < input.txt | ./sort > 输出.txt。尽管 ./pre 确实成功执行,但从未生成任何输出文件。

pre 是一个可执行文件,打印 GPA 超过 3.0 的名字

sort 是一个按字母顺序排列名称列表的可执行文件input.txt 是一个包含名称和 GPA 的文件(名称 3.1...)。

代码:

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

#ifndef READ
#define READ 0
#endif

#ifndef WRITE
#define WRITE 1
#endif

void clearArgumentContainer (int argumentContainer[]);

int main() {
/* professor-supplied variables for commands and command parsing */
char *iPath, *oPath, *argv[20], buf[80], n, *p;
int m, status, inword, continu;

int start[20];

/* flags for redirection (note: C does not have type bool; using integer value 0 or 1) */
int inputRedirectFlag, outputRedirectFlag;

/* variables for piping */
int count, pipes;
pid_t pid;

/* pipes */
int l_pipe[2], r_pipe[2];

/* required container for handling arguments */
int argumentContainer[20] = { 0 };

while (1) {

inword = m = continu = count = pipes = pid = 0;

p = buf;

/* redirection flags reset */
inputRedirectFlag = outputRedirectFlag = 0;

/* shell prompt */
printf("\nshhh> ");

/* command parsing */
while ((n = getchar()) != '\n' || continu)
{
if (n == ' ') {
if (inword)
{
inword = 0;
*p++ = 0;
}
}
else if (n == '\n')
continu = 0;
else if (n == '\\' && !inword)
continu = 1;
else {
if (!inword)
{
inword = 1;
argv[m++] = p;
*p++ = n;
}
else
*p++ = n;
}
} /* end of command parsing */

*p++ = 0;
argv[m] = 0;

/* user wishes to terminate program */
if (strcmp(argv[0], "exit") == 0)
exit(0);

/* manage redirection */
while (argv[count] != 0) {
if (strcmp(argv[count], "|") == 0) {
argv[count] = 0;
argumentContainer[pipes + 1] = count + 1;
++pipes;
}
else if (strcmp(argv[count], "<") == 0) {
iPath = strdup(argv[count + 1]); /* copy string argument (file string) */
argv[count] = 0;
argv[count + 1] = 0;
inputRedirectFlag = 1;
}
else if (strcmp(argv[count], ">") == 0) {
oPath = strdup(argv[count + 1]); /* copy string argument (file string) */
argv[count] = 0;
argv[count + 1] = 0;
outputRedirectFlag = 1;
}
else {
argumentContainer[count] = count;
}

++count;
} /* end of redirection management */

/* execute commands [<= in for-loop; n pipes require n+1 processes] */
for (int index = 0; index <= pipes; ++index) {
if (pipes > 0 && index != pipes) { /* if user has entered multiple commands with '|' */
pipe(r_pipe); /* no pipe(l_pipe); r_pipe becomes next child's l_pipe */
}

/* switch-statement for command execution */
switch (pid = fork()) {
/* fork() error */
case -1: perror("fork failed");
break;

case 0: /* child process manages redirection and executes */
if ((index == 0) && (inputRedirectFlag == 1)) {
int inputFileDescriptor = open(iPath, O_RDONLY , 0400);
if (inputFileDescriptor == -1) {
perror("input file failed to open\n");
return(EXIT_FAILURE);
}
close(READ);
dup(inputFileDescriptor);
close(inputFileDescriptor);
} /* end of input redirection management */

if ((index == pipes) && (outputRedirectFlag == 1)) {
int outputFileDescriptor = open(oPath, O_WRONLY | O_CREAT, 0755);
if (outputFileDescriptor < 0) {
perror("output file failed to open\n");
return(EXIT_FAILURE);
}
close(WRITE);
dup(outputFileDescriptor);
close(outputFileDescriptor);
} /* end of output redirection management */

/* manage pipes if (a) first child process, (b) middle child process, or (c) third/final child process */
if (pipes > 0) {
if (index == 0){ /* first child process */
close(WRITE);
dup(r_pipe[WRITE]);
close(r_pipe[WRITE]);
close(r_pipe[READ]);
}
else if (index < pipes) { /* middle child process */
close(READ);
dup(l_pipe[READ]);
close(l_pipe[READ]);
close(l_pipe[WRITE]);
close(WRITE);
dup(r_pipe[WRITE]);
close(r_pipe[READ]);
close(r_pipe[WRITE]);
}
else { /* third/final child process */
close(READ);
dup(l_pipe[READ]);
close(l_pipe[READ]);
close(l_pipe[WRITE]);
}
}

/* execute command */
execvp(argv[argumentContainer[index]], &argv[argumentContainer[index]]);

/* if execvp() fails */
perror("execution of command failed\n");

break;

default: /* parent process manages the pipes for child process(es) */
if (index > 0) {
close(l_pipe[READ]);
close(l_pipe[WRITE]);
}
l_pipe[READ] = r_pipe[READ];
l_pipe[WRITE] = r_pipe[WRITE];

/* parent waits for child process to complete */
wait(&status);

break;
} /* end of switch-statement for command execution */
} /* end of loop for all pipes */

// clear all executed commands
for (int i = 0; i < 20; ++i) {
argv[i] = 0;
}
}
}

void clearArgumentContainer (int argumentContainer[]){
// clear argument container
for (int i = 0; i < 20; ++i) {
argumentContainer[i] = 0;
}
}

这是我正在使用的输入文件:

Tim 3.5
Todd 2.1
Beth 3.9
Jason 3.5
Zander 3.3
Alex 3.5
Tyler 3.5
Lauren 3.6
Jack 2.3
Amir 3.4
Beth 3.2

pre executable 将只列出那些 GPA 高于 3.0 的名字排序可执行文件将按字母顺序对名称列表进行排序

最佳答案

这是我最终的工作代码。它没有像 cd 那样实现内置功能,但我计划尽快实现这些内置功能!程序确实满足作业的要求。

我的主要变化发生在重定向处理上。我不得不在两个地方删除一行代码:

argv[count + 1] = 0;

来自“<”和“>”的重定向。

我还添加了代码来处理管道的连接,无论我的进程是第一个、最后一个还是介于两者之间。

代码:

/***********************************************************************************************
***********************************************************************************************
Student: Douglas Adolph
Course: Operating Systems
Project #: 2

Program emulates shell, and can do the following:

1. Can execute a command with the accompanying arguments.
2. Recognize multiple pipe requests and handle them.
3. Recognize redirection requests and handle them.
4. Type "exit" to quit the shhh shell.

Notes:

Shell built-ins (cd, echo, etc.) not yet implemented

REFERENCED:

1. http://www.thinkplexx.com/learn/article/unix/command
2. http://man7.org/linux/man-pages/man2/open.2.html
3. https://stackoverflow.com/questions/19846272/redirecting-i-o-implementation-of-a-shell-in-c
**********************************************************************************************
*********************************************************************************************/

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

#ifndef READ
#define READ 0
#endif

#ifndef WRITE
#define WRITE 1
#endif

void clearArgIndexContainer (int argLocation[]);

int main() {
/* variables for command parsing and storage*/
char n, *parser, buf[80], *argv[20];
int m, status, inword, continu;

/* variables and flags for redirection (note: C does not have type bool; using integer value 0 or 1) */
char *in_path, *out_path;
int inputRedirectFlag, outputRedirectFlag;

/* variables for piping */
int count, pipes;
pid_t pid;

/* left and right pipes */
int l_pipe[2], r_pipe[2];

/* container for recording argument locations in argv[] */
int argLocation[20] = { 0 };

while (1) {

/* reset parsing and piping variable values */
m = inword = continu = count = pipes = pid = 0;

/* begin parsing at beginning of buffer */
parser = buf;

/* reset redirection flags */
inputRedirectFlag = outputRedirectFlag = 0;

/* print shell prompt */
printf("\nshhh> ");

/* parse commands */
while ((n = getchar()) != '\n' || continu)
{
if (n == ' ') {
if (inword)
{
inword = 0;
*parser++ = 0;
}
}
else if (n == '\n')
continu = 0;
else if (n == '\\' && !inword)
continu = 1;
else {
if (!inword)
{
inword = 1;
argv[m++] = parser;
*parser++ = n;
}
else
*parser++ = n;
}
} /* end of command parsing */

/* append terminating character to end of parser buffer and argv buffer */
*parser++ = 0;
argv[m] = 0;

/* user wishes to terminate program */
if (strcmp(argv[0], "exit") == 0)
exit(0);

/* manage redirection */
while (argv[count] != 0) {
if (strcmp(argv[count], "|") == 0) {
argv[count] = 0;
argLocation[pipes + 1] = count + 1;
++pipes;
}
else if (strcmp(argv[count], "<") == 0) {
in_path = strdup(argv[count + 1]);
argv[count] = 0;
inputRedirectFlag = 1;
}
else if (strcmp(argv[count], ">") == 0) {
out_path = strdup(argv[count + 1]);
argv[count] = 0;
outputRedirectFlag = 1;
}
else {
argLocation[count] = count;
}

++count;
} /* end of redirection management */

/* execute commands [<= in for-loop; n pipes require n+1 processes] */
for (int index = 0; index <= pipes; ++index) {
if (pipes > 0 && index != pipes) { /* if user has entered multiple commands with '|' */
pipe(r_pipe); /* no pipe(l_pipe); r_pipe becomes next child's l_pipe */
}

/* switch-statement for command execution */
switch (pid = fork()) {
case -1: perror("fork failed"); /* fork() error */
break;

case 0: /* child process manages redirection and executes */
if ((index == 0) && (inputRedirectFlag == 1)) {
int inputFileDescriptor = open(in_path, O_RDONLY , 0400);
if (inputFileDescriptor == -1) {
perror("input file failed to open\n");
return(EXIT_FAILURE);
}
close(READ);
dup(inputFileDescriptor);
close(inputFileDescriptor);
} /* end of input redirection management */

if ((index == pipes) && (outputRedirectFlag == 1)) {
//printf("DEBUG: here we should be about to create our output file\n");
int outputFileDescriptor = creat(out_path, 0700);
if (outputFileDescriptor < 0) {
perror("output file failed to open\n");
return(EXIT_FAILURE);
}
close(WRITE);
dup(outputFileDescriptor);
close(outputFileDescriptor);
} /* end of output redirection management */

/* manage pipes if (a) first child process, (b) in-between child process, or (c) final child process */
if (pipes > 0) {
if (index == 0){ /* first child process */
close(WRITE);
dup(r_pipe[WRITE]);
close(r_pipe[WRITE]);
close(r_pipe[READ]);
}
else if (index < pipes) { /* in-between child process */
close(READ);
dup(l_pipe[READ]);
close(l_pipe[READ]);
close(l_pipe[WRITE]);
close(WRITE);
dup(r_pipe[WRITE]);
close(r_pipe[READ]);
close(r_pipe[WRITE]);
}
else { /* final child process */
close(READ);
dup(l_pipe[READ]);
close(l_pipe[READ]);
close(l_pipe[WRITE]);
}
}

/* execute command */
execvp(argv[argLocation[index]], &argv[argLocation[index]]);

/* if execvp() fails */
perror("execution of command failed\n");

break;

default: /* parent process manages the pipes for child process(es) */
if (index > 0) {
close(l_pipe[READ]);
close(l_pipe[WRITE]);
}
l_pipe[READ] = r_pipe[READ];
l_pipe[WRITE] = r_pipe[WRITE];

/* parent waits for child process to complete */
wait(&status);

break;
} /* end of switch-statement for command execution */
} /* end of loop for all pipes */

// clear all executed commands
for (int i = 0; i < 20; ++i) {
argv[i] = 0;
}
}
}

void clearArgIndexContainer (int argLocation[]){
// clear argument container
for (int i = 0; i < 20; ++i) {
argLocation[i] = 0;
}
}

我在这里删除了使 argv[count + 1] = 0 的行; :

/* manage redirection */
while (argv[count] != 0) {
if (strcmp(argv[count], "|") == 0) {
argv[count] = 0;
argLocation[pipes + 1] = count + 1;
++pipes;
}
else if (strcmp(argv[count], "<") == 0) {
in_path = strdup(argv[count + 1]);
argv[count] = 0;
inputRedirectFlag = 1;
}
else if (strcmp(argv[count], ">") == 0) {
out_path = strdup(argv[count + 1]);
argv[count] = 0;
outputRedirectFlag = 1;
}
else {
argLocation[count] = count;
}

这是我处理管道的主要补充:

/* manage pipes if (a) first child process, (b) in-between child process, or (c) final child process */
if (pipes > 0) {
if (index == 0){ /* first child process */
close(WRITE);
dup(r_pipe[WRITE]);
close(r_pipe[WRITE]);
close(r_pipe[READ]);
}
else if (index < pipes) { /* in-between child process */
close(READ);
dup(l_pipe[READ]);
close(l_pipe[READ]);
close(l_pipe[WRITE]);
close(WRITE);
dup(r_pipe[WRITE]);
close(r_pipe[READ]);
close(r_pipe[WRITE]);
}
else { /* final child process */
close(READ);
dup(l_pipe[READ]);
close(l_pipe[READ]);
close(l_pipe[WRITE]);
}
}

我还有更多工作要做,即实现内置函数,但也将更多这些放入单独的函数中以清理代码并使其更具可读性。我还得到了一些关于一些可能写得更好的表达式的好建议,我很快就会解决这个问题。

关于C Shell : Redirection and piping working, 但不是输入和输出重定向与 1 个或多个管道的组合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46715490/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com