diff options
-rw-r--r-- | Makefile | 5 | ||||
-rw-r--r-- | include/base.h | 1 | ||||
-rw-r--r-- | include/libfmt.h | 1 | ||||
-rw-r--r-- | rules.mk | 4 | ||||
-rw-r--r-- | share/paths.mk | 3 | ||||
-rw-r--r-- | src/base/error/exits.c | 2 | ||||
-rw-r--r-- | src/base/os/dirname.c | 12 | ||||
-rw-r--r-- | src/base/os/rules.mk | 1 | ||||
-rw-r--r-- | src/cmd/core/basename.c | 36 | ||||
-rw-r--r-- | src/cmd/core/cat.c | 52 | ||||
-rw-r--r-- | src/cmd/core/date.c | 37 | ||||
-rw-r--r-- | src/cmd/core/rules.mk | 19 | ||||
-rw-r--r-- | src/cmd/rc/exec.c | 74 | ||||
-rw-r--r-- | src/cmd/rc/exec.h | 2 | ||||
-rw-r--r-- | src/cmd/rc/lex.c | 17 | ||||
-rw-r--r-- | src/cmd/rc/main.c | 42 | ||||
-rw-r--r-- | src/cmd/rc/prompt.c | 7 | ||||
-rw-r--r-- | src/cmd/rc/rc.h | 8 | ||||
-rw-r--r-- | src/cmd/rc/rules.mk | 2 | ||||
-rw-r--r-- | src/cmd/rc/var.c | 30 | ||||
-rw-r--r-- | src/cmd/rules.mk | 3 | ||||
-rw-r--r-- | src/libfmt/fprint.c | 2 | ||||
-rw-r--r-- | src/libfmt/panic.c | 15 | ||||
-rw-r--r-- | src/libfmt/rules.mk | 1 |
24 files changed, 290 insertions, 86 deletions
@@ -1,3 +1,6 @@ +MAKEFLAGS += --no-builtin-rules +MAKEFLAGS += --no-builtin-variables + # Compiler, Linker, and Assembler CC := gcc AR := ar @@ -32,7 +35,7 @@ ELIBS := -L$(LIB_DIR) -lc # Named generic rules (must be evaluated lazily) COMPILE = @echo "CC "$(@:$(OBJ_DIR)/%=%);\ - $(CC) -MD $(CFLAGS) $(TCFLAGS) $(INCS) $(TCINCS) -o $@ -c $< + $(CC) -MD $(CFLAGS) $(TCFLAGS) $(INCS) $(TCINCS) -o $@ -c $< LINK = @echo "LD "$(@:$(OBJ_DIR)/%=%);\ $(CC) -MD $(CFLAGS) $(STATIC) $(TCFLAGS) -o $@ $(CINIT) $< $(CFINI) $(TCLIBS) $(ELIBS) COMPLINK = @echo "CC "$(@:$(OBJ_DIR)/%=%);\ diff --git a/include/base.h b/include/base.h index 822cc09..3e544e5 100644 --- a/include/base.h +++ b/include/base.h @@ -159,6 +159,7 @@ long io·tell(io·Stream *s); /* basic os helpers */ int os·exists(byte *path, int flag); +byte *os·dirname(byte *path); byte *os·basename(byte *path); int os·sep(void); diff --git a/include/libfmt.h b/include/libfmt.h index 7ba40a0..4c187fd 100644 --- a/include/libfmt.h +++ b/include/libfmt.h @@ -51,6 +51,7 @@ enum /* normal printing interface */ int fmt·print(char *fmt, ...); int fmt·fprint(int fd, char *fmt, ...); +void fmt·panic(char *fmt, ...); int fmt·sprint(char *buf, char *fmt, ...); int fmt·nsprint(int len, char *buf, char *fmt, ...); @@ -64,8 +64,8 @@ $(OBJ_DIR)/%.o: $(SRC_DIR)/%.c $(OBJ_DIR)/%.o: $(SRC_DIR)/%.s $(ASSEMBLE) -$(OBJ_DIR)/%: $(SRC_DIR)%.c - $(COMPLNK) +$(OBJ_DIR)/%: $(SRC_DIR)/%.c + $(COMPLINK) targets: $(SYS) $(LIBS) $(BINS) $(TEST) diff --git a/share/paths.mk b/share/paths.mk index 371ab7a..112c254 100644 --- a/share/paths.mk +++ b/share/paths.mk @@ -23,3 +23,6 @@ OBJS += $(UNIT_$(d)) TEST_$(d) := $(patsubst $(SRC_DIR)/%, $(TEST_DIR)/%, $(TEST_$(d):.c=)) TEST += $(TEST_$(d)) + +# useful path +o := $(patsubst $(SRC_DIR)/%, $(OBJ_DIR)/%, $(d)) diff --git a/src/base/error/exits.c b/src/base/error/exits.c index 6be7d3b..7fd83c5 100644 --- a/src/base/error/exits.c +++ b/src/base/error/exits.c @@ -6,6 +6,6 @@ exits(char *s) if(s == nil || *s == 0) exit(0); - fputs(s, stderr); + //fputs(s, stderr); exit(1); } diff --git a/src/base/os/dirname.c b/src/base/os/dirname.c new file mode 100644 index 0000000..c7ed2ee --- /dev/null +++ b/src/base/os/dirname.c @@ -0,0 +1,12 @@ +#include "internal.h" + +char* +os·dirname(char *path) +{ + char *sep; + + if((sep = strrchr(path, '/'))) + *sep = 0; + + return path; +} diff --git a/src/base/os/rules.mk b/src/base/os/rules.mk index bf1e71d..c6eb43e 100644 --- a/src/base/os/rules.mk +++ b/src/base/os/rules.mk @@ -1,4 +1,5 @@ SRCS_$(d)+=\ $(d)/os/basename.c\ + $(d)/os/dirname.c\ $(d)/os/exists.c\ $(d)/os/sep.c\ diff --git a/src/cmd/core/basename.c b/src/cmd/core/basename.c new file mode 100644 index 0000000..ba9d4c9 --- /dev/null +++ b/src/cmd/core/basename.c @@ -0,0 +1,36 @@ +#include <u.h> +#include <base.h> +#include <libfmt.h> + +static void +usage(void) +{ + fmt·fprint(2,"usage: %s [-d] path [suffix]\n", argv0); + exits("usage"); +} + +int +main(int argc, char *argv[]) +{ + int d; + long n; + char *p, *s; + + ARGBEGIN{ + case 'd': d = 1; break; + default: + usage(); + }ARGEND; + + if(argc < 1 || argc > 2) + usage(); + + p = d ? os·dirname(argv[0]) : os·basename(argv[0]); + if(argc>1){ + n = strlen(p)-strlen(argv[1]); + if(n >= 0 && strcmp(p+n, argv[1])==0) + p[n] = 0; + } + puts(p); + exits(nil); +} diff --git a/src/cmd/core/cat.c b/src/cmd/core/cat.c new file mode 100644 index 0000000..4f0929c --- /dev/null +++ b/src/cmd/core/cat.c @@ -0,0 +1,52 @@ +#include <u.h> +#include <base.h> +#include <libfmt.h> + +static void +usage(void) +{ + fmt·panic("usage: %s [-u] [file ...]\n", argv0); + exits("usage"); +} + +static void +cat(int fd, char *s) +{ + long n; + char buf[8192]; + + while((n=read(fd, buf, sizeof(buf)))>0){ + if(write(1, buf, n) != n) + fmt·panic("write error copying %s: %r", s); + } + + if(n<0) + fmt·panic("error reading %s: %r", s); +} + +int +main(int argc, char *argv[]) +{ + int fd; + + ARGBEGIN{ + case 'u': /* ignore */ break; + default: + usage(); + }ARGEND; + + if(!argc){ + cat(0, "<stdin>"); + exits(0); + } + + while(argc-- > 0){ + if((fd = open(*argv, O_RDONLY))<0) + fmt·panic("can't open %s: %r", *argv); + + cat(fd, *argv); + close(fd); + + argv++; + } +} diff --git a/src/cmd/core/date.c b/src/cmd/core/date.c new file mode 100644 index 0000000..225333f --- /dev/null +++ b/src/cmd/core/date.c @@ -0,0 +1,37 @@ +#include <u.h> +#include <base.h> +#include <libfmt.h> + +static void +usage(void) +{ + fmt·fprint(2, "usage: date [-un] [seconds]\n"); + exits("usage"); +} + +int +main(int argc, char *argv[]) +{ + int n, u; + ulong now; + + ARGBEGIN{ + case 'n': n = 1; break; + case 'u': u = 1; break; + default: usage(); + }ARGEND; + + if(argc == 1) + now = strtoul(*argv, 0, 0); + else + now = time(0); + + if(n) + fmt·print("%ld\n", now); + else if(u) + fmt·print("%s", asctime(gmtime(now))); + else + fmt·print("%s", ctime(now)); + + exits(nil); +} diff --git a/src/cmd/core/rules.mk b/src/cmd/core/rules.mk new file mode 100644 index 0000000..9c4eb76 --- /dev/null +++ b/src/cmd/core/rules.mk @@ -0,0 +1,19 @@ +include share/push.mk + +BINS_$(d):=\ + $(d)/basename\ + $(d)/cat + +include share/paths.mk +libbase:=\ + $(OBJ_DIR)/libfmt/libfmt.a\ + $(OBJ_DIR)/libutf/libutf.a\ + $(OBJ_DIR)/base/base.a + +$(o)/basename: $(d)/basename.c $(libbase) + $(COMPLINK) + +$(o)/cat: $(d)/cat.c $(libbase) + $(COMPLINK) + +include share/pop.mk diff --git a/src/cmd/rc/exec.c b/src/cmd/rc/exec.c index 51e352a..bd68bf5 100644 --- a/src/cmd/rc/exec.c +++ b/src/cmd/rc/exec.c @@ -36,8 +36,7 @@ struct Builtin builtin[]={ /* words and lists */ -static -void +static void pushword(char *str) { if(!runner->args) @@ -46,8 +45,7 @@ pushword(char *str) runner->args->word = makeword(str, runner->args->word); } -static -void +static void popword(void) { Word *w; @@ -63,8 +61,7 @@ popword(void) efree(w); } -static -Word* +static Word* copywords(Word *a, Word *tail) { Word *v = nil, **end; @@ -76,8 +73,7 @@ copywords(Word *a, Word *tail) return v; } -static -void +static void freewords(Word *w) { Word *n; @@ -89,8 +85,7 @@ freewords(Word *w) } } -static -void +static void freelist(Word *w) { Word *n; @@ -100,7 +95,6 @@ freelist(Word *w) efree(w); w = n; } - } static void @@ -154,7 +148,7 @@ path(char *w) if(strncmp(w, "/", 1)==0 || strncmp(w, "./", 2)==0 || strncmp(w, "../", 3)==0 - || (path = var("path")->val)==0) + || !(path = var("path")->val)) path=&nullpath; return path; @@ -262,7 +256,7 @@ xforkx(void) initchild(runner, 1); pushword("exec"); xx(); - exit(2); // reach here on failed execs + exit(errno); // reach here on failed execs break; default: // parent initparent(runner, pid, 0); @@ -505,7 +499,7 @@ xcd(void) static Code dotcmd[14] = { - [0] = {.i = 0}, + [0] = {.i = 1}, // offset by 1 to ensure it never gets freed [1] = {.f = Xmark}, [2] = {.f = Xword}, [3] = {.s = "0"}, @@ -557,7 +551,7 @@ xdot(void) } if(fd<0){ - print(shell.err, "failed open: %s: ", base); + print(shell.err, "%s: ", base); setstatus("failed open"); Xerror(".: failed open"); return; @@ -626,41 +620,43 @@ xfg(void) foreground(job, 1); } +static Code bootstrap[32] = +{ + [0] = {.i = 1}, + [1] = {.f = Xmark}, + [2] = {.f = Xword}, + [3] = {.s = "*"}, + [4] = {.f = Xassign}, + [5] = {.f = Xmark}, + [6] = {.f = Xmark}, + [7] = {.f = Xword}, + [8] = {.s = "*"}, + [9] = {.f = Xdollar}, + [10] = {.f = Xword}, + [11] = {.s = nil}, /* XXX: to be filled in by caller */ + [12] = {.f = Xword}, + [13] = {.s = "."}, + [14] = {.f = Xbasic}, + [15] = {.f = Xexit}, + [16] = {.i = 0} +}; + void -xboot(int argc, char *argv[]) +xboot(char *exe, int argc, char *argv[]) { int i; - Code bootstrap[32]; char num[12]; - i = 0; - bootstrap[i++].i = 1; - bootstrap[i++].f = Xmark; - bootstrap[i++].f = Xword; - bootstrap[i++].s="*"; - bootstrap[i++].f = Xassign; - bootstrap[i++].f = Xmark; - bootstrap[i++].f = Xmark; - bootstrap[i++].f = Xword; - bootstrap[i++].s="*"; - bootstrap[i++].f = Xdollar; - bootstrap[i++].f = Xword; - bootstrap[i++].s = "./cmds"; /* /dev/stdin"; */ - bootstrap[i++].f = Xword; - bootstrap[i++].s="."; - bootstrap[i++].f = Xbasic; - bootstrap[i++].f = Xexit; - bootstrap[i].i = 0; - + bootstrap[11].s = exe; run(bootstrap, 1, nil, 0); runner->pid = runner->pgid = shell.pid; pushlist(); // prime bootstrap argv - argv0 = strdup(argv[0]); - for(i = argc-1; i > 0; --i) + /* initialize $* */ + for(i = argc-1; i >= 0; --i) pushword(argv[i]); - /* main interpreter loop */ + /* main loop */ for(;;){ runner->code.i++; (*runner->code.exe[runner->code.i-1].f)(); diff --git a/src/cmd/rc/exec.h b/src/cmd/rc/exec.h index 992af35..28cbd80 100644 --- a/src/cmd/rc/exec.h +++ b/src/cmd/rc/exec.h @@ -60,4 +60,4 @@ void xfg(void); void xjob(void); void xfunc(Var *v); -void xboot(int argc, char *argv[]); +void xboot(char *exe, int argc, char *argv[]); diff --git a/src/cmd/rc/lex.c b/src/cmd/rc/lex.c index 9283404..f2c0a60 100644 --- a/src/cmd/rc/lex.c +++ b/src/cmd/rc/lex.c @@ -147,8 +147,11 @@ readc(void) if(runner->flag.eof) return EOF; - if(!prompt(&lexer.doprompt)) - exit(1); // XXX: hack for signal handling right now... + if(lexer.doprompt){ + if(!prompt()) + exit(1); // XXX: hack for signal handling right now... + lexer.doprompt = 0; + } c = get(runner->cmd.io); lexer.doprompt = lexer.doprompt || c=='\n' || c==EOF; @@ -290,7 +293,7 @@ readhere(void) yyerror("failed to make heredoc"); io = openfd(c); - prompt(&lexer.doprompt); + prompt(); beg=line, s=line, end=arrend(line)-1, len=PAGESIZE; while((c=get(runner->cmd.io))!=EOF){ @@ -318,7 +321,7 @@ readhere(void) printstr(io, beg); /* reset */ s = beg; - prompt(&lexer.doprompt); + prompt(); printchar(io, c); } @@ -351,6 +354,12 @@ isidentchar(int c) return c>' ' && !strchr("!\"#$%&'()+,-./:;<=>?@[\\]^`{|}~", c); } +void +initlexer(int f) +{ + lexer.doprompt=f; +} + int yylex(void) { diff --git a/src/cmd/rc/main.c b/src/cmd/rc/main.c index 81c7b8c..337470a 100644 --- a/src/cmd/rc/main.c +++ b/src/cmd/rc/main.c @@ -15,9 +15,9 @@ Shell shell = { 0 }; // functions void -initshell(void) +initshell(int *iflag) { - if((shell.interactive=0)){ //isatty(0))){ + if((*iflag=isatty(0))){ while(tcgetpgrp(0) != (shell.pid = getpgrp())) kill(-shell.pid, SIGTTIN); @@ -27,8 +27,7 @@ initshell(void) signal(SIGTSTP, SIG_IGN); signal(SIGTTIN, SIG_IGN); signal(SIGTTOU, SIG_IGN); - /* - * NOTE: if SIGCHLD is set to SIG_IGN then + /* NOTE: if SIGCHLD is set to SIG_IGN then * 1. children that terminate do not become zombies * 2. call a to wait() will block until all children have terminated * 3. the call to wait will fail with errno == ECHILD @@ -49,20 +48,47 @@ initshell(void) // ----------------------------------------------------------------------- // main point of entry +static void +usage(void) +{ + print(shell.err, "usage: %s [-cei] [file]", argv0); + exit(2); +} + int main(int argc, char *argv[]) { + int flag; + char *exe, *cmd = nil; shell.err = openfd(2); - /* yydebug=1; */ - initenv(); initpath(); initkeywords(); - initshell(); inithistory(); + initshell(&flag); + + ARGBEGIN{ + case 'e': shell.noerror = 1; break; + case 'i': shell.interactive = 1; break; + case 'I': shell.interactive = 0; break; + case 'c': + cmd = EARGF(usage()); + panicf("not implemented"); + break; + default: + usage(); + }ARGEND; + + if(!argc){ + shell.interactive |= flag; + exe = "/dev/stdin"; + }else + exe = *argv++, argc--; + + initlexer(shell.interactive); /* enablevi(); */ - xboot(argc, argv); + xboot(exe, argc, argv); /* unreachable */ } diff --git a/src/cmd/rc/prompt.c b/src/cmd/rc/prompt.c index 1122d54..5579b0d 100644 --- a/src/cmd/rc/prompt.c +++ b/src/cmd/rc/prompt.c @@ -10,11 +10,9 @@ resetprompt(void) } int -prompt(ushort *flag) +prompt(void) { - int f = *flag; - - if(f){ + if(runner->flag.user){ if(!readline(promptstr)){ runner->flag.eof = 1; return 0; @@ -29,7 +27,6 @@ prompt(ushort *flag) promptstr = " "; runner->line++; - *flag = 0; } return 1; diff --git a/src/cmd/rc/rc.h b/src/cmd/rc/rc.h index f5c8a6d..f52e4e2 100644 --- a/src/cmd/rc/rc.h +++ b/src/cmd/rc/rc.h @@ -157,7 +157,10 @@ struct Shell int pid; Io *err; int status; - int interactive; + struct{ + int interactive; + int noerror; + }; /* flags */ Thread *jobs; }; @@ -187,7 +190,7 @@ int addhistory(char *); /* prompt.c */ void resetprompt(void); -int prompt(ushort *); +int prompt(void); /* io.c */ Io *openfd(int fd); @@ -205,6 +208,7 @@ void printchar(Io *, int); /* lex.c */ int yylex(void); void yyerror(const char *msg); +void initlexer(int); void readhere(void); Tree *heredoc(Tree *); diff --git a/src/cmd/rc/rules.mk b/src/cmd/rc/rules.mk index 206c517..0758439 100644 --- a/src/cmd/rc/rules.mk +++ b/src/cmd/rc/rules.mk @@ -24,7 +24,7 @@ BINS_$(d) := $(d)/rc include share/paths.mk $(d)/parse.h $(d)/parse.c: $(d)/syntax.y - bison --debug --defines=$(<D)/parse.h --output=$(<D)/parse.c $(<) + bison --defines=$(<D)/parse.h --output=$(<D)/parse.c $(<) # local rules $(BINS_$(d)): $(OBJS_$(d)) $(OBJ_DIR)/libutf/libutf.a $(OBJ_DIR)/base/base.a $(d)/parse.h diff --git a/src/cmd/rc/var.c b/src/cmd/rc/var.c index e2d3e08..f67e8e3 100644 --- a/src/cmd/rc/var.c +++ b/src/cmd/rc/var.c @@ -18,8 +18,7 @@ static struct Keyword keywords[100]; // sparse map means less hits // ----------------------------------------------------------------------- // internals -static -int +static int hash(char *s, int len) { int h =0, i = 1; @@ -30,8 +29,7 @@ hash(char *s, int len) return h < 0 ? h+len : h; } -static -void +static void ·setvar(char *name, Word *val, int call) { Var *v = var(name); @@ -44,8 +42,7 @@ void v->update(v); } -static -char* +static char* list2strcolon(Word *words) { char *value, *s, *t; @@ -70,8 +67,7 @@ list2strcolon(Word *words) return value; } -static -void +static void littlepath(Var *v) { /* convert $path to $PATH */ @@ -86,8 +82,7 @@ littlepath(Var *v) ·setvar("PATH", w, 1); } -static -void +static void bigpath(Var *v) { /* convert $PATH to $path */ @@ -103,7 +98,7 @@ bigpath(Var *v) w = nil; l = &w; - /* Doesn't handle escaped colon nonsense. */ + /* we don't handle escaped colons */ if(p[0] == 0) p = nil; @@ -195,13 +190,6 @@ var(char *name) return globalvar(name); } -static -int -cmpenv(const void *a, const void *b) -{ - return strcmp(*(char**)a, *(char**)b); -} - char** mkenv(void) { @@ -218,7 +206,7 @@ mkenv(void) nchr+=strlen(a->str)+1; \ } - for(v= runner->local; v; v=v->link){ + for(v = runner->local; v; v=v->link){ BODY } for(h=globals; h!=arrend(globals); h++){ @@ -262,8 +250,8 @@ mkenv(void) *ep=0; - qsort((char *)env, nvar, sizeof ep[0], cmpenv); - return env; + sort·string(nvar, env); + return env; } void diff --git a/src/cmd/rules.mk b/src/cmd/rules.mk index 72cd0ce..8a9cfab 100644 --- a/src/cmd/rules.mk +++ b/src/cmd/rules.mk @@ -8,6 +8,9 @@ include share/push.mk DIR := $(d)/rc include $(DIR)/rules.mk +DIR := $(d)/core +include $(DIR)/rules.mk + DIR := $(d)/walk include $(DIR)/rules.mk diff --git a/src/libfmt/fprint.c b/src/libfmt/fprint.c index 26343f7..5077359 100644 --- a/src/libfmt/fprint.c +++ b/src/libfmt/fprint.c @@ -1,7 +1,7 @@ #include "internal.h" int -fprint(int fd, char *fmt, ...) +fmt·fprint(int fd, char *fmt, ...) { int n; va_list args; diff --git a/src/libfmt/panic.c b/src/libfmt/panic.c new file mode 100644 index 0000000..25ee277 --- /dev/null +++ b/src/libfmt/panic.c @@ -0,0 +1,15 @@ +#include "internal.h" + +void +fmt·panic(char *fmt, ...) +{ + char buf[256]; + va_list arg; + + va_start(arg, fmt); + fmt·vesprint(buf, arrend(buf), fmt, arg); + va_end(arg); + + fmt·fprint(2, "%s: %s\n", argv0 ? argv0 : "<prog>", buf); + exits("fatal"); +} diff --git a/src/libfmt/rules.mk b/src/libfmt/rules.mk index 9080bba..75a7bc7 100644 --- a/src/libfmt/rules.mk +++ b/src/libfmt/rules.mk @@ -16,6 +16,7 @@ SRCS_$(d):=\ $(d)/vnsprint.c\ $(d)/vprint.c\ $(d)/vwrite.c\ + $(d)/panic.c\ $(d)/write.c LIBS_$(d):=\ |