aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/rc/sys.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/rc/sys.c')
-rw-r--r--src/cmd/rc/sys.c137
1 files changed, 137 insertions, 0 deletions
diff --git a/src/cmd/rc/sys.c b/src/cmd/rc/sys.c
new file mode 100644
index 0000000..807359d
--- /dev/null
+++ b/src/cmd/rc/sys.c
@@ -0,0 +1,137 @@
+#include "rc.h"
+
+// -----------------------------------------------------------------------
+// internal
+
+static
+char**
+mkargv(Word *args)
+{
+ char **argv=emalloc((count(args)+2)*sizeof(char *));
+ char **argp=argv+1; /* leave one at front for runcoms */
+
+ for(;args;args=args->link)
+ *argp++=args->str;
+ *argp=nil;
+
+ return argv;
+}
+
+static
+Word*
+envval(char *s)
+{
+ Word *v;
+ char *t, c;
+
+ for(t=s; *t && *t!='\1'; t++)
+ ;
+
+ c = *t;
+ *t = '\0';
+
+ v = makeword(s, (c=='\0') ? nil : envval(t+1));
+ *t=c;
+
+ return v;
+}
+
+// -----------------------------------------------------------------------
+// exported
+
+void
+initenv(void)
+{
+ extern char **environ;
+
+ char *s;
+ char **env;
+
+ for(env=environ; *env; env++) {
+ for(s=*env; *s && *s != '(' && *s != '='; s++)
+ ;
+ switch(*s){
+ case '\0':
+ break;
+ case '(': /* ignore functions */
+ break;
+ case '=':
+ *s = '\0';
+ setvar(*env, envval(s+1));
+ *s = '=';
+ break;
+ }
+ }
+}
+
+void
+execute(Word *cmd, Word *path)
+{
+ int nc;
+ char **argv = mkargv(cmd);
+ char **env = mkenv();
+ char file[1024];
+
+ for(; path; path=path->link){
+ nc = strlen(path->str);
+ if(nc < arrlen(file)){
+ strcpy(file, path->str);
+ if(file[0]){
+ strcat(file, "/");
+ nc++;
+ }
+ if(nc+strlen(argv[1]) < arrlen(file)){
+ strcat(file, argv[1]);
+ execve(file, argv+1, env);
+ }else
+ fatal("command name too long");
+ }
+ }
+ print(shell.err, "could not execute command: %s\n", argv[1]);
+ efree(argv);
+}
+
+void
+redirect(Redir *r)
+{
+ if(r){
+ redirect(r->link);
+ switch(r->type){
+ case Ropen:
+ if(r->from != r->to){
+ dup2(r->from, r->to);
+ close(r->from);
+ }
+ break;
+ case Rdupfd:
+ dup2(r->from, r->to); // TODO: error checking
+ break;
+ case Rclose:
+ close(r->from);
+ break;
+ default:
+ fatal("unrecognized redirection type %d\n", r->type);
+ }
+ }
+}
+
+int
+mapfd(int fd)
+{
+ Redir *r;
+ for(r = runner->redir.end; r; r = r->link){
+ switch(r->type){
+ case Rclose:
+ if(r->from == fd)
+ fd = -1;
+ break;
+ case Rdupfd:
+ case Ropen:
+ if(r->to == fd)
+ fd = r->from;
+ break;
+ }
+ }
+
+ return fd;
+}