From 6d50d5b97d49a74a8faf587ec2bbf234626adf0c Mon Sep 17 00:00:00 2001 From: Nicholas Noll Date: Tue, 19 Oct 2021 14:16:54 -0700 Subject: Feat(rc): added subshell commands and cd builtin Slowly chipping away at a decent feature list. Subshell commands are executed by @{ ... }. --- sys/cmd/rc/code.c | 12 ++ sys/cmd/rc/exec.c | 86 +++++++++++++- sys/cmd/rc/exec.h | 5 +- sys/cmd/rc/lex.c | 8 ++ sys/cmd/rc/parse.c | 334 +++++++++++++++++++++++++++------------------------- sys/cmd/rc/parse.h | 36 +++--- sys/cmd/rc/rc.h | 3 + sys/cmd/rc/syntax.y | 10 +- sys/cmd/rc/wait.c | 107 +++++++++-------- 9 files changed, 366 insertions(+), 235 deletions(-) (limited to 'sys') diff --git a/sys/cmd/rc/code.c b/sys/cmd/rc/code.c index 719e63b..38cc06a 100644 --- a/sys/cmd/rc/code.c +++ b/sys/cmd/rc/code.c @@ -110,6 +110,18 @@ walk(Tree *node) storepc(addr); break; + case Tsubshell: + emitf(Xsubshell); + addr = emiti(0); + walk(node->child[0]); + emitf(Xexit); + storepc(addr); + break; + + case Tbang: + walk(node->child[0]); + emitf(Xbang); + case Tword: emitf(Xword); emits(strdup(node->str)); diff --git a/sys/cmd/rc/exec.c b/sys/cmd/rc/exec.c index 37c289b..217f7ee 100644 --- a/sys/cmd/rc/exec.c +++ b/sys/cmd/rc/exec.c @@ -17,6 +17,7 @@ static Word nullpath = { .str="", .link=nil }; struct Builtin builtin[]={ {".", xdot}, + {"cd", xcd}, {"fg", xfg}, {"jobs", xjob}, 0, @@ -326,7 +327,7 @@ xdot(void) Thread *old; char file[512]; - popword(); + popword(); // "." #if 0 if(proc->args->word && strcmp(proc->args->word->str, "-i")==0){ iflag = 1; @@ -382,6 +383,49 @@ xdot(void) //ndot++; } +void +xcd(void) +{ + Word *arg; + Word *cdpath; + char dir[512]; + + popword(); // cd + + arg = runner->args->word; + switch(count(arg)){ + default: + print(shell.err, "usage: cd [directory]\n"); + break; + case 0: + arg = var("home")->val; + if(count(arg) >= 1){ + if(chdir(arg->str) < 0) + print(shell.err, "failed cd: %s\n", strerror(errno)); + }else{ + print(shell.err, "ambiguous cd: $home empty\n"); + } + break; + + case 1: + // TODO: add cdpath + cdpath = &nullpath; + for(; cdpath; cdpath = cdpath->link){ + strcpy(dir, cdpath->str); + if(dir[0]) + strcat(dir,"/"); + strcat(dir, arg->str); + if(chdir(dir) < 0){ + print(shell.err, "failed cd %s: %s\n", dir, strerror(errno)); + } + break; + } + break; + } + + poplist(); +} + void xjob(void) { @@ -680,6 +724,37 @@ Xasync(void) } } +void +Xsubshell(void) +{ + int pid; + + switch(pid=fork()){ + case -1: + Xerror("fork failed: try again"); + break; + + case 0: // child + clearwait(runner); + if(shell.interactive){ // NOTE: this needs to read off its caller's interactivity + setpid(getpid()); + tcsetpgrp(0, runner->pgid); + defaultsignal(); + } + run(runner->code.exe, runner->code.i+1, runner->local, 1); + runner->link = nil; + break; + + default: // parent + setpid(pid); + addwait(runner, pid); + waitfor(runner, pid); // wait until child finishes + runner->code.i = runner->code.exe[runner->code.i].i; // jump to end of subshell command and continue execution + } +} + + + void Xbasic(void) { @@ -780,6 +855,15 @@ Xflat(void) efree(str); } +void +Xbang(void) +{ + if(runner->status) + runner->status = 0; + else + runner->status = 1; +} + void Xexit(void) { diff --git a/sys/cmd/rc/exec.h b/sys/cmd/rc/exec.h index 0df01d0..9ad0f3d 100644 --- a/sys/cmd/rc/exec.h +++ b/sys/cmd/rc/exec.h @@ -15,8 +15,10 @@ void Xlocal(void); void Xreadcmd(void); void Xunlocal(void); void Xassign(void); +void Xbang(void); void Xasync(void); -void Xbasic(void); // Xbasic(args) run command and wait for result +void Xbasic(void); // Xbasic(args) run command and wait for result +void Xsubshell(void); void Xword(void); void Xcount(void); void Xflat(void); @@ -24,6 +26,7 @@ void Xflat(void); void Xerror(char*); /* builtin commands */ +void xcd(void); void xfg(void); void xdot(void); void xjob(void); diff --git a/sys/cmd/rc/lex.c b/sys/cmd/rc/lex.c index 06737ba..4325882 100644 --- a/sys/cmd/rc/lex.c +++ b/sys/cmd/rc/lex.c @@ -191,6 +191,14 @@ yylex(void) put1('&'); return '&'; + case '@': + put1('@'); + return Tsubshell; + + case '!': + put1('!'); + return Tbang; + case '$': if(nextis('#')){ put2('$','#'); diff --git a/sys/cmd/rc/parse.c b/sys/cmd/rc/parse.c index b88e8ab..c53f514 100644 --- a/sys/cmd/rc/parse.c +++ b/sys/cmd/rc/parse.c @@ -110,43 +110,44 @@ enum yysymbol_kind_t YYSYMBOL_Tif = 5, /* Tif */ YYSYMBOL_Telse = 6, /* Telse */ YYSYMBOL_Tbang = 7, /* Tbang */ - YYSYMBOL_Targs = 8, /* Targs */ - YYSYMBOL_Tindex = 9, /* Tindex */ - YYSYMBOL_Tbasic = 10, /* Tbasic */ - YYSYMBOL_Tparen = 11, /* Tparen */ - YYSYMBOL_Tblock = 12, /* Tblock */ - YYSYMBOL_Twhile = 13, /* Twhile */ - YYSYMBOL_14_n_ = 14, /* '\n' */ - YYSYMBOL_15_ = 15, /* '$' */ - YYSYMBOL_Tcount = 16, /* Tcount */ - YYSYMBOL_Tflat = 17, /* Tflat */ - YYSYMBOL_18_ = 18, /* '(' */ - YYSYMBOL_19_ = 19, /* ')' */ - YYSYMBOL_20_ = 20, /* '{' */ - YYSYMBOL_21_ = 21, /* '}' */ - YYSYMBOL_22_ = 22, /* ';' */ - YYSYMBOL_23_ = 23, /* '&' */ - YYSYMBOL_24_ = 24, /* '=' */ - YYSYMBOL_25_ = 25, /* '^' */ - YYSYMBOL_YYACCEPT = 26, /* $accept */ - YYSYMBOL_rc = 27, /* rc */ - YYSYMBOL_line = 28, /* line */ - YYSYMBOL_body = 29, /* body */ - YYSYMBOL_paren = 30, /* paren */ - YYSYMBOL_block = 31, /* block */ - YYSYMBOL_cmds = 32, /* cmds */ - YYSYMBOL_cmdsln = 33, /* cmdsln */ - YYSYMBOL_ifbody = 34, /* ifbody */ - YYSYMBOL_assign = 35, /* assign */ - YYSYMBOL_cmd = 36, /* cmd */ - YYSYMBOL_basic = 37, /* basic */ - YYSYMBOL_atom = 38, /* atom */ - YYSYMBOL_word = 39, /* word */ - YYSYMBOL_executable = 40, /* executable */ - YYSYMBOL_nonkeyword = 41, /* nonkeyword */ - YYSYMBOL_keyword = 42, /* keyword */ - YYSYMBOL_wordsnl = 43, /* wordsnl */ - YYSYMBOL_nl = 44 /* nl */ + YYSYMBOL_Tsubshell = 8, /* Tsubshell */ + YYSYMBOL_Targs = 9, /* Targs */ + YYSYMBOL_Tindex = 10, /* Tindex */ + YYSYMBOL_Tbasic = 11, /* Tbasic */ + YYSYMBOL_Tparen = 12, /* Tparen */ + YYSYMBOL_Tblock = 13, /* Tblock */ + YYSYMBOL_Twhile = 14, /* Twhile */ + YYSYMBOL_15_n_ = 15, /* '\n' */ + YYSYMBOL_16_ = 16, /* '$' */ + YYSYMBOL_Tcount = 17, /* Tcount */ + YYSYMBOL_Tflat = 18, /* Tflat */ + YYSYMBOL_19_ = 19, /* '(' */ + YYSYMBOL_20_ = 20, /* ')' */ + YYSYMBOL_21_ = 21, /* '{' */ + YYSYMBOL_22_ = 22, /* '}' */ + YYSYMBOL_23_ = 23, /* ';' */ + YYSYMBOL_24_ = 24, /* '&' */ + YYSYMBOL_25_ = 25, /* '=' */ + YYSYMBOL_26_ = 26, /* '^' */ + YYSYMBOL_YYACCEPT = 27, /* $accept */ + YYSYMBOL_rc = 28, /* rc */ + YYSYMBOL_line = 29, /* line */ + YYSYMBOL_body = 30, /* body */ + YYSYMBOL_paren = 31, /* paren */ + YYSYMBOL_block = 32, /* block */ + YYSYMBOL_cmds = 33, /* cmds */ + YYSYMBOL_cmdsln = 34, /* cmdsln */ + YYSYMBOL_ifbody = 35, /* ifbody */ + YYSYMBOL_assign = 36, /* assign */ + YYSYMBOL_cmd = 37, /* cmd */ + YYSYMBOL_basic = 38, /* basic */ + YYSYMBOL_atom = 39, /* atom */ + YYSYMBOL_word = 40, /* word */ + YYSYMBOL_executable = 41, /* executable */ + YYSYMBOL_nonkeyword = 42, /* nonkeyword */ + YYSYMBOL_keyword = 43, /* keyword */ + YYSYMBOL_wordsnl = 44, /* wordsnl */ + YYSYMBOL_nl = 45 /* nl */ }; typedef enum yysymbol_kind_t yysymbol_kind_t; @@ -472,21 +473,21 @@ union yyalloc #endif /* !YYCOPY_NEEDED */ /* YYFINAL -- State number of the termination state. */ -#define YYFINAL 31 +#define YYFINAL 37 /* YYLAST -- Last index in YYTABLE. */ -#define YYLAST 91 +#define YYLAST 97 /* YYNTOKENS -- Number of terminals. */ -#define YYNTOKENS 26 +#define YYNTOKENS 27 /* YYNNTS -- Number of nonterminals. */ #define YYNNTS 19 /* YYNRULES -- Number of rules. */ -#define YYNRULES 41 +#define YYNRULES 45 /* YYNSTATES -- Number of states. */ -#define YYNSTATES 61 +#define YYNSTATES 67 /* YYMAXUTOK -- Last valid token kind. */ -#define YYMAXUTOK 270 +#define YYMAXUTOK 271 /* YYTRANSLATE(TOKEN-NUM) -- Symbol number corresponding to TOKEN-NUM @@ -501,18 +502,18 @@ union yyalloc static const yytype_int8 yytranslate[] = { 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 14, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 15, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 15, 2, 23, 2, - 18, 19, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 22, - 2, 24, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 16, 2, 24, 2, + 19, 20, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 23, + 2, 25, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 25, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 26, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 20, 2, 21, 2, 2, 2, 2, + 2, 2, 2, 21, 2, 22, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, @@ -526,8 +527,8 @@ static const yytype_int8 yytranslate[] = 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 3, 4, - 5, 6, 7, 8, 9, 10, 11, 12, 13, 16, - 17 + 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 17, 18 }; #if YYDEBUG @@ -536,9 +537,9 @@ static const yytype_int8 yyrline[] = { 0, 36, 36, 37, 40, 41, 44, 45, 48, 51, 54, 55, 58, 59, 62, 63, 66, 69, 70, 71, - 72, 73, 76, 77, 86, 87, 90, 91, 94, 95, - 98, 99, 100, 101, 102, 106, 106, 113, 114, 115, - 117, 119 + 72, 73, 74, 75, 78, 79, 88, 89, 92, 93, + 96, 97, 100, 101, 102, 103, 104, 108, 108, 108, + 108, 115, 116, 117, 119, 121 }; #endif @@ -555,11 +556,12 @@ static const char *yysymbol_name (yysymbol_kind_t yysymbol) YY_ATTRIBUTE_UNUSED; static const char *const yytname[] = { "\"end of file\"", "error", "\"invalid token\"", "Tword", "Twords", - "Tif", "Telse", "Tbang", "Targs", "Tindex", "Tbasic", "Tparen", "Tblock", - "Twhile", "'\\n'", "'$'", "Tcount", "Tflat", "'('", "')'", "'{'", "'}'", - "';'", "'&'", "'='", "'^'", "$accept", "rc", "line", "body", "paren", - "block", "cmds", "cmdsln", "ifbody", "assign", "cmd", "basic", "atom", - "word", "executable", "nonkeyword", "keyword", "wordsnl", "nl", YY_NULLPTR + "Tif", "Telse", "Tbang", "Tsubshell", "Targs", "Tindex", "Tbasic", + "Tparen", "Tblock", "Twhile", "'\\n'", "'$'", "Tcount", "Tflat", "'('", + "')'", "'{'", "'}'", "';'", "'&'", "'='", "'^'", "$accept", "rc", "line", + "body", "paren", "block", "cmds", "cmdsln", "ifbody", "assign", "cmd", + "basic", "atom", "word", "executable", "nonkeyword", "keyword", + "wordsnl", "nl", YY_NULLPTR }; static const char * @@ -569,7 +571,7 @@ yysymbol_name (yysymbol_kind_t yysymbol) } #endif -#define YYPACT_NINF (-22) +#define YYPACT_NINF (-19) #define yypact_value_is_default(Yyn) \ ((Yyn) == YYPACT_NINF) @@ -583,13 +585,13 @@ yysymbol_name (yysymbol_kind_t yysymbol) STATE-NUM. */ static const yytype_int8 yypact[] = { - 14, -22, -17, 73, 73, 73, -22, 52, 10, 2, - -22, 52, 52, 1, 73, 16, -22, 52, -22, -22, - -22, -22, -22, -22, -22, -22, 68, 7, -22, 52, - 13, -22, -22, -22, -22, -22, -22, -22, -5, 73, - 73, 18, 46, -22, -22, -5, -22, -22, -22, 73, - -5, -22, -22, -22, 27, -22, -22, -22, -22, 46, - -22 + 18, -19, -18, 24, 24, 78, 78, 78, -19, 24, + 5, 7, -19, 24, 24, -4, 78, 41, -19, 24, + -19, -19, -19, -19, -19, -19, -19, -19, -19, -19, + -19, -19, 72, -6, -19, 24, 29, -19, -19, -19, + -19, -19, -19, -19, -2, 78, 78, 10, 55, -19, + -19, -2, -19, -19, -19, 78, -2, -19, -19, -19, + 43, -19, -19, -19, -19, 55, -19 }; /* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM. @@ -597,27 +599,27 @@ static const yytype_int8 yypact[] = means the default is an error. */ static const yytype_int8 yydefact[] = { - 17, 30, 0, 0, 0, 0, 37, 17, 0, 0, - 19, 17, 17, 4, 18, 22, 28, 17, 40, 35, - 36, 31, 24, 25, 33, 34, 0, 0, 12, 17, - 6, 1, 3, 5, 20, 10, 11, 26, 23, 0, - 0, 0, 17, 38, 32, 39, 9, 7, 13, 0, - 16, 29, 8, 41, 19, 21, 14, 27, 40, 17, - 15 + 17, 32, 0, 17, 17, 0, 0, 0, 41, 17, + 0, 0, 19, 17, 17, 4, 18, 24, 30, 17, + 44, 22, 23, 37, 38, 39, 40, 33, 26, 27, + 35, 36, 0, 0, 12, 17, 6, 1, 3, 5, + 20, 10, 11, 28, 25, 0, 0, 0, 17, 42, + 34, 43, 9, 7, 13, 0, 16, 31, 8, 45, + 19, 21, 14, 29, 44, 17, 15 }; /* YYPGOTO[NTERM-NUM]. */ static const yytype_int8 yypgoto[] = { - -22, -22, 11, -8, -22, 4, 15, -22, -22, -22, - 0, -22, 3, -21, -22, -1, -22, -22, -14 + -19, -19, 42, -7, -19, 9, 2, -19, -19, -19, + 0, -19, 4, 6, -19, 1, -19, -19, -10 }; /* YYDEFGOTO[NTERM-NUM]. */ static const yytype_int8 yydefgoto[] = { - 0, 8, 9, 27, 18, 10, 28, 29, 55, 12, - 30, 14, 37, 38, 15, 16, 23, 26, 42 + 0, 10, 11, 33, 20, 12, 34, 35, 61, 14, + 36, 16, 43, 44, 17, 18, 29, 32, 48 }; /* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM. If @@ -625,53 +627,53 @@ static const yytype_int8 yydefgoto[] = number is the opposite. If YYTABLE_NINF, syntax error. */ static const yytype_int8 yytable[] = { - 13, 17, 22, 22, 22, 45, 21, 24, 25, 41, - 31, 13, 34, 22, -2, 11, 32, 1, 50, 2, - 49, 47, 33, 35, 36, 22, 11, 48, 46, 3, - 4, 5, 6, 58, 7, 35, 36, 52, 22, 22, - 39, 40, 56, 51, 59, 0, 54, 0, 22, 1, - 0, 2, 57, 0, 0, 1, 0, 2, 0, 60, - 53, 3, 4, 5, 6, 0, 7, 3, 4, 5, - 6, 1, 7, 19, 20, 0, 1, 0, 19, 20, - 0, 0, 43, 3, 4, 5, 6, 44, 3, 4, - 5, 6 + 15, 19, 13, 21, 22, 37, 28, 28, 28, 27, + 30, 31, 47, 15, 40, 13, 52, 28, -2, 41, + 42, 1, 38, 2, 55, 3, 4, 1, 53, 2, + 58, 3, 4, 28, 5, 6, 7, 8, 51, 9, + 5, 6, 7, 8, 54, 9, 28, 28, 62, 64, + 57, 56, 41, 42, 65, 39, 28, 60, 1, 63, + 2, 0, 3, 4, 0, 66, 45, 46, 0, 0, + 59, 5, 6, 7, 8, 1, 9, 23, 24, 25, + 26, 1, 0, 23, 24, 25, 26, 49, 5, 6, + 7, 8, 50, 0, 5, 6, 7, 8 }; static const yytype_int8 yycheck[] = { - 0, 18, 3, 4, 5, 26, 3, 4, 5, 17, - 0, 11, 12, 14, 0, 0, 14, 3, 39, 5, - 25, 29, 11, 22, 23, 26, 11, 14, 21, 15, - 16, 17, 18, 6, 20, 22, 23, 19, 39, 40, - 24, 25, 42, 40, 58, -1, 42, -1, 49, 3, - -1, 5, 49, -1, -1, 3, -1, 5, -1, 59, - 14, 15, 16, 17, 18, -1, 20, 15, 16, 17, - 18, 3, 20, 5, 6, -1, 3, -1, 5, 6, - -1, -1, 14, 15, 16, 17, 18, 19, 15, 16, - 17, 18 + 0, 19, 0, 3, 4, 0, 5, 6, 7, 5, + 6, 7, 19, 13, 14, 13, 22, 16, 0, 23, + 24, 3, 15, 5, 26, 7, 8, 3, 35, 5, + 20, 7, 8, 32, 16, 17, 18, 19, 32, 21, + 16, 17, 18, 19, 15, 21, 45, 46, 48, 6, + 46, 45, 23, 24, 64, 13, 55, 48, 3, 55, + 5, -1, 7, 8, -1, 65, 25, 26, -1, -1, + 15, 16, 17, 18, 19, 3, 21, 5, 6, 7, + 8, 3, -1, 5, 6, 7, 8, 15, 16, 17, + 18, 19, 20, -1, 16, 17, 18, 19 }; /* YYSTOS[STATE-NUM] -- The symbol kind of the accessing symbol of state STATE-NUM. */ static const yytype_int8 yystos[] = { - 0, 3, 5, 15, 16, 17, 18, 20, 27, 28, - 31, 32, 35, 36, 37, 40, 41, 18, 30, 5, - 6, 38, 41, 42, 38, 38, 43, 29, 32, 33, - 36, 0, 14, 28, 36, 22, 23, 38, 39, 24, - 25, 29, 44, 14, 19, 39, 21, 29, 14, 25, - 39, 38, 19, 14, 31, 34, 36, 38, 6, 44, - 36 + 0, 3, 5, 7, 8, 16, 17, 18, 19, 21, + 28, 29, 32, 33, 36, 37, 38, 41, 42, 19, + 31, 37, 37, 5, 6, 7, 8, 39, 42, 43, + 39, 39, 44, 30, 33, 34, 37, 0, 15, 29, + 37, 23, 24, 39, 40, 25, 26, 30, 45, 15, + 20, 40, 22, 30, 15, 26, 40, 39, 20, 15, + 32, 35, 37, 39, 6, 45, 37 }; /* YYR1[RULE-NUM] -- Symbol kind of the left-hand side of rule RULE-NUM. */ static const yytype_int8 yyr1[] = { - 0, 26, 27, 27, 28, 28, 29, 29, 30, 31, - 32, 32, 33, 33, 34, 34, 35, 36, 36, 36, - 36, 36, 37, 37, 38, 38, 39, 39, 40, 40, - 41, 41, 41, 41, 41, 42, 42, 43, 43, 43, - 44, 44 + 0, 27, 28, 28, 29, 29, 30, 30, 31, 32, + 33, 33, 34, 34, 35, 35, 36, 37, 37, 37, + 37, 37, 37, 37, 38, 38, 39, 39, 40, 40, + 41, 41, 42, 42, 42, 42, 42, 43, 43, 43, + 43, 44, 44, 44, 45, 45 }; /* YYR2[RULE-NUM] -- Number of symbols on the right-hand side of rule RULE-NUM. */ @@ -679,9 +681,9 @@ static const yytype_int8 yyr2[] = { 0, 2, 0, 2, 1, 2, 1, 2, 3, 3, 2, 2, 1, 2, 1, 4, 3, 0, 1, 1, - 2, 4, 1, 2, 1, 1, 1, 3, 1, 3, - 1, 2, 3, 2, 2, 1, 1, 0, 2, 2, - 0, 2 + 2, 4, 2, 2, 1, 2, 1, 1, 1, 3, + 1, 3, 1, 2, 3, 2, 2, 1, 1, 1, + 1, 0, 2, 2, 0, 2 }; @@ -1417,149 +1419,161 @@ yyreduce: case 2: /* rc: %empty */ #line 36 "sys/cmd/rc/syntax.y" { return 0; } -#line 1421 "sys/cmd/rc/parse.c" +#line 1423 "sys/cmd/rc/parse.c" break; case 3: /* rc: line '\n' */ #line 37 "sys/cmd/rc/syntax.y" { return compile((yyvsp[-1].tree)); } -#line 1427 "sys/cmd/rc/parse.c" +#line 1429 "sys/cmd/rc/parse.c" break; case 5: /* line: cmds line */ #line 41 "sys/cmd/rc/syntax.y" { (yyval.tree) = maketree2(';', (yyvsp[-1].tree), (yyvsp[0].tree)); } -#line 1433 "sys/cmd/rc/parse.c" +#line 1435 "sys/cmd/rc/parse.c" break; case 7: /* body: cmdsln body */ #line 45 "sys/cmd/rc/syntax.y" { (yyval.tree) = maketree2(';', (yyvsp[-1].tree), (yyvsp[0].tree)); } -#line 1439 "sys/cmd/rc/parse.c" +#line 1441 "sys/cmd/rc/parse.c" break; case 8: /* paren: '(' body ')' */ #line 48 "sys/cmd/rc/syntax.y" { (yyval.tree) = maketree1(Tparen, (yyvsp[-1].tree)); } -#line 1445 "sys/cmd/rc/parse.c" +#line 1447 "sys/cmd/rc/parse.c" break; case 9: /* block: '{' body '}' */ #line 51 "sys/cmd/rc/syntax.y" { (yyval.tree) = maketree1(Tblock, (yyvsp[-1].tree)); } -#line 1451 "sys/cmd/rc/parse.c" +#line 1453 "sys/cmd/rc/parse.c" break; case 11: /* cmds: cmd '&' */ #line 55 "sys/cmd/rc/syntax.y" { (yyval.tree) = maketree1('&', (yyvsp[-1].tree)); } -#line 1457 "sys/cmd/rc/parse.c" +#line 1459 "sys/cmd/rc/parse.c" break; case 14: /* ifbody: cmd */ #line 62 "sys/cmd/rc/syntax.y" { (yyval.tree) = maketree2(Tif, nil, (yyvsp[0].tree)); } -#line 1463 "sys/cmd/rc/parse.c" +#line 1465 "sys/cmd/rc/parse.c" break; case 15: /* ifbody: block Telse nl cmd */ #line 63 "sys/cmd/rc/syntax.y" { (yyval.tree) = maketree3(Tif, nil, (yyvsp[-3].tree), (yyvsp[-2].tree)); } -#line 1469 "sys/cmd/rc/parse.c" +#line 1471 "sys/cmd/rc/parse.c" break; case 16: /* assign: executable '=' word */ #line 66 "sys/cmd/rc/syntax.y" { (yyval.tree) = maketree2('=', (yyvsp[-2].tree), (yyvsp[0].tree)); } -#line 1475 "sys/cmd/rc/parse.c" +#line 1477 "sys/cmd/rc/parse.c" break; case 17: /* cmd: %empty */ #line 69 "sys/cmd/rc/syntax.y" { (yyval.tree) = nil; } -#line 1481 "sys/cmd/rc/parse.c" +#line 1483 "sys/cmd/rc/parse.c" break; case 18: /* cmd: basic */ #line 70 "sys/cmd/rc/syntax.y" { (yyval.tree) = maketree1(Tbasic, (yyvsp[0].tree)); } -#line 1487 "sys/cmd/rc/parse.c" +#line 1489 "sys/cmd/rc/parse.c" break; case 20: /* cmd: assign cmd */ #line 72 "sys/cmd/rc/syntax.y" { (yyval.tree) = hangchild1((yyvsp[-1].tree), (yyvsp[0].tree), 2); } -#line 1493 "sys/cmd/rc/parse.c" +#line 1495 "sys/cmd/rc/parse.c" break; case 21: /* cmd: Tif paren nl ifbody */ #line 73 "sys/cmd/rc/syntax.y" { (yyval.tree) = hangchild1((yyvsp[-2].tree), (yyvsp[-3].tree), 0); } -#line 1499 "sys/cmd/rc/parse.c" +#line 1501 "sys/cmd/rc/parse.c" + break; + + case 22: /* cmd: Tbang cmd */ +#line 74 "sys/cmd/rc/syntax.y" + { (yyval.tree) = maketree1(Tbang, (yyvsp[0].tree)); } +#line 1507 "sys/cmd/rc/parse.c" + break; + + case 23: /* cmd: Tsubshell cmd */ +#line 75 "sys/cmd/rc/syntax.y" + { (yyval.tree) = maketree1(Tsubshell, (yyvsp[0].tree)); } +#line 1513 "sys/cmd/rc/parse.c" break; - case 23: /* basic: basic word */ -#line 77 "sys/cmd/rc/syntax.y" + case 25: /* basic: basic word */ +#line 79 "sys/cmd/rc/syntax.y" { (yyval.tree) = maketree2(Targs, (yyvsp[-1].tree), (yyvsp[0].tree)); } -#line 1505 "sys/cmd/rc/parse.c" +#line 1519 "sys/cmd/rc/parse.c" break; - case 25: /* atom: keyword */ -#line 87 "sys/cmd/rc/syntax.y" + case 27: /* atom: keyword */ +#line 89 "sys/cmd/rc/syntax.y" { (yyval.tree) = maketree1(Tword, (yyvsp[0].tree)); } -#line 1511 "sys/cmd/rc/parse.c" +#line 1525 "sys/cmd/rc/parse.c" break; - case 27: /* word: word '^' atom */ -#line 91 "sys/cmd/rc/syntax.y" + case 29: /* word: word '^' atom */ +#line 93 "sys/cmd/rc/syntax.y" { (yyval.tree) = maketree2('^', (yyvsp[-2].tree), (yyvsp[0].tree)); } -#line 1517 "sys/cmd/rc/parse.c" +#line 1531 "sys/cmd/rc/parse.c" break; - case 29: /* executable: executable '^' atom */ -#line 95 "sys/cmd/rc/syntax.y" + case 31: /* executable: executable '^' atom */ +#line 97 "sys/cmd/rc/syntax.y" { (yyval.tree) = maketree2('^', (yyvsp[-2].tree), (yyvsp[0].tree)); } -#line 1523 "sys/cmd/rc/parse.c" +#line 1537 "sys/cmd/rc/parse.c" break; - case 31: /* nonkeyword: '$' atom */ -#line 99 "sys/cmd/rc/syntax.y" + case 33: /* nonkeyword: '$' atom */ +#line 101 "sys/cmd/rc/syntax.y" { (yyval.tree) = maketree1('$', (yyvsp[0].tree)); } -#line 1529 "sys/cmd/rc/parse.c" +#line 1543 "sys/cmd/rc/parse.c" break; - case 32: /* nonkeyword: '(' wordsnl ')' */ -#line 100 "sys/cmd/rc/syntax.y" + case 34: /* nonkeyword: '(' wordsnl ')' */ +#line 102 "sys/cmd/rc/syntax.y" { (yyval.tree) = (yyvsp[-1].tree); } -#line 1535 "sys/cmd/rc/parse.c" +#line 1549 "sys/cmd/rc/parse.c" break; - case 33: /* nonkeyword: Tcount atom */ -#line 101 "sys/cmd/rc/syntax.y" + case 35: /* nonkeyword: Tcount atom */ +#line 103 "sys/cmd/rc/syntax.y" { (yyval.tree) = maketree1(Tcount, (yyvsp[0].tree)); } -#line 1541 "sys/cmd/rc/parse.c" +#line 1555 "sys/cmd/rc/parse.c" break; - case 34: /* nonkeyword: Tflat atom */ -#line 102 "sys/cmd/rc/syntax.y" + case 36: /* nonkeyword: Tflat atom */ +#line 104 "sys/cmd/rc/syntax.y" { (yyval.tree) = maketree1(Tflat, (yyvsp[0].tree)); } -#line 1547 "sys/cmd/rc/parse.c" +#line 1561 "sys/cmd/rc/parse.c" break; - case 37: /* wordsnl: %empty */ -#line 113 "sys/cmd/rc/syntax.y" + case 41: /* wordsnl: %empty */ +#line 115 "sys/cmd/rc/syntax.y" { (yyval.tree) = nil; } -#line 1553 "sys/cmd/rc/parse.c" +#line 1567 "sys/cmd/rc/parse.c" break; - case 39: /* wordsnl: wordsnl word */ -#line 115 "sys/cmd/rc/syntax.y" + case 43: /* wordsnl: wordsnl word */ +#line 117 "sys/cmd/rc/syntax.y" {(yyval.tree) = (!(yyvsp[-1].tree)) ? ((!(yyvsp[0].tree)) ? nil : (yyvsp[0].tree)) : ((!(yyvsp[0].tree)) ? (yyvsp[-1].tree) : maketree2(Twords, (yyvsp[-1].tree), (yyvsp[0].tree))); } -#line 1559 "sys/cmd/rc/parse.c" +#line 1573 "sys/cmd/rc/parse.c" break; -#line 1563 "sys/cmd/rc/parse.c" +#line 1577 "sys/cmd/rc/parse.c" default: break; } @@ -1783,5 +1797,5 @@ yyreturnlab: return yyresult; } -#line 120 "sys/cmd/rc/syntax.y" +#line 122 "sys/cmd/rc/syntax.y" diff --git a/sys/cmd/rc/parse.h b/sys/cmd/rc/parse.h index 85be043..b42cc2b 100644 --- a/sys/cmd/rc/parse.h +++ b/sys/cmd/rc/parse.h @@ -59,14 +59,15 @@ extern int yydebug; Tif = 260, /* Tif */ Telse = 261, /* Telse */ Tbang = 262, /* Tbang */ - Targs = 263, /* Targs */ - Tindex = 264, /* Tindex */ - Tbasic = 265, /* Tbasic */ - Tparen = 266, /* Tparen */ - Tblock = 267, /* Tblock */ - Twhile = 268, /* Twhile */ - Tcount = 269, /* Tcount */ - Tflat = 270 /* Tflat */ + Tsubshell = 263, /* Tsubshell */ + Targs = 264, /* Targs */ + Tindex = 265, /* Tindex */ + Tbasic = 266, /* Tbasic */ + Tparen = 267, /* Tparen */ + Tblock = 268, /* Tblock */ + Twhile = 269, /* Twhile */ + Tcount = 270, /* Tcount */ + Tflat = 271 /* Tflat */ }; typedef enum yytokentype yytoken_kind_t; #endif @@ -80,14 +81,15 @@ extern int yydebug; #define Tif 260 #define Telse 261 #define Tbang 262 -#define Targs 263 -#define Tindex 264 -#define Tbasic 265 -#define Tparen 266 -#define Tblock 267 -#define Twhile 268 -#define Tcount 269 -#define Tflat 270 +#define Tsubshell 263 +#define Targs 264 +#define Tindex 265 +#define Tbasic 266 +#define Tparen 267 +#define Tblock 268 +#define Twhile 269 +#define Tcount 270 +#define Tflat 271 /* Value type. */ #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED @@ -97,7 +99,7 @@ union YYSTYPE struct Tree *tree; -#line 101 "sys/cmd/rc/parse.h" +#line 103 "sys/cmd/rc/parse.h" }; typedef union YYSTYPE YYSTYPE; diff --git a/sys/cmd/rc/rc.h b/sys/cmd/rc/rc.h index 55a4eb2..606ca7b 100644 --- a/sys/cmd/rc/rc.h +++ b/sys/cmd/rc/rc.h @@ -207,8 +207,11 @@ void execute(Word *, Word*); /* wait.c */ void addwait(Thread *, int); +void delwait(Thread *, int); void clearwait(Thread*); + int waitall(Thread *); +int waitfor(Thread *, int); void killzombies(void); diff --git a/sys/cmd/rc/syntax.y b/sys/cmd/rc/syntax.y index 469260f..6334819 100644 --- a/sys/cmd/rc/syntax.y +++ b/sys/cmd/rc/syntax.y @@ -1,4 +1,4 @@ -%token Tword Twords Tif Telse Tbang +%token Tword Twords Tif Telse Tbang Tsubshell %token Targs Tindex %token Tbasic Tparen Tblock @@ -14,7 +14,7 @@ /* operator precendence: lowest first */ %left Twhile Telse %left '\n' -%left Tbang +%left Tbang Tsubshell %right '$' Tcount Tflat %right Tindex @@ -24,7 +24,7 @@ } %type line cmds cmdsln body paren block ifbody assign; %type cmd basic executable nonkeyword keyword word words wordsnl atom arg args; -%type Tbang; +%type Tbang Tsubshell Tindex; %type Tword Tif Telse; /* grammar */ @@ -71,6 +71,8 @@ cmd: | block | assign cmd %prec Tbang { $$ = hangchild1($1, $2, 2); } | Tif paren nl ifbody { $$ = hangchild1($2, $1, 0); } +| Tbang cmd { $$ = maketree1(Tbang, $2); } +| Tsubshell cmd { $$ = maketree1(Tsubshell, $2); } basic: executable @@ -103,7 +105,7 @@ nonkeyword: //| '`' block { $$ = maketree1('`', $2); } keyword: - Tif|Telse + Tif|Telse|Tbang|Tsubshell words: /* empty */ { $$ = nil; } diff --git a/sys/cmd/rc/wait.c b/sys/cmd/rc/wait.c index e3dcea1..6a8d859 100644 --- a/sys/cmd/rc/wait.c +++ b/sys/cmd/rc/wait.c @@ -84,6 +84,39 @@ shouldwait(Thread *job) return 0; } +static inline +void +notify(Thread *job, struct WaitMsg msg) +{ + int i; + for(i=0; i < job->wait.len; i++){ + if(job->wait.on[i].pid == msg.pid){ + job->status = msg.status; + switch(msg.type){ + case Pstop: + print(shell.err, "%d: suspended\n", msg.pid); + job->wait.status = Pstop; + job->wait.on[i].status = Pstop; + break; + + case Psig: + print(shell.err, "%d: terminated by signal %d\n", msg.pid, msg.status); + /* fallthrough */ + case Pdone: + job->wait.on[i].status = Pdone; + delwait(job, msg.pid); + if(!job->wait.len) + job->wait.status = Pdone; + break; + + default: + fatal("%d: unrecognized message type %d\n", msg.pid, msg.type); + } + break; + } + } +} + // ----------------------------------------------------------------------- // exported @@ -140,34 +173,31 @@ waitall(Thread *job) return 0; } - for(i=0; i < job->wait.len; i++){ - if(job->wait.on[i].pid == msg.pid){ - job->status = msg.status; - switch(msg.type){ - case Pstop: - print(shell.err, "%d: suspended\n", msg.pid); - job->wait.status = Pstop; - job->wait.on[i].status = Pstop; - break; - - case Psig: - print(shell.err, "%d: terminated by signal %d\n", msg.pid, msg.status); - /* fallthrough */ - case Pdone: - job->wait.on[i].status = Pdone; - delwait(job, msg.pid); - if(!job->wait.len) - job->wait.status = Pdone; - break; - - default: - fatal("%d: unrecognized message type %d\n", msg.pid, msg.type); - } - break; - } + notify(job, msg); + } + return 1; +} + +int +waitfor(Thread *job, int pid) +{ + int i; + Thread *t; + struct WaitMsg msg; + + while(shouldwait(job) && await(-job->pgid, WUNTRACED, &msg)){ + if(msg.pid == 0){ + perror("wait for"); + return 0; } + + notify(job, msg); + /* allow for an early exit */ + if(msg.pid == pid) + return 1; } return 1; + } void @@ -197,30 +227,3 @@ killzombies(void) } } } - -#if 0 -int -waitfor(int pid) -{ - Thread *t; - struct WaitMsg w; - - if(pid >= 0 && !havewait(pid)) - return 0; - - while(await(-proc->pgid, WUNTRACED, &w)){ - delwait(w.pid); - if(w.pid == pid){ - if(w.signal) - print(errio, "pid[%d]: signal: %d\n", w.pid, w.status); - return 1; - } - for(t=proc->link; t; t=t->link){ - if(t->pid == w.pid) - t->pid = -1; - } - } - - return 0; -} -#endif -- cgit v1.2.1