Initial commit
This commit is contained in:
commit
53fc85a9e6
|
@ -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
|
||||
|
||||
|
|
@ -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)
|
||||
|
|
@ -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;
|
||||
}
|
Loading…
Reference in New Issue