Initial Commit
This commit is contained in:
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
dist/
|
||||||
17
Makefile
Normal file
17
Makefile
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
CC ?= gcc
|
||||||
|
|
||||||
|
SOURCES := $(wildcard src/*.c)
|
||||||
|
|
||||||
|
|
||||||
|
.PHONY: clean
|
||||||
|
|
||||||
|
all: dist/msh
|
||||||
|
|
||||||
|
dist/msh: $(SOURCES) dist
|
||||||
|
$(CC) -o $@ $(SOURCES)
|
||||||
|
|
||||||
|
dist:
|
||||||
|
mkdir -p dist
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -rf dist
|
||||||
135
src/msh.c
Normal file
135
src/msh.c
Normal file
@@ -0,0 +1,135 @@
|
|||||||
|
#define _GNU_SOURCE
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
#include <sys/utsname.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
|
||||||
|
#define ESC \x1B
|
||||||
|
|
||||||
|
|
||||||
|
const int LINESIZE = 512;
|
||||||
|
|
||||||
|
int cd(int argc, char** argv) {
|
||||||
|
if (argc != 1) {
|
||||||
|
fprintf(stderr, "Usage: cd <directory>\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return chdir(argv[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void pretty_path_home(char** path) {
|
||||||
|
char* home = secure_getenv("HOME");
|
||||||
|
int home_len = strlen(home);
|
||||||
|
|
||||||
|
if (strncmp(home, *path, home_len) == 0) {
|
||||||
|
(*path)[home_len-1] = '~';
|
||||||
|
*path = *path + (home_len - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main(int argc, char** argv) {
|
||||||
|
char* tokens[LINESIZE] = {};
|
||||||
|
char** args;
|
||||||
|
char line[LINESIZE] = {};
|
||||||
|
char* tokenwork;
|
||||||
|
char* token;
|
||||||
|
char* newline;
|
||||||
|
int ntokens = 0;
|
||||||
|
|
||||||
|
int i;
|
||||||
|
int result;
|
||||||
|
|
||||||
|
int pid;
|
||||||
|
int laststatus = 0;
|
||||||
|
|
||||||
|
int wstatus;
|
||||||
|
char pwd[LINESIZE] = {};
|
||||||
|
char* pwd_disp;
|
||||||
|
|
||||||
|
char* user;
|
||||||
|
char* host;
|
||||||
|
|
||||||
|
struct utsname uts = {};
|
||||||
|
|
||||||
|
user = secure_getenv("USER");
|
||||||
|
|
||||||
|
result = uname(&uts);
|
||||||
|
if (result != 0) {
|
||||||
|
fprintf(stderr, "Error: %s\n", strerror(errno));
|
||||||
|
return errno;
|
||||||
|
}
|
||||||
|
|
||||||
|
host = uts.nodename;
|
||||||
|
|
||||||
|
while(1) {
|
||||||
|
getcwd(pwd, LINESIZE - 1);
|
||||||
|
pwd_disp = pwd;
|
||||||
|
|
||||||
|
pretty_path_home(&pwd_disp);
|
||||||
|
|
||||||
|
if (laststatus != 0) {
|
||||||
|
fprintf(stdout, "❌");
|
||||||
|
}
|
||||||
|
fprintf(stdout, "%s@%s %s$ ", user, host, pwd_disp);
|
||||||
|
char* fgets_res = fgets(line, LINESIZE, stdin);
|
||||||
|
|
||||||
|
if (fgets_res == NULL) {
|
||||||
|
printf("^D\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
newline = strrchr(line, '\n');
|
||||||
|
if (newline != NULL) {
|
||||||
|
newline[0] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (tokenwork = line, i = 0; ; tokenwork = NULL, i++) {
|
||||||
|
token = strtok(tokenwork, " \t");
|
||||||
|
if (token == NULL) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
tokens[i] = token;
|
||||||
|
}
|
||||||
|
|
||||||
|
ntokens = i;
|
||||||
|
tokens[ntokens] = NULL;
|
||||||
|
args = &tokens[1];
|
||||||
|
|
||||||
|
if (ntokens == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Shell builtins
|
||||||
|
if (strcmp("exit", tokens[0]) == 0) {
|
||||||
|
printf("Goodbye!\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strcmp("cd", tokens[0]) == 0) {
|
||||||
|
laststatus = cd(ntokens - 1, args);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Execute command
|
||||||
|
pid = fork();
|
||||||
|
|
||||||
|
if(pid == 0) {
|
||||||
|
return execvpe(tokens[0], tokens, NULL);
|
||||||
|
} else {
|
||||||
|
waitpid(pid, &wstatus, 0);
|
||||||
|
|
||||||
|
laststatus = WEXITSTATUS(wstatus);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Reference in New Issue
Block a user