# Ash
+While Unix shells are a solved problem in computer science, recent iterations have admittedly been more and more complicated by feature sets that attempt to cater to all users. Ash seeks to be a completely stripped down, simplified approach to shells, only including the essential parts, i.e., just the things *I personally use*. In fact, the main goals for this project in order or priority have been:
+
+1. To learn more about the interaction between shells, terminals, and the operating system.
+2. To create a utility I would personally want to use.
+3. To create a utility other people would want to use.
+
+## Feature Set
+
+- Foreground and background process groups (`fg`, `bg`, `&`)
+- Unix pipes
+- Conditional execution (`&&`, `||`)
+- Shell history (cached in `~/.ashhistory`)
+
+### Future features
+
+- File redirection
+- Environment variables
+- Scripting
+- File globbing
+
+## Building
+
+Similar to my other projects, ash uses [cbs](https://github.com/trenthuber/cbs) as its build system, included as a git submodule, so make sure to clone recursively.
+
+```console
+$ git clone --recursive https://github.com/trenthuber/ash
+$ cd ash
+$ cc -o build build.c
+$ ./build
+$ ./bin/ash
+```
+
+Note, you only need to run the `cc` command the first time you build the project, as the `./build` executable will recompile itself everytime it is run.
+
## Resources
+These websites have been invaluable in the making of ash.
+
- [TTY Demystified](http://www.linusakesson.net/programming/tty/)
- [Process Groups and Terminal Signaling](https://cs162.org/static/readings/ic221_s16_lec17.html)
static struct job jobarray[MAXJOBS + 1];
struct stack INITSTACK(jobs, jobarray, 0);
-void sigkill(pid_t jobid) {
- if (killpg(jobid, SIGKILL) == -1)
- warn("Unable to kill process group %d; manual termination may be required",
- jobid);
-}
-
void *findjob(pid_t jobid) {
if (jobs.b == jobs.t) return NULL;
for (jobs.c = jobs.b; CURRENT->id != jobid; INC(jobs, c))
#define CURRENT ((struct job *)jobs.c)
extern struct stack jobs;
-void sigkill(pid_t jobid);
void *findjob(pid_t jobid);
void *deletejob(void);
void waitbg(int sig);
exit(EXIT_FAILURE);
}
+static void sigkill(pid_t jobid) {
+ if (killpg(jobid, SIGKILL) == -1)
+ warn("Unable to kill process group %d; manual termination may be required",
+ jobid);
+}
+
int setfg(struct job job) {
if (tcsetattr(STDIN_FILENO, TCSANOW, &job.config) == -1)
warn("Unable to set termios structure");