Make sh able to execute from file

This commit is contained in:
Mark 2020-01-19 17:54:47 +02:00
parent 44cfef634b
commit d7a9bdee22
5 changed files with 84 additions and 4 deletions

View File

@ -1,4 +1,5 @@
#include <sys/fcntl.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <stdio.h>
@ -47,11 +48,15 @@ int main(int argc, char **argv) {
}
path = argv[1];
printf("open file %s\n", path);
if ((fd = open(path, O_RDONLY, 0)) < 0) {
perror(path);
return -1;
if (!strcmp(path, "-")) {
fd = STDIN_FILENO;
printf("Reading from stdin\n");
} else {
if ((fd = open(path, O_RDONLY, 0)) < 0) {
perror(path);
return -1;
}
}
offset = 0;

3
etc/test.sh Executable file
View File

@ -0,0 +1,3 @@
#!/bin/sh
echo Something

View File

@ -38,6 +38,42 @@ DEF_BUILTIN(clear) {
return 0;
}
DEF_BUILTIN(echo) {
for (int i = 1; i < cmd->argc; ++i) {
printf("%s ", cmd->args[i]);
}
printf("\n");
return 0;
}
DEF_BUILTIN(into) {
if (cmd->argc < 3) {
printf("usage: into <filename> <command> ...\n");
return -1;
}
int pid = fork();
if (pid < 0) {
perror("fork()");
return -1;
}
if (pid == 0) {
close(STDIN_FILENO);
int fd = open(cmd->args[1], O_RDONLY, 0);
if (fd < 0) {
perror(cmd->args[1]);
return -1;
}
exit(execve(cmd->args[2], (const char *const *) &cmd->args[2], NULL));
} else {
int st;
waitpid(pid, &st);
return 0;
}
}
// TODO: support usernames (getpwnam_r)
DEF_BUILTIN(setid) {
if (cmd->argc == 2) {
@ -78,8 +114,10 @@ static struct sh_builtin __builtins[] = {
DECL_BUILTIN(builtins),
DECL_BUILTIN(cd),
DECL_BUILTIN(clear),
DECL_BUILTIN(echo),
DECL_BUILTIN(exit),
DECL_BUILTIN(setid),
DECL_BUILTIN(into),
{NULL}
};

View File

@ -104,11 +104,16 @@ static int cmd_exec(const struct cmd_exec *cmd) {
int eval(char *str) {
struct cmd_exec cmd;
char *p;
while (isspace(*str)) {
++str;
}
if ((p = strchr(str, '#'))) {
*p = 0;
}
if (!*str) {
return 0;
}

29
sh/sh.c
View File

@ -73,9 +73,38 @@ static void display_prompt(void) {
}
int main(int argc, char **argv) {
int fd = STDIN_FILENO;
char linebuf[256];
int res;
if (argc == 2) {
fd = open(argv[1], O_RDONLY, 0);
if (fd < 0) {
perror(argv[1]);
return -1;
}
} else if (argc != 1) {
printf("usage: sh [filename]\n");
return -1;
}
if (!isatty(fd)) {
while (1) {
if (gets_safe(fd, linebuf, sizeof(linebuf)) < 0) {
break;
}
eval(linebuf);
}
if (fd != STDIN_FILENO) {
close(fd);
}
return 0;
}
while (1) {
update_prompt();
display_prompt();