📄 exec.c
字号:
/****************************************************************************** * Exec.c Exec fork and sbrk etc * T.Barnaby, Made 20/5/85 ****************************************************************************** */# include "../include/param.h"# include <a.out.h># include "../include/inode.h"# include "../include/signal.h"# include "../include/procs.h"# include "../include/memory.h"# include "../include/swap.h"# include <errno.h># include "../include/stat.h"# include <sys/dir.h># include "../include/state.h"# include "../include/inbin.h"# include "../include/dev.h"# include "../include/file.h"extern int proc_index; /* Proccess index (number of proccesse */extern struct Comm kercom[]; /* Internal kernal commands */long *saveargs(); /* Internal function declarations */char *putstack(), *putarea();struct procs *newproc();# define OPEN SEARCH# define ARGAREA 2048 /* Max area for argument strings */# define NARGS 60 /* Max number of arguments */# define NENVS 30 /* Number of enviroment varibles */char argarea[ARGAREA]; /* Area on system stack to save arguments */char *areaptr; /* Pointer to the area */char *aargv[NARGS]; /* Pointers to args in area */char *aenv[NENVS]; /* Pointers to environs in area *//****************************************************************************** * Xeq - Attempt to load and execute a command ****************************************************************************** * * This is used to execute a program from within the kernal (eg internal shell) * A new proccess number is found, but the old proccess is not swaped * out of core. * It effectivly forks a new process and then execls over the top * the program required. * Returns pid to parent on success (0 to child), or -1 on fail * with error no in errno. * Do not call this routine without using the syscall interface. */xeq(name, argv, env)char *name, *argv[], *env[];{ struct procs *child, *parent; short smask; struct inode *iptr;#ifdef TXEQprintf("XEQ: %s, %x, %x\n",name,argv,environ);ps();#endif /* Checks if internal kernal program, if not checks if program is * on disk and accessable */ if(!inbin(name)){ /* Try and get the file inode and get the object name */ if(!(iptr = namlock(name, EOPEN, NULLIPTR))) return error(ENOENT); /* Check file access permissions */ if(!i_access(iptr, IAEXEC)){ freeiptr(iptr); return error(EACCES); } /* Checks if regular file else retuens error */ if((iptr->i_mode & S_IFMT) != S_IFREG){ freeiptr(iptr); return error(EACCES); } freeiptr(iptr); } smask = smaskon(cur_proc, EVALL); /* Disables process switching */#ifdef TXEQprintf("Forking new process\n");#endif /* attempt to make process slot for new process */ if((child = newproc()) != (struct procs *)-1){ /* Gets area of memory for the process */ getmem(PROCSEG, 0); /* Sets parent to return childs pid */ parent = cur_proc; /* Process is now child */ cur_proc = child;#ifdef TXEQprintf("Execling new process\n");#endif /* Try and execl a process */ if(kexece(name, argv, env) == -1){#ifdef TXEQprintf("Exiting new process\n");#endif endmem(PROCSEG, 0); clrproc(); cur_proc->pid = 0; cur_proc->ppid = 0; cur_proc->sig = 0; cur_proc->flag = 0; cur_proc->majseg = 0; cur_proc->minseg = 0; cur_proc->wchan = 0; cur_proc->stat = 0; cur_proc->exitstatus = 0; proc_index--; cur_proc = parent; smaskoff(cur_proc, smask); return error(-1); } else { cur_proc = parent; smaskoff(child, EVOFF); smaskoff(cur_proc, smask); return child->pid; } } /* failed - no slot */ smaskoff(cur_proc, smask); return error(EAGAIN);}/****************************************************************************** * kexece - attempt to load and execute a command. ****************************************************************************** * * This is the standard system execl. It will check to see if the * program name is an internal kernal program, if so it will execute * this else will search the disk for the given program. * returns 0 on success, -1 on fail. * Do not call this routine without using the syscall interface. */kexece(name, argv, env)char *name, *argv[], *env[];{ unsigned long datastart; /* Start of data in process space */ short sticky; /* Sticky file indicator */ char swap; /* Program from swap space flag */ short mseg, smask, smask1; int c; long *sp; struct inode *iptr; /* Inode or the program */ struct Object object; struct Psize psize; struct file file;#ifdef TEXECprintf("EXEC: %s, %x, %x\n",name, argv, env);ps();#endif sticky = swap = 0; /* Checks if internal program if so executes it */ if(inbin(name)) return exinbin(name, argv, env); /* Try and get the file inode and get the object name */ if(!(iptr = namlock(name, EOPEN, NULLIPTR))) return error(ENOENT); object.majdev = iptr->i_mdev; object.mindev = iptr->i_minor; object.inode = iptr->i_ino; /* Check file access permissions */ if(!i_access(iptr, IAEXEC)){ freeiptr(iptr); return error(EACCES); } /* Checks if regular file else returns error */ if((iptr->i_mode & S_IFMT) != S_IFREG){ freeiptr(iptr); return error(EACCES); } smask = smaskon(cur_proc, EVALL); /* Mask process switch */ /* Store all arguments in argarea */ if(storeargs(argv, env) == -1){ freeiptr(iptr); smaskoff(cur_proc, smask); return -1; }#ifdef TEXECprintf("EXEC: checking swap\n");#endif /* Check if in swap space */ if(inswap(&object, &psize) != -1){ swap = 1; } /* If not check if in file */ else{#ifdef TEXECprintf("EXEC: Opening file\n");#endif if(f_open(&file, relock(iptr), READABLE) == -1){ freeiptr(iptr); smaskoff(cur_proc,smask); return error(ENOENT); }#ifdef TEXECprintf("EXEC: checking file\n");#endif infile(&file, &psize); }#ifdef TEXECprintf("EXEC: in %d filetype %x\n",swap, psize.fmagic);#endif /* Check file type */ if ((psize.fmagic != FMAGIC) && (psize.fmagic != NMAGIC)){ /* format wrong */ if(!swap) f_close(&file); freeiptr(iptr); return error(ENOEXEC); } /* Check if there is room for this program */ if((mseg = extmem(PROCSEG, cur_proc->minseg, psize.tsize + psize.dsize + psize.bsize)) == -1){ if(!swap) f_close(&file); freeiptr(iptr); smaskoff(cur_proc, smask); return error(ENOMEM); } /* Check if within process workspace */ if((psize.entry < (long)memstart(PROCSEG, mseg)) || (psize.entry >= (long)memend(PROCSEG, mseg))){ if(!swap) f_close(&file); freeiptr(iptr); smaskoff(cur_proc,smask); return error(ENOMEM); } /* Clears signals to default if they are not ignored ones */ for(c=0; c<NSIG; c++){ if(cur_proc->signals[c].func != SIG_IGN){ cur_proc->signals[c].func = SIG_DFL; } } cur_proc->sigmode = SIGMODEUNIX; /* Normal signal mode */ cur_proc->sigmask = ENALLSIG; /* Unmask all signals */ cur_proc->evcom = 0; /* All events off */ cur_proc->evenfile = 0; cur_proc->evfile = 0; cur_proc->alarm = 0; /* Event alarm clock ! */ /* Ps I only found this one 1 day */ /* before my Phd viva ! */ cur_proc->wchan = 0; /* Wakeup off */ cur_proc->pwakechan = 0; /* Pre-wake off */ cur_proc->pwakeevent = 0; /* Set program sizes */ if(psize.fmagic == FMAGIC){ datastart = psize.entry+psize.tsize; } else{ datastart = ((psize.entry+psize.tsize)&MMUMASK)+MMUBOUND; } /* Sets up stack pointer to end of stack */ sp = (long *)memend(PROCSEG, mseg); cur_proc->psize.ustack = (long)sp; /* Top of user stack */#ifdef TEXECprintf("EXEC: saveing args \n");#endif /* Saves arguments here either for codata exec */ sp = saveargs(sp, aargv, aenv); setusp(sp); /* Sets the user sp to here */ /* Modify process table entry for this new process */ cur_proc->pid = cur_proc->pid; /* Same proccess id */ cur_proc->reg->sr = 0x0000; /* Sets user state */ cur_proc->reg->usp = (long)sp; cur_proc->reg->pc = psize.entry; cur_proc->psize.fmagic = psize.fmagic; cur_proc->psize.entry = psize.entry; cur_proc->psize.tsize = psize.tsize; cur_proc->psize.dsize = psize.dsize; cur_proc->psize.bsize = psize.bsize; cur_proc->psize.ebss = (unsigned)(datastart+psize.dsize+psize.bsize); cur_proc->object.majdev = object.majdev; cur_proc->object.mindev = object.mindev; cur_proc->object.inode = object.inode; strncpy(cur_proc->name, name, PATHLEN); cur_proc->majseg = PROCSEG; cur_proc->minseg = mseg;#ifdef TEXECprintf("EXEC: GETING program\n");#endif /* If inswap space recover program from here */ if(swap){ if(stickin(&object)){ freeiptr(iptr); endmem(PROCSEG, mseg); smaskoff(cur_proc,smask); kexit(1 << 8); } } /* Else get program from opened file */ else { if(fromfile(&file, &psize)){ f_close(&file); freeiptr(iptr); endmem(PROCSEG, mseg); smaskoff(cur_proc,smask); kexit(1 << 8); } if(iptr->i_mode & ISVTX) sticky = 1; } if(!swap) f_close(&file); /* set BSS to zeroes */ byteclr((datastart+psize.dsize),psize.bsize); /* Sets euid, egid on execution */ if(iptr->i_mode & ISUID) cur_proc->euid = iptr->i_uid; if(iptr->i_mode & ISGID) cur_proc->egid = iptr->i_gid; /* If sticky process save in swap area */ if(sticky) stickout(cur_proc);#ifdef TEXECps();#endif cur_proc->flag = SLOAD; cur_proc->stat = SRUN; setmempid(PROCSEG, mseg, cur_proc->pid); freeiptr(iptr); smaskoff(cur_proc,smask); /* Reallow those nasty interupts */ return 0;}/* * Inbin() Determins whether the program is internal or not */inbin(name)char *name;{ if(strncmp(name, INBIN, strlen(INBIN))) return 0; return 1;}/* * Exinbin() Executes internal program * Checks if program exists, if so resets the process * table entry for 0 text, data and bss size, places * All arguments on user stack, and executes the * Internal process in super state with arguments pointing * to argc, argv, and env on the user stack. */exinbin(name, argv, env)char *name;char *argv[], *env[];{ int c; short smask; long *sp; struct Comm *coms; /* Finds comand name entry in internal kernal command jump table */ coms = kercom; while(coms->c_name && strcmp(coms->c_name, (name + strlen(INBIN)))) coms++; if(!coms->c_name) return error(ENOENT); smask = smaskon(cur_proc, EVALL); /* Mask process switch */ /* Store all arguments in argarea */ if(storeargs(argv, env) == -1){ smaskoff(cur_proc, smask); return -1; } /* Sets up stack pointer to end of stack (user stack) */ sp = (long *)memend(PROCSEG, 0); cur_proc->psize.ustack = (long)sp; /* Top of user stack */ /* Saves arguments here either for codata exec */ sp = saveargs(sp, aargv, aenv); /* Modify process table entry for this new process */ /* Clears signals to default if they are not ignored ones */ for(c=0; c<NSIG; c++){ if(cur_proc->signals[c].func != SIG_IGN){ cur_proc->signals[c].func = SIG_DFL; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -