home *** CD-ROM | disk | FTP | other *** search
- /**************************************************
- UZI (Unix Z80 Implementation) Kernel: scall2.c
- ***************************************************/
-
-
- /*LINTLIBRARY*/
- #include "unix.h"
- #include "extern.h"
-
-
- /* Getpid() */
-
- _getpid()
- {
- return(udata.u_ptab->p_pid);
- }
-
- /* Getppid() */
-
- _getppid()
- {
- return(udata.u_ptab->p_pptr->p_pid);
- }
-
-
- /* Getuid() */
-
- _getuid()
- {
- return(udata.u_ptab->p_uid);
- }
-
-
- _getgid()
- {
- return(udata.u_gid);
- }
-
-
- /*********************************
- setuid(uid)
- int uid;
- ***********************************/
-
- #define uid (int)udata.u_argn
-
- _setuid()
- {
- if (super() || udata.u_ptab->p_uid == uid)
- {
- udata.u_ptab->p_uid = uid;
- udata.u_euid = uid;
- return(0);
- }
- udata.u_error = EPERM;
- return(-1);
- }
-
- #undef uid
-
-
-
- /*****************************************
- setgid(gid)
- int gid;
- ****************************************/
-
- #define gid (int16)udata.u_argn
-
- _setgid()
- {
- if (super() || udata.u_gid == gid)
- {
- udata.u_gid = gid;
- udata.u_egid = gid;
- return(0);
- }
- udata.u_error = EPERM;
- return(-1);
- }
-
- #undef gid;
-
-
-
- /***********************************
- time(tvec)
- int tvec[];
- **************************************/
-
- #define tvec (int *)udata.u_argn
-
- _time()
- {
- rdtime(tvec); /* In machdep.c */
- return(0);
- }
-
- #undef tvec
-
-
- /**************************************
- stime(tvec)
- int tvec[];
- **********************************/
-
- #define tvec (int *)udata.u_argn
-
- _stime()
- {
- /*
- ifnot (super())
- {
- udata.u_error = EPERM;
- return(-1);
- }
- sttime(tvec);
- return(0);
- */
-
- udata.u_error = EPERM;
- return(-1);
- }
-
- #undef tvec
-
-
-
- /********************************************
- times(buf)
- char *buf;
- **********************************************/
-
- #define buf (char *)udata.u_argn
-
- _times()
- {
- ifnot (valadr(buf,6*sizeof(time_t)))
- return(-1);
-
- di();
- bcopy(&udata.u_utime, buf, 4*sizeof(time_t));
- bcopy(&ticks, buf + 4*sizeof(time_t), sizeof(time_t));
- ei();
- return(0);
- }
-
- #undef buf
-
-
-
- /* User's execve() call. All other flavors are library routines. */
-
- /*****************************************
- execve(name, argv, envp)
- char *name;
- char *argv[];
- char *envp[];
- *****************************************/
-
- #define name (char *)udata.u_argn2
- #define argv (char **)udata.u_argn1
- #define envp (char **)udata.u_argn
-
- _execve()
- {
- register inoptr ino;
- register char *buf;
- inoptr n_open();
- char *bread();
- blkno_t bmap();
-
- ifnot (ino = n_open(name,NULLINOPTR))
- return(-1);
-
- if (ino->c_node.i_size.o_blkno >= ((uint16)(&udata)/512))
- {
- udata.u_error = ENOMEM;
- goto nogood;
- }
-
- ifnot ( (getperm(ino) & OTH_EX) &&
- (ino->c_node.i_mode & F_REG) &&
- (ino->c_node.i_mode & (OWN_EX | OTH_EX | GRP_EX)) )
- {
- udata.u_error = EACCES;
- goto nogood;
- }
-
- setftime(ino, A_TIME);
-
- /* Gather the arguments, and put them on the root device */
- /* Put environment on another block */
- if (wargs(argv, 0) || wargs(envp, 1))
- goto nogood;
-
- /* Read in the first block of the new program */
- buf = bread( ino->c_dev, bmap(ino, 0, 1), 0);
-
- if ((*buf & 0xff) != EMAGIC)
- {
- udata.u_error = ENOEXEC;
- goto nogood2;
- }
-
- /* Here, check the setuid stuff. No other changes need be made in
- the user data */
- if (ino->c_node.i_mode & SET_UID)
- udata.u_euid = ino->c_node.i_uid;
-
- if (ino->c_node.i_mode & SET_GID)
- udata.u_egid = ino->c_node.i_gid;
-
- bcopy(buf,PROGBASE,512);
- bfree(buf, 0);
-
- /* At this point, we are committed to reading in and executing
- the program. We switch to a local stack, and pass to it
- the necessary parameter: ino */
-
- udata.u_ino = ino; /* Termorarily stash these here */
-
- tempstk();
- exec2(); /* Never returns */
-
- nogood2:
- bfree(buf, 0);
- nogood:
- i_deref(ino);
- return(-1);
-
- }
-
- #undef name
- #undef argv
- #undef envp
-
-
- exec2()
- {
- register blkno_t blk;
- register char **argv;
- register char **envp;
- register int (**sp)();
- int argc;
- char *rargs();
- register char *progptr;
- char *buf;
- blkno_t pblk;
- blkno_t bmap();
- char *bread();
-
- /* Read in the rest of the program */
- progptr = PROGBASE+512;
- for (blk = 1; blk <= udata.u_ino->c_node.i_size.o_blkno; ++blk)
- {
- pblk = bmap(udata.u_ino, blk, 1);
- if (pblk != -1)
- {
- buf = bread( udata.u_ino->c_dev, pblk, 0);
- bcopy(buf, progptr, 512);
- bfree(buf, 0);
- }
- progptr += 512;
- }
- i_deref(udata.u_ino);
-
- /* Zero out the free memory */
- bzero(progptr,(uint16)((char *)&udata - progptr));
- udata.u_break = progptr;
-
-
- /* Read back the arguments and the environment */
- argv = (char **)rargs((char *)&udata, 0, &argc);
- envp = (char **)rargs((char *)argv, 1, NULL);
-
- /* Fill in udata.u_name */
- bcopy(*argv,udata.u_name,8);
-
- /* Turn off caught signals */
- for (sp= udata.u_sigvec; sp < (udata.u_sigvec+NSIGS); ++sp)
- if (*sp != SIG_IGN)
- *sp = SIG_DFL;
-
- /* Shove argc and the address of argv just below envp */
- *(envp - 1) = (char *)argc;
- *(envp - 2) = (char *)argv;
-
- /* Go jump into the program, first setting the stack */
- doexec((int16 *)(udata.u_isp = envp - 2));
-
- }
-
-
- wargs(argv,blk)
- char **argv;
- int blk;
- {
- register char *ptr; /* Address of base of arg strings in user space */
- register int n;
- struct s_argblk *argbuf;
- register char *bufp;
- register int j;
- char *zerobuf();
- char *bread();
-
- /* Gather the arguments, and put them on the swap device */
- argbuf = (struct s_argblk *)bread(SWAPDEV, udata.u_ptab->p_swap+blk, 2);
- bufp = argbuf->a_buf;
- for (j=0; argv[j] != NULL; ++j)
- {
- ptr = argv[j];
- do
- {
- *bufp++ = *ptr;
- if (bufp >= argbuf->a_buf+500)
- {
- udata.u_error = E2BIG;
- bfree((char *)argbuf, 1);
- return (1);
- }
- }
- while (*ptr++ != '\0');
- }
-
- argbuf->a_argc = j; /* Store argc in argbuf. */
- argbuf->a_arglen = bufp - argbuf->a_buf; /*Store total string size. */
-
- /* Swap out the arguments into the given swap block */
- bfree((char *)argbuf, 1);
-
- return (0);
- }
-
-
-
- char *
- rargs(ptr,blk,cnt)
- register char *ptr;
- int blk;
- int *cnt;
- {
- struct s_argblk *argbuf;
- register char **argv; /* Address of users argv[], just below ptr */
- register int n;
- char *bread();
-
- /* Read back the arguments */
- argbuf = (struct s_argblk *)bread(SWAPDEV,udata.u_ptab->p_swap+blk, 0);
-
- /* Move them into the users address space, at the very top */
- ptr -= argbuf->a_arglen;
- if (argbuf->a_arglen)
- bcopy(argbuf->a_buf, ptr, argbuf->a_arglen);
-
- /* Set argv to point below the argument strings */
- argv = (char **)ptr - (argbuf->a_argc + 1);
-
- /* Set each element of argv[] to point to its argument string */
- argv[0] = ptr;
- for (n=1; n < argbuf->a_argc; ++n)
- argv[n] = argv[n-1] + strlen(argv[n-1]) + 1;
- argv[argbuf->a_argc] = NULL;
-
- if (cnt)
- *cnt = argbuf->a_argc;
-
- bfree((char *)argbuf, 0);
- return (argv);
- }
-
-
-
- /**********************************
- brk(addr)
- char *addr;
- ************************************/
-
- #define addr (char *)udata.u_argn
-
- _brk()
- {
- char dummy; /* A thing to take address of */
-
- /* A hack to get approx val of stack ptr. */
- if (addr < PROGBASE || (addr+64) >= (char *)&dummy)
- {
- udata.u_error = ENOMEM;
- return(-1);
- }
- udata.u_break = addr;
- return(0);
- }
-
- #undef addr
-
-
-
- /************************************
- sbrk(incr)
- uint16 incr;
- ***************************************/
-
- #define incr (uint16)udata.u_argn
-
- _sbrk()
- {
- register char *oldbrk;
-
- udata.u_argn += (oldbrk = udata.u_break);
- if (_brk())
- return(-1);
-
- return((int)oldbrk);
- }
-
- #undef incr
-
-
-
- /**************************************
- wait(statloc)
- int *statloc;
- ****************************************/
-
- #define statloc (int *)udata.u_argn
-
- _wait()
- {
- register ptptr p;
- register int retval;
-
- if (statloc > (int *)(&udata))
- {
- udata.u_error = EFAULT;
- return(-1);
- }
-
- di();
- /* See if we have any children. */
- for (p=ptab;p < ptab+PTABSIZE; ++p)
- {
- if (p->p_status && p->p_pptr == udata.u_ptab && p != udata.u_ptab)
- goto ok;
- }
- udata.u_error = ECHILD;
- ei();
- return (-1);
-
- ok:
- /* Search for an exited child; */
- for (;;)
- {
- chksigs();
- if (udata.u_cursig)
- {
- udata.u_error = EINTR;
- return(-1);
- }
- di();
- for(p=ptab;p < ptab+PTABSIZE; ++p)
- {
- if (p->p_status == P_ZOMBIE && p->p_pptr == udata.u_ptab)
- {
- if (statloc)
- *statloc = p->p_exitval;
- p->p_status = P_EMPTY;
- retval = p->p_pid;
-
- /* Add in child's time info */
- /* It was stored on top of p_wait in the childs process
- table entry */
- addtick(&udata.u_cutime, &(p->p_wait));
- addtick(&udata.u_cstime, (char *)(&(p->p_wait)) +
- sizeof(time_t));
-
- ei();
- return(retval);
- }
- }
- /* Nothing yet, so wait */
- psleep(udata.u_ptab);
- }
-
- }
-
- #undef statloc
-
-
-
- /**************************************
- _exit(val)
- int16 val;
- **************************************/
-
- #define val (int16)udata.u_argn
-
- __exit()
- {
- doexit(val,0);
- }
-
- #undef val
-
-
-
- doexit(val,val2)
- int16 val;
- int16 val2;
- {
- register int16 j;
- register ptptr p;
-
- for (j=0; j < UFTSIZE; ++j)
- {
- ifnot (udata.u_files[j] & 0x80) /* Portable equivalent of == -1 */
- doclose(j);
- }
-
- /* _sync(); /* Not necessary, but a good idea. */
-
- di();
- udata.u_ptab->p_exitval = (val<<8) | (val2 & 0xff);
-
- /* Set child's parents to init */
- for(p=ptab;p < ptab+PTABSIZE; ++p)
- {
- if (p->p_status && p->p_pptr == udata.u_ptab)
- p->p_pptr = initproc;
- }
- i_deref(udata.u_cwd);
-
- /* Stash away child's execution tick counts in process table,
- overlaying some no longer necessary stuff. */
- addtick(&udata.u_utime,&udata.u_cutime);
- addtick(&udata.u_stime,&udata.u_cstime);
- bcopy(&udata.u_utime, &(udata.u_ptab->p_wait), 2 * sizeof(time_t));
-
- /* Wake up a waiting parent, if any. */
- if (udata.u_ptab != initproc)
- wakeup((char *)udata.u_ptab->p_pptr);
- udata.u_ptab->p_status = P_ZOMBIE;
- ei();
- swapin(getproc());
- panic("doexit:won't exit");
- }
-
-
- _fork()
- {
- return (dofork());
- }
-
-
-
- _pause()
- {
- psleep(0);
- udata.u_error = EINTR;
- return(-1);
- }
-
-
- /*************************************
- signal(sig, func)
- int16 sig;
- int16 (*func)();
- ***************************************/
-
- #define sig (int16)udata.u_argn1
- #define func (int (*)())udata.u_argn
-
- _signal()
- {
- int retval;
-
- di();
- if (sig < 1 || sig == SIGKILL || sig >= NSIGS)
- {
- udata.u_error = EINVAL;
- goto nogood;
- }
-
- if (func == SIG_IGN)
- udata.u_ptab->p_ignored |= sigmask(sig);
- else
- {
- if (func != SIG_DFL && ((char *)func < PROGBASE ||
- (struct u_data *)func >= &udata))
- {
- udata.u_error = EFAULT;
- goto nogood;
- }
- udata.u_ptab->p_ignored &= ~sigmask(sig);
- }
- retval = udata.u_sigvec[sig];
- udata.u_sigvec[sig] = func;
- ei();
- return(retval);
-
- nogood:
- ei();
- return(-1);
- }
-
- #undef sig
- #undef func
-
-
-
- /**************************************
- kill(pid, sig)
- int16 pid;
- int16 sig;
- *****************************************/
-
- #define pid (int16)udata.u_argn1
- #define sig (int16)udata.u_argn
-
- _kill()
- {
- ptptr p;
-
- if (sig <= 0 || sig > 15)
- goto nogood;
-
- for (p=ptab; p < ptab+PTABSIZE; ++p)
- {
- if (p->p_pid == pid)
- {
- sendsig(p,sig);
- return(0);
- }
- }
-
- nogood:
- udata.u_error = EINVAL;
- return(-1);
- }
-
- #undef pid
- #undef sig
-
-
-
- /********************************
- alarm(secs)
- uint16 secs;
- *********************************/
-
- #define secs (int16)udata.u_argn
-
- _alarm()
- {
- int retval;
-
- di();
- retval = udata.u_ptab->p_alarm;
- udata.u_ptab->p_alarm = secs;
- ei();
- return(retval);
- }
-
- #undef secs
-
-