diff --git a/kernel/exec.c b/kernel/exec.c index e18bbb6..7c36a14 100644 --- a/kernel/exec.c +++ b/kernel/exec.c @@ -39,6 +39,28 @@ exec(char *path, char **argv) } ilock(ip); + // Check for #! at the beginning + // Shell scripts look like this at the start: + // #!/sh argument (argument not implemented) + char shebang[2]; + readi(ip, 0, (uint64)&shebang, 0, sizeof(shebang)); + if (shebang[0] == '#' && shebang[1] == '!') { + char interpreter[MAXPATH]; + int read_sz = readi( + ip, 0, (uint64)&interpreter, sizeof(shebang), sizeof(interpreter)); + for (int i = 0; i < MAXPATH && i < read_sz; ++i) { + if (interpreter[i] == '\n' || interpreter[i] == ' ') { + interpreter[i] = '\0'; + break; + } + } + + char *new_argv[] = { interpreter, argv[0], 0 }; + iunlockput(ip); + end_op(); + return exec(interpreter, new_argv); + } + // Check ELF header if(readi(ip, 0, (uint64)&elf, 0, sizeof(elf)) != sizeof(elf)) goto bad; diff --git a/tests/shell-scripting/test.sh b/tests/shell-scripting/test.sh new file mode 100644 index 0000000..dd4b990 --- /dev/null +++ b/tests/shell-scripting/test.sh @@ -0,0 +1,10 @@ +#!/sh +# Please add this to Makefile to test + +echo Testing shell script functionality +echo +echo Welcome to my script +echo My script is amazing +echo Look at these files +ls / +echo Byte now diff --git a/user/sh.c b/user/sh.c index 836ebcb..ec2fa6b 100644 --- a/user/sh.c +++ b/user/sh.c @@ -132,18 +132,19 @@ runcmd(struct cmd *cmd) } int -getcmd(char *buf, int nbuf) +getcmd(char *buf, int nbuf, int fd) { - write(2, "$ ", 2); + if (fd == 0) + write(2, "$ ", 2); // only print prompt if interactive (no script) memset(buf, 0, nbuf); - gets(buf, nbuf); + fgets(fd, buf, nbuf); if(buf[0] == 0) // EOF return -1; return 0; } int -main(void) +main(int argc, char *argv[]) { static char buf[100]; int fd; @@ -156,8 +157,16 @@ main(void) } } + fd = 0; + if (argc > 1) { + fd = open(argv[1], O_RDONLY); + } + // Read and run input commands. - while(getcmd(buf, sizeof(buf)) >= 0){ + while(getcmd(buf, sizeof(buf), fd) >= 0){ + if (buf[0] == '#') { + continue; + } if(buf[0] == 'c' && buf[1] == 'd' && buf[2] == ' '){ // Chdir must be called by the parent, not the child. buf[strlen(buf)-1] = 0; // chop \n