summaryrefslogtreecommitdiff
path: root/libc/gnu_i386/exec.c
diff options
context:
space:
mode:
Diffstat (limited to 'libc/gnu_i386/exec.c')
-rw-r--r--libc/gnu_i386/exec.c292
1 files changed, 292 insertions, 0 deletions
diff --git a/libc/gnu_i386/exec.c b/libc/gnu_i386/exec.c
new file mode 100644
index 0000000..411b744
--- /dev/null
+++ b/libc/gnu_i386/exec.c
@@ -0,0 +1,292 @@
+
+#include <errno.h>
+#include <sys/stat.h>
+
+extern char ** environ;
+
+#ifdef L_execl
+int
+execl(fname, arg0)
+char * fname, *arg0;
+{
+ return execve(fname, &arg0, environ);
+}
+#endif
+
+#ifdef L_execv
+int
+execv(fname, argv)
+char * fname, **argv;
+{
+ return execve(fname, argv, environ);
+}
+#endif
+
+#ifdef L_execle
+int
+execle(fname, arg0)
+char *fname, *arg0;
+{
+ char ** envp = &arg0;
+ while(*envp) envp++;
+ return execve(fname, &arg0, envp+1);
+}
+#endif
+
+#ifdef L_execve
+int
+execve(fname, argv, envp)
+char * fname;
+char ** argv;
+char ** envp;
+{
+ char **p;
+ int argv_len=0, argv_count=0;
+ int envp_len=0, envp_count=0;
+ int stack_bytes;
+ unsigned short * pip;
+ char * pcp, * stk_ptr, *baseoff;
+ int rv;
+
+ /* How much space for argv */
+ for(p=argv; p && *p && argv_len >= 0; p++)
+ {
+ argv_count++; argv_len += strlen(*p)+1;
+ }
+
+ /* How much space for envp */
+ for(p=envp; p && *p && envp_len >= 0; p++)
+ {
+ envp_count++; envp_len += strlen(*p)+1;
+ }
+
+ /* tot it all up */
+ stack_bytes = 2 /* argc */
+ + argv_count * 2 + 2 /* argv */
+ + argv_len
+ + envp_count * 2 + 2 /* envp */
+ + envp_len;
+
+ /* Allocate it */
+ if( argv_len < 0 || envp_len < 0 || stack_bytes <= 0
+ || (int)(stk_ptr = (char*)sbrk(stack_bytes)) == -1)
+ {
+ errno = ENOMEM;
+ return -1;
+ }
+
+/* Sanity check
+ printf("Argv = (%d,%d), Envp=(%d,%d), stack=%d\n",
+ argv_count, argv_len, envp_count, envp_len, stack_bytes);
+*/
+
+ /* Now copy in the strings */
+ pip=(unsigned short *) stk_ptr;
+ pcp=stk_ptr+2*(1+argv_count+1+envp_count+1);
+
+ /* baseoff = stk_ptr + stack_bytes; */
+ baseoff = stk_ptr;
+ *pip++ = argv_count;
+ for(p=argv; p && *p; p++)
+ {
+ int l;
+ *pip++ = pcp-baseoff;
+ l = strlen(*p)+1;
+ memcpy(pcp, *p, l);
+ pcp += l;
+ }
+ *pip++ = 0;
+
+ for(p=envp; p && *p; p++)
+ {
+ int l;
+ *pip++ = pcp-baseoff;
+ l = strlen(*p)+1;
+ memcpy(pcp, *p, l);
+ pcp += l;
+ }
+ *pip++ = 0;
+
+ rv = __exec(fname, stk_ptr, stack_bytes);
+ /* FIXME: This will probably have to interpret '#!' style exe's */
+ sbrk(-stack_bytes);
+ return rv;
+}
+#endif
+
+#ifdef L_execlp
+int
+execlp(fname, arg0)
+char * fname, *arg0;
+{
+ return execvp(fname, &arg0);
+}
+#endif
+
+#ifdef L_execvp
+int
+execvp(fname, argv)
+char * fname, **argv;
+{
+ char *pname = fname, *path;
+ int besterr = ENOENT;
+ int flen, plen;
+ char * bp = sbrk(0);
+
+ if( *fname != '/' && (path = getenv("PATH")) != 0 )
+ {
+ flen = strlen(fname)+2;
+
+ for(;path;)
+ {
+ if( *path == ':' || *path == '\0' )
+ {
+ tryrun(fname, argv);
+ if( errno == EACCES ) besterr = EACCES;
+ if( *path ) path++; else break;
+ }
+ else
+ {
+ char * p = strchr(path, ':');
+ if(p) *p = '\0';
+ plen = strlen(path);
+ pname = sbrk(plen+flen);
+
+ strcpy(pname, path);
+ strcat(pname, "/");
+ strcat(pname, fname);
+
+ tryrun(pname, argv);
+ if( errno == EACCES ) besterr = EACCES;
+
+ brk(pname);
+ pname = fname;
+ if(p) *p++ = ':';
+ path=p;
+ }
+ }
+ }
+
+ tryrun(pname, argv);
+ brk(bp);
+ if( errno == ENOENT || errno == 0 ) errno = besterr;
+ return -1;
+}
+
+static int tryrun(pname, argv)
+char * pname;
+char ** argv;
+{
+static char *shprog[] = {"/bin/sh", "", 0};
+ struct stat st;
+
+ if( stat(pname, &st) < 0 ) return;
+ if( !S_ISREG(st.st_mode) ) return;
+
+#ifdef __AS386_16__
+ __execvve(pname, (void*)0, argv, environ);
+ if( errno == ENOEXEC )
+ {
+ shprog[1] = pname;
+ __execvve(shprog[0], shprog, argv, environ);
+ }
+#else
+ execve(pname, argv, environ);
+ /* FIXME - running /bin/sh in 386 mode */
+#endif
+}
+
+#ifdef __AS386_16__
+static int
+__execvve(fname, interp, argv, envp)
+char * fname;
+char ** interp;
+char ** argv;
+char ** envp;
+{
+ char **p;
+ int argv_len=0, argv_count=0;
+ int envp_len=0, envp_count=0;
+ int stack_bytes;
+ unsigned short * pip;
+ char * pcp, * stk_ptr, *baseoff;
+ int rv;
+
+ /* How much space for argv */
+ for(p=interp; p && *p && argv_len >= 0; p++)
+ {
+ argv_count++; argv_len += strlen(*p)+1;
+ }
+ for(p=argv; p && *p && argv_len >= 0; p++)
+ {
+ argv_count++; argv_len += strlen(*p)+1;
+ }
+
+ /* How much space for envp */
+ for(p=envp; p && *p && envp_len >= 0; p++)
+ {
+ envp_count++; envp_len += strlen(*p)+1;
+ }
+
+ /* tot it all up */
+ stack_bytes = 2 /* argc */
+ + argv_count * 2 + 2 /* argv */
+ + argv_len
+ + envp_count * 2 + 2 /* envp */
+ + envp_len;
+
+ /* Allocate it */
+ if( argv_len < 0 || envp_len < 0 || stack_bytes <= 0
+ || (int)(stk_ptr = (char*)sbrk(stack_bytes)) == -1)
+ {
+ errno = ENOMEM;
+ return -1;
+ }
+
+/* Sanity check
+ printf("Argv = (%d,%d), Envp=(%d,%d), stack=%d\n",
+ argv_count, argv_len, envp_count, envp_len, stack_bytes);
+*/
+
+ /* Now copy in the strings */
+ pip=(unsigned short *) stk_ptr;
+ pcp=stk_ptr+2*(1+argv_count+1+envp_count+1);
+
+ /* baseoff = stk_ptr + stack_bytes; */
+ baseoff = stk_ptr;
+ *pip++ = argv_count;
+ for(p=interp; p && *p; p++)
+ {
+ int l;
+ *pip++ = pcp-baseoff;
+ l = strlen(*p)+1;
+ memcpy(pcp, *p, l);
+ pcp += l;
+ }
+ for(p=argv; p && *p; p++)
+ {
+ int l;
+ *pip++ = pcp-baseoff;
+ l = strlen(*p)+1;
+ memcpy(pcp, *p, l);
+ pcp += l;
+ }
+ *pip++ = 0;
+
+ for(p=envp; p && *p; p++)
+ {
+ int l;
+ *pip++ = pcp-baseoff;
+ l = strlen(*p)+1;
+ memcpy(pcp, *p, l);
+ pcp += l;
+ }
+ *pip++ = 0;
+
+ rv = __exec(fname, stk_ptr, stack_bytes);
+ /* FIXME: This will probably have to interpret '#!' style exe's */
+ sbrk(-stack_bytes);
+ return rv;
+}
+#endif
+#endif