Initial commit

This commit is contained in:
g1n 2021-09-17 18:24:48 +03:00
commit 53fc85a9e6
3 changed files with 156 additions and 0 deletions

12
README.org Normal file
View File

@ -0,0 +1,12 @@
#+TITLE: GRU orsh - simple shell on C
** Features:
- echo and pwd builtin
- working environment variables
** How to build:
- cd src
- make
- orsh is executable of shell

14
src/Makefile Normal file
View File

@ -0,0 +1,14 @@
CC = gcc
CFLAGS= -O2 -Wall -Wextra
LFLAGS=
SRCFILES= main.c
OBJFILES= orsh
.PHONY: all clean
all: main
main:
$(CC) $(CFLAGS) $(SRCFILES) -o $(OBJFILES)

130
src/main.c Normal file
View File

@ -0,0 +1,130 @@
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
int position = 0;
char pwd[128]; // FIXME: change to PATH_MAX
char **split_line(char *line) {
int bufsize = 64;
position = 0;
char **tokens = malloc(bufsize * sizeof(char*));
char *token;
if (!tokens) {
fprintf(stderr, "orsh: allocation error\n");
exit(EXIT_FAILURE);
}
token = strtok(line, " ");
while (token != NULL) {
tokens[position] = token;
position++;
token = strtok(NULL, " ");
}
tokens[position] = NULL;
return tokens;
}
int execute(char **command, int status) {
status = 0;
pid_t pid, wpid;
pid = fork();
if (pid == 0) {
// Child process
if (execvp(command[0], command) == -1) {
perror("orsh");
}
status = 1; // FIXME: add error status
exit(EXIT_FAILURE);
} else if (pid < 0) {
// Error forking
perror("orsh");
status = 1; // FIXME: add error status
} else {
// Parent process
do {
wpid = waitpid(pid, &status, WUNTRACED); // FIXME: warning unused variable
} while (!WIFEXITED(status) && !WIFSIGNALED(status));
}
return status;
}
int parse_command(char **command) {
int variable = 0;
int where_var[position - 1];
for (int i = 0; i <= position - 1; i++) { // Loop for checking if line has variable
if (command[i][0] == '$') {
where_var[i] = 1;
variable++;
}
}
if (variable >= 1) {
for (int i = 0; i <= position - 1; i++) {
if(where_var[i] == 1) {
command[i]++; // Deleting '$' char
command[i] = getenv(command[i]);
}
}
}
int status = 0; // FIXME: add status as argument (to know status of last command)
if (command[0][strlen(command[0]) - 1] == ';'){ // FIXME: parse all word not only first
command[0][strlen(command[0])-1] = '\0';
} else if (command[0][0] == ';'){ // Check if command is ; or first char of command is ;
command[0][0] = '\0';
}
if (!strcmp(command[0], "exit")) { // FIXME: add switch statement (if possible)
printf("exit\n");
exit(0);
} else if (!strcmp(command[0], "echo")) {
for (int i = 1; i <= position - 1; i++)
printf("%s ", command[i]);
printf("\n");
return 0;
} else if (!strcmp(command[0], "cd")) {
if (position == 1) {
printf("HOME todo\n");
} else if (position >= 3) {
printf("orsh: cd: too many arguments\n");
} else {
chdir(command[1]);
getcwd(pwd, sizeof(pwd));
}
} else if (!strcmp(command[0], "pwd")) {
printf("%s\n", pwd);
} else {
status = execute(command, status);
}
return status;
}
int main() {//int argc, char *argv[]) {
char *line = NULL;
size_t len = 0;
char** args;
int status = 0; // FIXME
int command_status = 0; // FIXME
getcwd(pwd, sizeof(pwd));
while(1) {
printf("orsh> "); // FIXME or TODO: add PS1 var
status = getline(&line, &len, stdin);
if (status == EOF) {
printf("\nexit\n");
break;
}
line[strlen(line) - 1] = '\0';
args = split_line(line);
command_status = parse_command(args);
}
return command_status;
}