summaryrefslogtreecommitdiff
path: root/sys/src/cmd/5e/proc.c
diff options
context:
space:
mode:
authoraiju <aiju@phicode.de>2011-06-16 17:49:24 +0200
committeraiju <aiju@phicode.de>2011-06-16 17:49:24 +0200
commit2acb5433d8008012d7208a7bfcb9c6a1544f218f (patch)
tree19f0c7afc013113c5f8b3de005b2245e33ce2f5e /sys/src/cmd/5e/proc.c
parentfcf30f314b4c4157b536647a09a214576711ad16 (diff)
added 5e (not finished)
Diffstat (limited to 'sys/src/cmd/5e/proc.c')
-rw-r--r--sys/src/cmd/5e/proc.c244
1 files changed, 244 insertions, 0 deletions
diff --git a/sys/src/cmd/5e/proc.c b/sys/src/cmd/5e/proc.c
new file mode 100644
index 000000000..411420282
--- /dev/null
+++ b/sys/src/cmd/5e/proc.c
@@ -0,0 +1,244 @@
+#include <u.h>
+#include <libc.h>
+#include <thread.h>
+#include <bio.h>
+#include <mach.h>
+#include <ctype.h>
+#include <tos.h>
+#include "dat.h"
+#include "fns.h"
+
+void
+initproc(void)
+{
+ P = emallocz(sizeof(Process));
+ P->pid = getpid();
+ P->fd = newfd();
+}
+
+static void
+initstack(int argc, char **argv)
+{
+ ulong tos, sp, ap, size, i, len;
+
+ tos = STACKTOP - sizeof(Tos) * 2;
+ sp = tos;
+
+ size = 8;
+ for(i = 0; i < argc; i++)
+ size += strlen(argv[i]) + 5;
+
+ sp -= size;
+ sp &= ~7;
+ P->R[0] = tos;
+ P->R[1] = STACKTOP - 4;
+ P->R[13] = sp;
+
+ *(ulong *) vaddrnol(sp) = argc;
+ sp += 4;
+ ap = sp + (argc + 1) * 4;
+ for(i = 0; i < argc; i++) {
+ *(ulong *) vaddrnol(sp) = ap;
+ sp += 4;
+ len = strlen(argv[i]) + 1;
+ memcpy(vaddrnol(ap), argv[i], len);
+ ap += len;
+ }
+ *(ulong *) vaddrnol(sp) = 0;
+
+ ((Tos *) vaddrnol(tos))->pid = getpid();
+}
+
+static int
+loadscript(int fd, char *file, int argc, char **argv)
+{
+ char buf[513], *p, **q, **nargv;
+ int rc, nargc, i;
+
+ seek(fd, 0, 0);
+ rc = readn(fd, buf, 512);
+ if(rc <= 0)
+ goto invalid;
+ close(fd);
+ buf[rc] = 0;
+ p = strchr(buf, '\n');
+ if(p == nil)
+ goto invalid;
+ *p = 0;
+ while(isspace(*--p))
+ *p = 0;
+ nargc = 0;
+ p = buf + 2;
+ while(*p) {
+ while(*p && isspace(*p))
+ p++;
+ nargc++;
+ while(*p && !isspace(*p))
+ p++;
+ }
+ if(nargc == 0)
+ goto invalid;
+ nargv = emallocz(sizeof(char *) * (nargc + argc));
+ q = nargv;
+ p = buf + 2;
+ while(*p) {
+ while(*p && isspace(*p))
+ p++;
+ *(p-1) = 0;
+ *q++ = p;
+ while(*p && !isspace(*p))
+ p++;
+ }
+ *q++ = file;
+ for(i = 1; i < argc; i++)
+ *q++ = argv[i];
+ rc = loadtext(*nargv, argc + nargc, nargv);
+ free(nargv);
+ return rc;
+
+invalid:
+ werrstr("exec header invalid");
+ return -1;
+}
+
+int
+loadtext(char *file, int argc, char **argv)
+{
+ int fd, i;
+ Fhdr fp;
+ Segment *text, *data, *bss, *stack;
+ char buf[2];
+
+ fd = open(file, OREAD);
+ if(fd < 0) return -1;
+ if(pread(fd, buf, 2, 0) == 2 && buf[0] == '#' && buf[1] == '!')
+ return loadscript(fd, file, argc, argv);
+ seek(fd, 0, 0);
+ if(crackhdr(fd, &fp) == 0) {
+ werrstr("exec header invalid");
+ return -1;
+ }
+ if(fp.magic != E_MAGIC) {
+ werrstr("exec header invalid");
+ return -1;
+ }
+ freesegs();
+ memset(P->R, 0, sizeof(P->R));
+ P->CPSR = 0;
+ text = newseg(fp.txtaddr - fp.hdrsz, fp.txtsz + fp.hdrsz, SEGTEXT);
+ data = newseg(fp.dataddr, fp.datsz, SEGDATA);
+ bss = newseg(fp.dataddr + fp.datsz, fp.bsssz, SEGBSS);
+ stack = newseg(STACKTOP - STACKSIZE, STACKSIZE, SEGSTACK);
+ seek(fd, fp.txtoff - fp.hdrsz, 0);
+ if(readn(fd, text->data, fp.txtsz + fp.hdrsz) < fp.txtsz + fp.hdrsz)
+ sysfatal("%r");
+ seek(fd, fp.datoff, 0);
+ if(readn(fd, data->data, fp.datsz) < fp.datsz)
+ sysfatal("%r");
+ memset(bss->data, 0, bss->size);
+ memset(stack->data, 0, stack->size);
+ P->R[15] = fp.entry;
+ if(havesymbols && syminit(fd, &fp) < 0)
+ fprint(2, "initializing symbol table: %r\n");
+ close(fd);
+ for(i = 0; i < P->fd->nfds * 8; i++)
+ if(iscexec(P->fd, i))
+ close(i);
+ wlock(P->fd);
+ free(P->fd->fds);
+ P->fd->fds = nil;
+ P->fd->nfds = 0;
+ wunlock(P->fd);
+ initstack(argc, argv);
+ return 0;
+}
+
+void
+cherrstr(char *str, ...)
+{
+ va_list va;
+
+ va_start(va, str);
+ vsnprint(P->errbuf, ERRMAX, str, va);
+ va_end(va);
+}
+
+u32int
+noteerr(u32int x, u32int y)
+{
+ if(((int)x) >= ((int)y))
+ return x;
+ rerrstr(P->errbuf, ERRMAX);
+ return x;
+}
+
+Fd *
+newfd(void)
+{
+ Fd *fd;
+
+ fd = emallocz(sizeof(*fd));
+ incref(&fd->ref);
+ return fd;
+}
+
+Fd *
+copyfd(Fd *old)
+{
+ Fd *new;
+
+ rlock(old);
+ new = newfd();
+ if(old->nfds > 0) {
+ new->nfds = old->nfds;
+ new->fds = emalloc(old->nfds);
+ memcpy(new->fds, old->fds, old->nfds);
+ }
+ runlock(old);
+ return new;
+}
+
+void
+fddecref(Fd *fd)
+{
+ if(decref(&fd->ref) == 0) {
+ free(fd->fds);
+ free(fd);
+ }
+}
+
+int
+iscexec(Fd *fd, int n)
+{
+ int r;
+
+ r = 0;
+ rlock(fd);
+ if(n / 8 < fd->nfds)
+ r = (fd->fds[n / 8] & (1 << (n % 8))) != 0;
+ runlock(fd);
+ return r;
+}
+
+void
+setcexec(Fd *fd, int n, int status)
+{
+ int old;
+
+ wlock(fd);
+ if(n / 8 >= fd->nfds) {
+ if(status == 0) {
+ wunlock(fd);
+ return;
+ }
+ old = fd->nfds;
+ fd->nfds = (n / 8) + 1;
+ fd->fds = erealloc(fd->fds, fd->nfds);
+ memset(fd->fds + old, 0, fd->nfds - old);
+ }
+ if(status == 0)
+ fd->fds[n / 8] &= ~(1 << (n % 8));
+ else
+ fd->fds[n / 8] |= (1 << (n % 8));
+ wunlock(fd);
+}