From ab400c0be5577cab2a66d242183887ebbd61717f Mon Sep 17 00:00:00 2001 From: Nicholas Date: Wed, 17 Nov 2021 08:22:03 -0800 Subject: checkin --- src/cmd/core/basename.c | 36 ++++++++++++++++++++++++ src/cmd/core/cat.c | 52 ++++++++++++++++++++++++++++++++++ src/cmd/core/date.c | 37 +++++++++++++++++++++++++ src/cmd/core/rules.mk | 19 +++++++++++++ src/cmd/rc/exec.c | 74 +++++++++++++++++++++++-------------------------- src/cmd/rc/exec.h | 2 +- src/cmd/rc/lex.c | 17 +++++++++--- src/cmd/rc/main.c | 42 ++++++++++++++++++++++------ src/cmd/rc/prompt.c | 7 ++--- src/cmd/rc/rc.h | 8 ++++-- src/cmd/rc/rules.mk | 2 +- src/cmd/rc/var.c | 30 ++++++-------------- src/cmd/rules.mk | 3 ++ 13 files changed, 248 insertions(+), 81 deletions(-) create mode 100644 src/cmd/core/basename.c create mode 100644 src/cmd/core/cat.c create mode 100644 src/cmd/core/date.c create mode 100644 src/cmd/core/rules.mk (limited to 'src/cmd') 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 +#include +#include + +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 +#include +#include + +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, ""); + 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 +#include +#include + +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=$(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 -- cgit v1.2.1