diff --git a/WEGA/src/uts/sys/acct.c b/WEGA/src/uts/sys/acct.c new file mode 100644 index 0000000..a358b2c --- /dev/null +++ b/WEGA/src/uts/sys/acct.c @@ -0,0 +1,109 @@ +#include "sys/param.h" +#include "sys/systm.h" +#include "sys/acct.h" +#include "sys/dir.h" +#include "sys/user.h" +#include "sys/inode.h" + +/* + * Perform process accounting functions. + */ + +sysacct() +{ + register struct inode *ip; + register struct a { + char *fname; + } *uap; + + uap = (struct a *)u.u_ap; + if (!suser()) + return; + if (uap->fname==NULL) { + if (acctp) { + plock(acctp); + iput(acctp); + acctp = NULL; + } + return; + } + if (acctp) { + u.u_error = EBUSY; + return; + } +#ifndef PNETDFS + ip = namei(uchar, 0); +#else + ip = namei(uchar, 0, NULL); +#endif + if(ip == NULL) + return; + if((ip->i_mode & IFMT) != IFREG) { + u.u_error = EACCES; + iput(ip); + return; + } + acctp = ip; + prele(ip); +} + +/* + * On exit, write a record on the accounting file. + */ +acct(st) +{ + register struct inode *ip; + off_t siz; + + if ((ip=acctp)==NULL) + return; + plock(ip); + bcopy(u.u_comm,acctbuf.ac_comm,sizeof(acctbuf.ac_comm)); + acctbuf.ac_btime = u.u_start; + acctbuf.ac_utime = compress(u.u_utime); + acctbuf.ac_stime = compress(u.u_stime); + acctbuf.ac_etime = compress(lbolt - u.u_ticks); + acctbuf.ac_mem = compress(u.u_mem); + acctbuf.ac_io = compress(u.u_ioch); + acctbuf.ac_rw = compress(u.u_ior+u.u_iow); + acctbuf.ac_uid = u.u_ruid; + acctbuf.ac_gid = u.u_rgid; + acctbuf.ac_tty = u.u_ttyp ? u.u_ttyd : NODEV; + acctbuf.ac_stat = st; + acctbuf.ac_flag = u.u_acflag; + siz = ip->i_size; + u.u_offset = siz; + u.u_base = (caddr_t)&acctbuf; + u.u_count = sizeof(acctbuf); + u.u_segflg = 1; + u.u_error = 0; + u.u_limit = (daddr_t)5000; + writei(ip); + if(u.u_error) + ip->i_size = siz; + prele(ip); +} + +/* + * Produce a pseudo-floating point representation + * with 3 bits base-8 exponent, 13 bits fraction. + */ +compress(t) +register time_t t; +{ + register exp = 0, round = 0; + + while (t >= 8192) { + exp++; + round = t&04; + t >>= 3; + } + if (round) { + t++; + if (t >= 8192) { + t >>= 3; + exp++; + } + } + return((exp<<13) + t); +} diff --git a/WEGA/src/uts/sys/nami.c b/WEGA/src/uts/sys/nami.c new file mode 100644 index 0000000..3d5e256 --- /dev/null +++ b/WEGA/src/uts/sys/nami.c @@ -0,0 +1,265 @@ +/****************************************************************************** +******************************************************************************* + + W E G A - Quelle + + KERN 3.2 Modul: nami.c + + + Bearbeiter: O. Lehmann + Datum: 17.05.08 + Version: 1.0 + +******************************************************************************* +******************************************************************************/ + +char namiwstr[] = "@[$]nami.c Rev : 4.1 08/27/83 11:56:22"; + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * Convert a pathname into a pointer to + * an inode. Note that the inode is locked. + * + * func = function called to get next char of name + * &uchar if name is in user space + * &schar if name is in system space + * flag = 0 if name is sought + * 1 if name is to be created + * 2 if name is to be deleted + */ +struct inode * +namei(func, flag) +int (*func)(); +{ + register struct inode *dp; + register c; + register char *cp; + struct buf *bp; + int i; + dev_t d; + off_t eo; + + /* + * If name starts with '/' start from + * root; otherwise start from current dir. + */ + + sysinfo.namei++; + c = (*func)(); + if (c == '\0') { + u.u_error = ENOENT; + return(NULL); + } + if (c == '/') { + if ((dp = u.u_rdir) == NULL) + dp = rootdir; + while(c == '/') + c = (*func)(); + if(c == '\0' && flag != 0) { + u.u_error = ENOENT; + return(NULL); + } + } else + dp = u.u_cdir; + iget(dp->i_dev, dp->i_number); + +cloop: + /* + * Here dp contains pointer + * to last component matched. + */ + + if(u.u_error) + goto out; + if(c == '\0') + return(dp); + + /* + * If there is another component, + * gather up name into users' dir buffer. + */ + + + cp = &u.u_dent.d_name[0]; + while(c != '/' && c != '\0' && u.u_error == 0) { + if(cp < &u.u_dent.d_name[DIRSIZ]) + *cp++ = c; + c = (*func)(); + } + while(cp < &u.u_dent.d_name[DIRSIZ]) + *cp++ = '\0'; + while(c == '/') + c = (*func)(); + +seloop: + /* + * dp must be a directory and + * must have X permission. + */ + if ((dp->i_mode&IFMT) != IFDIR || dp->i_nlink==0) + u.u_error = ENOTDIR; + else + access(dp, IEXEC); + if (u.u_error) + goto out; + + /* + * set up to search a directory + */ + u.u_offset = 0; + eo = 0; + bp = NULL; + if (dp == u.u_rdir) + if (u.u_dent.d_name[0] == '.') + if (u.u_dent.d_name[1] == '.') + if (u.u_dent.d_name[2] == '\0') + goto cloop; + +eloop: + + /* + * If at the end of the directory, + * the search failed. Report what + * is appropriate as per flag. + */ + + if(u.u_offset >= dp->i_size) { + if(bp != NULL) + brelse(bp); + if(flag==1 && c=='\0') { + if(access(dp, IWRITE)) + goto out; + u.u_pdir = dp; + if (eo) + u.u_offset = eo - sizeof(struct direct); + bmap(dp, (daddr_t)(u.u_offset>>BSHIFT), B_WRITE); + if (u.u_error) + goto out; + return(NULL); + } + u.u_error = ENOENT; + goto out; + } + + /* + * If offset is on a block boundary, + * read the next directory block. + * Release previous if it exists. + */ + + if((u.u_offset&BMASK) == 0) { + daddr_t bn; + + if(bp != NULL) + brelse(bp); + sysinfo.dirblk++; + bn = bmap(dp, (daddr_t)(u.u_offset>>BSHIFT), B_READ); + if (u.u_error) + goto out; + if (bn < 0) { + u.u_error = EIO; + goto out; + } + bp = bread(dp->i_dev, bn); + if (u.u_error) { + brelse(bp); + goto out; + } + } + + /* + * Note first empty directory slot + * in eo for possible creat. + * String compare the directory entry + * and the current component. + * If they do not match, go back to eloop. + */ + + cp = bp->b_un.b_addr+(u.u_offset&BMASK); + u.u_offset += sizeof(struct direct); + u.u_dent.d_ino = ((struct direct *)cp)->d_ino; + if(u.u_dent.d_ino == 0) { + if(eo == 0) + eo = u.u_offset; + goto eloop; + } + cp = &((struct direct *)cp)->d_name[0]; + for(i=0; ii_dev; + if(u.u_dent.d_ino == ROOTINO) + if(dp->i_number == ROOTINO) + if(u.u_dent.d_name[1] == '.') + for(i=1; ii_count++; + plock(dp); + goto seloop; + } + iput(dp); + dp = iget(d, u.u_dent.d_ino); + if(dp == NULL) + return(NULL); + goto cloop; + +out: + iput(dp); + return(NULL); +} + +/* + * Return the next character from the + * kernel string pointed at by dirp. + */ +schar() +{ + + return(u.u_dirp.left++ & 0377); +} + +/* + * Return the next character from the + * user string pointed at by dirp. + */ +uchar() +{ + register c; + + c = fubyte(u.u_dirp.left++); + if(!c) + u.u_error = EFAULT; + return(c); +} diff --git a/WEGA/src/uts/sys/sig.c b/WEGA/src/uts/sys/sig.c new file mode 100644 index 0000000..2fe3bc4 --- /dev/null +++ b/WEGA/src/uts/sys/sig.c @@ -0,0 +1,425 @@ +#include "sys/plexus.h" +#include "sys/param.h" +#include "sys/systm.h" +#include "sys/dir.h" +#include "sys/user.h" +#include "sys/proc.h" +#include "sys/inode.h" +#include "sys/reg.h" +#include "sys/text.h" +#include "sys/seg.h" +#include "sys/var.h" +#include "sys/psl.h" + +/* + * Priority for tracing + */ +#define IPCPRI PZERO + +/* + * Tracing variables. + * Used to pass trace command from + * parent to child being traced. + * This data base cannot be + * shared and is locked + * per user. + */ +struct +{ + int ip_lock; + int ip_req; + int *ip_addr; + int ip_data; +} ipc; + +/* + * Send the specified signal to + * all processes with 'pgrp' as + * process group. + * Called by tty.c for quits and + * interrupts. + */ +signal(pgrp, sig) +register pgrp; +{ + register struct proc *p; + + if(pgrp == 0) + return; + for(p = &proc[1]; p < (struct proc *)v.ve_proc; p++) + if(p->p_pgrp == pgrp) + psignal(p, sig); +} + +/* + * Send the specified signal to + * the specified process. + */ +psignal(p, sig) +register struct proc *p; +register sig; +{ + + sig--; + if (sig < 0 || sig >= NSIG) + return; + p->p_sig |= 1L<p_stat == SSLEEP && p->p_pri > PZERO) { + if(p->p_pri > PUSER) + p->p_pri = PUSER; + setrun(p); + } +} + +/* + * Returns true if the current + * process has a signal to process. + * This is asked at least once + * each time a process enters the + * system. + * A signal does not do anything + * directly to a process; it sets + * a flag that asks the process to + * do something to itself. + */ +issig() +{ + register n; + register struct proc *p, *q; + + p = u.u_procp; + while(p->p_sig) { + n = fsig(p); + if (n == SIGCLD) { + if (u.u_signal[SIGCLD-1]&01) { + for (q = &proc[1]; + q < (struct proc *)v.ve_proc; q++) { + if (p->p_pid == q->p_ppid && + q->p_stat == SZOMB) + freeproc(q, 0) ; + } + } else + if (u.u_signal[SIGCLD-1]) + return(n) ; + } else + if((u.u_signal[n-1]&1) == 0 || (p->p_flag&STRC)) + return(n); + p->p_sig &= ~(1L<<(n-1)); + } + return(0); +} + +/* + * Enter the tracing STOP state. + * In this state, the parent is + * informed and the process is able to + * receive commands from the parent. + */ +stop() +{ + register struct proc *pp, *cp; + +loop: + cp = u.u_procp; + if(cp->p_ppid != 1) + for (pp = &proc[0]; pp < (struct proc *)v.ve_proc; pp++) + if (pp->p_pid == cp->p_ppid) { + wakeup((caddr_t)pp); + cp->p_stat = SSTOP; + swtch(); + if ((cp->p_flag&STRC)==0 || procxmt()) + return; + goto loop; + } + exit(fsig(u.u_procp)); +} + +/* + * Perform the action specified by + * the current signal. + * The usual sequence is: + * if(issig()) + * psig(); + */ +psig() +{ + register n, p; + register struct proc *rp; + + rp = u.u_procp; + if (rp->p_flag&STRC) + stop(); + n = fsig(rp); + if (n==0) + return; + rp->p_sig &= ~(1L<<(n-1)); + if((p=u.u_signal[n-1]) != 0) { + u.u_error = 0; + if(n != SIGILL && n != SIGTRAP) + u.u_signal[n-1] = 0; + sendsig(p, n); + return; + } + switch(n) { + + case SIGQUIT: + case SIGILL: + case SIGTRAP: + case SIGIOT: + case SIGEMT: + case SIGFPE: + case SIGBUS: + case SIGSEGV: + case SIGSYS: + if(core()) + n += 0200; + } + exit(n); +} + +/* + * find the signal in bit-position + * representation in p_sig. + */ +fsig(p) +struct proc *p; +{ + register i; + long n; + + n = p->p_sig; + for(i=1; i<=NSIG; i++) { + if(n & 1L) + return(i); + n >>= 1; + } + return(0); +} + +/* + * Create a core image on the file "core" + * + * It writes USIZE block of the + * user.h area followed by the entire + * data+stack segments. + */ +core() +{ + register struct inode *ip; + register unsigned s; + extern schar(); + + if (u.u_uid != u.u_ruid) + return(0); + u.u_error = 0; + u.u_dirp = "core"; +#ifndef PNETDFS + ip = namei(schar, 1); +#else + ip = namei(schar, 1, NULL); +#endif + if(ip == NULL) { + if(u.u_error) + return(0); + ip = maknode(0666); + if (ip==NULL) + return(0); + } + if(!access(ip, IWRITE) && (ip->i_mode&IFMT) == IFREG) { + itrunc(ip); + u.u_offset = 0; + u.u_base = (caddr_t)&u; + u.u_count = ctob(USIZE); + u.u_segflg = 1; + u.u_limit = (daddr_t)ctod(MAXMEM); + writei(ip); + s = u.u_procp->p_size - USIZE; + estabur((unsigned)0, s, (unsigned)0, 0, RO); + u.u_base = 0; + u.u_count = ctob(s); + u.u_segflg = 0; + writei(ip); + } else + u.u_error = EACCES; + iput(ip); + return(u.u_error==0); +} + +/* + * grow the stack to include the SP + * true return if successful. + */ + +grow(sp) +unsigned sp; +{ + register si, i; + register struct proc *p; + register a; + + si = btoc(USRSTACK-sp) - u.u_ssize; + if(si <= 0) + return(0); + if(estabur(u.u_tsize, u.u_dsize, u.u_ssize+si, u.u_sep, RO)) + return(0); + p = u.u_procp; + expand(p->p_size+si); + a = p->p_addr + p->p_size; + for(i=u.u_ssize; i; i--) { + a--; + copyseg(a-si, a); + } + for(i=si; i; i--) + clearseg(--a); + u.u_ssize += si; + return(1); +} + +/* + * sys-trace system call. + */ +ptrace() +{ + register struct proc *p; + register struct a { + int data; + int pid; + int *addr; + int req; + } *uap; + + uap = (struct a *)u.u_ap; + if (uap->req <= 0) { + u.u_procp->p_flag |= STRC; + return; + } + for (p=proc; p < (struct proc *)v.ve_proc; p++) + if (p->p_stat==SSTOP + && p->p_pid==uap->pid + && p->p_ppid==u.u_procp->p_pid) + goto found; + u.u_error = ESRCH; + return; + + found: + while (ipc.ip_lock) + sleep((caddr_t)&ipc, IPCPRI); + ipc.ip_lock = p->p_pid; + ipc.ip_data = uap->data; + ipc.ip_addr = uap->addr; + ipc.ip_req = uap->req; + p->p_flag &= ~SWTED; + setrun(p); + while (ipc.ip_req > 0) + sleep((caddr_t)&ipc, IPCPRI); + u.u_rval1 = ipc.ip_data; + if (ipc.ip_req < 0) + u.u_error = EIO; + ipc.ip_lock = 0; + wakeup((caddr_t)&ipc); +} + +/* + * Code that the child process + * executes to implement the command + * of the parent process in tracing. + */ +procxmt() +{ + register int i; + register *p; + register struct text *xp; + + if (ipc.ip_lock != u.u_procp->p_pid) + return(0); + i = ipc.ip_req; + ipc.ip_req = 0; + wakeup((caddr_t)&ipc); + switch (i) { + + /* read user I */ + case 1: + ipc.ip_data = fuiword((caddr_t)ipc.ip_addr); + break; + + /* read user D */ + case 2: + ipc.ip_data = fuword((caddr_t)ipc.ip_addr); + break; + + /* read u */ + case 3: + i = (int)ipc.ip_addr; + if (i<0 || i >= ctob(USIZE)) + goto error; + ipc.ip_data = ((physadr)&u)->r[i>>1]; + break; + + /* write user I */ + /* Must set up to allow writing */ + case 4: + /* + * If text, must assure exclusive use + */ + if (xp = u.u_procp->p_textp) { + if (xp->x_count!=1 || xp->x_iptr->i_mode&ISVTX) + goto error; + xp->x_iptr->i_flag &= ~ITEXT; + } + estabur(u.u_tsize, u.u_dsize, u.u_ssize, u.u_sep, RW); + i = suiword((caddr_t)ipc.ip_addr, 0); + suiword((caddr_t)ipc.ip_addr, ipc.ip_data); + estabur(u.u_tsize, u.u_dsize, u.u_ssize, u.u_sep, RO); + if (i<0) + goto error; + if (xp) + xp->x_flag |= XWRIT; + break; + + /* write user D */ + case 5: + if (suword((caddr_t)ipc.ip_addr, 0) < 0) + goto error; + suword((caddr_t)ipc.ip_addr, ipc.ip_data); + break; + + /* write u */ + case 6: + i = (int)ipc.ip_addr; + p = (int *)&((physadr)&u)->r[i>>1]; + for (i=0; i<15; i++) + if (p == &u.u_ar0[regloc[i]]) + goto ok; + if (p == &u.u_ar0[PC]) + goto ok; + if (p == &u.u_ar0[FCW]) { + ipc.ip_data &= (M_FLGS << S_FLGS); + ipc.ip_data |= (B_VI | B_NVI); + goto ok; + } + goto error; + + ok: + *p = ipc.ip_data; + break; + + /* set signal and continue */ + /* one version causes a trace-trap */ + case 9: + u.u_ar0[FCW] |= B_SINGL; + case 7: + u.u_procp->p_sig = 0; + if (ipc.ip_data) + psignal(u.u_procp, ipc.ip_data); + return(1); + + /* force exit */ + case 8: + exit(fsig(u.u_procp)); + + default: + error: + ipc.ip_req = -1; + } + return(0); +} diff --git a/WEGA/src/uts/sys/sys2.c b/WEGA/src/uts/sys/sys2.c new file mode 100644 index 0000000..f404881 --- /dev/null +++ b/WEGA/src/uts/sys/sys2.c @@ -0,0 +1,435 @@ +#include "sys/param.h" +#include "sys/systm.h" +#include "sys/dir.h" +#include "sys/user.h" +#include "sys/file.h" +#include "sys/inode.h" +#include "sys/sysinfo.h" +#ifdef PNETDFS +extern ddbug; +#endif + +/* + * read system call + */ +read() +{ + rdwr(FREAD); +} + +/* + * write system call + */ +write() +{ + rdwr(FWRITE); +} + +/* + * common code for read and write calls: + * check permissions, set base, count, and offset, + * and switch out to readi or writei code. + */ +rdwr(mode) +register mode; +{ + register struct file *fp; + register struct inode *ip; + register struct a { + int fdes; + char *cbuf; + unsigned count; + } *uap; + int type; + + uap = (struct a *)u.u_ap; + fp = getf(uap->fdes); + if (fp == NULL) + return; + if ((fp->f_flag&mode) == 0) { + u.u_error = EBADF; + return; + } + u.u_base = (caddr_t)uap->cbuf; + u.u_count = uap->count; + u.u_segflg = 0; + u.u_fmode = fp->f_flag; + ip = fp->f_inode; +#ifdef PNETDFS + if ( ip->i_flag & IRMT ) { + rrdwr( ip, uap->fdes, mode ); + goto dfsout; + } +#endif + type = ip->i_mode&IFMT; + if (type==IFREG || type==IFDIR) { + if ((u.u_fmode&FAPPEND) && (mode == FWRITE)) + fp->f_offset = ip->i_size; + if (ip->i_locklist && + locked(1, ip, fp->f_offset, fp->f_offset + u.u_count)) + return; + plock(ip); + } else if (type == IFIFO) { + fp->f_offset = 0; + if (ip->i_locklist && + locked(1, ip, fp->f_offset, fp->f_offset + u.u_count)) + return; + plock(ip); + } + u.u_offset = fp->f_offset; + if (mode == FREAD) + readi(ip); + else + writei(ip); + if (type==IFREG || type==IFDIR || type==IFIFO) + prele(ip); +#ifdef PNETDFS + dfsout: +#endif + fp->f_offset += uap->count-u.u_count; + u.u_rval1 = uap->count-u.u_count; + u.u_ioch += u.u_rval1; + if (mode == FREAD) + sysinfo.readch += u.u_rval1; + else + sysinfo.writech += u.u_rval1; +} + +/* + * open system call + */ +open() +{ + register struct a { + char *fname; + int mode; + int crtmode; + } *uap; + + uap = (struct a *)u.u_ap; + copen(uap->mode-FOPEN, uap->crtmode); +} + +/* + * creat system call + */ +creat() +{ + register struct a { + char *fname; + int fmode; + } *uap; + + uap = (struct a *)u.u_ap; + copen(FWRITE|FCREAT|FTRUNC, uap->fmode); +} + +/* + * common code for open and creat. + * Check permissions, allocate an open file structure, + * and call the device open routine if any. + */ +copen(mode, arg) +register mode; +{ + register struct inode *ip; + register struct file *fp; + int i; + + if ((mode&(FREAD|FWRITE)) == 0) { + u.u_error = EINVAL; + return; + } + if (mode&FCREAT) { +#ifndef PNETDFS + ip = namei(uchar, 1); +#else + ip = namei(uchar, 1, NULL); +#endif + if (ip == NULL) { + if (u.u_error) + return; + ip = maknode(arg&07777&(~ISVTX)); + if (ip == NULL) + return; + mode &= ~FTRUNC; + } else { + if (ip->i_locklist != NULL && + (ip->i_flag & IFMT) == IFREG && + locked(2, ip, (long)(0L), (long)(1L<<30))) { + iput(ip); + return; + } + if (mode&FEXCL) { + u.u_error = EEXIST; + iput(ip); + return; + } + mode &= ~FCREAT; + } + } else { +#ifndef PNETDFS + ip = namei(uchar, 0); +#else + ip = namei(uchar, 0, NULL); +#endif + if (ip == NULL) + return; + } + if (!(mode&FCREAT)) { + if (mode&FREAD) + access(ip, IREAD); + if (mode&(FWRITE|FTRUNC)) { + access(ip, IWRITE); + if ((ip->i_mode&IFMT) == IFDIR) + u.u_error = EISDIR; + } + } + if (u.u_error || (fp = falloc()) == NULL) { + iput(ip); + return; + } + if (mode&FTRUNC) + itrunc(ip); + prele(ip); + fp->f_flag = mode&FMASK; + fp->f_inode = ip; + i = u.u_rval1; + if (setjmp(u.u_qsav)) { /* catch half-opens */ + if (u.u_abreq) + (*u.u_abreq)(); + if (u.u_error == 0) + u.u_error = EINTR; + closef(fp); + u.u_ofile[i] = NULL; + } else { + openi(ip, mode); + if (u.u_error == 0) + return; + u.u_ofile[i] = NULL; + fp->f_count--; + iput(ip); + } +} + +/* + * close system call + */ +close() +{ + register struct file *fp; + register struct a { + int fdes; + } *uap; + + uap = (struct a *)u.u_ap; + fp = getf(uap->fdes); + if (fp == NULL) + return; + closef(fp); + u.u_ofile[uap->fdes] = NULL; +} + +/* + * seek system call + */ +seek() +{ + register struct file *fp; + register struct inode *ip; + register struct a { + int fdes; + off_t off; + int sbase; + } *uap; + + uap = (struct a *)u.u_ap; + fp = getf(uap->fdes); + if (fp == NULL) + return; + ip = fp->f_inode; + if ((ip->i_mode&IFMT)==IFIFO) { + u.u_error = ESPIPE; + return; + } +#ifdef PNETDFS + if ( ip->i_flag & IRMT ) { +if ( ddbug ) { + printf( "remote seek %x\n", ip ); + debug(); +} + rseek( uap->fdes, uap->off, uap->sbase ); + return; + } +#endif + if (uap->sbase == 1) + uap->off += fp->f_offset; + else if (uap->sbase == 2) + uap->off += fp->f_inode->i_size; + else if (uap->sbase != 0) { + u.u_error = EINVAL; + psignal(u.u_procp, SIGSYS); + return; + } + if (uap->off < 0) { + u.u_error = EINVAL; + return; + } + fp->f_offset = uap->off; + u.u_roff = uap->off; +} + +/* + * link system call + */ +link() +{ + register struct inode *ip, *xp; + register struct a { + char *target; + char *linkname; + } *uap; + + uap = (struct a *)u.u_ap; +#ifndef PNETDFS + ip = namei(uchar, 0); +#else + ip = namei(uchar, 0, NULL); +#endif + if (ip == NULL) + return; + if (ip->i_nlink >= MAXLINK) { + u.u_error = EMLINK; + goto out; + } + if ((ip->i_mode&IFMT)==IFDIR && !suser()) + goto out; + /* + * Unlock to avoid possibly hanging the namei. + * Sadly, this means races. (Suppose someone + * deletes the file in the meantime?) + * Nor can it be locked again later + * because then there will be deadly + * embraces. + */ + prele(ip); + u.u_dirp = (caddr_t)uap->linkname; +#ifndef PNETDFS + xp = namei(uchar, 1); +#else + xp = namei(uchar, 1, NULL); +#endif + if (xp != NULL) { + u.u_error = EEXIST; + iput(xp); + goto out; + } + if (u.u_error) + goto out; +#ifdef PNETDFS + if ( u.u_pdir && u.u_pdir->i_flag & IRMT ) { + printf( "link on remote dfs, not there yet\n" ); + debug(); + u.u_error = EXDEV; + iput( u.u_pdir ); + goto out; + } +#endif + if (u.u_pdir->i_dev != ip->i_dev) { + iput(u.u_pdir); + u.u_error = EXDEV; + goto out; + } + wdir(ip); + if (u.u_error==0) { + ip->i_nlink++; + ip->i_flag |= ICHG; + } + +out: + iput(ip); +} + +/* + * mknod system call + */ +mknod() +{ + register struct inode *ip; + register struct a { + char *fname; + int fmode; + dev_t dev; + } *uap; +#ifdef PNETDFS + struct inode *rmaknode(); +#endif + + uap = (struct a *)u.u_ap; + if ((uap->fmode&IFMT) != IFIFO && !suser()) + return; +#ifndef PNETDFS + ip = namei(uchar, 1); +#else + ip = namei(uchar, 1, NULL); +#endif + if (ip != NULL) { + u.u_error = EEXIST; + goto out; + } + if (u.u_error) + return; +#ifdef PNETDFS + if ( u.u_pdir->i_flag & IRMT ) { + ip = rmaknode( uap->fmode ); + return; + } +#endif + ip = maknode(uap->fmode); + if (ip == NULL) + return; + switch(ip->i_mode&IFMT) { + case IFCHR: + case IFBLK: + ip->i_rdev = (dev_t)uap->dev; + ip->i_flag |= ICHG; + } + +out: + iput(ip); +} + +/* + * access system call + */ +saccess() +{ + register svuid, svgid; + register struct inode *ip; + register struct a { + char *fname; + int fmode; + } *uap; + + uap = (struct a *)u.u_ap; + svuid = u.u_uid; + svgid = u.u_gid; + u.u_uid = u.u_ruid; + u.u_gid = u.u_rgid; +#ifndef PNETDFS + ip = namei(uchar, 0); +#else + ip = namei(uchar, 0, NULL); +#endif + if (ip != NULL) { + if (uap->fmode&(IREAD>>6)) + access(ip, IREAD); + if (uap->fmode&(IWRITE>>6)) + access(ip, IWRITE); + if (uap->fmode&(IEXEC>>6)) + access(ip, IEXEC); + iput(ip); + } + u.u_uid = svuid; + u.u_gid = svgid; +} diff --git a/WEGA/src/uts/sys/sys3.c b/WEGA/src/uts/sys/sys3.c new file mode 100644 index 0000000..2961fad --- /dev/null +++ b/WEGA/src/uts/sys/sys3.c @@ -0,0 +1,428 @@ +#include "sys/param.h" +#include "sys/systm.h" +#include "sys/stat.h" +#include "sys/mount.h" +#include "sys/ino.h" +#include "sys/buf.h" +#include "sys/filsys.h" +#include "sys/dir.h" +#include "sys/user.h" +#include "sys/inode.h" +#include "sys/file.h" +#include "sys/conf.h" +#include "sys/ioctl.h" +#include "sys/var.h" +#ifdef PNETDFS +extern ddbug; +#endif + +/* + * the fstat system call. + */ +fstat() +{ + register struct file *fp; + register struct a { + int fdes; + struct stat *sb; + } *uap; + + uap = (struct a *)u.u_ap; + fp = getf(uap->fdes); + if(fp == NULL) + return; + stat1(fp->f_inode, uap->sb); +} + +/* + * the stat system call. + */ +stat() +{ + register struct inode *ip; + register struct a { + char *fname; + struct stat *sb; + } *uap; + + uap = (struct a *)u.u_ap; +#ifndef PNETDFS + ip = namei(uchar, 0); +#else + ip = namei(uchar, 0, NULL); +#endif + if(ip == NULL) + return; + stat1(ip, uap->sb); + iput(ip); +} + +/* + * The basic routine for fstat and stat: + * get the inode and pass appropriate parts back. + */ +stat1(ip, ub) +register struct inode *ip; +struct stat *ub; +{ + register struct buf *bp; + struct stat ds; + +#ifdef PNETDFS + if ( ip->i_flag & IRMT ) { + rstat1( ip, ub ); + return; + } +#endif + + if(ip->i_flag&(IACC|IUPD|ICHG)) + iupdat(ip, &time, &time); + /* + * first copy from inode table + */ + ds.st_dev = ip->i_dev; + ds.st_ino = ip->i_number; + ds.st_mode = ip->i_mode; + ds.st_nlink = ip->i_nlink; + ds.st_uid = ip->i_uid; + ds.st_gid = ip->i_gid; + ds.st_rdev = (dev_t)ip->i_rdev; + ds.st_size = ip->i_size; + /* + * next the dates in the disk + */ + bp = bread(ip->i_dev, itod(ip->i_number)); + copyio(paddr(bp)+itoo(ip->i_number)*sizeof(struct dinode) + +(long)(&((struct dinode *)0)->di_atime), + &ds.st_atime, 3*sizeof(time_t), U_RKD); + brelse(bp); + if (copyout((caddr_t)&ds, (caddr_t)ub, sizeof(ds)) < 0) + u.u_error = EFAULT; +} + +/* + * the dup system call. + * + * dup2 has been added to the stock SYSTEM III code for compatibility + * with v7. + */ +dup() +{ + register struct file *fp; + register struct a { + int fdes; + int fdes2; + } *uap; + register i,m; + + uap = (struct a *)u.u_ap; + m = uap->fdes & ~077; + uap->fdes &= 077; + fp = getf(uap->fdes); + if(fp == NULL) + return; + if ((m&0100) == 0) { + if ((i = ufalloc(0)) < 0) + return; + } else { + i = uap->fdes2; + if (i<0 || i>=NOFILE) { + u.u_error = EBADF; + return; + } + u.u_rval1 = i; + } + if (i!=uap->fdes) { + if (u.u_ofile[i]!=NULL) + closef(u.u_ofile[i]); + u.u_ofile[i] = fp; + fp->f_count++; + } +} + +/* + * the file control system call. + */ +fcntl() +{ + register struct file *fp; + register struct a { + int fdes; + int cmd; + int arg; + } *uap; + register i; + + uap = (struct a *)u.u_ap; + fp = getf(uap->fdes); + if (fp == NULL) + return; + switch(uap->cmd) { + case 0: + i = uap->arg; + if (i < 0 || i > NOFILE) { + u.u_error = EINVAL; + return; + } + if ((i = ufalloc(i)) < 0) + return; +#ifdef PNETDFS + if ( fp->f_inode->i_flag & IRMT ) { +if ( ddbug ) { + printf( "fcntl dup on remote file %x\n", fp ); + debug(); +} + rfcntl( uap->fdes, i, 0, uap->arg ); + } +#endif + u.u_ofile[i] = fp; + fp->f_count++; + break; + + case 1: + u.u_rval1 = u.u_pofile[uap->fdes]; + break; + + case 2: + u.u_pofile[uap->fdes] = uap->arg; + break; + + case 3: + u.u_rval1 = fp->f_flag+FOPEN; + break; + + case 4: + fp->f_flag &= (FREAD|FWRITE); +#ifdef PNETDFS + if ( fp->f_inode->i_flag & IRMT ) { +if ( ddbug ) { + printf( "fcntl setfl on remote file %x\n", fp ); + debug(); +} + rfcntl( uap->fdes, i, 4, uap->arg ); + } +#endif + fp->f_flag |= (uap->arg-FOPEN) & ~(FREAD|FWRITE); + break; + + default: + u.u_error = EINVAL; + } +} + +/* + * character special i/o control + */ +ioctl() +{ + register struct file *fp; + register struct inode *ip; + register struct a { + int fdes; + int cmd; + int arg; + } *uap; + register dev_t dev; + + uap = (struct a *)u.u_ap; + if ((fp = getf(uap->fdes)) == NULL) + return; + ip = fp->f_inode; + if ((ip->i_mode&IFMT) != IFCHR) { + u.u_error = ENOTTY; + return; + } + u.u_rval1 = 0; +#ifdef PNETDFS + if ( ip->i_flag & IRMT ) { + rioctl( uap->fdes, uap->cmd, uap->arg ); + return; + } +#endif + dev = (dev_t)ip->i_rdev; + (*cdevsw[major(dev)].d_ioctl)(minor(dev),uap->cmd,uap->arg,fp->f_flag); +} + +/* + * old stty and gtty + */ +stty() +{ + register struct a { + int fdes; + int arg; + int narg; + } *uap; + + uap = (struct a *)u.u_ap; + uap->narg = uap->arg; + uap->arg = TIOCSETP; + ioctl(); +} + +gtty() +{ + register struct a { + int fdes; + int arg; + int narg; + } *uap; + + uap = (struct a *)u.u_ap; + uap->narg = uap->arg; + uap->arg = TIOCGETP; + ioctl(); +} + +/* + * the mount system call. + */ +smount() +{ + dev_t dev; + register struct inode *ip; + register struct mount *mp; + struct mount *smp; + register struct filsys *fp; + struct buf *bp; + register struct a { + char *fspec; + char *freg; + int ronly; + } *uap; + + uap = (struct a *)u.u_ap; + if(!suser()) + return; + dev = getmdev(); + if(u.u_error) + return; + u.u_dirp = (caddr_t)uap->freg; +#ifndef PNETDFS + ip = namei(uchar, 0); +#else + ip = namei(uchar, 0, NULL); +#endif + if(ip == NULL) + return; + if ((ip->i_mode&IFMT) != IFDIR) { + u.u_error = ENOTDIR; + goto out; + } + if (ip->i_count != 1) + goto out; + if (ip->i_number == ROOTINO) + goto out; + smp = NULL; + for(mp = &mount[0]; mp < (struct mount *)v.ve_mount; mp++) { + if(mp->m_flags != MFREE) { + if(dev == mp->m_dev) + goto out; + } else + if(smp == NULL) + smp = mp; + } + mp = smp; + if(mp == NULL) + goto out; + mp->m_flags = MINTER; + mp->m_dev = dev; + (*bdevsw[major(dev)].d_open)(minor(dev), !uap->ronly); + if(u.u_error) + goto out1; + bp = bread(dev, SUPERB); + if(u.u_error) { + brelse(bp); + goto out1; + } + mp->m_inodp = ip; + mp->m_bufp = getablk(1); + fp = (struct filsys *)paddr(mp->m_bufp); + copyio(paddr(bp), fp, sizeof(struct filsys), U_RKD); + mp->m_flags = MINUSE; + fp->s_ilock = 0; + fp->s_flock = 0; + fp->s_ninode = 0; + fp->s_inode[0] = 0; + fp->s_ronly = uap->ronly & 1; + brelse(bp); + ip->i_flag |= IMOUNT; + prele(ip); + return; + +out1: + mp->m_flags = MFREE; +out: + if (u.u_error == 0) + u.u_error = EBUSY; + iput(ip); +} + +/* + * the umount system call. + */ +sumount() +{ + dev_t dev; + register struct inode *ip; + register struct mount *mp; + register struct a { + char *fspec; + }; + + if(!suser()) + return; + dev = getmdev(); + if(u.u_error) + return; + xumount(dev); /* remove unused sticky files from text table */ + update(); + for(mp = &mount[0]; mp < (struct mount *)v.ve_mount; mp++) + if(mp->m_flags == MINUSE && dev == mp->m_dev) + goto found; + u.u_error = EINVAL; + return; + +found: + for(ip = &inode[0]; ip < (struct inode *)v.ve_inode; ip++) + if(ip->i_number != 0 && dev == ip->i_dev) { + u.u_error = EBUSY; + return; + } + (*bdevsw[major(dev)].d_close)(minor(dev), 0); + binval(dev); + ip = mp->m_inodp; + ip->i_flag &= ~IMOUNT; + plock(ip); + iput(ip); + brelse(mp->m_bufp); + mp->m_bufp = NULL; + mp->m_flags = MFREE; +} + +/* + * Common code for mount and umount. + * Check that the user's argument is a reasonable + * thing on which to mount, and return the device number if so. + */ +dev_t +getmdev() +{ + dev_t dev; + register struct inode *ip; + +#ifndef PNETDFS + ip = namei(uchar, 0); +#else + ip = namei(uchar, 0, NULL); +#endif + if(ip == NULL) + return(NODEV); + if((ip->i_mode&IFMT) != IFBLK) + u.u_error = ENOTBLK; + dev = (dev_t)ip->i_rdev; + if(major(dev) >= bdevcnt) + u.u_error = ENXIO; + iput(ip); + return(dev); +} diff --git a/WEGA/src/uts/sys/sys4.c b/WEGA/src/uts/sys/sys4.c new file mode 100644 index 0000000..fa9ba1a --- /dev/null +++ b/WEGA/src/uts/sys/sys4.c @@ -0,0 +1,531 @@ +#include "sys/param.h" +#include "sys/plexus.h" +#include "sys/systm.h" +#include "sys/dir.h" +#include "sys/user.h" +#include "sys/inode.h" +#include "sys/proc.h" +#include "sys/var.h" + +#ifdef PNETDFS +extern int ddbug; +#endif +/* + * Everything in this file is a routine implementing a system call. + */ + +gtime() +{ + u.u_rtime = time; +} + +stime() +{ + register struct a { + time_t time; + } *uap; + + uap = (struct a *)u.u_ap; + if (suser()) { + logtchg(uap->time); + time = uap->time; + puttod(time); + } +} + +setuid() +{ + register uid; + register struct a { + int uid; + } *uap; + + uap = (struct a *)u.u_ap; + uid = uap->uid; + if (uid >= MAXUID) { + u.u_error = EINVAL; + return; + } + if (u.u_ruid == uid || suser()) { + u.u_uid = uid; + u.u_procp->p_uid = uid; + u.u_ruid = uid; + } +} + +getuid() +{ + + u.u_rval1 = u.u_ruid; + u.u_rval2 = u.u_uid; +} + +setgid() +{ + register gid; + register struct a { + int gid; + } *uap; + + uap = (struct a *)u.u_ap; + gid = uap->gid; + if (gid >= MAXUID) { + u.u_error = EINVAL; + return; + } + if (u.u_rgid == gid || suser()) { + u.u_gid = gid; + u.u_rgid = gid; + } +} + +getgid() +{ + + u.u_rval1 = u.u_rgid; + u.u_rval2 = u.u_gid; +} + +getpid() +{ + u.u_rval1 = u.u_procp->p_pid; + u.u_rval2 = u.u_procp->p_ppid; +} + +setpgrp() +{ + register struct a { + int flag; + } *uap; + + uap = (struct a *)u.u_ap; + if (uap->flag) { + u.u_procp->p_pgrp = u.u_procp->p_pid; + u.u_ttyp = NULL; + } + u.u_rval1 = u.u_procp->p_pgrp; +} + +sync() +{ + + update(); +} + +nice() +{ + register n; + register struct a { + int niceness; + } *uap; + + uap = (struct a *)u.u_ap; + n = uap->niceness; + if ((n < 0 || n > 2*NZERO) && !suser()) + n = 0; + n += u.u_procp->p_nice; + if (n >= 2*NZERO) + n = 2*NZERO -1; + if (n < 0) + n = 0; + u.u_procp->p_nice = n; + u.u_rval1 = n - NZERO; +} + +/* + * Unlink system call. + * Hard to avoid races here, especially + * in unlinking directories. + */ +unlink() +{ + register struct inode *ip, *pp; + struct a { + char *fname; + }; + +#ifndef PNETDFS + pp = namei(uchar, 2); +#else + pp = namei(uchar, 2, NULL); +#endif + if (pp == NULL) + return; +#ifdef PNETDFS + if ( pp->i_flag & IRMT ) { +if ( ddbug ) { + printf( "remote unlink, not there yet\n" ); + debug(); +} + goto out1; + } +#endif + /* + * Check for unlink(".") + * to avoid hanging on the iget + */ + if (pp->i_number == u.u_dent.d_ino) { + ip = pp; + ip->i_count++; + } else + ip = iget(pp->i_dev, u.u_dent.d_ino); + if (ip == NULL) + goto out1; + if ((ip->i_mode&IFMT) == IFDIR && !suser()) + goto out; + /* + * Don't unlink a mounted file. + */ + if (ip->i_dev != pp->i_dev) { + u.u_error = EBUSY; + goto out; + } + if (ip->i_flag&ITEXT) + xrele(ip); /* try once to free text */ + if (ip->i_flag&ITEXT && ip->i_nlink == 1) { + u.u_error = ETXTBSY; + goto out; + } + u.u_offset -= sizeof(struct direct); + u.u_base = (caddr_t)&u.u_dent; + u.u_count = sizeof(struct direct); + u.u_dent.d_ino = 0; + u.u_segflg = 1; + writei(pp); + if (u.u_error) + goto out; + ip->i_nlink--; + ip->i_flag |= ICHG; + +out: + iput(ip); +out1: + iput(pp); +} + +chdir() +{ + chdirec(&u.u_cdir); +} + +chroot() +{ + if (!suser()) + return; + chdirec(&u.u_rdir); +} + +chdirec(ipp) +register struct inode **ipp; +{ + register struct inode *ip; + struct a { + char *fname; + }; + +#ifndef PNETDFS + ip = namei(uchar, 0); +#else + ip = namei(uchar, 0, NULL); +#endif + if (ip == NULL) + return; + if ((ip->i_mode&IFMT) != IFDIR) { + u.u_error = ENOTDIR; + goto bad; + } + if (access(ip, IEXEC)) + goto bad; + prele(ip); + if (*ipp) { + plock(*ipp); + iput(*ipp); + } + *ipp = ip; + return; + +bad: + iput(ip); +} + +chmod() +{ + register struct inode *ip; + register struct a { + char *fname; + int fmode; + } *uap; + + uap = (struct a *)u.u_ap; + if ((ip = owner()) == NULL) + return; + ip->i_mode &= ~07777; + if (u.u_uid) { + uap->fmode &= ~ISVTX; + if (u.u_gid != ip->i_gid) + uap->fmode &= ~ISGID; + } +#ifdef PNETDFS + if ( ip->i_flag & IRMT ) { + rchmod( ip, uap->fmode ); + return; + } +#endif + ip->i_mode |= uap->fmode&07777; + ip->i_flag |= ICHG; + if (ip->i_flag&ITEXT && (ip->i_mode&ISVTX)==0) + xrele(ip); + iput(ip); +} + +chown() +{ + register struct inode *ip; + register struct a { + char *fname; + int uid; + int gid; + } *uap; + + uap = (struct a *)u.u_ap; + if ((ip = owner()) == NULL) + return; +#ifdef PNETDFS + if ( ip->i_flag & IRMT ) { + rchown( ip, uap->uid, uap->gid ); + return; + } +#endif + ip->i_uid = uap->uid; + ip->i_gid = uap->gid; + if (u.u_uid != 0) + ip->i_mode &= ~(ISUID|ISGID); + ip->i_flag |= ICHG; + iput(ip); +} + +ssig() +{ + register a; + register struct proc *p; + struct a { + int signo; + int fun; + } *uap; + + uap = (struct a *)u.u_ap; + a = uap->signo; + if (a <= 0 || a > NSIG || a == SIGKILL) { + u.u_error = EINVAL; + return; + } + u.u_rval1 = u.u_signal[a-1]; + u.u_signal[a-1] = uap->fun; + u.u_procp->p_sig &= ~(1L<<(a-1)); + if (a == SIGCLD) { + a = u.u_procp->p_pid; + for (p = &proc[1]; p < (struct proc *)v.ve_proc; p++) { + if (a == p->p_ppid && p->p_stat == SZOMB) + psignal(u.u_procp, SIGCLD); + } + } +} + +kill() +{ + register struct proc *p, *q; + register arg; + register struct a { + int pid; + int signo; + } *uap; + int f; + + uap = (struct a *)u.u_ap; + if (uap->signo < 0 || uap->signo > NSIG) { + u.u_error = EINVAL; + return; + } + f = 0; + arg = uap->pid; + if (arg > 0) + p = &proc[1]; + else + p = &proc[2]; + q = u.u_procp; + if (arg == 0 && q->p_pgrp == 0) { + u.u_error = ESRCH; + return; + } + for(; p < (struct proc *)v.ve_proc; p++) { + if (p->p_stat == NULL) + continue; + if (arg > 0 && p->p_pid != arg) + continue; + if (arg == 0 && p->p_pgrp != q->p_pgrp) + continue; + if (arg < -1 && p->p_pgrp != -arg) + continue; + if (u.u_uid != 0 && u.u_uid != p->p_uid && u.u_procp != p) + if (arg > 0) { + u.u_error = EPERM; + return; + } else + continue; + f++; + if (uap->signo) + psignal(p, uap->signo); + if (arg > 0) + break; + } + if (f == 0) + u.u_error = ESRCH; +} + +times() +{ + register struct a { + time_t (*times)[4]; + } *uap; + + uap = (struct a *)u.u_ap; + if (copyout((caddr_t)&u.u_utime, (caddr_t)uap->times, sizeof(*uap->times))) + u.u_error = EFAULT; + spl7(); + u.u_rtime = lbolt; + spl0(); +} + +profil() +{ + register struct a { + short *bufbase; + unsigned bufsize; + unsigned pcoffset; + unsigned pcscale; + } *uap; + + uap = (struct a *)u.u_ap; + u.u_prof.pr_base = uap->bufbase; + u.u_prof.pr_size = uap->bufsize; + u.u_prof.pr_off = uap->pcoffset; + u.u_prof.pr_scale = uap->pcscale; +} + +/* + * alarm clock signal + */ +alarm() +{ + register struct proc *p; + register c; + register struct a { + int deltat; + } *uap; + + uap = (struct a *)u.u_ap; + p = u.u_procp; + c = p->p_clktim; + p->p_clktim = uap->deltat; + u.u_rval1 = c; +} + +/* + * indefinite wait. + * no one should wakeup(&u) + */ +pause() +{ + + for(;;) + sleep((caddr_t)&u, PSLEP); +} + +/* + * mode mask for creation of files + */ +umask() +{ + register struct a { + int mask; + } *uap; + register t; + + uap = (struct a *)u.u_ap; + t = u.u_cmask; + u.u_cmask = uap->mask & 0777; + u.u_rval1 = t; +} + +/* + * Set IUPD and IACC times on file. + */ +utime() +{ + register struct a { + char *fname; + time_t *tptr; + } *uap; + register struct inode *ip; + time_t tv[2]; + + uap = (struct a *)u.u_ap; + if (uap->tptr != NULL) { + if (copyin((caddr_t)uap->tptr, (caddr_t)tv, sizeof(tv))) { + u.u_error = EFAULT; + return; + } + } else { + tv[0] = time; + tv[1] = time; + } +#ifndef + ip = namei(uchar, 0); +#else + ip = namei(uchar, 0, NULL); +#endif + if (ip == NULL) + return; + if (u.u_uid != ip->i_uid && u.u_uid != 0) { + if (uap->tptr != NULL) + u.u_error = EPERM; + else + access(ip, IWRITE); + } + if (!u.u_error) { +#ifdef PNETDFS + if ( ip->i_flag & IRMT ) { + rutime( ip, &tv[0], &tv[1] ); + return; + } +#endif + ip->i_flag |= IACC|IUPD|ICHG; + iupdat(ip, &tv[0], &tv[1]); + } + iput(ip); +} + +ulimit() +{ + register struct a { + int cmd; + long arg; + } *uap; + + register brk, stk; + + uap = (struct a *)u.u_ap; + switch(uap->cmd) { + case 2: + if (uap->arg > u.u_limit && !suser()) + return; + u.u_limit = uap->arg; + case 1: + u.u_roff = u.u_limit; + break; + + case 3: + u.u_roff = ctob((long)(NUMLOGPAGE - u.u_ssize)); + break; + } +} diff --git a/WEGA/src/uts/sys/ureg.c b/WEGA/src/uts/sys/ureg.c new file mode 100644 index 0000000..22c0039 --- /dev/null +++ b/WEGA/src/uts/sys/ureg.c @@ -0,0 +1,107 @@ +#include "sys/plexus.h" +#include "sys/param.h" +#include "sys/systm.h" +#include "sys/dir.h" +#include "sys/user.h" +#include "sys/proc.h" +#include "sys/text.h" +#include "sys/seg.h" + +/* + * Load the user hardware segmentation + * registers from the software prototype. + * The software registers must have + * been setup prior by estabur. + */ +sureg() +{ + int taddr, daddr; + register i, c; + struct text *tp; + int maptemp[NUMLOGPAGE]; + + taddr = daddr = u.u_procp->p_addr; + if ((tp=u.u_procp->p_textp) != NULL) + taddr = tp->x_caddr; + + for (i = 0; i < NUMLOGPAGE; i++) { + c = u.u_uisa[i]; + if ((c & B_IP) == 0) + if (c & B_EX) + c += taddr; + else + c += daddr; + maptemp[i] = c; + } + copymout(maptemp, P_MUI0, NUMLOGPAGE << 1); + + for (i = 0; i < NUMLOGPAGE; i++) { + c = u.u_uisa[i + NUMLOGPAGE]; + if ((c & B_IP) == 0) + if (c & B_EX) + c += taddr; + else + c += daddr; + maptemp[i] = c; + } + copymout(maptemp, P_MUD0, NUMLOGPAGE << 1); +} + +/* + * Set up software prototype segmentation + * registers to implement the 3 pseudo + * text,data,stack segment sizes passed + * as arguments. + * The argument sep specifies if the + * text and data+stack segments are to + * be separated. + * The last argument determines whether the text + * segment is read-write or read-only. + */ +estabur(nt, nd, ns, sep, xrw) +unsigned nt, nd, ns; +{ + register a, *ap, i; + + if (checkur(nt, nd, ns, sep)) + return(-1); + a = 0; + ap = &u.u_uisa[0]; + for (i = 0; i < nt; i++) + *ap++ = a++ | B_EX | (xrw == RO ? B_RO : 0); + if (sep) + for (i = 0; i < (NUMLOGPAGE - nt); i++) + *ap++ = B_IP | B_RO; + a = USIZE; + for (i = 0; i < nd; i++) + *ap++ = a++; + for (i = 0; i < (NUMLOGPAGE - nd - ns - ((!sep) ? nt : 0)); i++) + *ap++ = B_IP | B_RO; + for (i = 0; i < ns; i++) + *ap++ = a++; + if (!sep) { + ap = &u.u_uisa[0]; + for (i = 0; i < NUMLOGPAGE; i++) + ap[i + NUMLOGPAGE] = ap[i]; + } + sureg(); + return(0); +} + +checkur(nt, nd, ns, sep) +{ + if(sep) { + if(ctos(nt) > NUMLOGPAGE || ctos(nd)+ctos(ns) > NUMLOGPAGE) + goto err; + } else { + if(ctos(nt)+ctos(nd)+ctos(ns) > NUMLOGPAGE) + goto err; + } + if(nt+nd+ns+USIZE > maxmem) + goto err; + return(0); + +err: + u.u_error = ENOMEM; + return(-1); +}