/* $Id: sys.c,v 1.1 1998/02/02 08:19:05 taubert Exp $ */ #pragma optimize 79 segment "KERN2 "; /* sys.c GS/IX Kernel routines for process control Copyright 1991-1998, Procyon, Inc. Jawaid Bazyar and Derek Taubert */ #include "conf.h" #include "proc.h" #include "kernel.h" #include "gno.h" #include "kvm.h" #include "sys.h" #include "/lang/orca/libraries/orcacdefs/stdio.h" #include "/lang/orca/libraries/orcacdefs/string.h" #include "/lang/orca/libraries/orcacdefs/stdlib.h" #include #include #include #include #include #include #include #include extern kernelStructPtr kp; /* signal context record */ typedef struct ctxt { word ctx_A; word ctx_X; word ctx_Y; word ctx_state; word ctx_D; byte ctx_B; byte ctx_B1; word ctx_P; word ctx_S1; longword ctx_PC; } ctxt, *ctxtPtr; struct GSString1K { Word length; /* Number of Chars in text field */ char text[1024]; } ; typedef struct GSString1K GSString1K, *GSString1KPtr; struct ResultBuf1K { Word bufSize; GSString1K bufString; } ; typedef struct ResultBuf1K ResultBuf1K, *ResultBuf1KPtr; /* this is the info kept per-process on what sorts of shit the process expects for I/O. This is similar to a special case of user.h fd table including only the stdin/stdout fds (0-2). */ typedef struct ttyinf { word InANDMask; word InORMask; word OutANDMask; word OutORMask; word ErrANDMask; word ErrORMask; word InDeviceType; word OutDeviceType; word ErrDeviceType; longword InSlot; longword OutSlot; longword ErrSlot; word dummy; } ttyinf; #define NPGRP 32 pgrp pgrpInfo[NPGRP]; typedef struct ttyInfo { word pgrp; } ttyInfo; extern ttyStruct; ttyInfo *ttys = (ttyInfo *) &ttyStruct; #define isbadpgrp(p) ((p < 0) || (p >= NPGRP)) static word hiWord(longword w) { word h; asm { lda w+2 sta h } return h; } static word loWord(longword w) { word l; asm { lda w sta l } return l; } void *kmalloc(size_t size) { handle h; word p_uid; void *x; /* $$$ p_uid = kp->procTable[Kgetpid()].userID; */ p_uid = PROC->userID; h = NewHandle(size, p_uid, 0xC008, NULL); if (toolerror()) { fprintf(stderr, "kmalloc:%04X\n",toolerror()); return NULL; } x = *h; return x; } void *pmalloc(size_t size, word p_uid) { handle h; void *x; h = NewHandle(size, p_uid, 0xC008, NULL); if (toolerror()) { fprintf(stderr, "pmalloc:%04X\n",toolerror()); return NULL; } x = *h; return x; } int kfree(void *mem) { handle h; if (h = (FindHandle(mem) == NULL)) return SYSERR; DisposeHandle(h); return (OK); } static int findEmptyProc(void) { int i; for (i = 0; i < NPROC; i++) if (kp->procTable[i].processState == procUNUSED) return i; return -1; } #if 0 int isbadpid( int pid ) { int mpid; mpid = mapPID(pid); if (mpid == -1) return SYSERR; else return SYSOK; } #endif static int createProc(word stack, word dp, longword process) { int p; disableps(); /* printf("creating process stack=%04X, dp=%04X, addr=%08lX\n", stack, dp, process); */ p = findEmptyProc(); if (p == -1) { enableps(); return SYSERR; } kp->procTable[p].processState = procSUSPENDED; kp->procTable[p].parentpid = Kgetpid(); kp->procTable[p].irq_S = stack; kp->procTable[p].irq_D = dp; kp->procTable[p].irq_PC = (word) process; kp->procTable[p].irq_B = kp->procTable[p].irq_K = (process >> 16); kp->procTable[p].irq_P = 4; /* interrupts must be OFF you putz */ /* assign child same TTY as parent */ kp->procTable[p].ttyID = PROC->ttyID; /* $$$ kp->procTable[Kgetpid()].ttyID; */ enableps(); return p; } #if 0 #define BUSY_FLAG ((byte *)0xE100FFl) int _ready(int pid, int resch) { int mpid; unsigned x; mpid = mapPID(pid); if (mpid == -1) return SYSERR; disableps(); if (kp->procTable[mpid].processState != procUNUSED) kp->procTable[mpid].processState = procREADY; if (resch) { asm { php sei } x = *BUSY_FLAG; *BUSY_FLAG = 0; _resched(); *BUSY_FLAG = x; asm { plp } } enableps(); return OK; } #endif /* * Allocates a new file descriptor in this process. If the fd table is * full, resizes the table and proceeds with the allocation. * allocFD does NOT adjust the fdCount field, as it's possible that * we must unallocate the fd later due to an error and it saves * a bit of code. (i.e. the caller must inc fdCount) */ fdentryPtr allocFD(int *fdn) { fdtablePtr ft; int i,j; unsigned s; /* $$$ ft = kp->procTable[Kgetpid()].openFiles; */ ft = PROC->openFiles; j = 0; /* change this when tables are dynamically allocated */ disableps(); retry: while (j < ft->fdTableSize) { if (ft->fds[j].refNum == 0) { ft->fds[j].refNum = -1; /* just to make this item look allocated */ enableps(); if (fdn != NULL) *fdn = j+1; return &(ft->fds[j]); } else j++; } ft->fdTableSize += 32; i = ft->fdTableSize; ft = realloc(ft,sizeof(fdtable) + sizeof(fdentry)*(i-1)); /* zero out the new entries */ memset(&ft->fds[i-32],0,sizeof(fdentry)*32); PROC->openFiles = ft; goto retry; } struct rc { int rn; int rt; int cn; }; #ifdef NOTDEFINED void printFDS(fdtablePtr f) { int i; struct rc *r; extern struct rc *FINDREFNUM(int,int); fputc('[',stderr); for (i = 0; i < 32; i++) { if (f->fds[i].refNum) { fprintf(stderr,"(%d ",i); switch (f->fds[i].refType) { case rtGSOS: fprintf(stderr,"GSOS "); break; case rtPIPE: fprintf(stderr,"PIPE "); break; case rtTTY : fprintf(stderr,"TTY "); break; default : fprintf(stderr,"%d ",f->fds[i].refType); } fprintf(stderr,"%d/%d ", f->fds[i].refNum,f->fds[i].refLevel); r = FINDREFNUM(f->fds[i].refType,f->fds[i].refNum); if (r == NULL) fprintf(stderr,"!!)"); else fprintf(stderr,"%d)",r->cn); } } fputc(']',stderr); fputc('\n',stderr); } #endif #pragma databank 1 void endproc(void) { /* * printfs in here won't work with quiting orca/c progs because ~C_SHUTDOWN * closes ALL open file descriptors */ /* printf("end of process %d\n",Kgetpid()); */ /* $$$ kp->procTable[Kgetpid()].flags |= FL_NORMTERM; */ PROC->flags |= FL_NORMTERM; /* kill(kp->procTable[Kgetpid()].flpid,9); */ Kkill(&errno, 9, PROC->flpid); /* not reached */ PANIC("ENDPROC KILL OVERRUN"); } int CommonQuit(char *pname, int flag) { /*struct pentry *p = &kp->procTable[Kgetpid()];*/ char *pcopy; quitStack *qs; GSString255Ptr gp; enableps(); if (flag & 0x4000) PROC->flags |= FL_RESTART; if (pname && *pname) { if (flag & 0x8000) { gp = (GSString255Ptr) LGetPathname2(PROC->userID,1); qs = malloc(gp->length+5); qs->next = PROC->returnStack; memcpy(qs->data,gp->text,gp->length); qs->data[gp->length] = 0; PROC->returnStack = qs; } pcopy = kmalloc(strlen(pname)+1); strcpy(pcopy,pname); nfree(pname); Kexecve(&errno,pcopy,pcopy); } else { if ((qs = PROC->returnStack) != NULL) { pcopy = kmalloc(strlen(qs->data)+1); strcpy(pcopy,qs->data); PROC->returnStack = qs->next; nfree(qs); Kexecve(&errno,pcopy,pcopy); } else Kkill(&errno, 9, PROC->flpid); } disableps(); return 0x27; } #pragma toolparms 1 /* subr is the address to begin the process at */ pascal int KERNSetGNOQuitRec(word pCount,GSString255Ptr pathname, word flags, int *ERRNO) { extern QuitRecGS quitParms; quitParms.pCount = pCount; quitParms.pathname = pathname; quitParms.flags = flags; } int KERNgetpid() /* get the process id of currently executing process */ { /*$$$ return( kp->procTable[kp->truepid].flpid ); */ return (PROC->flpid); } int KERNgetppid(int *ERRNO) /* get the pid of the process' parent */ { return (kp->procTable[PROC->parentpid].flpid); } int KERNgetpgrp(int *ERRNO, int pid) /* get the pgrp field for a specified process */ { int mpid; mpid = mapPID(pid); if (mpid == -1) { *ERRNO = ESRCH; return -1; } return( kp->procTable[mpid].pgrp ); } int KERNsetpgrp(int *ERRNO, int pgrp, int pid) { int mpid; int pp; mpid = mapPID(pid); if (mpid == -1) { *ERRNO = ESRCH; return -1; } if (isbadpgrp(pgrp)) { *ERRNO = ESRCH; return -1; } if (kp->procTable[mpid].pgrp != pgrp) { if (pgrp != 0) pgrpInfo[pgrp-2].pgrpref++; if ((pp = kp->procTable[mpid].pgrp) != 0) pgrpInfo[pp-2].pgrpref--; } return 0; } int KERNgetuid(int *ERRNO) { return (PROC->p_uid); /* $$$ return (kp->procTable[Kgetpid()].p_uid); */ } int KERNgeteuid(int *ERRNO) { return (PROC->p_euid); /* $$$ return (kp->procTable[Kgetpid()].p_euid); */ } int KERNgetgid(int *ERRNO) { return (PROC->p_gid); /* $$$ return (kp->procTable[Kgetpid()].p_gid); */ } int KERNgetegid(int *ERRNO) { return (PROC->p_egid); /* $$$ return (kp->procTable[Kgetpid()].p_egid); */ } int KERNsetreuid(int *ERRNO, int ruid, int euid) { if (ruid == -1) ruid = PROC->p_uid; if (euid == -1) euid = PROC->p_euid; if ((PROC->p_uid != 0) && (((euid != PROC->p_uid) && (euid != PROC->p_euid)) || ((ruid != PROC->p_euid) && (ruid != PROC->p_uid)))) { *ERRNO = EPERM; return -1; } PROC->p_uid = ruid; PROC->p_euid = euid; return 0; } int KERNsetuid(int *ERRNO, int uid) { /* $$$ struct pentry *p; p = &(kp->procTable[Kgetpid()]); */ if ((PROC->p_uid == 0) || (uid == PROC->p_uid) || (uid == PROC->p_euid)) { PROC->p_uid = uid; PROC->p_euid = uid; return 0; } *ERRNO = EPERM; return -1; } int KERNsetregid(int *ERRNO, int rgid, int egid) { if (rgid == -1) rgid = PROC->p_gid; if (egid == -1) egid = PROC->p_egid; if ((PROC->p_uid != 0) && (((egid != PROC->p_gid) && (egid != PROC->p_egid)) || ((rgid != PROC->p_egid) && (rgid != PROC->p_gid)))) { *ERRNO = EPERM; return -1; } PROC->p_gid = rgid; PROC->p_egid = egid; return 0; } int KERNsetgid(int *ERRNO, int gid) { /* $$$ struct pentry *p; p = &(kp->procTable[Kgetpid()]); */ if ((PROC->p_uid == 0) || (gid == PROC->p_gid) || (gid == PROC->p_egid)) { PROC->p_gid = gid; PROC->p_egid = gid; return 0; } *ERRNO = EPERM; return -1; } int KERNtimes(int *ERRNO, struct tms *buffer) { /* $$$ buffer->tms_utime = kp->procTable[Kgetpid()].ticks; buffer->tms_cutime = kp->procTable[Kgetpid()].childTicks; buffer->tms_stime = buffer->tms_cstime = 0l; */ buffer->tms_utime = PROC->ticks; buffer->tms_cutime = PROC->childTicks; /* a->i1 = a->i2 = b BROKEN in C 2.0.3 */ #if 0 buffer->tms_stime = buffer->tms_cstime = 0l; #else buffer->tms_stime = 0l; buffer->tms_cstime = 0l; #endif return 0; } #pragma toolparms 0 char *a_strncpy_max(char *s, word max_len) { word l; char *x; if (s == NULL) return NULL; while ((l < max_len) && (s[l] != 0)) l++; x = malloc(l+1); strncpy(x,s,l); x[l] = 0; return x; } int commonFork(void (*funcptr)(), word stackSize, int prio, char *name, word *argv, int *ERRNO) { word dPageAddr, buffSize,nargs; int newID,newPID,parentPID; int flpid; longword *ret; handle fstack; struct pentry *parent,*child; word state; byte statereg,slot; int i,j,k; extern void endproc2(void); extern void FORKInitGlob(void); extern void IncRefnum(int,int); extern void incPipe(int,int); extern int allocPID(void); /* printf("address = %08lX\n",subr); */ if (kp->gsosDebug & 16) fprintf(stderr, "fork(%06lX)\n",funcptr); newID = GetNewID(0x1000); fstack = NewHandle((long) stackSize,newID | 0x0100,0xC105, NULL); if (toolerror()) { *ERRNO = ENOMEM; return -1; } dPageAddr = (word) *fstack; buffSize = stackSize; /* calculate the # of bytes of parameters */ nargs = (*argv) * 2; ret = (longword *) (dPageAddr+buffSize-4-nargs); /* place this first, or it'll clobber some parameters */ *ret = ((longword) endproc2)-1; /* go to endproc when process is done */ /* if they're passing in params, copy them to the target stack */ if (nargs) memcpy( (((byte *) ret)+3), argv+1, nargs); disableps(); newPID = createProc(dPageAddr+buffSize-5-nargs,dPageAddr, (longword) funcptr); if (newPID == SYSERR) { *ERRNO = EAGAIN; DisposeHandle(fstack); enableps(); return -1; } child = &(kp->procTable[newPID]); parent = PROC; /* $$$ &(kp->procTable[Kgetpid()]); */ child->parentpid = Kgetpid(); child->irq_A = newID; child->irq_X = child->irq_Y = 0; child->userID = newID; if (name != NULL) { name = a_strncpy_max(name,128); child->args = malloc(strlen(name)+9); strcpy(child->args,"BYTEWRKS"); strcat(child->args,name); nfree(name); } else child->args = NULL; /* make sure we keep the pgrp refcount up to date */ child->pgrp = parent->pgrp; if (child->pgrp != 0) pgrpInfo[child->pgrp-2].pgrpref++; child->siginfo = malloc(sizeof(struct sigrec)); memcpy(child->siginfo, parent->siginfo, sizeof(struct sigrec)); child->waitq = NULL; i = sizeof(fdentry)*(parent->openFiles->fdTableSize-1); child->openFiles = malloc(sizeof(fdtable)+i); memcpy(child->openFiles, parent->openFiles, sizeof(fdtable)+i); child->prefix = malloc(33*sizeof(GSString255Ptr)); for (i = 0; i < 33; i++) { if (parent->prefix[i] != NULL) { child->prefix[i] = malloc( ((GSString255Ptr) parent->prefix[i])->length+2 ); copygsstr(child->prefix[i],parent->prefix[i]); } else child->prefix[i] = NULL; } child->LInfo = parent->LInfo; child->ticks = 0l; child->childTicks = 0l; child->flags = FL_FORKED | FL_COMPLIANT; child->ttyID = parent->ttyID; child->executeHook = parent->executeHook; child->returnStack = NULL; child->p_uid = parent->p_uid; child->p_gid = parent->p_gid; child->p_euid = parent->p_euid; child->p_egid = parent->p_egid; child->SANEwap = parent->SANEwap; child->lastTool = parent->lastTool; /* actually the resource app number */ asm { lda 0xE0C035 sta state sep #0x30 lda 0xE0C02D sta slot lda 0xE0C068 sta statereg rep #0x30 } child->irq_state = state; child->irq_SLTROM = slot; child->irq_STATEREG = statereg; child->alarmCount = 0l; child->t2StackPtr = 0; child->processState = procNEW; /* brand new! */ parentPID = Kgetpid(); asm { ldy newPID ldx parentPID jsl FORKInitGlob } /* make sure the system knows about all of our new copies of those file descriptors we inherited */ i = child->openFiles->fdCount; k = 0; while (i) { if (j = child->openFiles->fds[k].refNum) { if (child->openFiles->fds[k].refType == rtPIPE) incPipe(child->openFiles->fds[k].refFlags,j); IncRefnum(child->openFiles->fds[k].refType,j); i--; } k++; if (k > child->openFiles->fdTableSize) PANIC("BAD FILE DESCRIPTOR TABLE"); } child->flpid = allocPID(); kp->numProcs++; enableps(); return child->flpid; } #pragma toolparms 1 int KERNfork(int *ERRNO,void *subr) { word nargs = 0; return commonFork((void *)subr, 1024, 0, NULL, &nargs, ERRNO); } pascal int KERNfork2(void (*funcptr)(), word stackSize, int prio, char *name, word *argv, int *ERRNO) { return commonFork(funcptr, stackSize, prio, name, argv, ERRNO); } typedef struct GetUserPathRec { int pCount; int fileSysID; int commandNum; GSString255Ptr prefixPtr; } GetUserPathRec; /* * This MUST be in a function by itself so the PROC-> dereference will have * an allocated DP to use. */ static void kill_self(void) { Kkill(&errno, 9, PROC->flpid); } int KERNexecve(int *ERRNO, char *cmdline, char *filename) { union { InitialLoadOutputRec il; RestartOutRec r; } il_out; #define il_rec il_out.il #define r_rec il_out.r int e; word newID; GSString255Ptr pfn; ResultBuf1KPtr resBuf; int ind; longword *ret; handle fstack; int *optionList; char **ourPFhand; char *args,*argscopy; int i,j; struct pentry *p; ExpandPathRecGS ep; PrefixRecGS sp; FileInfoRecGS fi; int ssf = 0,restart,force_norest = 0; word oldUserID, oldFlags, newStack; extern ctxt ctxtstuff; extern GSString255Ptr __C2GSMALLOC(char *); extern void endproc2(void); extern void execveHook(void); extern void disableBuf(void); extern void enableBuf(void); /* always disableps() when screwing with process tables */ disableps(); if (kp->gsosDebug & 16) fprintf(stderr,"execve(%s,%s)\n",filename,cmdline); p = PROC; /* $$$ &(kp->procTable[Kgetpid()]);*//* aaaaaaaaaaarrrgghhh!!!!! */ /* Don't do anything with the file tables- we simply pass them on to the new process */ /* turn the input path into a GSString255 */ pfn = __C2GSMALLOC(filename); /* do an ExpandPath on the input path */ resBuf = malloc(sizeof(ResultBuf1K)); ep.pCount = 2; ep.inputPath = pfn; resBuf->bufSize = 1024; ep.outputPath = (ResultBuf255Ptr) resBuf; ExpandPathGS(&ep); restart = 1; newID = GetUserID2((Pointer)&resBuf->bufString); if (toolerror() == 0x1101) { /* allocate a new UserID for the program */ newID = GetNewID(0x1000); restart = 0; } else { /* if the 'newID' is being used by a process, force another copy from disk */ for (i = 0; i < NPROC; i++) { if (kp->procTable[i].processState != procUNUSED) if (kp->procTable[i].userID == newID) { newID = GetNewID(0x1000); restart = 0; force_norest = 1; break; } } } if (restart) { r_rec = Restart(newID); } else { il_rec = InitialLoad2(newID, (Pointer)&resBuf->bufString, 1, 1); } if ((e = toolerror())) { switch(e) { case volNotFound: case pathNotFound: case fileNotFound: *ERRNO = ENOENT; break; default: *ERRNO = EIO; break; } nfree(resBuf); enableps(); return -1; } /* get info about the executable so we know how to set up the environment */ optionList = malloc(48l); /* should be large enough for everything */ fi.pCount = 8; fi.pathname = (GSString255Ptr) &(resBuf->bufString); fi.optionList = (void *) optionList; optionList[0] = 48; GetFileInfoGS(&fi); /* if the executable had no defined stack segment, create 1K by default */ if (il_rec.buffSize == 0) { /* no stack/dp segment- create one */ fstack = NewHandle(4096l,newID,0xC015, NULL); il_rec.dPageAddr = (word) *fstack; il_rec.buffSize = 4096; } /* S16s (and others) get no command line arguments, but we should put their name in the process table anyway */ if (cmdline != NULL) { size_t len = strlen(cmdline)+11; /* build the command line by tacking the shellid() onto the real line */ args = (char *) malloc(len); strcpy(args,"BYTEWRKS"); strcat(args, cmdline); args[((word)(len-1))] = 0; /* Orca 2.0 does this for compat */ argscopy = pmalloc(len,newID); memcpy(argscopy,args,len); } else args = argscopy = NULL; /* tricky- shove the address of our generic RTL-exiting shutdown routine onto the process stack so we can always keep track of processes */ ret = (longword *) (il_rec.dPageAddr+il_rec.buffSize-4); *ret = ((longword) endproc2)-1; /* go to endproc when process is done */ /* set up the registers to point to the command line/shell id combo */ if (p->args) nfree(p->args); /* free the args string of the old executable */ p->args = args; if (fi.fileType != 0xB5) argscopy = NULL; ctxtstuff.ctx_A = newID; ctxtstuff.ctx_X = hiWord((longword) argscopy); ctxtstuff.ctx_Y = loWord((longword) argscopy); newStack = ctxtstuff.ctx_S1 = il_rec.dPageAddr+il_rec.buffSize-5; ctxtstuff.ctx_D = il_rec.dPageAddr; ctxtstuff.ctx_B = ctxtstuff.ctx_B1 = (((longword) il_rec.startAddr) >> 16); ctxtstuff.ctx_PC = (longword) il_rec.startAddr; oldUserID = p->userID; oldFlags = p->flags; p->userID = newID; p->ticks = 0l; p->flags = FL_COMPLIANT; if (force_norest) p->flags |= FL_NORESTART; p->SANEwap = 0; /* reset to the 'not started up' state */ p->lastTool = 0x401E; /* reset res app to standard */ /* is program compliant? */ if (fi.auxType == 0xDC00l) { p->flags &= (~FL_COMPLIANT); /* turn off compliance flag */ disableBuf(); /* disablebuf now turns off the cursor */ } /* * Set up the prefixes for the new process image */ /* modify prefixes 1 and 9 to point to the directory the appl. is in */ ourPFhand = PROC->prefix; /* $$$ kp->procTable[Kgetpid()].prefix; */ nfree(ourPFhand[0]); /* the '@' prefix */ nfree(ourPFhand[1+1]); nfree(ourPFhand[9+1]); /* set Prefixes 1 and 9 to the directory the executable is in */ for (ind = resBuf->bufString.length-1; ind > 0; ind--) if (resBuf->bufString.text[ind] == ':') { resBuf->bufString.length = ind+1; break; /* +1 -> snag the colon */ } /* there will always be one */ ourPFhand[9+1] = malloc(resBuf->bufString.length+2); copygsstr(ourPFhand[9+1],&resBuf->bufString); if (optionList[2] == 0x0D) { /* app is on AppleShare volume - set '@' */ GetUserPathRec gp; gp.pCount = 3; gp.fileSysID = 0x0D; gp.commandNum = 8; FSTSpecific(&gp); ourPFhand[0] = malloc(gp.prefixPtr->length+3); copygsstr(ourPFhand[0],gp.prefixPtr); ourPFhand[0][gp.prefixPtr->length+2] = ':'; ((GSString255Ptr)ourPFhand[0])->length++; } else { ourPFhand[0] = malloc(resBuf->bufString.length+2); copygsstr(ourPFhand[0],&resBuf->bufString); } /* if prefix 1 would be longer than 64 chars, set it to the NULL prefix */ if (resBuf->bufString.length > 64) resBuf->bufString.length = 0; ourPFhand[2] = malloc(resBuf->bufString.length+2); copygsstr(ourPFhand[2],&resBuf->bufString); nfree(pfn); nfree(resBuf); nfree(optionList); /* If we're launching a S16 application, copy prefix 0 to prefix 8 */ if (fi.fileType == 0xB3) { pfn = (GSString255Ptr) ourPFhand[0+1]; pfn = malloc(pfn->length+2); copygsstr(pfn,ourPFhand[0+1]); nfree(ourPFhand[8+1]); ourPFhand[8+1] = (char *)pfn; } /* Ignored/blocked signals remain ignored/blocked, but caught signals are reset to their default state */ for (i = 0; i < 32; i++) { if (p->siginfo->v_signal[i] != SIG_IGN) p->siginfo->v_signal[i] = SIG_DFL; } SET_STOP_FLAG(&ssf); if (!(oldFlags & FL_COMPLIANT)) { enableBuf(); } if ((fi.auxType & 0xDB02) != 0xDB02) if (oldFlags & FL_QDSTARTUP) *((byte *)0xE0C029l) &= 0x7F; /* switch over to the new stack before we deallocate the one we're using */ asm { lda newStack tcs } if ((fi.auxType == 0xDC00) && (p->ttyID != 3)) { fprintf(stderr, "Program can only run on console.\n"); if (oldFlags & FL_FORKED) { DisposeAll(oldUserID); /* process was fork()ed, don't USD */ DeleteID(oldUserID); } else { UserShutDown(oldUserID, ((oldFlags & FL_RESTART) && !(oldFlags & FL_NORESTART)) ? 0x4000 : 0); } /* don't use any local variables beyond this point */ /* STACK REPAIR MUST BE OFF TO CALL kill_self() */ kill_self(); /* not reached */ PANIC("EXECVE KILL OVERRUN"); } else { if (oldFlags & FL_FORKED) { DisposeAll(oldUserID); /* process was fork()ed, don't USD */ DeleteID(oldUserID); } else { UserShutDown(oldUserID, ((oldFlags & FL_RESTART) && !(oldFlags & FL_NORESTART)) ? 0x4000 : 0); } /* don't use any local variables beyond this point */ } asm { jmp >execveHook } } /* open the kernel to access the process structures */ kvmt *KERNkvm_open(int *ERRNO) { kvmt *newk; newk = (kvmt *) kmalloc(sizeof(kvmt)); if (newk == NULL) { *ERRNO = ENOMEM; return NULL;} Kkvmsetproc(ERRNO, newk); return newk; } SYSCALL KERNkvm_close(int *ERRNO,kvmt *k) { if (kfree(k)) return SYSERR; return (OK); } struct pentry *KERNkvmgetproc(int *ERRNO, int pid, kvmt *kd) { int mpid; mpid = mapPID(pid); if (mpid == -1) { *ERRNO = ESRCH; return NULL; } memcpy(&(kd->kvm_pent), &(kp->procTable[mpid]), sizeof(struct pentry)); kd->pid = pid; kd->kvm_pent.parentpid = kp->procTable[kp->procTable[mpid].parentpid].flpid; return &(kd->kvm_pent); } struct pentry *KERNkvmnextproc(int *ERRNO, kvmt *kd) { int i; int mpid; if (kd->procIndex < NPROC) { memcpy(&(kd->kvm_pent), &(kp->procTable[kd->procIndex]), sizeof(struct pentry)); kd->pid = kd->kvm_pent.flpid; mpid = mapPID(kd->pid); kd->kvm_pent.parentpid = kp->procTable[kp->procTable[mpid].parentpid].flpid; i = kd->procIndex+1; while ((i < NPROC) && (kp->procTable[i].processState == procUNUSED)) i++; kd->procIndex = i; return &kd->kvm_pent; } else return NULL; } int KERNkvmsetproc(int *ERRNO,kvmt *kd) { int i; for (i = 0; i < NPROC; i++) if (kp->procTable[i].processState != procUNUSED) { kd->procIndex = i; return OK; } return SYSERR; } int KERNtcnewpgrp(int *ERRNO, int fdtty) { unsigned i,devNum,ttyPgrp; fdentryPtr tty; extern fdentryPtr getFDptr(int); tty = getFDptr(fdtty); if ((tty == NULL) || (tty->refNum == 0)) { *ERRNO = EBADF; return -1; } if (tty->refType != rtTTY) { *ERRNO = ENOTTY; return -1; } devNum = tty->refNum-1; disableps(); for (i = 0; i < NPGRP; i++) if (!pgrpInfo[i].pgrpref) break; if (i == NPGRP) { enableps(); return -1; } /* we're leaving a PTY, decrement the refcount */ if (ttyPgrp = ttys[devNum].pgrp) pgrpInfo[ttyPgrp-2].pgrpref--; if (kp->gsosDebug & 16) fprintf(stderr, "tcnewpgrp- TTY:%d pgrp:%d\n",devNum,i+2); ttys[devNum].pgrp = i+2; pgrpInfo[i].pgrpref++; enableps(); return 0; } int KERNsettpgrp(int *ERRNO, int fdtty) { int p,pid = Kgetpid(); int pp,devNum; fdentryPtr tty; extern fdentryPtr getFDptr(int); tty = getFDptr(fdtty); if ((tty == NULL) || (tty->refNum == 0)) { *ERRNO = EBADF; return -1; } if (tty->refType != rtTTY) { *ERRNO = ENOTTY; return -1; } devNum = tty->refNum-1; p = ttys[devNum].pgrp; if (kp->gsosDebug & 16) fprintf(stderr, "settpgrp pid: %d, oldpgrp: %d, ", PROC->flpid, PROC->pgrp); /* $$$ kp->procTable[pid].flpid, kp->procTable[pid].pgrp); */ disableps(); /* $$$ if (kp->procTable[pid].pgrp != p) */ if (PROC->pgrp != p) { if (p != 0) pgrpInfo[p-2].pgrpref++; /* $$$ if ((pp = kp->procTable[pid].pgrp) != 0) */ if ((pp = PROC->pgrp) != 0) pgrpInfo[pp-2].pgrpref--; } if (kp->gsosDebug & 16) fprintf(stderr,"newpgrp: %d\n",p); /* $$$ kp->procTable[pid].pgrp = p; */ PROC->pgrp = p; enableps(); } int KERNtctpgrp(int *ERRNO, int pid, int fdtty) { int p,mpid,devNum; fdentryPtr tty; extern fdentryPtr getFDptr(int); /* should check pid to be sure it's == getpid or a child of it */ mpid = mapPID(pid); if (mpid == -1) { *ERRNO = ESRCH; return -1; } /* if (!((mpid == Kgetpid()) || (kp->procTable[mpid].parentpid == Kgetpid()))) { *ERRNO = ERANGE; return -1; } */ tty = getFDptr(fdtty); if ((tty == NULL) || (tty->refNum == 0)) { *ERRNO = EBADF; return -1; } devNum = tty->refNum-1; if (tty->refType != rtTTY) { *ERRNO = ENOTTY; return -1; } disableps(); p = kp->procTable[mpid].pgrp; if (p != ttys[devNum].pgrp) { if (p != 0) pgrpInfo[p-2].pgrpref++; if (ttys[devNum].pgrp != 0) pgrpInfo[ttys[devNum].pgrp-2].pgrpref--; } if (kp->gsosDebug & 16) fprintf(stderr,"tctpgrp TTY:%d pid:%d pgrp:%d\n",devNum,pid,p); ttys[devNum].pgrp = p; enableps(); } int KERNsetdebug(int code) { int old; if (kp->gsosDebug & 16) fprintf(stderr,"setdebug %d\n",code); if ((code < 0) || (code > 63)) return SYSERR; old = kp->gsosDebug; kp->gsosDebug = code; return old; } void *KERNsetsystemvector(void * execvec) { void *x; x = PROC->executeHook; PROC->executeHook = execvec; /* $$$ x = kp->procTable[Kgetpid()].executeHook; kp->procTable[Kgetpid()].executeHook = execvec; */ return x; } #ifdef NOTDEFINED struct pipest { handle bufferH; /* the pipe data handle */ word in; /* write pointer */ word out; /* read pointer */ word qflags; word RrnCount; /* Why? Because special stuff has to */ word WrnCount; /* happen in strange conditions */ int accessSem; int readSem; int writeSem; int writeStatus; } #endif /* filedes[0] is read only, filedes[1] is write only */ int KERNpipe(int *ERRNO, int filedes[2]) { fdentryPtr pread,pwrite; int fdread,fdwrite; fdtablePtr ft; int pipen; extern int newPipe(void); if (kp->gsosDebug & 16) printf("pipe(%06lX)\n",filedes); /* $$$ ft = kp->procTable[Kgetpid()].openFiles; */ pipen = newPipe(); pread = allocFD(&fdread); if (pread == NULL) { *ERRNO = EMFILE; disposePipe(pipen); return -1; } pwrite = allocFD(&fdwrite); ft = PROC->openFiles; /* deref pointer after calls to allocFD */ if (pwrite == NULL) { pread->refNum = 0; /* deallocate the read file descriptor */ *ERRNO = EMFILE; disposePipe(pipen); return -1; } disableps(); filedes[0] = fdread; filedes[1] = fdwrite; /* a->i1 = a->i2 = b BROKEN in C 2.0.3 */ #if 0 pread->refNum = pwrite->refNum = pipen; pread->refType = pwrite->refType = rtPIPE; pread->refLevel = pwrite->refLevel = ft->fdLevel | ft->fdLevelMode; pwrite->NLenableMask = pread->NLenableMask = 0; #else pread->refNum = pipen; pwrite->refNum = pipen; pread->refType = rtPIPE; pwrite->refType = rtPIPE; pwrite->refLevel = ft->fdLevel | ft->fdLevelMode; pread->refLevel = pwrite->refLevel; pwrite->NLenableMask = 0; pread->NLenableMask = 0; #endif pread->refFlags = rfPIPEREAD; pwrite->refFlags = rfPIPEWRITE; AddRefnum(rtPIPE,pipen); IncRefnum(rtPIPE,pipen); ft->fdCount += 2; /* we opened two new files */ enableps(); return 0; } int KERNdup(int *ERRNO, int filedes) { /* $$$ struct pentry *p; */ fdtablePtr ft; fdentryPtr newFD,oldFD; int nfd; int i,j,fd; extern void IncRefnum(int,int); disableps(); /* $$$ p = &(kp->procTable[Kgetpid()]); */ fd = filedes-1; ft = PROC->openFiles; if ((filedes < 1) || (filedes > 32) || (ft->fds[fd].refNum == 0)) { *ERRNO = EBADF; enableps(); return -1; } newFD = allocFD(&nfd); ft = PROC->openFiles; if (newFD == NULL) { *ERRNO = EMFILE; enableps(); return -1; } oldFD = &(ft->fds[fd]); memcpy(newFD,oldFD,sizeof(fdentry)); IncRefnum(newFD->refType,newFD->refNum); if (newFD->refType == rtPIPE) incPipe(newFD->refFlags,newFD->refNum); ft->fdCount++; /* we created a new one... */ enableps(); return nfd; } int KERNdup2(int *ERRNO, int filedes2, int filedes) { /* $$$ struct pentry *p; */ fdtablePtr ft; fdentryPtr newFD,oldFD; int i,j,fd,fd2; extern void IncRefnum(int,int); int cl[2]; disableps(); /* $$$ p = &(kp->procTable[Kgetpid()]); */ ft = PROC->openFiles; fd = filedes-1; fd2 = filedes2-1; newFD = &(ft->fds[fd2]); oldFD = &(ft->fds[fd]); if ((filedes < 1) || (filedes2 < 1) || (filedes > 32) || (filedes2 > 32) || (oldFD->refNum == 0)) { *ERRNO = EBADF; enableps(); return -1; } /* if they're duping a file to itself, pretend we did it */ if (fd == fd2) { enableps(); return 0; } if (newFD->refNum) { cl[0] = 1; cl[1] = filedes2; CloseGS(cl); } memcpy(newFD,oldFD,sizeof(fdentry)); IncRefnum(newFD->refType,newFD->refNum); if (newFD->refType == rtPIPE) incPipe(newFD->refFlags,newFD->refNum); ft->fdCount++; /* we created a new one... */ enableps(); return 0; } #pragma databank 0 #pragma toolparms 0