home *** CD-ROM | disk | FTP | other *** search
- #ifdef THINK_C
- #include <LoMem.h>
- #include <THINK.h>
- #define get_time() TimeLM
- #define get_ticks() Ticks
- #else
- #include <Types.h>
- #include <Errors.h>
- #include <Memory.h>
- #include <OSUtils.h>
- #include <SegLoad.h>
- #include <Quickdraw.h>
- #include <Files.h>
- #include <Menus.h>
- #include <Fonts.h>
- #include <Resources.h>
- #include <GestaltEqu.h>
- #include <Traps.h>
- #include <Aliases.h>
- #include <Packages.h>
- #include <Processes.h>
- #include <AppleEvents.h>
- #include <ToolUtils.h>
- #include <SysEqu.h>
- #define get_time() (*(long *)TimeLM)
- #define get_ticks() (*(long *)Ticks)
- enum {FALSE,TRUE};
- #endif
- #include <GestaltEqu.h>
- #include <ToolUtils.h>
- #include <Retrace.h>
- #include <OSUtils.h>
- #include <stdio.h>
- #include <errno.h>
- #include <string.h>
- #include <stdlib.h>
- #include <dirent.h>
- #include <fcntl.h>
- #include <utime.h>
- #include <unistd.h>
- #include <sys/uio.h>
- #include <sys/mman.h>
- #include <sys/stat.h>
- #include <sys/syscall.h>
- #include <sys/ioctl.h>
- #include <sys/syslimits.h>
- #include <sys/time.h>
- #include <sys/resource.h>
- #include <sys/signal.h>
- #include <sys/signalvar.h>
- #include <sys/ptrace.h>
- #include <sys/wait.h>
- #include "crtlocal.h"
- #include "proc_mmu.h"
-
- struct page_chain *head = 0;
- struct mmu *crp,*swapper;
-
- #define unixTime(t) (t - (time_t)0x7c25b080)
-
- int kernel_errno;
- unsigned char interrupt;
- long kInterval=12; /* set for 1/5 second between calls */
-
- long *system_vectors = 0;
-
- long activated_pages = 0;
- long page_size,old_ticks;
- long user_vectors[256];
- long supervisor_vectors[256];
-
- #if 0
- CursHandle nxt[8];
- unsigned char ccnt;
- #endif
-
- #ifdef PROTECTED
-
- int check2(struct mmu *crp, unsigned long addr)
- {
- Zone *pzone = ApplicZone();
- long phys_addr = (long)LTP(addr);
- if (mmutype == -1) return 0;
- if (phys_addr==-1)
- {
- crp->result = -1;
- errno = EFAULT;
- return -1;
- }
- if (0 && debug && (addr >= crp->sbreak)
- && ((addr < crp->registers.save[15]) || (addr >= crp->stack_limit)))
- {
- char err[99];
- ksprintf(err+1, "Possible bus error soon, logical address %8.8X\n", addr);
- *err = strlen(err+1);
- DebugStr((ConstStr255Param)err);
- }
- if ((phys_addr < (long)&(pzone->heapData)) || (phys_addr >= (long)(pzone->bkLim)))
- {
- char err[99];
- ksprintf(err+1, "Physical address %8.8X outside kernel memory\n", phys_addr);
- *err = strlen(err+1);
- DebugStr((ConstStr255Param)err);
- }
- return 0;
- }
-
- #define CHECK(addr) CHECK2(crp, addr)
-
- void setmaxstack(long value)
- {
- crp->maxstack = value;
- if (value > stack_headroom*2) value = stack_headroom*2;
- upper_space(crp, value);
- }
-
- #endif
-
- void patch_traps(void)
- {
- int i = 16;
- long old_sr;
- #ifdef PROTECTED
- if (virtual) old_sr = EnterSupervisorMode();
- #endif
- system_vectors = (long *)vbr();
- #ifdef PROTECTED
- if (virtual) asm
- {
- move.w old_sr,sr
- }
- #endif
- memcpy(supervisor_vectors, system_vectors, sizeof(supervisor_vectors));
- memcpy(user_vectors, system_vectors, sizeof(user_vectors));
- while (--i) user_vectors[i+32] = (long)trap_patch_1();
- user_vectors[32] = (long)trap_patch_0();
- #ifdef PROTECTED
- if (virtual)
- ((long *)0)[2] = (long)trap_patch_1(); /* bus error */
- else
- #endif
- user_vectors[2] = (long)trap_patch_1(); /* bus error */
- user_vectors[3] = (long)trap_patch_1(); /* address error */
- user_vectors[4] = (long)trap_patch_1(); /* illegal inst */
- user_vectors[5] = (long)trap_patch_1(); /* zero divide */
- user_vectors[6] = (long)trap_patch_1(); /* range error */
- user_vectors[7] = (long)trap_patch_1(); /* trapv */
- user_vectors[8] = (long)trap_patch_1(); /* privilege */
- user_vectors[9] = (long)trap_patch_1(); /* trace */
- // user_vectors[10] = (long)trap_patch_1(); /* line-A emulation */
- user_vectors[11] = (long)trap_patch_1(); /* Line-F emulation */
- }
-
- static recursive = 0;
-
- void *xmalloc(size_t siz)
- {
- void *ptr = malloc(siz);
- if (!ptr)
- {
- kInterval = 0;
- if (recursive)
- {
- ExitToShell();
- }
- recursive = 1;
- kprintf("Out of memory\n");
- while (!Button());
- exit(1);
- }
- memset(ptr, 0, siz);
- return ptr;
- }
-
- void *xrealloc(void *oldptr, size_t siz)
- {
- void *ptr = realloc(oldptr, siz);
- if (!ptr)
- {
- kInterval = 0;
- if (recursive)
- {
- ExitToShell();
- }
- recursive = 1;
- kprintf("Out of memory\n");
- while (!Button());
- exit(1);
- }
- return ptr;
- }
-
- #ifdef PROTECTED
- int ukmemcpy(struct mmu *crp, long dest, void *src, long siz)
- {
- if (siz > 0)
- {
- CHECK(dest);
- CHECK(dest+siz-1);
- if (virtual)
- {
- memcpy((void *)dest, src, siz);
- return 0;
- }
- put_user_root((long)crp);
- flush_mmu_caches();
- put_dfc(2);
- asm {
- move.l siz,d1
- move.l src,a1
- move.l dest,a0
- @1: move.b (a1)+,d0
- moves.b d0,(a0)+
- subq.l #1,d1
- bne @1
- }
- }
- return 0;
- }
-
- long ustrlen(struct mmu *crp, long src)
- {
- long result;
- CHECK(src);
- if (virtual) return strlen((void *)src);
- put_user_root((long)crp);
- flush_mmu_caches();
- put_sfc(2);
- asm {
- move.l src,a1
- @1: moves.b (a1)+,d0
- tst.b d0
- bne @1
- move.l a1,result
- }
- return result-src-1;
- }
-
- int kustrcpy(struct mmu *crp, void *dest, long src)
- {
- CHECK(src);
- if (virtual)
- {
- strcpy((void *)dest, (void *)src);
- return 0;
- }
- put_user_root((long)crp);
- flush_mmu_caches();
- put_sfc(2);
- asm {
- move.l src,a1
- move.l dest,a0
- @1: moves.b (a1)+,d0
- move.b d0,(a0)+
- bne @1
- }
- return 0;
- }
-
- int kumemcpy(struct mmu *crp, void *dest, long src, long siz)
- {
- if (siz > 0)
- {
- CHECK(src);
- CHECK(src+siz-1);
- if (virtual)
- {
- memcpy(dest, (void *)src, siz);
- return 0;
- }
- put_user_root((long)crp);
- flush_mmu_caches();
- put_sfc(2);
- asm {
- move.l siz,d1
- move.l src,a1
- move.l dest,a0
- @1: moves.b (a1)+,d0
- move.b d0,(a0)+
- subq.l #1,d1
- bne @1
- }
- }
- return 0;
- }
-
- int umemset(struct mmu *crp, long dest, char value, long siz)
- {
- if (siz > 0)
- {
- CHECK(dest);
- CHECK(dest+siz-1);
- if (virtual)
- {
- memset((void *)dest, value, siz);
- return 0;
- }
- put_user_root((long)crp);
- flush_mmu_caches();
- put_dfc(2);
- asm {
- move.l siz,d1
- move.b value,d0
- move.l dest,a0
- @1: moves.b d0,(a0)+
- subq.l #1,d1
- bne @1
- }
- }
- return 0;
- }
-
- int uumemcpy(struct mmu *destrp, struct mmu *srcrp, long dest, long src, long size)
- {
- enum {bufsiz=8192};
- char *kbuf = xmalloc(bufsiz);
- long uaddr = 0;
- CHECK2(srcrp, src);
- CHECK2(destrp, dest);
- CHECK2(srcrp, src+size-1);
- CHECK2(destrp, dest+size-1);
- while (size > 0)
- {
- long amount = size>bufsiz?bufsiz:size;
- kumemcpy(srcrp, kbuf, src, amount);
- src += amount;
- ukmemcpy(destrp, dest, kbuf, amount);
- dest += amount;
- size -= amount;
- }
- free(kbuf);
- return 0;
- }
-
- int uread(struct mmu *crp, int fd, long useraddr, long size)
- {
- enum {bufsiz=8192};
- char *kbuf = xmalloc(bufsiz);
- while (size > 0)
- {
- long amount = size>bufsiz?bufsiz:size;
- long actual = read(fd, kbuf, amount);
- if (actual > 0)
- {
- ukmemcpy(crp, useraddr, kbuf, actual);
- useraddr += actual;
- size -= actual;
- }
- else
- {
- if (!actual) kprintf("Caution - executable too short for header\n");
- size = 0;
- }
- }
- free(kbuf);
- return 0;
- }
-
- int page_free(long addr)
- {
- struct page_chain *ptr = head;
- long buf,tries;
- if (addr) while (ptr)
- {
- if (((ptr->free_list[0]&~0x80000000L) <= addr) &&
- ((ptr->free_list[sizeof(head->pages)/page_size-1]&~0x80000000L) >= addr))
- {
- buf = (addr - (ptr->free_list[0]&~0x80000000L))/page_size;
- if (ptr->free_list[buf] == ((addr&~(page_size-1))|0x80000000L))
- {
- ptr->free_list[buf] &= ~0x80000000L;
- if (ptr->idx == -1) ptr->idx = buf;
- return --activated_pages;
- }
- }
- ptr = ptr->nxt;
- }
- return activated_pages;
- }
-
- long page_alloc(void)
- {
- struct page_chain *ptr = head;
- long buf,tries;
- while (ptr)
- {
- tries = 256;
- if (ptr->idx != -1)
- {
- do
- ptr->idx = (ptr->idx+1)&255;
- while ((ptr->free_list[ptr->idx] <= 0) && --tries);
- if (tries)
- {
- buf = ptr->free_list[ptr->idx];
- ptr->free_list[ptr->idx] ^= 0x80000000L;
- ++activated_pages;
- memset((void *)buf, 0, page_size);
- return buf;
- }
- else ptr->idx = -1; /* all pages used */
- }
- ptr = ptr->nxt;
- }
- ptr = malloc(sizeof(struct page_chain));
- if (ptr)
- {
- ptr->nxt = head;
- head = ptr;
- buf = ((((long)head->padding)|(page_size-1))+1);
- tries = sizeof(head->pages)/page_size;
- while (tries--)
- {
- long addr = buf+tries*page_size;
- head->free_list[tries] = (addr);
- }
- head->free_list[head->idx] ^= 0x80000000L;
- ++activated_pages;
- memset((void *)buf, 0, page_size);
- return buf;
- }
- errno = ENOMEM;
- return 0;
- }
-
- #endif
-
- void read_memory(long addr, void *buf, long maxlen)
- {
- kumemcpy(crp, buf, addr, maxlen);
- }
-
- short nxt_pid = 1;
-
- int newproc(char *kbuf, char **args, char **envs, struct mmu *parent, long argcnt, long envcnt)
- {
- long addr2,addr;
- long siz = 0;
- int proc_no = 0;
- char *buf = (void *)xmalloc(512+sizeof(struct mmu));
- crp = (struct mmu *)((((long)buf)|511)+1);
- crp->self = buf;
- crp->stack_limit = 1<<25;
- crp->parent = parent;
- crp->root_parID = root_parID;
- crp->crt_parID = crt_parID;
- crp->pid = nxt_pid++;
- crp->state = 'R';
- crp->p_sigacts = (struct sigacts *)xmalloc(sizeof(struct sigacts));
- while (proc_tab[proc_no] && (proc_no < sizeof(proc_tab)/sizeof(*proc_tab)))
- ++proc_no;
- if (proc_tab[proc_no])
- {
- kInterval = 0;
- exit(1);
- }
- proc_tab[proc_no] = crp;
- #ifdef PROTECTED
- wipeout(crp);
- #endif
- if (kbuf)
- {
- int proc = open(kbuf, O_RDONLY);
- if (proc < 0)
- {
- crp->state = 'Z';
- return proc;
- }
- if (parent)
- {
- memcpy(crp->fd_tab, parent->fd_tab, sizeof(crp->fd_tab));
- crp->trace_me = parent->trace_me;
- }
- else
- {
- #if 1
- static winidx = 0;
- int console = next_fd(1);
- crt_fd_tab[console].fd = (100<<8)|++winidx; /* console */
- crt_fd_tab[console].flags = O_RDWR|O_PIPE;
- #else
- int console = open("/dev/console", O_RDWR);
- if (console == -1)
- {
- kprintf("Creating /dev/console ...");
- mkdir("/dev", 0777);
- mknod("/dev/console", S_IFCHR|0666, 100<<8);
- console = open("/dev/console", O_RDWR);
- if (console == -1)
- {
- kprintf(" failed - sorry !\n");
- exit(99);
- }
- else
- {
- kprintf(" succeeded\n");
- }
- }
- #endif
- crp->fd_tab[0] = crp->fd_tab[1] = crp->fd_tab[2] = console;
- }
- read(proc, (void *)&(crp->header), sizeof(crp->header));
- if (N_BADMAG(crp->header))
- {
- char **args;
- long *addr = (long *)(crp->registers.save[15]);
- char *default_shell = "/bin/sh";
- char *shell = (char *)&(crp->header);
- if (*shell++ != '#') shell = default_shell;
- else if (*shell++ == '!')
- {
- char *end = strchr(shell,'\n');
- if (end) *end = 0;
- else shell = default_shell;
- }
- else shell = default_shell;
- close(proc);
- proc = open(shell, O_RDONLY);
- read(proc, (void *)&(crp->header), sizeof(crp->header));
- if (N_BADMAG(crp->header))
- {
- errno = ENOEXEC;
- crp->state = 'Z';
- return -1;
- }
- kumemcpy(crp, args, (long)addr, sizeof(long));
- ukmemcpy(crp, (long)--addr, args, sizeof(long));
- crp->registers.save[15] = (long)addr;
- crp->registers.save[14]++;
-
- }
- if (crp->header.a_trsize || crp->header.a_drsize)
- {
- extern void *big_stack;
- long stack_headroom = 1<<16;
- long resource_size = loader_main(proc, &(crp->header));
- if (resource_size == -1)
- {
- crp->state = 'Z';
- return -1;
- }
- #ifdef PROTECTED
- supervisor_space(crp, crp->header.a_entry, crp->header.a_entry+resource_size);
- kprintf("Relocatable module, entry point %X\n", crp->header.a_entry);
- #endif
- crp->storage = (struct mem_chain *)(crp->header.a_entry-sizeof(struct exec));
- SetPtrSize((void *)crp->storage,
- N_DATOFF(crp->header) +
- (crp->header).a_data +
- (crp->header).a_bss);
-
- if (big_stack)
- {
- stack_headroom = stack_headroom*4 + resource_size/4;
- #ifdef DEBUGSTACK
- kprintf("Stack boosted to %d bytes for %s\n", stack_headroom, kbuf);
- #endif
- }
- crp->storage->nxt = (struct mem_chain *)NewPtrClear(stack_headroom);
- if (MemError())
- {
- crp->state = 'Z';
- return -1;
- }
- crp->stack_limit = ((long)crp->storage->nxt) + stack_headroom;
- #ifdef PROTECTED
- supervisor_space(crp, ((long)crp->storage->nxt), crp->stack_limit);
- #endif
- crp->registers.save[15] = crp->stack_limit-256;
- }
- else
- {
- #ifdef PROTECTED
- if (virtual)
- #endif
- {
- kprintf("Sorry, this machine cannot run protected mode executables\n");
- crp->state = 'Z';
- return -1;
- }
- #ifdef PROTECTED
- if (upper_space(crp, stack_headroom))
- {
- crp->state = 'Z';
- return -1;
- }
- crp->registers.save[15] = crp->stack_limit-256;
- crp->sbreak = N_ALIGN(crp->header, N_BSSADDR(crp->header) + crp->header.a_bss);
- if (lower_space(crp, crp->sbreak))
- {
- crp->state = 'Z';
- return -1;
- }
- lseek(proc, N_TXTOFF(crp->header), 0);
- uread(crp,proc, N_TXTADDR(crp->header), crp->header.a_text);
- lseek(proc, N_DATOFF(crp->header), 0);
- uread(crp,proc,N_DATADDR(crp->header), crp->header.a_data);
- umemset(crp,N_BSSADDR(crp->header), 0, crp->header.a_bss);
- #endif
- }
- close(proc);
- if (parent) parent->state = 'Z';
- crp->registers.pc = crp->header.a_entry;
- }
- else /* !kbuf */
- {
- int usp = parent->registers.save[15];
- crp->sbreak = parent->sbreak;
- crp->registers = parent->registers;
- #ifdef PROTECTED
- if (lower_space(crp, crp->sbreak))
- {
- crp->state = 'Z';
- return -1;
- }
- uumemcpy(crp, parent, 0, 0, crp->sbreak); /* duplicate prog+data space */
- if (upper_space(crp, crp->stack_limit-usp+stack_headroom))
- {
- crp->state = 'Z';
- return -1;
- }
- uumemcpy(crp, parent, usp, usp, crp->stack_limit-usp); /* duplicate stack space */
- #else
- crp->stack_limit = parent->stack_limit;
- if (parent->savestack)
- parent->savestack = xrealloc(parent->savestack, crp->stack_limit-usp);
- else
- parent->savestack = xmalloc(crp->stack_limit-usp);
- kumemcpy(parent, parent->savestack, usp, crp->stack_limit-usp);
- crp->savestack = xmalloc(crp->stack_limit-usp);
- kumemcpy(parent, crp->savestack, usp, crp->stack_limit-usp);
- #endif
- memcpy(crp->fd_tab, parent->fd_tab, sizeof(crp->fd_tab));
- crp->header = parent->header;
- crp->root_parID = parent->root_parID;
- crp->crt_parID = parent->crt_parID;
- crp->trace_me = parent->trace_me;
- *(crp->p_sigacts) = *(parent->p_sigacts);
- }
- if (argcnt)
- {
- long *addr = (long *)(crp->stack_limit-256);
- long i;
- for (i = envcnt; i--; )
- {
- int len = strlen(envs[i]);
- addr -= len+4 >> 2;
- ukmemcpy(crp, (long)addr, envs[i], len+1);
- free(envs[i]);
- envs[i] = (char *)addr;
- }
- for (i = argcnt; i--; )
- {
- int len = strlen(args[i]);
- addr -= len+4 >> 2;
- ukmemcpy(crp, (long)addr, args[i], len+1);
- free(args[i]);
- args[i] = (char *)addr;
- }
- if (envcnt)
- {
- umemset(crp, (long)--addr, 0, sizeof(long));
- for (i = envcnt; i--; )
- ukmemcpy(crp, (long)--addr, &envs[i], sizeof(long));
- ukmemcpy(crp, (long)(addr-1), &addr, sizeof(long));
- addr--;
- }
- umemset(crp, (long)--addr, 0, sizeof(long));
- for (i = argcnt; i--; )
- ukmemcpy(crp, (long)--addr, &args[i], sizeof(long));
- ukmemcpy(crp, (long)--addr, args, sizeof(long));
- crp->registers.save[15] = (long)addr;
- crp->registers.save[14] = argcnt;
- }
- return 0;
- }
-
- /* Prototypes */
- OSErr InstallVBL (void);
- pascal long GetVBLRec (void);
- void DoVBL (unsigned short fault);
-
- void ProcessDoc (FSSpec *curDocFSS)
- {
- extern char **environ;
- char cname[64];
- char *args[2] = {cname, 0};
- short refnum;
- crt_ioVRefNum = curDocFSS->vRefNum;
- root_parID = crt_parID = curDocFSS->parID;
- memcpy(cname, &(curDocFSS->name[1]), curDocFSS->name[0]);
- cname[curDocFSS->name[0]] = 0;
- newproc(cname, args, environ, 0, 1, 1);
- }
-
- #ifdef PROTECTED
-
- typedef struct VBLRec {
- VBLTask myVBLTask;
- long vblA5; /* 4 bytes before the VBLTask data */
- } VBLRec, *VBLRecPtr;
-
- /* Globals */
- VBLRec gMyVBLRec; /* global VBL record */
-
- pascal long GetVBLRec (void)
- = 0x2E88;
-
- OSErr InstallVBL ()
- {
- long addr,addr2;
- long page = page_alloc();
- char *buf = (void *)xmalloc(512+sizeof(struct mmu));
- swapper = (struct mmu *)((((long)buf)|511)+1);
- swapper->self = buf;
- memset((void *)page, 0x4E, page_size);
- for (addr = 0; addr < 128; addr++)
- {
- swapper->u.u4.level1[addr] = 0xA + (long)(swapper->u.u4.level2);
- swapper->u.u4.level2[addr] = 0xA + (long)&(swapper->u.u4.level3[addr][0]);
- for (addr2 = (1<<18)/page_size; addr2--; )
- {
- swapper->u.u4.level3[addr][addr2] = 0x39 + page;
- }
- }
- gMyVBLRec.myVBLTask.qType = vType;
- gMyVBLRec.myVBLTask.vblAddr = (ProcPtr) DoVBL;/* address of task */
- gMyVBLRec.myVBLTask.vblCount = kInterval; /* Set the interval */
- gMyVBLRec.vblA5 = (long) CurrentA5; /* Save app's A5 in structure */
-
- return VInstall((QElemPtr) &gMyVBLRec.myVBLTask);
- }
-
- /* ============= the VBL task code itself =============*/
-
- void DoVBL(unsigned short fault)
- {
- long curA5;
- VBLRecPtr recPtr;
-
- recPtr = (VBLRecPtr) GetVBLRec ();
- curA5 = SetA5 (recPtr->vblA5);
- /* read app A5 from structure and save */
- /* current value of A5 */
-
- /* ... now that it's OK to access application variables, do the task ... */
-
- flush_mmu_caches();
- if (system_vectors[46] == (long)trap_patch_1()) put_user_root((long)swapper);
- flush_mmu_caches();
-
- /* Reset vblCount so that this procedure executes again */
- recPtr->myVBLTask.vblCount = kInterval;
- curA5 = SetA5(curA5);
- }
-
- #endif