ref: 5bc9b0c3cac34864d479c099283793ec4ae5565e
dir: /sys/src/games/v8e/v8e.c/
#include <u.h> #include <libc.h> #include <auth.h> #include <ctype.h> #include "dat.h" #include "fns.h" Segment segs[3]; void * emalloc(ulong n) { void *v; v = malloc(n); if(v == nil) sysfatal("malloc: %r"); memset(v, 0, n); setmalloctag(v, getcallerpc(&n)); return v; } enum { OMAGIC = 0407, NMAGIC = 0410, ZMAGIC = 0413, }; static int readn32(int fd, u32int *l, int sz) { static uchar buf[8192]; uchar *p; int n, rc; while(sz > 0){ n = 8192; if(n > sz) n = sz; rc = readn(fd, buf, n); if(rc < 0) return -1; if(rc < n){ werrstr("unexpected eof"); return -1; } sz -= n; p = buf; for(; n >= 4; n -= 4){ *l++ = U32(p); p += 4; } switch(n){ case 1: *l = p[0]; break; case 2: *l = p[0] | p[1] << 8; break; case 3: *l = p[0] | p[1] << 8 | p[2] << 16; break; } } return 0; } static void setupstack(char **argv) { u32int *nargv; int i, j; int argc; r[14] = 0x7ffff400; #define push32(x) { r[14] -= 4; memwrite(r[14], x, -1); } for(argc = 0; argv[argc] != nil; argc++) ; nargv = emalloc(sizeof(u32int) * argc); for(i = argc; --i >= 0; ){ r[14] -= strlen(argv[i]) + 1; nargv[i] = r[14]; for(j = 0; argv[i][j] != 0; j++) writem(r[14] + j, argv[i][j], 0); } r[14] &= -4; push32(0); push32(0); push32(0); for(i = argc; --i >= 0; ) push32(nargv[i]); push32(argc); free(nargv); } static int shload(int fd, char *file, char **argv, char **envp) { char buf[256]; char *s, *a; char *p; int rc; char **nargv, **pp; int n; rc = read(fd, buf, sizeof(buf) - 1); if(rc <= 0){ werrstr("invalid magic"); return -1; } close(fd); buf[rc] = 0; p = strchr(buf, '\n'); if(p == nil) *p = 0; p = buf; while(isspace(*p)) p++; s = p; while(*p != 0 && !isspace(*p)) p++; if(*p != 0){ *p = 0; while(isspace(*p)) p++; if(*p != 0){ a = p; while(*p != 0 && !isspace(*p)) p++; }else a = nil; }else a = nil; for(n = 0; argv[n] != nil; n++) ; nargv = emalloc((n + 3) * sizeof(char *)); pp = nargv; *pp++ = s; if(a != nil) *pp++ = a; while(n--) *pp++ = *argv++; load(s, nargv, envp); free(nargv); return 0; } int load(char *file, char **argv, char **envp) { uchar hdr[32]; int fd; u32int hmagic, htext, hdata, hbss, hentry; fd = open(file, OREAD); if(fd < 0) return -1; if(readn(fd, hdr, 2) < 2) return -1; if(hdr[0] == '#' && hdr[1] == '!') return shload(fd, file, argv, envp); if(readn(fd, hdr + 2, 30) < 30) return -1; hmagic = U32(&hdr[0]); htext = U32(&hdr[4]); hdata = U32(&hdr[8]); hbss = U32(&hdr[12]); hentry = U32(&hdr[20]); switch(hmagic){ case ZMAGIC: case OMAGIC: case NMAGIC: break; default: werrstr("invalid magic %.6o", hmagic); return -1; } free(segs[0].data); free(segs[1].data); free(segs[2].data); segs[0].start = 0; segs[0].size = htext; segs[0].data = emalloc(-(-htext & -4)); segs[1].start = -(-htext & -1024); segs[1].size = hdata + hbss; segs[1].data = emalloc(-(-(hdata + hbss) & -4)); segs[2].start = 0x7ffff400 - STACKSIZE; segs[2].size = STACKSIZE; segs[2].data = emalloc(STACKSIZE); if(hmagic != OMAGIC) segs[0].flags = SEGRO; if(hmagic == ZMAGIC) seek(fd, 1024, 0); if(readn32(fd, segs[0].data, htext) < 0) exits(smprint("%r")); if(readn32(fd, segs[1].data, hdata) < 0) exits(smprint("%r")); close(fd); memset(r, 0, sizeof(r)); r[15] = hentry + 2; setupstack(argv); return 0; } static void usage(void) { sysfatal("usage"); } void main(int argc, char **argv) { extern void fptest(void); rfork(RFNAMEG); fptest(); ARGBEGIN{ case 'N': if(addns(nil, EARGF(usage())) < 0) sysfatal("addns: %r"); break; default: usage(); }ARGEND; if(argc < 1) usage(); sysinit(); if(load(argv[0], argv, nil) < 0) sysfatal("load: %r"); for(;;) step(); }