summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
exec arguments
-rw-r--r--Makefile10
-rw-r--r--Notes2
-rw-r--r--echo.c14
-rw-r--r--mkfs.c5
-rw-r--r--syscall.c70
-rw-r--r--userfs.c3
-rw-r--r--usertests.c2
7 files changed, 89 insertions, 17 deletions
diff --git a/Makefile b/Makefile
index d45bc6f..d405284 100644
--- a/Makefile
+++ b/Makefile
@@ -66,6 +66,10 @@ usertests : usertests.o $(ULIB)
$(LD) -N -e main -Ttext 0 -o usertests usertests.o $(ULIB)
$(OBJDUMP) -S usertests > usertests.asm
+echo : echo.o $(ULIB)
+ $(LD) -N -e main -Ttext 0 -o echo echo.o $(ULIB)
+ $(OBJDUMP) -S echo > echo.asm
+
userfs : userfs.o $(ULIB)
$(LD) -N -e main -Ttext 0 -o userfs userfs.o $(ULIB)
$(OBJDUMP) -S userfs > userfs.asm
@@ -73,12 +77,12 @@ userfs : userfs.o $(ULIB)
mkfs : mkfs.c fs.h
cc -o mkfs mkfs.c
-fs.img : mkfs usertests
- ./mkfs fs.img usertests
+fs.img : mkfs usertests echo
+ ./mkfs fs.img usertests echo
-include *.d
clean :
rm -f *.o *.d *.asm vectors.S parport.out \
bootblock kernel xv6.img user1 userfs usertests \
- fs.img mkfs
+ fs.img mkfs echo
diff --git a/Notes b/Notes
index f0955b8..22658fc 100644
--- a/Notes
+++ b/Notes
@@ -161,3 +161,5 @@ need to lock bufs in bio between bread and brelse
test 14-character file names
and file arguments longer than 14
and directories longer than one sector
+
+kalloc() can return 0; do callers handle this right?
diff --git a/echo.c b/echo.c
new file mode 100644
index 0000000..89e19a9
--- /dev/null
+++ b/echo.c
@@ -0,0 +1,14 @@
+#include "user.h"
+
+int
+main(int argc, char *argv[])
+{
+ int i;
+
+ for(i = 0; i < argc; i++){
+ puts(argv[i]);
+ puts(" ");
+ }
+ puts("\n");
+ exit();
+}
diff --git a/mkfs.c b/mkfs.c
index ae66dfd..1022adf 100644
--- a/mkfs.c
+++ b/mkfs.c
@@ -144,11 +144,6 @@ winode(uint inum, struct dinode *ip)
dip = ((struct dinode *) buf) + (inum % IPB);
*dip = *ip;
wsect(bn, buf);
- printf("wi %d size %d addrs %d %d...\n",
- inum,
- xint(dip->size),
- xint(dip->addrs[0]),
- xint(dip->addrs[1]));
}
void
diff --git a/syscall.c b/syscall.c
index a855774..ab9dd17 100644
--- a/syscall.c
+++ b/syscall.c
@@ -58,17 +58,20 @@ fetcharg(int argno, void *ip)
return fetchint(curproc[cpu()], esp + 4 + 4*argno, ip);
}
-// check that an entire string is valid in user space
+// check that an entire string is valid in user space.
+// returns the length, not including null, or -1.
int
checkstring(uint s)
{
char c;
+ int len = 0;
while(1){
if(fetchbyte(curproc[cpu()], s, &c) < 0)
return -1;
if(c == '\0')
- return 0;
+ return len;
+ len++;
s++;
}
}
@@ -244,14 +247,17 @@ int
sys_exec(void)
{
struct proc *cp = curproc[cpu()];
- uint arg0, sz;
- int i;
+ uint arg0, arg1, sz=0, ap, sp, p1, p2;
+ int i, nargs, argbytes, len;
struct inode *ip;
struct elfhdr elf;
struct proghdr ph;
+ char *mem = 0;
if(fetcharg(0, &arg0) < 0)
return -1;
+ if(fetcharg(1, &arg1) < 0)
+ return -1;
if(checkstring(arg0) < 0)
return -1;
ip = namei(cp->mem + arg0);
@@ -278,14 +284,62 @@ sys_exec(void)
sz += 4096 - (sz % 4096);
sz += 4096;
+ mem = kalloc(sz);
+ if(mem == 0)
+ goto bad;
+ memset(mem, 0, sz);
+
+ // arg1 is a pointer to an array of pointers to string.
+ nargs = 0;
+ argbytes = 0;
+ for(i = 0; ; i++){
+ if(fetchint(cp, arg1 + 4*i, &ap) < 0)
+ goto bad;
+ if(ap == 0)
+ break;
+ len = checkstring(ap);
+ if(len < 0)
+ goto bad;
+ nargs++;
+ argbytes += len + 1;
+ }
+
+ // argn\0
+ // ...
+ // arg0\0
+ // 0
+ // ptr to argn
+ // ...
+ // 12: ptr to arg0
+ // 8: argv (points to ptr to arg0)
+ // 4: argc
+ // 0: fake return pc
+ sp = sz - argbytes - (nargs+1)*4 - 4 - 4 - 4;
+ *(uint*)(mem + sp) = 0xffffffff;
+ *(uint*)(mem + sp + 4) = nargs;
+ *(uint*)(mem + sp + 8) = (uint)(sp + 12);
+
+ p1 = sp + 12;
+ p2 = sp + 12 + (nargs + 1) * 4;
+ for(i = 0; i < nargs; i++){
+ fetchint(cp, arg1 + 4*i, &ap);
+ len = checkstring(ap);
+ memmove(mem + p2, cp->mem + ap, len + 1);
+ *(uint*)(mem + p1) = p2;
+ p1 += 4;
+ p2 += len + 1;
+ }
+ *(uint*)(mem + p1) = 0;
+
// commit to the new image.
kfree(cp->mem, cp->sz);
cp->sz = sz;
- cp->mem = kalloc(cp->sz);
+ cp->mem = mem;
+ mem = 0;
for(i = 0; i < elf.phnum; i++){
if(readi(ip, &ph, elf.phoff + i * sizeof(ph), sizeof(ph)) != sizeof(ph))
- goto bad;
+ goto bad2;
if(ph.type != ELF_PROG_LOAD)
continue;
if(ph.va + ph.memsz > sz)
@@ -298,13 +352,15 @@ sys_exec(void)
iput(ip);
cp->tf->eip = elf.entry;
- cp->tf->esp = cp->sz;
+ cp->tf->esp = sp;
setupsegs(cp);
return 0;
bad:
cprintf("exec failed early\n");
+ if(mem)
+ kfree(mem, sz);
iput(ip);
return -1;
diff --git a/userfs.c b/userfs.c
index aad9326..d3a4923 100644
--- a/userfs.c
+++ b/userfs.c
@@ -3,12 +3,13 @@
// file system tests
char buf[1024];
+char *args[] = { "echo", "hello", "goodbye", 0 };
int
main(void)
{
puts("userfs running\n");
block();
- exec("usertests");
+ exec("echo", args);
return 0;
}
diff --git a/usertests.c b/usertests.c
index 370054b..cba362f 100644
--- a/usertests.c
+++ b/usertests.c
@@ -115,7 +115,7 @@ exitwait(void)
}
int
-main(void)
+main(int argc, char *argv[])
{
puts("usertests starting\n");