git: 9front

Download patch

ref: 00da90ce6ee61be1567f8817eee381498dc7b3f8
parent: 0f680ca73d159088abcf975456d4e836c63bebb0
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Mon Feb 22 17:25:21 EST 2016

rc: terminate rc when exec fails, cleanup

The execexec() function should never return, as it irreversably changes
the filedescriptor table for the new program. This means rc's internal
filedesciptors for reading the script get implicitely closed and we cannot
continue the rc interpreter when Execute() fails. So Execute() now sets the
error status, and execexec() runs Xexit() in case Execute() returns.

--- a/sys/src/cmd/rc/glob.c
+++ b/sys/src/cmd/rc/glob.c
@@ -101,7 +101,7 @@
 		return;
 	}
 	globname = emalloc(globlen);
-	globname[0]='\0';
+	memset(globname, 0, globlen);
 	globdir(p, (uchar *)globname);
 	efree(globname);
 	if(svglobv==globv){
--- a/sys/src/cmd/rc/haventfork.c
+++ b/sys/src/cmd/rc/haventfork.c
@@ -189,7 +189,7 @@
 {
 	char **argv;
 	char file[1024];
-	int nc;
+	int nc, mc;
 	word *path;
 	int pid;
 
@@ -196,23 +196,20 @@
 	if(runq->argv->words==0)
 		return -1;
 	argv = mkargv(runq->argv->words);
-
+	mc = strlen(argv[1])+1;
 	for(path = searchpath(runq->argv->words->word);path;path = path->next){
 		nc = strlen(path->word);
-		if(nc < sizeof file - 1){	/* 1 for / */
-			strcpy(file, path->word);
-			if(file[0]){
-				strcat(file, "/");
-				nc++;
-			}
-			if(nc+strlen(argv[1])<sizeof(file)){
-				strcat(file, argv[1]);
-				pid = ForkExecute(file, argv+1, mapfd(0), mapfd(1), mapfd(2));
-				if(pid >= 0){
-					free(argv);
-					return pid;
-				}
-			}
+		if(nc + mc >= sizeof file - 1)	/* 1 for / */
+			continue;
+		if(nc > 0){
+			memmove(file, path->word, nc);
+			file[nc++] = '/';
+		}
+		memmove(file+nc, argv[1], mc);
+		pid = ForkExecute(file, argv+1, mapfd(0), mapfd(1), mapfd(2));
+		if(pid >= 0){
+			free(argv);
+			return pid;
 		}
 	}
 	free(argv);
--- a/sys/src/cmd/rc/plan9.c
+++ b/sys/src/cmd/rc/plan9.c
@@ -305,32 +305,9 @@
 
 /* not used on plan 9 */
 int
-ForkExecute(char *file, char **argv, int sin, int sout, int serr)
+ForkExecute(char *, char **, int, int, int)
 {
-	int pid;
-
-	if(access(file, 1) != 0)
-		return -1;
-	switch(pid = fork()){
-	case -1:
-		return -1;
-	case 0:
-		if(sin >= 0)
-			dup(sin, 0);
-		else
-			close(0);
-		if(sout >= 0)
-			dup(sout, 1);
-		else
-			close(1);
-		if(serr >= 0)
-			dup(serr, 2);
-		else
-			close(2);
-		exec(file, argv);
-		exits(file);
-	}
-	return pid;
+	return -1;
 }
 
 void
@@ -337,40 +314,27 @@
 Execute(word *args, word *path)
 {
 	char **argv = mkargv(args);
-	char file[1024], errstr[1024];
-	int nc;
+	char file[1024];
+	int nc, mc;
 
 	Updenv();
-	errstr[0] = '\0';
+	mc = strlen(argv[1])+1;
 	for(;path;path = path->next){
 		nc = strlen(path->word);
-		if(nc < sizeof file - 1){	/* 1 for / */
-			strcpy(file, path->word);
-			if(file[0]){
-				strcat(file, "/");
-				nc++;
-			}
-			if(nc + strlen(argv[1]) < sizeof file){
-				strcat(file, argv[1]);
-				exec(file, argv+1);
-				rerrstr(errstr, sizeof errstr);
-				/*
-				 * if file exists and is executable, exec should
-				 * have worked, unless it's a directory or an
-				 * executable for another architecture.  in
-				 * particular, if it failed due to lack of
-				 * swap/vm (e.g., arg. list too long) or other
-				 * allocation failure, stop searching and print
-				 * the reason for failure.
-				 */
-				if (strstr(errstr, " allocat") != nil ||
-				    strstr(errstr, " full") != nil)
-					break;
-			}
-			else werrstr("command name too long");
+		if(nc + mc >= sizeof file - 1){	/* 1 for / */
+			werrstr("command path name too long");
+			continue;
 		}
+		if(nc > 0){
+			memmove(file, path->word, nc);
+			file[nc++] = '/';
+		}
+		memmove(file+nc, argv[1], mc);
+		exec(file, argv+1);
 	}
-	pfmt(err, "%s: %s\n", argv[1], errstr);
+	rerrstr(file, sizeof file);
+	setstatus(file);
+	pfmt(err, "%s: %s\n", argv[1], file);
 	efree((char *)argv);
 }
 #define	NDIR	256		/* shoud be a better way */
@@ -464,7 +428,7 @@
 	}
 	if(dir[f].i == dir[f].n)
 		return 0;
-	strcpy(p, dir[f].dbuf[dir[f].i].name);
+	strncpy((char*)p, dir[f].dbuf[dir[f].i].name, NDIR);
 	dir[f].i++;
 	return 1;
 }
--- a/sys/src/cmd/rc/simple.c
+++ b/sys/src/cmd/rc/simple.c
@@ -55,7 +55,6 @@
 			/* fork and wait is redundant */
 			pushword("exec");
 			execexec();
-			Xexit();
 		}
 		else{
 			flush(err);
@@ -120,6 +119,7 @@
 	doredir(runq->redir);
 	Execute(runq->argv->words, searchpath(runq->argv->words->word));
 	poplist();
+	Xexit();
 }
 
 void
--- a/sys/src/cmd/rc/subr.c
+++ b/sys/src/cmd/rc/subr.c
@@ -9,7 +9,6 @@
 	void *p = Malloc(n);
 	if(p==0)
 		panic("Can't malloc %d bytes", n);
-/*	if(err){ pfmt(err, "malloc %d->%p\n", n, p); flush(err); } /**/
 	return p;
 }
 
