summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJacob McDonnell <jacob@jacobmcdonnell.com>2024-03-05 18:46:44 -0500
committerJacob McDonnell <jacob@jacobmcdonnell.com>2024-03-05 18:46:44 -0500
commitc40f400f6ab879e08d54de753aabc987fd6ba07a (patch)
tree295f95070362d14d987638b558ad6bb1ba2415e2
parente32262d86c90e2ac73b2c38a47a1bb6b60935098 (diff)
Added a simple shell, jsh
-rw-r--r--.DS_Storebin6148 -> 0 bytes
-rw-r--r--.vscode/configurationCache.log1
-rw-r--r--.vscode/dryrun.log5
-rw-r--r--.vscode/settings.json3
-rw-r--r--.vscode/targets.log275
-rwxr-xr-x[-rw-r--r--]makefile8
-rw-r--r--src/.DS_Storebin6148 -> 6148 bytes
-rw-r--r--src/cmd/.DS_Storebin6148 -> 6148 bytes
-rwxr-xr-xsrc/cmd/cat/cat.c54
-rwxr-xr-xsrc/cmd/cat/makefile12
-rw-r--r--src/cmd/coin/coin.c37
-rwxr-xr-x[-rw-r--r--]src/cmd/coin/makefile8
-rw-r--r--src/cmd/dice/dice.c2
-rwxr-xr-x[-rw-r--r--]src/cmd/dice/makefile8
-rw-r--r--src/cmd/echo/echo.c2
-rwxr-xr-x[-rw-r--r--]src/cmd/echo/makefile10
-rwxr-xr-xsrc/cmd/jsh/README.md3
-rwxr-xr-xsrc/cmd/jsh/jsh.c81
-rwxr-xr-xsrc/cmd/jsh/makefile12
-rwxr-xr-xsrc/cmd/ls/ls.c78
-rwxr-xr-xsrc/cmd/ls/makefile12
-rw-r--r--src/cmd/makefile2
-rwxr-xr-xsrc/cmd/pwd/makefile12
-rwxr-xr-xsrc/cmd/pwd/pwd.c30
-rw-r--r--src/makefile2
25 files changed, 336 insertions, 321 deletions
diff --git a/.DS_Store b/.DS_Store
deleted file mode 100644
index b48a754..0000000
--- a/.DS_Store
+++ /dev/null
Binary files differ
diff --git a/.vscode/configurationCache.log b/.vscode/configurationCache.log
deleted file mode 100644
index 3fb4b13..0000000
--- a/.vscode/configurationCache.log
+++ /dev/null
@@ -1 +0,0 @@
-{"buildTargets":["all","clean","install","src"],"launchTargets":[],"customConfigurationProvider":{"workspaceBrowse":{"browsePath":[],"compilerArgs":[]},"fileIndex":[]}} \ No newline at end of file
diff --git a/.vscode/dryrun.log b/.vscode/dryrun.log
deleted file mode 100644
index 51f061e..0000000
--- a/.vscode/dryrun.log
+++ /dev/null
@@ -1,5 +0,0 @@
-make all -f "/Users/jmm/Documents/git/ProjectMustang/makefile" --dry-run --always-make --keep-going --print-directory
-make: Entering directory `/Users/jmm/Documents/git/ProjectMustang'
-make: Nothing to be done for `all'.
-make: Leaving directory `/Users/jmm/Documents/git/ProjectMustang'
-
diff --git a/.vscode/settings.json b/.vscode/settings.json
deleted file mode 100644
index 65e1ec0..0000000
--- a/.vscode/settings.json
+++ /dev/null
@@ -1,3 +0,0 @@
-{
- "makefile.extensionOutputFolder": "./.vscode"
-} \ No newline at end of file
diff --git a/.vscode/targets.log b/.vscode/targets.log
deleted file mode 100644
index 4086f67..0000000
--- a/.vscode/targets.log
+++ /dev/null
@@ -1,275 +0,0 @@
-make all -f "/Users/jmm/Documents/git/ProjectMustang/makefile" --print-data-base --no-builtin-variables --no-builtin-rules --question
-# GNU Make 3.81
-# Copyright (C) 2006 Free Software Foundation, Inc.
-# This is free software; see the source for copying conditions.
-# There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
-# PARTICULAR PURPOSE.
-
-# This program built for i386-apple-darwin11.3.0
-
-# Make data base, printed on Mon Nov 1 11:39:40 2021
-
-# Variables
-
-# automatic
-<D = $(patsubst %/,%,$(dir $<))
-# automatic
-?F = $(notdir $?)
-# environment
-VSCODE_LOG_NATIVE = false
-# automatic
-?D = $(patsubst %/,%,$(dir $?))
-# automatic
-@D = $(patsubst %/,%,$(dir $@))
-# automatic
-@F = $(notdir $@)
-# makefile
-CURDIR := /Users/jmm/Documents/git/ProjectMustang
-# makefile
-SHELL = /bin/sh
-# environment
-VSCODE_NLS_CONFIG = {"locale":"en-us","availableLanguages":{},"_languagePackSupport":true}
-# environment
-_ = /usr/bin/make
-# makefile (from `/Users/jmm/Documents/git/ProjectMustang/makefile', line 1)
-MAKEFILE_LIST := /Users/jmm/Documents/git/ProjectMustang/makefile
-# environment
-VSCODE_VERBOSE_LOGGING = true
-# environment
-__CFBundleIdentifier = com.visualstudio.code.oss
-# environment
-INFOPATH = /opt/homebrew/share/info:
-# environment
-PLAN9 = /opt/plan9port
-# environment
-VSCODE_IPC_HOOK_EXTHOST = /var/folders/qq/frtrjqf10vlcgdw8_fwlhm_c0000gn/T/vscode-ipc-0d1cd7ca-fb65-4182-a0f6-057ab4f3f736.sock
-# environment
-VSCODE_CWD = /
-# environment
-PATH = /opt/ProjectMustang/bin:/Users/jmm/.local/bin:/opt/CEdev/bin:/opt/homebrew/bin:/opt/homebrew/sbin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/go/bin:/opt/X11/bin:/Library/Apple/usr/bin:/Library/Frameworks/Mono.framework/Versions/Current/Commands:/opt/plan9port/bin
-# environment
-ZDOTDIR = /Users/jmm/.config/shells/zsh
-# environment
-VSCODE_LOG_STACK = false
-# environment
-ELECTRON_RUN_AS_NODE = 1
-# default
-.FEATURES := target-specific order-only second-expansion else-if archives jobserver check-symlink
-# environment
-SSH_AUTH_SOCK = /private/tmp/com.apple.launchd.rBEHA7GWj3/Listeners
-# automatic
-%F = $(notdir $%)
-# makefile (from `/Users/jmm/Documents/git/ProjectMustang/makefile', line 1)
-(CC) = clang
-# environment
-DISPLAY = /private/tmp/com.apple.launchd.gZJXoHdnVC/org.xquartz:0
-# automatic
-*F = $(notdir $*)
-# environment
-VSCODE_PIPE_LOGGING = true
-# environment
-PWD = /Users/jmm/Documents/git/ProjectMustang
-# environment
-HOMEBREW_CELLAR = /opt/homebrew/Cellar
-# environment
-ORIGINAL_XDG_CURRENT_DESKTOP = undefined
-# environment
-MANPATH = /opt/homebrew/share/man::
-# environment
-VSCODE_AMD_ENTRYPOINT = vs/workbench/services/extensions/node/extensionHostProcess
-# environment
-HOME = /Users/jmm
-# environment
-XDG_CACHE_HOME = /Users/jmm/.cache
-# default
-MAKEFILEPATH := /Applications/Xcode.app/Contents/Developer/Makefiles
-# environment
-VSCODE_CODE_CACHE_PATH = /Users/jmm/Library/Application Support/VSCodium/CachedData/6cba118ac49a1b88332f312a8f67186f7f3c1643
-# environment
-LOGNAME = jmm
-# environment
-APPLICATION_INSIGHTS_NO_DIAGNOSTIC_CHANNEL = true
-# environment
-ZSH = /Users/jmm/.config/shells/zsh
-# environment
-VSCODE_HANDLES_UNCAUGHT_ERRORS = true
-# automatic
-^D = $(patsubst %/,%,$(dir $^))
-# environment
-ProMust = /opt/ProjectMustang
-# environment
-SHELLDIR = /Users/jmm/.config/shells
-# environment
-XPC_FLAGS = 0x0
-# default
-MAKE = $(MAKE_COMMAND)
-# default
-MAKECMDGOALS := all
-# environment
-SHLVL = 1
-# default
-MAKE_VERSION := 3.81
-# environment
-USER = jmm
-# makefile
-.DEFAULT_GOAL := src
-# automatic
-%D = $(patsubst %/,%,$(dir $%))
-# default
-MAKE_COMMAND := /Applications/Xcode.app/Contents/Developer/usr/bin/make
-# default
-.VARIABLES :=
-# environment
-TMPDIR = /var/folders/qq/frtrjqf10vlcgdw8_fwlhm_c0000gn/T/
-# environment
-CEDEV = /opt/CEdev
-# environment
-VSCODE_IPC_HOOK = /Users/jmm/Library/Application Support/VSCodium/1.61.2-main.sock
-# makefile
-MAKEFLAGS = Rrqp
-# environment
-MFLAGS = -Rrqp
-# automatic
-*D = $(patsubst %/,%,$(dir $*))
-# environment
-HOMEBREW_SHELLENV_PREFIX = /opt/homebrew
-# environment
-XPC_SERVICE_NAME = application.com.visualstudio.code.oss.20131101.20131106
-# environment
-HOMEBREW_PREFIX = /opt/homebrew
-# automatic
-+D = $(patsubst %/,%,$(dir $+))
-# automatic
-+F = $(notdir $+)
-# environment
-HOMEBREW_REPOSITORY = /opt/homebrew
-# environment
-__CF_USER_TEXT_ENCODING = 0x1F5:0x0:0x0
-# environment
-COMMAND_MODE = unix2003
-# default
-MAKEFILES :=
-# automatic
-<F = $(notdir $<)
-# environment
-XDG_CONFIG_HOME = /Users/jmm/.config
-# environment
-LC_ALL = C
-# environment
-LESSHISTFILE = -
-# automatic
-^F = $(notdir $^)
-# environment
-XDG_DATA_HOME = /Users/jmm/.local/share
-# default
-SUFFIXES :=
-# default
-.INCLUDE_DIRS = /usr/local/include
-# makefile (from `/Users/jmm/Documents/git/ProjectMustang/makefile', line 4)
-PROROOT := /Users/jmm/Documents/git/ProjectMustang
-# environment
-MAKELEVEL := 0
-# environment
-ENV = /Users/jmm/.config/shells/ksh/kshrc
-# makefile (from `/Users/jmm/Documents/git/ProjectMustang/makefile', line 3)
-SUBDIRS := src
-# environment
-LANG = C
-# environment
-VSCODE_PID = 30994
-# variable set hash-table stats:
-# Load=83/1024=8%, Rehash=0, Collisions=3/113=3%
-
-# Pattern-specific Variable Values
-
-# No pattern-specific variable values.
-
-# Directories
-
-
-# No files, no impossibilities in 0 directories.
-
-# Implicit Rules
-
-# No implicit rules.
-
-# Files
-
-all:
-# Phony target (prerequisite of .PHONY).
-# Command-line target.
-# Implicit rule search has not been done.
-# File does not exist.
-# File has been updated.
-# Successfully updated.
-
-.PHONY: install all clean src
-# Implicit rule search has not been done.
-# Modification time never checked.
-# File has not been updated.
-
-# Not a target:
-/Users/jmm/Documents/git/ProjectMustang/makefile:
-# Implicit rule search has been done.
-# Last modified 2021-10-10 19:11:05
-# File has been updated.
-# Successfully updated.
-# variable set hash-table stats:
-# Load=0/32=0%, Rehash=0, Collisions=0/0=0%
-
-# Not a target:
-.SUFFIXES:
-# Implicit rule search has not been done.
-# Modification time never checked.
-# File has not been updated.
-
-src:
-# Phony target (prerequisite of .PHONY).
-# Implicit rule search has not been done.
-# File does not exist.
-# File has not been updated.
-# commands to execute (from `/Users/jmm/Documents/git/ProjectMustang/makefile', line 9):
- $(MAKE) -C $@ $(MAKECMDGOALS)
-
-
-# Not a target:
-.DEFAULT:
-# Implicit rule search has not been done.
-# Modification time never checked.
-# File has not been updated.
-
-clean: src
-# Phony target (prerequisite of .PHONY).
-# Implicit rule search has not been done.
-# File does not exist.
-# File has not been updated.
-# commands to execute (from `/Users/jmm/Documents/git/ProjectMustang/makefile', line 18):
- @rm $(wildcard build/bin/*)
-
-
-install:
-# Phony target (prerequisite of .PHONY).
-# Implicit rule search has not been done.
-# File does not exist.
-# File has not been updated.
-# commands to execute (from `/Users/jmm/Documents/git/ProjectMustang/makefile', line 14):
- @rm -r /opt/ProjectMustang
- @cp -r build/ /opt/ProjectMustang/
-
-
-# files hash-table stats:
-# Load=8/1024=1%, Rehash=0, Collisions=0/26=0%
-# VPATH Search Paths
-
-# No `vpath' search paths.
-
-# No general (`VPATH' variable) search path.
-
-# # of strings in strcache: 1
-# # of strcache buffers: 1
-# strcache size: total = 4096 / max = 4096 / min = 4096 / avg = 4096
-# strcache free: total = 4047 / max = 4047 / min = 4047 / avg = 4047
-
-# Finished Make data base on Mon Nov 1 11:39:40 2021
-
-
diff --git a/makefile b/makefile
index b35e42a..0185b2e 100644..100755
--- a/makefile
+++ b/makefile
@@ -1,4 +1,4 @@
-export (CC) = clang
+export (CC) = gcc
#TOPTARGETS := all
SUBDIRS := src
export PROROOT := ${CURDIR}
@@ -8,7 +8,9 @@ export PROROOT := ${CURDIR}
$(SUBDIRS):
$(MAKE) -C $@ $(MAKECMDGOALS)
-all: $(SUBRIRS)
+all: build install
+
+build: $(SUBDIRS)
install:
@rm -r /opt/ProjectMustang
@@ -17,4 +19,4 @@ install:
clean: $(SUBDIRS)
@rm $(wildcard build/bin/*)
-.PHONY: install all clean $(TOPTARGETS) $(SUBDIRS)
+.PHONY: install build all clean $(TOPTARGETS) $(SUBDIRS)
diff --git a/src/.DS_Store b/src/.DS_Store
index 29f25d4..e76ba5a 100644
--- a/src/.DS_Store
+++ b/src/.DS_Store
Binary files differ
diff --git a/src/cmd/.DS_Store b/src/cmd/.DS_Store
index ddbc73c..5047d2a 100644
--- a/src/cmd/.DS_Store
+++ b/src/cmd/.DS_Store
Binary files differ
diff --git a/src/cmd/cat/cat.c b/src/cmd/cat/cat.c
new file mode 100755
index 0000000..1c3e40a
--- /dev/null
+++ b/src/cmd/cat/cat.c
@@ -0,0 +1,54 @@
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdbool.h>
+
+void fileoutput(FILE *, const char *);
+bool isdir(const char *);
+
+/* concatinate files to a file stream */
+int main(int argc, char **argv)
+{
+ FILE *fp;
+ if (argc == 1) {
+ fileoutput(stdin, "stdin");
+ } else {
+ while (--argc > 0 && !ferror(stdout)) {
+ if (isdir(*++argv)) {
+ perror("cat");
+ continue;
+ }
+ if ((fp = fopen(*argv, "r")) == NULL) {
+ perror("cat");
+ continue;
+ }
+ fileoutput(fp, *argv);
+ }
+ }
+ if (ferror(stdout)) {
+ perror("cat");
+ return -1;
+ }
+ return 0;
+}
+
+/* fileoutput: output a file to stdout */
+void fileoutput(FILE *fp, const char *name)
+{
+ int c;
+ while ((c = getc(fp)) != EOF)
+ putc(c, stdout);
+ if (ferror(fp)) {
+ perror("cat");
+ }
+ fclose(fp);
+}
+
+/* isdir: return true if the file as the path is a directory */
+bool isdir(const char *path)
+{
+ struct stat sbuf;
+ stat(path, &sbuf);
+ return S_ISDIR(sbuf.st_mode);
+}
+
diff --git a/src/cmd/cat/makefile b/src/cmd/cat/makefile
new file mode 100755
index 0000000..bb8db9e
--- /dev/null
+++ b/src/cmd/cat/makefile
@@ -0,0 +1,12 @@
+CFLAGS=-Wall -Werror
+
+build: cat
+ @cp cat $(PROROOT)/build/bin/cat
+
+cat: cat.c
+ $(CC) $(CFLAGS) -o cat cat.c
+
+clean:
+ @rm -r cat
+
+.PHONY: build clean
diff --git a/src/cmd/coin/coin.c b/src/cmd/coin/coin.c
index c18d66c..4471959 100644
--- a/src/cmd/coin/coin.c
+++ b/src/cmd/coin/coin.c
@@ -4,61 +4,58 @@
#include <string.h>
#include <limits.h>
-unsigned long coinFlip (unsigned long times);
+int coinFlip (int times);
int
main (int argc, char *argv[])
{
- int nflag = 0, i, mflag = 0;
- unsigned long times = 1, tails, heads;
+ int nflag = 0, times = 1, i, tails, heads;
+ float ph, pt;
argc--;
for (i = 1; i <= argc; i++) {
- if (strcmp(argv[i], "-n") == 0)
+ if (strcmp(argv[i], "-n") == 0) {
nflag++;
- else if (strcmp(argv[i], "-m") == 0) {
- mflag++;
+ } else if (strcmp(argv[i], "-m") == 0) {
+ times = INT_MAX;
break;
- } else if (nflag == 1)
+ } else if (nflag == 1) {
times = atoi(argv[i]);
if (times == 0) {
printf("Non Integer Value Inputted\n");
return -1;
}
+ break;
+ }
}
- if (mflag == 1)
- times = ULONG_MAX;
-
if (times == 1)
printf("%s\n", coinFlip(times) ? "Heads" : "Tails");
else {
tails = coinFlip(times);
heads = times - tails;
- float ph = (float)heads/times, pt = (float)tails/times;
+ ph = (float)heads/times;
+ pt = (float)tails/times;
- printf("Heads: %lu\nTails: %ld\nProb Heads: %f\nProb Tails: %f\n", heads, tails, ph, pt);
+ printf("Heads: %d\nTails: %d\nProb Heads: %f\nProb Tails: %f\n", heads, tails, ph, pt);
}
return 0;
}
/* coinFlip: Flips a coin n numbers of times and returns the number of tails */
-unsigned long
-coinFlip (unsigned long times)
+int
+coinFlip (int times)
{
- unsigned long tails, i;
- int c;
+ int tails, i, c;
time_t t;
srand((unsigned) time(&t));
- tails = 0;
-
- for (i = 0; i < times; i++) {
+ for (i = tails = 0; i < times; i++) {
c = rand() % 2;
if (c == 1)
tails++;
}
return tails;
-} \ No newline at end of file
+}
diff --git a/src/cmd/coin/makefile b/src/cmd/coin/makefile
index cf8289d..7cd5d6e 100644..100755
--- a/src/cmd/coin/makefile
+++ b/src/cmd/coin/makefile
@@ -1,10 +1,12 @@
-all: coin
+CFLAGS=-Wall -Werror
+
+build: coin
@cp coin $(PROROOT)/build/bin/coin
coin: coin.c
- $(CC) -o coin coin.c
+ $(CC) $(CFLAGS) -o coin coin.c
clean:
@rm -r coin
-.PHONY: all clean \ No newline at end of file
+.PHONY: build clean
diff --git a/src/cmd/dice/dice.c b/src/cmd/dice/dice.c
index f211d67..b31670f 100644
--- a/src/cmd/dice/dice.c
+++ b/src/cmd/dice/dice.c
@@ -12,4 +12,4 @@ main (void)
printf("%d\n", (rand() % sides) + 1);
return 0;
-} \ No newline at end of file
+}
diff --git a/src/cmd/dice/makefile b/src/cmd/dice/makefile
index 5c0e384..2acc850 100644..100755
--- a/src/cmd/dice/makefile
+++ b/src/cmd/dice/makefile
@@ -1,10 +1,12 @@
-all: dice
+CFLAGS=-Wall -Werror
+
+build: dice
@cp dice $(PROROOT)/build/bin/dice
dice: dice.c
- $(CC) -o dice dice.c
+ $(CC) $(CFLAGS) -o dice dice.c
clean:
@rm -r dice
-.PHONY: all clean \ No newline at end of file
+.PHONY: build clean
diff --git a/src/cmd/echo/echo.c b/src/cmd/echo/echo.c
index 3dc8334..4733830 100644
--- a/src/cmd/echo/echo.c
+++ b/src/cmd/echo/echo.c
@@ -14,4 +14,4 @@ main (int argc, char *argv[])
printf("%s%c", argv[i], (i == argc) ? ((nflag == 1) ? '\0' : '\n') : ' ');
}
return 0;
-} \ No newline at end of file
+}
diff --git a/src/cmd/echo/makefile b/src/cmd/echo/makefile
index 0301f23..59f976f 100644..100755
--- a/src/cmd/echo/makefile
+++ b/src/cmd/echo/makefile
@@ -1,10 +1,12 @@
-all: echo
+CFLAGS=-Wall -Werror
+
+build: echo
@cp echo $(PROROOT)/build/bin/echo
echo: echo.c
- $(CC) -o echo echo.c
+ $(CC) $(CFLAGS) -o echo echo.c
clean:
@rm -r echo
-
-.PHONY: all clean \ No newline at end of file
+
+.PHONY: build clean
diff --git a/src/cmd/jsh/README.md b/src/cmd/jsh/README.md
new file mode 100755
index 0000000..db638ed
--- /dev/null
+++ b/src/cmd/jsh/README.md
@@ -0,0 +1,3 @@
+#J-Shell (jsh)
+
+J-Shell is a simple unix shell written in C.
diff --git a/src/cmd/jsh/jsh.c b/src/cmd/jsh/jsh.c
new file mode 100755
index 0000000..320a93d
--- /dev/null
+++ b/src/cmd/jsh/jsh.c
@@ -0,0 +1,81 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdbool.h>
+#include <ctype.h>
+
+size_t getargs(const size_t n, char *args[n], FILE * const stream);
+int shellexec(size_t n, char * const args[n]);
+
+static bool run = true;
+
+int main(int argc, char *argv[]) {
+ char *words[BUFSIZ] = {NULL};
+ FILE *fp = stdin;
+ size_t numberofwords = 0;
+ if (argc == 2) {
+ if ((fp = fopen(argv[1], "r")) == NULL) {
+ perror("jsh");
+ return EXIT_FAILURE;
+ }
+ }
+ while (run) {
+ printf("$ ");
+ numberofwords = getargs(BUFSIZ, words, fp);
+ shellexec(BUFSIZ, words);
+ for (int i = 0; i < numberofwords; i++) {
+ free(words[i]);
+ words[i] = NULL;
+ }
+ }
+ return 0;
+}
+
+size_t getargs(const size_t n, char *args[n], FILE * const stream) {
+ size_t i = 0;
+ char c = 0, s[BUFSIZ], *sp = s;
+ memset(s, '\0', sizeof(s));
+ while ((c = fgetc(stream)) != EOF && i < n && sp < s + BUFSIZ) {
+ if (isspace(c)) {
+ *sp = '\0';
+ args[i++] = strdup(s);
+ sp = s;
+ if (strcmp(args[i-1], "") == 0) {
+ free(args[i-1]);
+ args[i-1] = NULL;
+ i--;
+ }
+ if (c == '\n') {
+ break;
+ }
+ } else {
+ *sp++ = c;
+ }
+ }
+ return i;
+}
+
+int shellexec(size_t n, char * const args[n]) {
+ if (strcmp(args[0], "exit") == 0) {
+ run = false;
+ return 0;
+ }
+ pid_t pid = fork();
+ int status;
+ if (pid == 0) {
+ if (execvp(args[0], args) == -1) {
+ perror("jsh");
+ }
+ exit(EXIT_FAILURE);
+ } else if (pid < 0) {
+ perror("jsh");
+ exit(EXIT_FAILURE);
+ } else {
+ do {
+ waitpid(pid, &status, WUNTRACED);
+ } while (!WIFEXITED(status) && !WIFSIGNALED(status));
+ }
+ return 0;
+}
+
diff --git a/src/cmd/jsh/makefile b/src/cmd/jsh/makefile
new file mode 100755
index 0000000..72d7d68
--- /dev/null
+++ b/src/cmd/jsh/makefile
@@ -0,0 +1,12 @@
+CFLAGS=-Wall -Werror
+
+build: jsh
+ @cp jsh $(PROROOT)/build/bin/jsh
+
+jsh: jsh.c
+ $(CC) $(CFLAGS) -o jsh jsh.c
+
+clean:
+ @rm -r jsh
+
+.PHONY: build clean
diff --git a/src/cmd/ls/ls.c b/src/cmd/ls/ls.c
new file mode 100755
index 0000000..a937457
--- /dev/null
+++ b/src/cmd/ls/ls.c
@@ -0,0 +1,78 @@
+/* TODO:
+ * - add flags
+ * - add option to print more file information
+ */
+#include <stdio.h>
+#include <sys/types.h>
+#include <dirent.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <sys/stat.h>
+
+void dirwalk(DIR *);
+void error(char *);
+void printdirent(struct dirent *);
+void printfile(char *);
+
+/* print information about files and directories */
+int main(int argc, char **argv)
+{
+ DIR *dp;
+ if (argc == 1) {
+ if ((dp = opendir(".")) == NULL) {
+ perror("ls");
+ return -1;
+ }
+ dirwalk(dp);
+ } else if (argc == 2) {
+ if ((dp = opendir(argv[1])) == NULL) {
+ perror("ls");
+ return -1;
+ }
+ dirwalk(dp);
+ } else {
+ while (--argc > 0 && !ferror(stdout)) {
+ errno = 0;
+ if ((dp = opendir(*++argv)) == NULL) {
+ perror("ls");
+ continue;
+ }
+ dirwalk(dp);
+ }
+ }
+}
+
+/* dirwalk: read all the directory entries in a directory */
+void dirwalk(DIR *d)
+{
+ struct dirent *dir;
+ while ((dir = readdir(d)) != NULL) {
+ errno = 0;
+ if (strcmp(dir->d_name, ".") == 0 || strcmp(dir->d_name, "..") == 0)
+ continue;
+ printdirent(dir);
+ }
+ if (errno != 0) {
+ perror("ls");
+ }
+}
+
+/* printdirent: print a directory entry and any selected information */
+void printdirent(struct dirent *dir)
+{
+ printf("%s\n", dir->d_name);
+}
+
+/* printfile: print a file and any other selected information */
+void printfile(char *name)
+{
+ struct stat stbuf;
+ int e = stat(name, &stbuf);
+ if (e != 0) {
+ perror("ls");
+ return;
+ }
+ printf("%s\n", name);
+}
+
diff --git a/src/cmd/ls/makefile b/src/cmd/ls/makefile
new file mode 100755
index 0000000..d6a3c8d
--- /dev/null
+++ b/src/cmd/ls/makefile
@@ -0,0 +1,12 @@
+CFLAGS=-Wall -Werror
+
+build: ls
+ @cp ls $(PROROOT)/build/bin/ls
+
+ls: ls.c
+ $(CC) $(CFLAGS) -o ls ls.c
+
+clean:
+ @rm -r ls
+
+.PHONY: build clean
diff --git a/src/cmd/makefile b/src/cmd/makefile
index 52ddd59..481e827 100644
--- a/src/cmd/makefile
+++ b/src/cmd/makefile
@@ -1,4 +1,4 @@
-TOPTARGETS := all clean install
+TOPTARGETS := all build clean install
SUBDIRS := $(wildcard */.)
diff --git a/src/cmd/pwd/makefile b/src/cmd/pwd/makefile
new file mode 100755
index 0000000..85f4d06
--- /dev/null
+++ b/src/cmd/pwd/makefile
@@ -0,0 +1,12 @@
+CFLAGS=-Wall -Werror
+
+build: pwd
+ @cp pwd $(PROROOT)/build/bin/pwd
+
+pwd: pwd.c
+ $(CC) $(CFLAGS) -o pwd pwd.c
+
+clean:
+ @rm -r pwd
+
+.PHONY: build clean
diff --git a/src/cmd/pwd/pwd.c b/src/cmd/pwd/pwd.c
new file mode 100755
index 0000000..d8c4c2a
--- /dev/null
+++ b/src/cmd/pwd/pwd.c
@@ -0,0 +1,30 @@
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <errno.h>
+
+#define MAXLEN 1024
+
+/* print the current working directory */
+int main(void)
+{
+ char *cwd, i = 1;
+
+ do {
+ size_t size = i * MAXLEN;
+ cwd = (char *)malloc(size);
+ getcwd(cwd, size);
+ if (errno == ERANGE)
+ free((void *)cwd);
+ } while (errno == ERANGE && ++i < 10);
+
+ if (errno == ERANGE) {
+ fprintf(stderr, "pwd: directory name is too large\n");
+ return -1;
+ }
+
+ printf("%s\n", cwd);
+ free((void *)cwd);
+ return 0;
+}
+
diff --git a/src/makefile b/src/makefile
index 52ddd59..481e827 100644
--- a/src/makefile
+++ b/src/makefile
@@ -1,4 +1,4 @@
-TOPTARGETS := all clean install
+TOPTARGETS := all build clean install
SUBDIRS := $(wildcard */.)