diff --git a/2-str_concat.c b/2-str_concat.c
new file mode 100644
index 0000000..3efa485
--- /dev/null
+++ b/2-str_concat.c
@@ -0,0 +1,49 @@
+#include "simpleshell.h"
+/**
+ * str_concat - concatenates two strings
+ * @s1: string one
+ * @s2: string two
+ * Return: ptr
+ */
+char *str_concat(char *s1, char *s2)
+{
+ /* declare your variables */
+ int len1 = 0, len2 = 0, count = 0, begs = 0;
+ char *cat;
+
+ /* check for empty strings */
+ if (s1 == NULL)
+ s1 = "";
+ if (s2 == NULL)
+ s2 = "";
+
+ /* find length of strings */
+ while (s1[len1] != '\0')
+ len1++;
+ while (s2[len2] != '\0')
+ len2++;
+
+ begs = len1 + len2 + 1;
+ /* allocate memory for concatenated string */
+ cat = malloc(begs * sizeof(char));
+ /* malloc fail safe */
+ if (cat == NULL)
+ return (NULL);
+
+ len2 = 0;
+
+ /* duplicate s1 to cat */
+ while (count < begs)
+ {
+ if (count < len1)
+ cat[count] = s1[count];
+ else
+ {
+ cat[count] = s2[len2];
+ len2++;
+ }
+ count++;
+ }
+ cat[count] = '\0';
+ return (cat);
+}
diff --git a/3-strcmp.c b/3-strcmp.c
new file mode 100644
index 0000000..9e59d20
--- /dev/null
+++ b/3-strcmp.c
@@ -0,0 +1,21 @@
+#include "simpleshell.h"
+
+/**
+ *_strcmp - shows the pointer of the var
+ *@s2: var for p
+ *@s1: p
+ *Return: equal
+ */
+
+int _strcmp(char *s1, char *s2)
+{
+ int i = 0;
+ int equal = 0;
+
+ for (i = 0; (*(s1 + i) || *(s2 + i)) && !equal; i++)
+ {
+ if (*(s1 + i) != *(s2 + i))
+ equal = *(s1 + i) - *(s2 + i);
+ }
+ return (equal);
+}
diff --git a/README.md b/README.md
index d980af8..827ca43 100644
--- a/README.md
+++ b/README.md
@@ -1 +1,106 @@
-# simple_shell
+
+
+# Shell Project `(simple Shell)`
+
+By Marcelo R-M, and Flavio
+
+** This project is our implementation of a simple shell. **
+
+## Topics:
+
+- ### How the shell works?
+
+ 1. ** The shell prompts for user input **
+
+ Using the `write()` function to display (stdout(1)) `$ `
+
+ 2. Get user input.
+
+ Using the `char *user_input(void);` function, which uses `getline()`function to get and store user input into a buffer, which getline mallocs for, if getline succeds, the function returns the buffer that holds the user input.
+
+ 3. Parse the input.
+
+ Using the `char **tokens(char *buffer);` function, tokanizes the user input and saves each token into a double pointer erray(**hold_tokens). The double pointer erray is then returned.
+
+ 4. Run the command.
+
+ 1. Using the `int _execute(char **args);` function, checks if the user input is a builtin or not(this is called a filler). For example if the command `exit` is the user input. the function will make sure the command is in the array list of builtin commands."exit" or "env".
+
+ 2. If it's not then then the `int run(char **args);` function is returned.
+
+ 3. Using the `int run(char **args);` function, creates a child Proccess, In the child process we check if the user input is a path command (`/bin/ls`) or a regular command (`ls`). If it is a regular command (`ls`) we tokanize the path variable whos value is equall to PATH env variable, and cp = strcat("/", ls); = `/ls`, we then append `cp` to every path's token deliminated by `:`. This is saved into a variable called new. And then using `access` we check if the `new` variable is correct(`ls` is in the dir) or if we can execute `ls`. If so then `execve` the new varible. But if the user input is is a path then we skip all the above steps and just assigned the path to `execve`. AND finally if neither is true then `perror`.(print error).
+
+ 5. Starts again at number 1 until terminated(exit, or with kill signals).
+
+- ### The PATH(env var)
+
+ ** PATH ** is an environmental ** variable in Linux ** and other Unix-like operating systems that tells the shell which directories to search for executable files. Understanding the path, is really important to buiding a shell. Its important to know how to access the PATH (working with environmental variables).
+
+
+
+- ### Builtins
+
+ A builtin command is a Linux/Unix command which is "* built into a shell interpreter * such as sh, ksh, bash, etc.
+
+
+
+ ```c
+ #include "simpleshell.h"
+
+ /**
+ * main - main shell function, where the magic happens
+ * takes in no arg
+ * Return: return (0) on success
+ */
+
+ int main(void)
+ {
+ /* the dollar :)*/
+ char *prompt = "$ ";
+
+ char *buffer;
+ char **cmd;
+
+ while (1)
+ {
+ write(1, prompt, (sizeof(char) * 2));
+ buffer = user_input();
+ cmd = tokens(buffer);
+ _execute(cmd);
+
+ /* free(buffer);*/
+ /* free(cmd);*/
+ }
+ }
+ ```
+
+
+
+
+
+| Function `(name)` | File `(name)` |
+| ------------------------------------------------------------ | ------------------------------------------------------------ |
+| `char *user_input(void);` | [user_input.c](https://github.com/fvesp18/simple_shell/blob/master/user_input.c) |
+| `char **tokens(char *buffer);` | [tokens.c](https://github.com/fvesp18/simple_shell/blob/master/tokens.c) |
+| `int main(void);` | [shell_main.c](https://github.com/fvesp18/simple_shell/blob/master/shell_main.c) |
+| `char *_getenv(char *var_name);` | [shell_getenv.c](https://github.com/fvesp18/simple_shell/blob/master/shell_getenv.c) |
+| `int run(char **args);` | [run.c](https://github.com/fvesp18/simple_shell/blob/master/run.c) |
+| `void *_realloc(void *ptr, size_t old_size, size_t new_size);` | [100-realloc.c](https://github.com/fvesp18/simple_shell/blob/master/100-realloc.c) |
+| `int _execute(char **args);`
`int _exit(char **argv)` | [execute.c](https://github.com/fvesp18/simple_shell/blob/master/execute.c) |
+| ** String functions **
`int _strlen(char *s);`
`char *_strchr(char *s, char c);`
`char *_strcat(char *dest, char *src);`
`int _strcmp(char *s1, char *s2);`
`char *str_concat(char *s1, char *s2);` |
[_strlen.c](https://github.com/fvesp18/simple_shell/blob/master/_strlen.c)
[_strchr.c](https://github.com/fvesp18/simple_shell/blob/master/_strchr.c)
[_strcat.c](https://github.com/fvesp18/simple_shell/blob/master/_strcat.c)
[_strcmp.c](https://github.com/fvesp18/simple_shell/blob/master/3-strcmp.c)
[2-str_concat.c](https://github.com/fvesp18/simple_shell/blob/master/2-str_concat.c) |
+| `man_1_simple_shell` | [man_1_simple_shell](https://github.com/fvesp18/simple_shell/blob/master/man_1_simple_shell) |
+
+
+
+## what works:
+
+- PATH being passed as a command ex.(`/bin/ls`).
+- single commands ex.(`ls`)
+- muiltiple commands : parsed user input : (`ls -l`)
+
+## Bugs:
+
+- Exit - doesn't work first time it's typed in.
+- exit and env don't work togther, either or works.(only one can be typed in at the time the shell is running)
+- memory leak
+- Etc...
diff --git a/_strcat.c b/_strcat.c
new file mode 100644
index 0000000..d501c0f
--- /dev/null
+++ b/_strcat.c
@@ -0,0 +1,22 @@
+#include "simpleshell.h"
+/**
+ * _strcat - will concatenate two strings
+ * @dest: destination string
+ * @src: src string
+ * Return: 0
+ */
+char *_strcat(char *dest, char *src)
+{
+ int srci = 0;
+ int countdest = _strlen(dest);
+
+ while (src[srci] != '\0')
+ {
+ dest[countdest + srci] = src[srci];
+ srci++;
+ }
+
+ dest[countdest + srci] = '\0';
+
+ return (dest);
+}
diff --git a/_strchr.c b/_strchr.c
new file mode 100644
index 0000000..d1da3cc
--- /dev/null
+++ b/_strchr.c
@@ -0,0 +1,18 @@
+#include "simpleshell.h"
+
+/**
+ **_strchr - finds and return char
+ *@s: pointer
+ *@c: int var
+ *Return: (s)
+ */
+
+char *_strchr(char *s, char c)
+{
+ while (*s++)
+ {
+ if (*s == c)
+ return (s);
+ }
+ return (0);
+}
diff --git a/_strlen.c b/_strlen.c
new file mode 100644
index 0000000..4acd443
--- /dev/null
+++ b/_strlen.c
@@ -0,0 +1,18 @@
+#include "simpleshell.h"
+/**
+ * _strlen - print length of string
+ * @s: string
+ * Return: void
+ */
+int _strlen(char *s)
+{
+ int count = 0;
+
+ while (s[count] != '\0')
+ {
+
+ count++;
+
+ }
+ return (count);
+}
diff --git a/builtin_func.c b/builtin_func.c
deleted file mode 100644
index 9aecaf6..0000000
--- a/builtin_func.c
+++ /dev/null
@@ -1,30 +0,0 @@
-#include "simpleshell.h"
-
-
-/**
-* my_exit - exit func implementation
-* @n: num to exit
-* Return: exit
-*
-*/
-
-int my_exit(int n)
-{
- return (n);
-}
-
-/**
-* my_cd - change directory
-* @args: what dir to change to
-* Return: 1
-*/
-
-int my_cd(char **args)
-{
- if (args[1] == NULL)
- perror("No dir to cd to");
- else
- chdir(args[1]);
-
- return (1);
-}
diff --git a/execute.c b/execute.c
index a214e9f..746e1d0 100644
--- a/execute.c
+++ b/execute.c
@@ -1,13 +1,67 @@
#include "simpleshell.h"
/**
-* Work on forking - fork(), wait(), exexve()
-*
-*
-*
+ * _printenv - prints environmental variables
+ * Return: (N/A)
+ */
+
+void _printenv(void)
+{
+ int i;
+
+ for (i = 0; environ[i] != NULL; i++)
+ {
+ write(1, environ[i], _strlen(environ[i]));
+ write(1, "\n", (sizeof(char) * 2));
+ }
+
+}
+
+/**
+* shell_exit - exits the shell
+* @argv: user input
+* Return: exit (EXIT_SUCCESS)
*/
-int execute()
+int shell_exit(char **argv)
+{
+ free(argv);
+ exit(EXIT_SUCCESS);
+}
+
+/**
+ * _execute - filters if builtin or not
+ * @args: user input
+ * Return: run(cmd)
+ */
+
+int _execute(char **args)
{
+ int type;
+ char *cmd[4] = {"", "env", "exit", NULL};
+ type = 0;
+ if (args[type] == NULL)
+ return (1);
+ /* filter */
+ while (cmd[type] != NULL)
+ {
+ if (_strcmp(cmd[type], args[0]) == 0)
+ break;
+ type++;
+ }
+ /* call to cmds */
+ switch (type)
+ {
+ case (1):
+ _printenv();
+ break;
+ case (2):
+ shell_exit(args);
+ break;
+ default:
+ run(args);
+ break;
+ }
+ return (type);
}
diff --git a/get_line.c b/get_line.c
deleted file mode 100644
index ab1aeb9..0000000
--- a/get_line.c
+++ /dev/null
@@ -1,48 +0,0 @@
-#include "simpleshell.h"
-
-/**
-* _getline - getline func implimentation
-* @buff: buffer to hold the input
-* @size: size of buffer
-* Return: the size of chars read
-*
-*/
-
-ssize_t _getline(char **buff)
-{
- if (buff == NULL)
- return (-1);
-
- /* buffer to realloc */
- /* char **buff_realloc; */
- /* size of buffer (buff) */
- size_t buff_size = 4096;
- /* the number of bytes read is returned */
- ssize_t read_size;
- /* malloc for buffer */
- *buff = malloc(buff_size);
- /* check if malloc was successful */
- /*if (buff == NULL)
- {
- perror("failed to malloc");
- return (-1);
- }*/
- read_size = read(0, *buff, buff_size);
- /* check for read */
- if (read_size == -1)
- {
- perror("read failed");
- return (-1);
- }
- /* realloc in case we need more momory */
- /*if ((read_size + 1) < buff_size)
- {
- *buff_realloc = _realloc(*buff, *size, buff_size);
- if (buff_realloc == NULL)
- return (-1);
- *buff = *buff_realloc;
- *size = buff_size;
- }*/
-
- return (read_size);
-}
diff --git a/hsh b/hsh
new file mode 100755
index 0000000..b6e6001
Binary files /dev/null and b/hsh differ
diff --git a/man_1_simple_shell b/man_1_simple_shell
new file mode 100644
index 0000000..b3d72b3
--- /dev/null
+++ b/man_1_simple_shell
@@ -0,0 +1,146 @@
+.TH HSH 1 "Version 1.0" "26 NOV 2019 "General Commands Manual"
+.SH NAME
+ .hsh - simple shell implementation
+.SH SYNOPSIS
+.br
+.RS
+.B .hsh
+.I FORMAT [ARGUMENT]...
+.br
+.B .hsh
+.I OPTIONS
+.RE
+.SH DESCRIPTION
+The simple shell is a program that alongside the terminal facilitates the interaction between the operating system and the keyboard (user input). It works like a command line interface, including certain commands to help navigate files and directory as well as take care of processes underneath the hood.
+.SH OPTIONS
+There are currently no implementations for options for the shell. However, the .sh program takes the following options
+.PP
+.B -i
+.RS
+interactive mode
+.RE
+.PP
+.B -l
+.RS
+non-interactive mode
+.RE
+.PP
+.B -r
+.RS
+restricted mode
+.RE
+.SH INVOCATION
+.PP
+These modes define different environments for the shell. For example, in interactive mode, the prompt will always display and return as well as handle errors. The non-interactive mode, however, can be toggled to achieve a process and exit immediately upon the processes completion. Lastly, the restricted more offers the prompt though only takes a smaller scope of arguments
+.SH ARGUMENTS
+.PP
+In order for the shell to execute commands, the prompt must only be one command long. The shell can take arguements containing the PATH to the command's file. If the PATH isn't given, the shell will find it. Otherwise, if the command's file isn't found in the path, then the shell will search for builtin a.k.a. external function files. Upon discovery, it executes, returns and displays the prompt.
+.PP
+.br
+.B SYNTAX:
+$options -arguments
+.br
+.B EXAMPLE:
+$ls -l
+.br
+or
+.br
+.B EXAMPLE:
+$pwd
+.SH DEFINITIONS
+.PP
+.B end of file (EOF)
+- signals to the shell that the file is done reading
+.PP
+.B exit status
+- signals to the operating system upon command execution
+.PP
+.B process id (pid)
+- a unique identification given to processes occuring in the shell
+.PP
+.B prompt ($) -
+the character at the beginning of the command line which indicates it can take in user input
+.PP
+.B signal
+- works with wait, waitpid to execute a variety of different handling
+.RE
+.PP
+.SH ENVIRONMENTAL VARIABLES
+.PP
+.B env
+- a warehouse for all possible function files
+.PP
+.B pwd
+- a variable containing all the current working directory
+.PP
+.B PATH
+- a string containing all paths to functions files, delimited by colons (:)
+.PP
+.SH FUNCTIONS
+.PP
+.B exit
+- function that terminates shell
+.PP
+.B getline
+- function that get user input
+.PP
+.B strtok
+- function that tokenizes a string by specified delimiter; destroys/ alters original string
+.PP
+.SH GLOBAL VARIABLES
+.PP
+.B environ
+- a variable containing an array with all environment variables; works to get env
+.PP
+.SH COMMANDS
+.PP
+.B cd
+- toggles between directories
+.PP
+.B env
+- displays all the environmental variables
+.PP
+.B ls
+- displays the contents of the current working directory
+.PP
+.SH SPECIAL VARIABLES
+.PP
+.B $?
+- contains return value of last executed process
+.PP
+.B $$
+- contains the process identification of the ongoing process
+.PP
+.B $#
+- contains the number of arguments typed into the command line
+.PP
+.B $*
+- contains list of args in the ongoing process
+.SH SYSCALLS
+.PP
+.B execve
+- ends last process to execute specified process; needs PATH to command file
+.PP
+.B fork
+- creates a parallel process to that of the current process called the child process.
+.PP
+.B getpid
+- attains the process identification number of a child process
+.PP
+.B getppid
+- attains the process identification number of a parent process
+.PP
+.B read
+- takes a file descriptor from the kernel and read said file
+.PP
+.B signal
+- sends signal to wait, waitpid to inform the process of something
+.PP
+.B wait
+- waits for a child to fully execute
+.SH SEE ALSO
+.I pwd(1), cd(1), echo(1), exit(1), execve(2), exit(3), fork(3), signal(3), wait(2), waitpid(2)
+.SH BUGS
+Some issues may arise when trying to use the env. The user can toggle between being able to use env or exit depending on where the switch case breaks, which determines whether to go into exit or env. Sometimes it grabs the PATH to env from the main terminal, however, no implementation has been introduced.
+.SH AUTHORS
+Flavio Espinoza and Marcelo Martins
diff --git a/run.c b/run.c
index 86d70c8..8f4376f 100644
--- a/run.c
+++ b/run.c
@@ -7,75 +7,39 @@
*
*/
-extern char** environ;
-
int run(char **args)
{
- int status;
pid_t pid;
- pid_t wait_for_child;
- int i;
- /*char *buffer = tokens(args);*/
+ int status;
char *buffer = _getenv("PATH");
char *path = malloc(sizeof(char) * 1024);
char *cp = malloc(sizeof(char) * 1024);
char *new = malloc(sizeof(char) * 1024);
- /* creating a child processes */
- printf("args -> %s\n", *args);
- printf("buffer -> %s\n", buffer);
pid = fork();
if (pid == 0)
{
path = strtok(buffer, ":");
- printf("path -> %s\n", path);
- printf("%s\n", "forking");
- /*cp = strcat(*args, "/");
- printf("cp -> %s <- the slash\n", cp);*/
+ cp = str_concat("/", *args);
while (path)
{
- cp = strcat("/", *args);
- printf("cp -> %s <- the slash\n", cp);
- printf("%s\n", "we in the while loop :)");
- new = strcat(path, cp);
- printf("new -> %s\n", new);
+ if (_strchr(*args, '/') != NULL)
+ execve(*args, args, environ);
- if (access(new, (R_OK | X_OK)) == 0)
+ new = str_concat(path, cp);
+ if ((access(new, X_OK | R_OK)) == 0)
{
- printf("%s\n", "exec");
execve(new, args, environ);
+ break;
}
path = strtok(NULL, ":");
- i++;
- printf("the loop runs %d times!", i);
}
+ free(args);
}
- else
- {
- printf("%s\n", "we in the parent process :)");
- wait_for_child = waitpid(pid, &status, 0);
- }
-
+ waitpid(pid, &status, 0);
+ free(path);
+ free(cp);
+ free(new);
return (1);
}
-
-/**
-* execute - function to execute the run commands and builtins
-* @args: arguments
-* Return: run function
-*
-*/
-
-/*int execute(char **args)
-{
- return (run(args));
-}
-*/
-/*int main(char **args)
-{
- printf("$ \n");
-
- return (run(args));
-
-}*/
diff --git a/shell_getenv.c b/shell_getenv.c
index 24c75cd..1f080a6 100644
--- a/shell_getenv.c
+++ b/shell_getenv.c
@@ -6,9 +6,6 @@
* Return: char*
*
*/
-
-extern char** environ;
-
char *_getenv(char *var_name)
{
char **env;
@@ -24,11 +21,10 @@ char *_getenv(char *var_name)
break;
}
}
- if ((*char_p == '='))
+ if (*char_p == '=')
{
return (char_p + 1);
}
}
return (NULL);
}
-
diff --git a/shell_main.c b/shell_main.c
index 42c0b6f..954c15f 100644
--- a/shell_main.c
+++ b/shell_main.c
@@ -5,26 +5,21 @@
* takes in no arg
* Return: return (0) on success
*/
-
-void main(void)
+int main(void)
{
- /* the dollar :)*/
char *prompt = "$ ";
-
char *buffer;
char **cmd;
- int i = 0;
while (1)
{
write(1, prompt, (sizeof(char) * 2));
buffer = user_input();
- printf("buffer -> %s\n", buffer);
cmd = tokens(buffer);
- printf("cmd -> %s\n", *cmd);
- run(cmd);
+ _execute(cmd);
free(buffer);
free(cmd);
}
+ return (1);
}
diff --git a/simpleshell.h b/simpleshell.h
index 5cdb765..a479b54 100644
--- a/simpleshell.h
+++ b/simpleshell.h
@@ -1,14 +1,18 @@
#ifndef SIMPLESHELL_H
#define SIMPLESHELL_H
-
#include
#include
#include
#include
#include
#include
-/* environ declearation */
+/* environ declaration */
+extern char **environ;
+void shell_env(char **args);
+int shell_exit(char **argv);
+char *_strchr(char *s, char c);
+int _execute(char **args);
int n_strlen(char *str);
char *n_strtoke(char *str, const char *delim);
char *_strcpy(char *dest, char *src);
@@ -23,5 +27,6 @@ char *_getenv(char *var_name);
char *_strcat(char *dest, char *src);
int _strlen(char *s);
int _strcmp(char *s1, char *s2);
+char *str_concat(char *s1, char *s2);
#endif
diff --git a/tokens.c b/tokens.c
index c17ac64..d0dab30 100644
--- a/tokens.c
+++ b/tokens.c
@@ -1,51 +1,24 @@
#include "simpleshell.h"
-
/**
* tokens - puts tokens in an array
* @buffer: the line read from input
* Return: tokens
*/
-
char **tokens(char *buffer)
{
int buffer_size = 1024;
char **hold_tokens;
- char *token;
- int i;
+ int i = 0;
- hold_tokens = malloc(sizeof(char*) * buffer_size);
+ hold_tokens = malloc(sizeof(char *) * buffer_size);
if (hold_tokens == NULL)
exit(-1);
- token = strtok(buffer, " ");
- printf("token -> %s\n", token);
- for (i = 0; token != NULL; i++)
+ hold_tokens[i] = strtok(buffer, " \n");
+ while (hold_tokens[i] != NULL)
{
- hold_tokens[i] = token;
- printf("hold_tokens[%d] -> %s\n", i, hold_tokens[i]);
- token = strtok(NULL, " ");
- printf("next token -> %s\n", token);
+ i++;
+ hold_tokens[i] = strtok(NULL, " \n");
}
-
- hold_tokens[i] == NULL;
- printf("last ld_tokens -> %s\n", hold_tokens[i]);
return (hold_tokens);
}
-
-/*int main(void)
-{
- char *buffer;
- char **cmd;
- int i;
-
- buffer = user_input();
- printf("buffer -> %s\n", buffer);
- cmd = tokens(buffer);
-
- for (i = 0; i < cmd[i + 1]; i++)
- {
- printf("cmd[%d] -> %s\n", i, cmd[i]);
- break;
- }
- return (1);
-}*/
diff --git a/uinput b/uinput
deleted file mode 100755
index f57ab8e..0000000
Binary files a/uinput and /dev/null differ
diff --git a/user_input.c b/user_input.c
index 6c522d7..68f662b 100644
--- a/user_input.c
+++ b/user_input.c
@@ -1,17 +1,16 @@
#include "simpleshell.h"
-
+/**
+ * user_input - gets user input and send to stdin
+ * Return: buffer, pointer
+ */
char *user_input(void)
{
char *buffer = NULL;
size_t bsize = 0;
- /* check for get line */
int count_char;
count_char = getline(&buffer, &bsize, stdin);
- if (count_char == -1)
- perror("getline() failed ( count_char == -1 )");
-
- /* count_char = _getline(&buffer); */
-
+ if (count_char == EOF)
+ exit(0);
return (buffer);
}