aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoriceyrazor <iceyrazor@mailfence.com>2026-02-28 23:49:02 -0600
committericeyrazor <iceyrazor@mailfence.com>2026-02-28 23:49:02 -0600
commit1b8967ea87c63342f03c340d44a084ea7f62cae9 (patch)
tree06b7998b94fe9b05115d59c2a584339af8943445
parentbecbecb016f16c2dea64aacd7077973f45ed0517 (diff)
command typing
now can chain commands with just ;
-rw-r--r--README.md4
-rw-r--r--src/lsh_main_func.c133
-rw-r--r--src/lsh_split_line.c181
-rwxr-xr-xsrc/main.c31
-rw-r--r--src/main.h23
5 files changed, 252 insertions, 120 deletions
diff --git a/README.md b/README.md
index 0bd1473..7ffc1ad 100644
--- a/README.md
+++ b/README.md
@@ -25,11 +25,11 @@ Going to try and make it mostly POSIX compliant.
- [ ] prompt uses PS1
- [ ] pipes |
- [ ] &&
- - [ ] ;
+ - [x] ;
- [ ] vi mode
- [ ] redirections > <
- [ ] append >>
- - [ ] heredoc
+ - [ ] heredoc <<
- [ ] &
- [ ] rcfile
- [ ] rcfile in config dir
diff --git a/src/lsh_main_func.c b/src/lsh_main_func.c
index 5f46183..1604073 100644
--- a/src/lsh_main_func.c
+++ b/src/lsh_main_func.c
@@ -8,6 +8,7 @@
#include <unistd.h>
#include <stdbool.h>
+#include "main.h"
#include "helper_functions.c"
#define LSH_RL_BUFSIZE 1024
@@ -43,74 +44,8 @@ char *lsh_read_line(void)
}
}
-char *handle_vars(char *token){
- char *ret_token=(char*)malloce(sizeof(char)*strlen(token)+1);
- strcpy(ret_token,token);
-
- if (token[0]=='~'){
- token++;
- if(!getenv("HOME")){
- fprintf(stderr,"lsh: you aint got no home. da hell\n");
- free(ret_token);
- ret_token=(char*)malloce(sizeof(char)*strlen(token)+1);
- strcpy(ret_token,token);
- return ret_token;
- }
- free(ret_token);
- ret_token=(char*)malloce(sizeof(char)*strlen(token)+strlen(getenv("HOME"))+1);
- strcpy(ret_token,getenv("HOME"));
- strcat(ret_token,token);
- }
-
- char *tmp_token=(char*)malloce(sizeof(char)*strlen(ret_token)+1);
- strcpy(tmp_token,ret_token);
- int i=0;
- while (tmp_token[i]!='\0'){
- if(tmp_token[i]=='$'){
- char sep[2]=" \0";
- int j=0; while(tmp_token[i+j]){
- j++;
- if(tmp_token[i+j]==' ') break;
- if(tmp_token[i+j]=='$'){
- sep[0]='$';
- break;
- }
- }
-
- char *varname=(char*)malloce(sizeof(char)*j+1);
- varname[j]='\0';
- strncpy(varname,&tmp_token[i+1],j);
- varname[j-1]='\0';
-
- char *env = getenv(varname);
- if(!env) env="";
-
- free(ret_token);
- int tmp_len=strlen(tmp_token);
- ret_token=(char*)malloce(sizeof(char)*(strlen(tmp_token)-strlen(varname))+strlen(env)+1);
- tmp_token[i]='\0';
- tmp_token[i+j]='\0';
-
- strcpy(ret_token,tmp_token);
- strcat(ret_token,env);
- strcat(ret_token,sep);
- if(i+j+1 < tmp_len){
- strcat(ret_token,&tmp_token[i+j+1]);
- }
-
- free(tmp_token);
- tmp_token=(char*)malloce(sizeof(char)*strlen(ret_token)+1);
- strcpy(tmp_token,ret_token);
-
- free(varname);
- }
- i++;
- }
- free(tmp_token);
- return ret_token;
-}
-
-char * strtok_quotes(char *token){
+char * strtok_cmd(char *token, cmd_t *type){
+ *type=Stdout;
static char* parse_args_last_p;
if(token != NULL){
parse_args_last_p=token;
@@ -137,43 +72,31 @@ char * strtok_quotes(char *token){
in_quote=parse_args_last_p[ch_i];
if (parse_args_last_p[ch_i+1] == '\0')
break;
- if(ch_i==0){
- parse_args_last_p[0]='\0';
- parse_args_last_p=&parse_args_last_p[1];
- return_char=&return_char[1];
- } else {
- pop(return_char,ch_i);
- }
ch_i++;
}
}
- if(in_quote!=' '){
+ if (in_quote!=' '){
if (parse_args_last_p[ch_i]==in_quote){
bool pass_check=true;
if(ch_i>0 && parse_args_last_p[ch_i-1]=='\\')
pass_check=false;
- if(pass_check==true){
+ if (pass_check)
in_quote=' ';
- if(parse_args_last_p[ch_i+1]=='\0'){
- parse_args_last_p[ch_i]='\0';
- } else if(parse_args_last_p[ch_i+1]==' '){
- parse_args_last_p[ch_i]='\0';
- parse_args_last_p = &parse_args_last_p[ch_i+2];
- pop(return_char,ch_i);
- return return_char;
- }
- pop(return_char,ch_i);
- }
- }
- } else {
- if (parse_args_last_p[ch_i] == ' '){
- parse_args_last_p[ch_i] = '\0';
- parse_args_last_p = &parse_args_last_p[ch_i+1];
- return return_char;
}
+ } 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;
}
+
ch_i++;
}
parse_args_last_p=NULL;
@@ -181,30 +104,30 @@ char * strtok_quotes(char *token){
return return_char;
}
-#define LSH_TOK_BUFSIZE 64
-char **lsh_split_line(char *line)
+CMD **lsh_split_command(char *line)
{
- int bufsize = LSH_TOK_BUFSIZE, position = 0;
- char **tokens = malloce(bufsize * sizeof(char*));
+ int bufsize = sizeof(CMD*), position = 0;
+ CMD **tokens = malloce(bufsize);
char *token;
+ cmd_t cmd_type;
- token = strtok_quotes(line);
+ token = strtok_cmd(line,&cmd_type);
while (token != NULL) {
- token = handle_vars(token);
- tokens[position] = token;
+ tokens[position] = malloce(sizeof(CMD));
+ tokens[position]->cmd = token;
+ tokens[position]->type = cmd_type;
position++;
-
- if (position >= bufsize) {
- bufsize += LSH_TOK_BUFSIZE;
- tokens = realloc(tokens, bufsize * sizeof(char*));
+ if (position * bufsize >= bufsize) {
+ bufsize += sizeof(CMD*);
+ tokens = realloc(tokens, bufsize);
if (!tokens) {
fprintf(stderr, "lsh: allocation error\n");
exit(EXIT_FAILURE);
}
}
- token = strtok_quotes(NULL);
+ token = strtok_cmd(NULL,&cmd_type);
}
tokens[position] = NULL;
return tokens;
diff --git a/src/lsh_split_line.c b/src/lsh_split_line.c
new file mode 100644
index 0000000..ff4f644
--- /dev/null
+++ b/src/lsh_split_line.c
@@ -0,0 +1,181 @@
+#ifndef split_line
+#define split_line
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include <stdbool.h>
+
+#include "helper_functions.c"
+
+char *handle_vars(char *token){
+ char *ret_token=(char*)malloce(sizeof(char)*strlen(token)+1);
+ strcpy(ret_token,token);
+
+ if (token[0]=='~'){
+ token++;
+ if(!getenv("HOME")){
+ fprintf(stderr,"lsh: you aint got no home. da hell\n");
+ free(ret_token);
+ ret_token=(char*)malloce(sizeof(char)*strlen(token)+1);
+ strcpy(ret_token,token);
+ return ret_token;
+ }
+ free(ret_token);
+ ret_token=(char*)malloce(sizeof(char)*strlen(token)+strlen(getenv("HOME"))+1);
+ strcpy(ret_token,getenv("HOME"));
+ strcat(ret_token,token);
+ }
+
+ char *tmp_token=(char*)malloce(sizeof(char)*strlen(ret_token)+1);
+ strcpy(tmp_token,ret_token);
+ int i=0;
+ while (tmp_token[i]!='\0'){
+ if(tmp_token[i]=='$'){
+ char sep[2]=" \0";
+ int j=0; while(tmp_token[i+j]){
+ j++;
+ if(tmp_token[i+j]==' ') break;
+ if(tmp_token[i+j]=='$'){
+ sep[0]='$';
+ break;
+ }
+ }
+
+ char *varname=(char*)malloce(sizeof(char)*j+1);
+ varname[j]='\0';
+ strncpy(varname,&tmp_token[i+1],j);
+ varname[j-1]='\0';
+
+ char *env = getenv(varname);
+ if(!env) env="";
+
+ free(ret_token);
+ int tmp_len=strlen(tmp_token);
+ ret_token=(char*)malloce(sizeof(char)*(strlen(tmp_token)-strlen(varname))+strlen(env)+1);
+ tmp_token[i]='\0';
+ tmp_token[i+j]='\0';
+
+ strcpy(ret_token,tmp_token);
+ strcat(ret_token,env);
+ strcat(ret_token,sep);
+ if(i+j+1 < tmp_len){
+ strcat(ret_token,&tmp_token[i+j+1]);
+ }
+
+ free(tmp_token);
+ tmp_token=(char*)malloce(sizeof(char)*strlen(ret_token)+1);
+ strcpy(tmp_token,ret_token);
+
+ free(varname);
+ }
+ i++;
+ }
+ free(tmp_token);
+ return ret_token;
+}
+
+char * strtok_quotes(char *token){
+ static char* parse_args_last_p;
+ if(token != NULL){
+ parse_args_last_p=token;
+ }
+ if(parse_args_last_p==NULL){
+ return NULL;
+ }
+
+ char *return_char=parse_args_last_p;
+ char in_quote=' ';
+
+ if(parse_args_last_p != NULL){
+ int ch_i=0;
+ while(1){
+ if (parse_args_last_p[ch_i] == '\0')
+ break;
+
+ if (in_quote==' ' && (parse_args_last_p[ch_i]=='"' || parse_args_last_p[ch_i]=='\'')){
+ bool pass_check=true;
+ if(ch_i>0 && parse_args_last_p[ch_i-1]=='\\')
+ pass_check=false;
+
+ if(pass_check==true){
+ in_quote=parse_args_last_p[ch_i];
+ if (parse_args_last_p[ch_i+1] == '\0')
+ break;
+ if(ch_i==0){
+ parse_args_last_p[0]='\0';
+ parse_args_last_p=&parse_args_last_p[1];
+ return_char=&return_char[1];
+ } else {
+ pop(return_char,ch_i);
+ }
+ ch_i++;
+ }
+ }
+
+ if(in_quote!=' '){
+ if (parse_args_last_p[ch_i]==in_quote){
+ bool pass_check=true;
+ if(ch_i>0 && parse_args_last_p[ch_i-1]=='\\')
+ pass_check=false;
+
+ if(pass_check==true){
+ in_quote=' ';
+ if(parse_args_last_p[ch_i+1]=='\0'){
+ parse_args_last_p[ch_i]='\0';
+ } else if(parse_args_last_p[ch_i+1]==' '){
+ parse_args_last_p[ch_i]='\0';
+ parse_args_last_p = &parse_args_last_p[ch_i+2];
+ pop(return_char,ch_i);
+ return return_char;
+ }
+ pop(return_char,ch_i);
+ }
+ }
+ } else {
+ if (parse_args_last_p[ch_i] == ' '){
+ parse_args_last_p[ch_i] = '\0';
+ parse_args_last_p = &parse_args_last_p[ch_i+1];
+ return return_char;
+ }
+ }
+ ch_i++;
+ }
+ parse_args_last_p=NULL;
+ }
+ return return_char;
+}
+
+#define LSH_TOK_BUFSIZE 64
+char **lsh_split_line(char *line)
+{
+ int bufsize = LSH_TOK_BUFSIZE, position = 0;
+ char **tokens = malloce(bufsize * sizeof(char*));
+ char *token;
+
+ token = strtok_quotes(line);
+ while (token != NULL) {
+ token = handle_vars(token);
+ tokens[position] = token;
+ position++;
+
+
+ if (position >= bufsize) {
+ bufsize += LSH_TOK_BUFSIZE;
+ tokens = realloc(tokens, bufsize * sizeof(char*));
+ if (!tokens) {
+ fprintf(stderr, "lsh: allocation error\n");
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ token = strtok_quotes(NULL);
+ }
+ tokens[position] = NULL;
+ return tokens;
+}
+
+#endif
+
diff --git a/src/main.c b/src/main.c
index 3b2db6e..ef42a50 100755
--- a/src/main.c
+++ b/src/main.c
@@ -2,19 +2,16 @@
#include <stdlib.h>
#include <unistd.h>
+#include "main.h"
#include "helper_functions.c"
#include "lsh_main_func.c"
+#include "lsh_split_line.c"
#include "lsh_builtins.c"
-typedef struct{
- char *prompt;
- char *pre_prompt;
-} SHELL_OB;
-
-void lsh_loop(SHELL_OB *shell_obj)
-{
+void lsh_loop(SHELL_OB *shell_obj){
char *line;
char **args;
+ CMD **cmds;
int status;
do {
@@ -25,14 +22,22 @@ void lsh_loop(SHELL_OB *shell_obj)
free(pwd);
printf("%s",shell_obj->prompt);
line = lsh_read_line();
- args = lsh_split_line(line);
- status = lsh_execute(args);
+ cmds = lsh_split_command(line);
+ int j=0;
+ while (cmds[j]){
+ args = lsh_split_line(cmds[j]->cmd);
+ status = lsh_execute(args);
+ free(cmds[j]);
+ j++;
+
+ int i=0;
+ while (args[i])
+ free(args[i++]);
+ free(args);
+ }
+ free(cmds);
free(line);
- int i=0;
- while (args[i])
- free(args[i++]);
- free(args);
} while (status);
}
diff --git a/src/main.h b/src/main.h
new file mode 100644
index 0000000..2b8505b
--- /dev/null
+++ b/src/main.h
@@ -0,0 +1,23 @@
+#ifndef mainh
+#define mainh
+
+typedef struct{
+ char *prompt;
+ char *pre_prompt;
+} SHELL_OB;
+
+typedef enum{
+ Stdout=0,
+ Redirect=1,
+ Pipe=2,
+ If=3,
+ Continue=4
+} cmd_t;
+
+typedef struct{
+ char *cmd;
+ cmd_t type;
+ char *Stdout;
+} CMD;
+
+#endif