#include "external/cbs/cbs.c"
-#define SRCDIR "src/"
-#define SRC \
- SRCDIR "builtins", \
- SRCDIR "input", \
- SRCDIR "history", \
- SRCDIR "job", \
- SRCDIR "parse", \
- SRCDIR "main", \
- SRCDIR "options", \
- SRCDIR "run", \
- SRCDIR "stack", \
- SRCDIR "utils"
-#define BINDIR "bin/"
-#define ASH BINDIR "ash"
-
int main(void) {
- char **src;
-
- build(NULL);
-
- src = (char *[]){SRC, NULL};
- // cflags = (char *[]){"-ferror-limit=1", NULL};
- while (*src) compile(*src++, NULL);
+ build("./");
- load('x', ASH, SRC, NULL);
+ build("src/");
return EXIT_SUCCESS;
}
-Subproject commit a2cb47c262bee92a2f7cab689e42ae8452c9e952
+Subproject commit 47569fbe806a5138763e7ef3447dca254357dff8
--- /dev/null
+struct cbsfile {
+ char *name, **flags, type;
+};
+
+void buildfiles(struct cbsfile *files) {
+ char **c, **l, **names;
+ struct cbsfile *target;
+ size_t i;
+
+ c = cflags;
+ l = lflags;
+
+ target = files++;
+
+ for (i = 0; files[i].name; ++i) if (files[i].flags) {
+ cflags = files[i].flags;
+ compile(files[i].name);
+ }
+
+ names = allocate((i + 1) * sizeof *names);
+ for (i = 0; files[i].name; ++i) names[i] = files[i].name;
+
+ lflags = target->flags;
+ load(target->type, target->name, names);
+
+ free(names);
+
+ cflags = c;
+ lflags = l;
+}
--- /dev/null
+libbuiltin.a
--- /dev/null
+#include "../external/cbs/cbs.c"
+#include "../external/cbsfile.c"
+
+int main(void) {
+ build("./");
+
+ build("builtin/");
+
+ buildfiles((struct cbsfile []){{"../bin/ash", NONE, 'x'},
+
+ {"input", NONE},
+ {"history", NONE},
+ {"job", NONE},
+ {"parse", NONE},
+ {"main", NONE},
+ {"options", NONE},
+ {"run", LIST("-Ibuiltin/")},
+ {"stack", NONE},
+ {"utils", NONE},
+
+ {"builtin.a"},
+
+ {NULL}});
+
+ return EXIT_SUCCESS;
+}
--- /dev/null
+#include <limits.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <sys/errno.h>
+#include <termios.h>
+
+#include "builtin.h"
+#include "job.h"
+#include "stack.h"
+#include "utils.h"
+
+BUILTINSIG(bg) {
+ long jobid;
+ struct job *job;
+
+ if (sigaction(SIGCHLD, &sigdfl, NULL) == -1) {
+ note("Unable to acquire lock on the job stack");
+ return 1;
+ }
+
+ if (argv[1]) {
+ errno = 0;
+ if ((jobid = strtol(argv[1], NULL, 10)) == LONG_MAX && errno
+ || jobid <= 0) {
+ note("Invalid job id");
+ return 1;
+ }
+ if (!(job = findjob((pid_t)jobid))) {
+ note("Unable to find job %d", (pid_t)jobid);
+ return 1;
+ }
+ if (job->type == BACKGROUND) {
+ note("Job %d already in background", (pid_t)jobid);
+ return 1;
+ }
+ } else {
+ for (jobs.c = MINUSONE(jobs, t); jobs.c != MINUSONE(jobs, b); DEC(jobs, c))
+ if (CURRENT->type == SUSPENDED) break;
+ if (jobs.c == MINUSONE(jobs, b)) {
+ note("No suspended jobs to run in background");
+ return 1;
+ }
+ }
+ job = deletejob();
+
+ if (!(push(&jobs, job))) {
+ note("Unable to add job to background; too many jobs");
+ return 1;
+ }
+ if (killpg(job->id, SIGCONT) == -1) {
+ note("Unable to wake up suspended process group %d", job->id);
+ return 1;
+ }
+ job->type = BACKGROUND;
+
+ if (sigaction(SIGCHLD, &sigchld, NULL) == -1) {
+ note("Unable to install SIGCHLD handler");
+ return 1;
+ }
+
+ return 0;
+}
--- /dev/null
+#include <err.h>
+#include <fcntl.h>
+#include <dirent.h>
+#include <string.h>
+#include <sys/errno.h>
+
+#include "../../external/cbs/cbs.c"
+#include "../../external/cbsfile.c"
+#include "../config.h"
+
+int main(void) {
+ int listfd, l;
+ DIR *dir;
+ size_t i, offset;
+ struct cbsfile files[1 + MAXBUILTINS + 1];
+ struct dirent *entry;
+ char *name, *identifier;
+
+ build("./");
+
+ if ((listfd = open("list.c", O_WRONLY | O_CREAT | O_TRUNC, 0644)) == -1)
+ err(EXIT_FAILURE, "Unable to open/create `list.c'");
+ if (!(dir = opendir("./")))
+ err(EXIT_FAILURE, "Unable to open current directory");
+
+ dprintf(listfd, "#include <stdlib.h>\n\n#include \"builtin.h\"\n"
+ "#include \"list.h\"\n\n");
+
+ errno = i = 0;
+ files[i++] = (struct cbsfile){"../builtin", NONE, 's'};
+ files[i++] = (struct cbsfile){"list", NONE};
+ offset = i;
+ while ((entry = readdir(dir))) {
+ if (strcmp(entry->d_name, "build.c") == 0) continue;
+ if (!(name = strrchr(entry->d_name, '.')) || strcmp(name, ".c") != 0)
+ continue;
+ if (i == 1 + MAXBUILTINS + 1)
+ errx(EXIT_FAILURE, "Maximum allowed builtins (%d) exceeded", MAXBUILTINS);
+ if (!(name = strdup(entry->d_name)))
+ err(EXIT_FAILURE, "Unable to duplicate directory entry");
+ name[strlen(name) - strlen(".c")] = '\0';
+ if (strcmp(name, "list") == 0) continue;
+ if (strcmp(name, "builtin") != 0)
+ dprintf(listfd, "extern BUILTINSIG(%s);\n", name);
+ files[i++] = (struct cbsfile){name, LIST("-I../")};
+ }
+ if (errno) err(EXIT_FAILURE, "Unable to read from current directory");
+ files[i] = (struct cbsfile){NULL};
+
+ identifier = "struct builtin builtins[] = {";
+ l = (int)strlen(identifier);
+ dprintf(listfd, "\n%s", identifier);
+ for (i = offset; (name = files[i].name); ++i)
+ if (strcmp(name, "builtin") != 0 && strcmp(name, "list") != 0)
+ dprintf(listfd, "{\"%s\", %s},\n%*s", name, name, l, "");
+ dprintf(listfd, "{NULL}};");
+
+ if (closedir(dir) == -1)
+ err(EXIT_FAILURE, "Unable to close current directory");
+ if (close(listfd) == -1) err(EXIT_FAILURE, "Unable to close `list.c'");
+
+ buildfiles(files);
+
+ while (files[offset].name) free(files[offset++].name);
+
+ return EXIT_SUCCESS;
+}
--- /dev/null
+#include <string.h>
+
+#include "builtin.h"
+#include "list.h"
+
+int isbuiltin(char **args, int *statusp) {
+ struct builtin *builtinp;
+ size_t n;
+
+ for (builtinp = builtins; builtinp->func; ++builtinp)
+ if (strcmp(*args, builtinp->name) == 0) {
+ for (n = 0; args[n]; ++n);
+ *statusp = builtinp->func(n, args);
+ return 1;
+ }
+ return 0;
+}
--- /dev/null
+#define BUILTINSIG(name) int name(int argc, char **argv)
+
+int isbuiltin(char **args, int *statusp);
--- /dev/null
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "builtin.h"
+#include "utils.h"
+
+BUILTINSIG(cd) {
+ char *fullpath;
+
+ if (argv[1]) {
+ if (!(fullpath = realpath(argv[1], NULL))) {
+ note("Could not resolve path name");
+ return 1;
+ }
+ } else fullpath = home;
+ if (chdir(fullpath) == -1) {
+ note("Unable to change directory to `%s'", argv[1]);
+ return 1;
+ }
+ if (setenv("PWD", fullpath, 1) == -1)
+ note("Unable to change $PWD$ to `%s'", fullpath);
+ if (fullpath != home) free(fullpath);
+ return 0;
+}
--- /dev/null
+#include <limits.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <sys/errno.h>
+#include <termios.h>
+
+#include "builtin.h"
+#include "job.h"
+#include "stack.h"
+#include "utils.h"
+
+BUILTINSIG(fg) {
+ long jobid;
+ struct job *job;
+
+ if (sigaction(SIGCHLD, &sigdfl, NULL) == -1) {
+ note("Unable to acquire lock on the job stack");
+ return 1;
+ }
+
+ if (argv[1]) {
+ errno = 0;
+ if ((jobid = strtol(argv[1], NULL, 10)) == LONG_MAX && errno
+ || jobid <= 0) {
+ note("Invalid process group id");
+ return 1;
+ }
+ if (!(job = findjob((pid_t)jobid))) {
+ note("Unable to find process group %d", (pid_t)jobid);
+ return 1;
+ }
+ job = deletejob();
+ } else if (!(job = pull(&jobs))) {
+ note("No processes to bring into the foreground");
+ return 1;
+ }
+
+ if (sigaction(SIGCHLD, &sigchld, NULL) == -1) {
+ note("Unable to install SIGCHLD handler");
+ return 1;
+ }
+
+ if (!setfg(*job)) return 1;
+ waitfg(*job);
+
+ return 0;
+}
--- /dev/null
+struct builtin {
+ char *name;
+ BUILTINSIG((*func));
+};
+
+extern struct builtin builtins[];
--- /dev/null
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/stat.h>
+#include <sys/errno.h>
+#include <string.h>
+
+#include "builtin.h"
+#include "list.h"
+#include "utils.h"
+
+static int inpath(char *dir, char *filename) {
+ char *filepath;
+ struct stat estat;
+
+ if (stat(filepath = catpath(dir, filename), &estat) != -1) {
+ if (estat.st_mode & S_IXUSR) {
+ puts(filepath);
+ putchar('\r');
+ return 1;
+ }
+ } else if (errno != ENOENT) note("Unable to check if `%s' exists", filepath);
+ return 0;
+}
+
+BUILTINSIG(which) {
+ struct builtin *builtin;
+ char *path, *dir, *p;
+
+ if (!argv[1]) return 1;
+ for (builtin = builtins; builtin->func; ++builtin)
+ if (strcmp(argv[1], builtin->name) == 0) {
+ puts("Built-in command\r");
+ return 0;
+ }
+
+ if (!(path = getenv("PATH"))) {
+ note("Unable to examine $PATH$");
+ return 1;
+ }
+ if (!(path = p = strdup(path))) {
+ note("Unable to duplicate $PATH$");
+ return 1;
+ }
+ do {
+ if (!(dir = p)) break;
+ if ((p = strchr(dir, ':'))) *p++ = '\0';
+ } while (!inpath(dir, argv[1]));
+ free(path);
+ if (dir) return 0;
+
+ printf("%s not found\r\n", argv[1]);
+ return 1;
+}
+++ /dev/null
-#include <limits.h>
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/errno.h>
-#include <termios.h>
-#include <unistd.h>
-#include <sys/stat.h>
-
-#include "job.h"
-#include "stack.h"
-#include "term.h"
-#include "utils.h"
-
-#define BUILTINSIG(name) int name(int argc, char **argv)
-
-struct builtin {
- char *name;
- BUILTINSIG((*func));
-};
-
-BUILTINSIG(cd) {
- char *fullpath;
-
- if (argv[1]) {
- if (!(fullpath = realpath(argv[1], NULL))) {
- note("Could not resolve path name");
- return 1;
- }
- } else fullpath = home;
- if (chdir(fullpath) == -1) {
- note("Unable to change directory to `%s'", argv[1]);
- return 1;
- }
- if (setenv("PWD", fullpath, 1) == -1)
- note("Unable to change $PWD$ to `%s'", fullpath);
- if (fullpath != home) free(fullpath);
- return 0;
-}
-
-BUILTINSIG(fg) {
- long jobid;
- struct job *job;
-
- if (sigaction(SIGCHLD, &sigdfl, NULL) == -1) {
- note("Unable to acquire lock on the job stack");
- return 1;
- }
-
- if (argv[1]) {
- errno = 0;
- if ((jobid = strtol(argv[1], NULL, 10)) == LONG_MAX && errno
- || jobid <= 0) {
- note("Invalid process group id");
- return 1;
- }
- if (!(job = findjob((pid_t)jobid))) {
- note("Unable to find process group %d", (pid_t)jobid);
- return 1;
- }
- job = deletejob();
- } else if (!(job = pull(&jobs))) {
- note("No processes to bring into the foreground");
- return 1;
- }
-
- if (sigaction(SIGCHLD, &sigchld, NULL) == -1) {
- note("Unable to install SIGCHLD handler");
- return 1;
- }
-
- if (!setfg(*job)) return 1;
- waitfg(*job);
-
- return 0;
-}
-
-BUILTINSIG(bg) {
- long jobid;
- struct job *job;
-
- if (sigaction(SIGCHLD, &sigdfl, NULL) == -1) {
- note("Unable to acquire lock on the job stack");
- return 1;
- }
-
- if (argv[1]) {
- errno = 0;
- if ((jobid = strtol(argv[1], NULL, 10)) == LONG_MAX && errno
- || jobid <= 0) {
- note("Invalid job id");
- return 1;
- }
- if (!(job = findjob((pid_t)jobid))) {
- note("Unable to find job %d", (pid_t)jobid);
- return 1;
- }
- if (job->type == BACKGROUND) {
- note("Job %d already in background", (pid_t)jobid);
- return 1;
- }
- } else {
- for (jobs.c = MINUSONE(jobs, t); jobs.c != MINUSONE(jobs, b); DEC(jobs, c))
- if (CURRENT->type == SUSPENDED) break;
- if (jobs.c == MINUSONE(jobs, b)) {
- note("No suspended jobs to run in background");
- return 1;
- }
- }
- job = deletejob();
-
- if (!(push(&jobs, job))) {
- note("Unable to add job to background; too many jobs");
- return 1;
- }
- if (killpg(job->id, SIGCONT) == -1) {
- note("Unable to wake up suspended process group %d", job->id);
- return 1;
- }
- job->type = BACKGROUND;
-
- if (sigaction(SIGCHLD, &sigchld, NULL) == -1) {
- note("Unable to install SIGCHLD handler");
- return 1;
- }
-
- return 0;
-}
-
-#define BUILTIN(name) {#name, name}
-BUILTINSIG(which);
-struct builtin builtins[] = {
- BUILTIN(cd),
- BUILTIN(fg),
- BUILTIN(bg),
- BUILTIN(which),
- BUILTIN(NULL),
-};
-
-static int inpath(char *dir, char *filename) {
- char *filepath;
- struct stat estat;
-
- if (stat(filepath = catpath(dir, filename), &estat) != -1) {
- if (estat.st_mode & S_IXUSR) {
- puts(filepath);
- putchar('\r');
- return 1;
- }
- } else if (errno != ENOENT) note("Unable to check if `%s' exists", filepath);
- return 0;
-}
-
-BUILTINSIG(which) {
- struct builtin *builtin;
- char *path, *dir, *p;
-
- if (!argv[1]) return 1;
- for (builtin = builtins; builtin->func; ++builtin)
- if (strcmp(argv[1], builtin->name) == 0) {
- puts("Built-in command\r");
- return 0;
- }
-
- if (!(path = getenv("PATH"))) {
- note("Unable to examine $PATH$");
- return 1;
- }
- if (!(path = p = strdup(path))) {
- note("Unable to duplicate $PATH$");
- return 1;
- }
- do {
- if (!(dir = p)) break;
- if ((p = strchr(dir, ':'))) *p++ = '\0';
- } while (!inpath(dir, argv[1]));
- free(path);
- if (dir) return 0;
-
- printf("%s not found\r\n", argv[1]);
- return 1;
-}
-
-int isbuiltin(char **args, int *statusp) {
- struct builtin *builtinp;
- size_t n;
-
- for (builtinp = builtins; builtinp->func; ++builtinp)
- if (strcmp(*args, builtinp->name) == 0) {
- for (n = 0; args[n]; ++n);
- *statusp = builtinp->func(n, args);
- return 1;
- }
- return 0;
-}
+++ /dev/null
-int isbuiltin(char **args, int *statusp);
#define INTERACTIVEFILE ".ashinteractive"
#define LOGINFILE ".ashlogin"
+#define MAXBUILTINS 100 // Maximum number of builtin commands
#define MAXCHARS 1000 // Maximum number of character per line
#define MAXCMDS 100 // Maximum number of commands per line
#define MAXHIST 100 // Maximum number of entries to store in history file
#include <termios.h>
#include <unistd.h>
-#include "builtins.h"
+#include "builtin.h"
#include "config.h"
#include "job.h"
#include "parse.h"