@@ -16,8 +15,8 @@
 void*
 erealloc(void *p, long n)
 {
-	p = Realloc(p, n);		/* botch, should be Realloc */
-	if(p==0)
+	p = Realloc(p, n);
+	if(p==0 && n!=0)
 		panic("Can't realloc %d bytes\n", n);
 	return p;
 }
@@ -25,7 +24,6 @@
 void
 efree(void *p)
 {
-/*	pfmt(err, "free %p\n", p); flush(err); /**/
 	if(p)
 		free(p);
 	else pfmt(err, "free 0\n");
--- a/sys/src/cmd/rc/unix.c
+++ b/sys/src/cmd/rc/unix.c
@@ -275,6 +275,7 @@
 		}
 	}
 Bad:
+	setstatus(msg);
 	pfmt(err, "%s: %s\n", argv[1], msg);
 	efree((char *)env);
 	efree((char *)argv);
@@ -319,7 +320,7 @@
 	struct direct *dp = readdir(dirlist[f]);
 	if(dp==0)
 		return 0;
-	strcpy(p, dp->d_name);
+	strncpy(p, dp->d_name, NDIR);
 	return 1;
 }
 Closedir(f){
--- a/sys/src/cmd/rc/win32.c
+++ b/sys/src/cmd/rc/win32.c
@@ -299,6 +299,7 @@
 		}
 	}
 	rerrstr(file, sizeof file);
+	setstatus(file);
 	pfmt(err, "%s: %s\n", argv[1], file);
 	efree((char *)argv);
 }
@@ -393,7 +394,7 @@
 	}
 	if(dir[f].i == dir[f].n)
 		return 0;
-	strcpy(p, dir[f].dbuf[dir[f].i].name);
+	strncpy(p, dir[f].dbuf[dir[f].i].name, NDIR);
 	dir[f].i++;
 	return 1;
 }
--