aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoriceyrazor <iceyrazor@mailfence.com>2026-03-03 00:17:36 -0600
committericeyrazor <iceyrazor@mailfence.com>2026-03-03 00:17:36 -0600
commitf7af740cf2bccde2e6edbac31a0182fafe05d25e (patch)
treee110bdaee77f97d6dd4931e8daa28b77e19e1f63
parent1b8967ea87c63342f03c340d44a084ea7f62cae9 (diff)
pipes
-rw-r--r--README.md6
-rw-r--r--src/lsh_builtins.c4
-rw-r--r--src/lsh_main_func.c71
-rwxr-xr-xsrc/main.c8
-rw-r--r--src/main.h10
5 files changed, 74 insertions, 25 deletions
diff --git a/README.md b/README.md
index 7ffc1ad..fc9126e 100644
--- a/README.md
+++ b/README.md
@@ -23,13 +23,15 @@ Going to try and make it mostly POSIX compliant.
- [x] single quotes
- [x] pop quotes a'b'c -> abc
- [ ] prompt uses PS1
- - [ ] pipes |
+ - [x] pipes |
- [ ] &&
- [x] ;
- [ ] vi mode
- - [ ] redirections > <
+ - [ ] redirection >
+ - [ ] redirection <
- [ ] append >>
- [ ] heredoc <<
- [ ] &
+- [ ] Env="something" ... executable args
- [ ] rcfile
- [ ] rcfile in config dir
diff --git a/src/lsh_builtins.c b/src/lsh_builtins.c
index 0986cfe..dda49c4 100644
--- a/src/lsh_builtins.c
+++ b/src/lsh_builtins.c
@@ -101,7 +101,7 @@ int export(char **args){
-int lsh_execute(char **args)
+int lsh_execute(char **args, CMD *cmd)
{
int i;
@@ -116,6 +116,6 @@ int lsh_execute(char **args)
}
}
- return lsh_launch(args);
+ return lsh_launch(args, cmd);
}
#endif
diff --git a/src/lsh_main_func.c b/src/lsh_main_func.c
index 1604073..ff05a2b 100644
--- a/src/lsh_main_func.c
+++ b/src/lsh_main_func.c
@@ -3,7 +3,6 @@
#include <stdio.h>
#include <stdlib.h>
-#include <string.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdbool.h>
@@ -44,7 +43,24 @@ char *lsh_read_line(void)
}
}
-char * strtok_cmd(char *token, cmd_t *type){
+int cleanup_token(char **parse_args_last_p, int ch_i){
+ (*parse_args_last_p)[ch_i]='\0';
+ if((*parse_args_last_p)[ch_i+1]=='\0')
+ return -1;
+
+ //remove spaces and tabs around sep char
+ int i=ch_i-1;
+ while ((*parse_args_last_p)[i]==' '|| (*parse_args_last_p)[0]=='\t'){
+ (*parse_args_last_p)[i--]='\0';
+ }
+
+ *parse_args_last_p=&(*parse_args_last_p)[ch_i+1];
+ while((*parse_args_last_p)[0]==' ' || (*parse_args_last_p)[0]=='\t')
+ *parse_args_last_p=&(*parse_args_last_p)[1];
+ return 0;
+}
+
+char *strtok_cmd(char *token, cmd_t *type){
*type=Stdout;
static char* parse_args_last_p;
if(token != NULL){
@@ -85,16 +101,18 @@ char * strtok_cmd(char *token, cmd_t *type){
if (pass_check)
in_quote=' ';
}
- } else if(parse_args_last_p[ch_i]==';'){
- if(parse_args_last_p[ch_i]=='\0')
- break;
- parse_args_last_p[ch_i]='\0';
- if(parse_args_last_p[ch_i+1]=='\0')
- break;
- parse_args_last_p=&parse_args_last_p[ch_i+1];
- while(parse_args_last_p[0]==' ' || parse_args_last_p[0]=='\t')
- parse_args_last_p=&parse_args_last_p[1];
- return return_char;
+ } else{
+ switch (parse_args_last_p[ch_i]){
+ case ';':
+ if(cleanup_token(&parse_args_last_p, ch_i)!=0) break;
+ return return_char;
+ break;
+ case '|':
+ if(cleanup_token(&parse_args_last_p, ch_i)!=0) break;
+ *type=Pipe;
+ return return_char;
+ break;
+ }
}
ch_i++;
@@ -116,6 +134,10 @@ CMD **lsh_split_command(char *line)
tokens[position] = malloce(sizeof(CMD));
tokens[position]->cmd = token;
tokens[position]->type = cmd_type;
+ tokens[position]->stdInFd = 0;
+ tokens[position]->next = NULL;
+ if(position>0) tokens[position-1]->next = tokens[position];
+
position++;
if (position * bufsize >= bufsize) {
@@ -133,17 +155,33 @@ CMD **lsh_split_command(char *line)
return tokens;
}
-int lsh_launch(char **args)
+int lsh_launch(char **args, CMD *cmd)
{
pid_t pid, wpid;
int status;
+ int stdOutPipe[2];
+ pipe(stdOutPipe);
+ if(cmd->type==Pipe){
+ cmd->next->stdInFd=stdOutPipe[0];
+ }
pid = fork();
if (pid == 0) {
// Child process
- if (execvp(args[0], args) == -1) {
- perror("lsh");
+ if(cmd->type!=Stdout){
+ close(stdOutPipe[0]); // close reading end in the child
+
+ dup2(stdOutPipe[1], 1); // send stdout to the pipe
+ dup2(stdOutPipe[1], 2); // send stderr to the pipe
+
+ close(stdOutPipe[1]); // this descriptor is no longer needed
}
+
+ if(cmd->stdInFd!=0)
+ dup2(cmd->stdInFd,STDIN_FILENO);
+
+ if (execvp(args[0], args) == -1) perror("lsh");
+
exit(EXIT_FAILURE);
} else if (pid < 0) {
// Error forking
@@ -153,6 +191,9 @@ int lsh_launch(char **args)
do {
wpid = waitpid(pid, &status, WUNTRACED);
} while (!WIFEXITED(status) && !WIFSIGNALED(status));
+
+ close(stdOutPipe[1]); // close the write end of the pipe in the parent
+ if(cmd->stdInFd!=0) close(cmd->stdInFd);
}
return 1;
diff --git a/src/main.c b/src/main.c
index ef42a50..9dbf65c 100755
--- a/src/main.c
+++ b/src/main.c
@@ -26,8 +26,7 @@ void lsh_loop(SHELL_OB *shell_obj){
int j=0;
while (cmds[j]){
args = lsh_split_line(cmds[j]->cmd);
- status = lsh_execute(args);
- free(cmds[j]);
+ status = lsh_execute(args,cmds[j]);
j++;
int i=0;
@@ -36,6 +35,11 @@ void lsh_loop(SHELL_OB *shell_obj){
free(args);
}
+ int i=0;
+ while(cmds[i]){
+ free(cmds[i]);
+ i++;
+ }
free(cmds);
free(line);
} while (status);
diff --git a/src/main.h b/src/main.h
index 2b8505b..aaaea13 100644
--- a/src/main.h
+++ b/src/main.h
@@ -10,14 +10,16 @@ typedef enum{
Stdout=0,
Redirect=1,
Pipe=2,
- If=3,
- Continue=4
+ Continue=3,
+ If=4,
} cmd_t;
-typedef struct{
+typedef struct CMD{
char *cmd;
cmd_t type;
- char *Stdout;
+ int stdInFd;
+ struct CMD *next;
+ int status;
} CMD;
#endif