sys/sys1.c

03400 #include "../h/param.h" 03401 #include "../h/systm.h" 03402 #include "../h/map.h" 03403 #include "../h/dir.h" 03404 #include "../h/user.h" 03405 #include "../h/proc.h" 03406 #include "../h/buf.h" 03407 #include "../h/reg.h" 03408 #include "../h/inode.h" 03409 #include "../h/seg.h" 03410 #include "../h/acct.h" 03411 03412 /* 03413 * exec system call, with and without environments. 03414 */ 03415 struct execa { 03416 char *fname; 03417 char **argp; 03418 char **envp; 03419 }; 03420 03421 exec() 03422 { 03423 ((struct execa *)u.u_ap)->envp = NULL; 03424 exece(); 03425 } 03426 03427 exece() 03428 { 03429 register nc; 03430 register char *cp; 03431 register struct buf *bp; 03432 register struct execa *uap; 03433 int na, ne, bno, ucp, ap, c; 03434 struct inode *ip; 03435 03436 if ((ip = namei(uchar, 0)) == NULL) 03437 return; 03438 bno = 0; 03439 bp = 0; 03440 if(access(ip, IEXEC)) 03441 goto bad; 03442 if((ip->i_mode & IFMT) != IFREG || 03443 (ip->i_mode & (IEXEC|(IEXEC>>3)|(IEXEC>>6))) == 0) { 03444 u.u_error = EACCES; 03445 goto bad; 03446 } 03447 /* 03448 * Collect arguments on "file" in swap space. 03449 */ 03450 na = 0; 03451 ne = 0; 03452 nc = 0; 03453 uap = (struct execa *)u.u_ap; 03454 if ((bno = malloc(swapmap,(NCARGS+BSIZE-1)/BSIZE)) == 0) 03455 panic("Out of swap"); 03456 if (uap->argp) for (;;) { 03457 ap = NULL; 03458 if (uap->argp) { 03459 ap = fuword((caddr_t)uap->argp); 03460 uap->argp++; 03461 } 03462 if (ap==NULL && uap->envp) { 03463 uap->argp = NULL; 03464 if ((ap = fuword((caddr_t)uap->envp)) == NULL) 03465 break; 03466 uap->envp++; 03467 ne++; 03468 } 03469 if (ap==NULL) 03470 break; 03471 na++; 03472 if(ap == -1) 03473 u.u_error = EFAULT; 03474 do { 03475 if (nc >= NCARGS-1) 03476 u.u_error = E2BIG; 03477 if ((c = fubyte((caddr_t)ap++)) < 0) 03478 u.u_error = EFAULT; 03479 if (u.u_error) 03480 goto bad; 03481 if ((nc&BMASK) == 0) { 03482 if (bp) 03483 bawrite(bp); 03484 bp = getblk(swapdev, swplo+bno+(nc>>BSHIFT)); 03485 cp = bp->b_un.b_addr; 03486 } 03487 nc++; 03488 *cp++ = c; 03489 } while (c>0); 03490 } 03491 if (bp) 03492 bawrite(bp); 03493 bp = 0; 03494 nc = (nc + NBPW-1) & ~(NBPW-1); 03495 if (getxfile(ip, nc) || u.u_error) 03496 goto bad; 03497 03498 /* 03499 * copy back arglist 03500 */ 03501 03502 ucp = -nc - NBPW; 03503 ap = ucp - na*NBPW - 3*NBPW; 03504 u.u_ar0[R6] = ap; 03505 suword((caddr_t)ap, na-ne); 03506 nc = 0; 03507 for (;;) { 03508 ap += NBPW; 03509 if (na==ne) { 03510 suword((caddr_t)ap, 0); 03511 ap += NBPW; 03512 } 03513 if (--na < 0) 03514 break; 03515 suword((caddr_t)ap, ucp); 03516 do { 03517 if ((nc&BMASK) == 0) { 03518 if (bp) 03519 brelse(bp); 03520 bp = bread(swapdev, swplo+bno+(nc>>BSHIFT)); 03521 cp = bp->b_un.b_addr; 03522 } 03523 subyte((caddr_t)ucp++, (c = *cp++)); 03524 nc++; 03525 } while(c&0377); 03526 } 03527 suword((caddr_t)ap, 0); 03528 suword((caddr_t)ucp, 0); 03529 setregs(); 03530 bad: 03531 if (bp) 03532 brelse(bp); 03533 if(bno) 03534 mfree(swapmap, (NCARGS+BSIZE-1)/BSIZE, bno); 03535 iput(ip); 03536 } 03537 03538 /* 03539 * Read in and set up memory for executed file. 03540 * Zero return is normal; 03541 * non-zero means only the text is being replaced 03542 */ 03543 getxfile(ip, nargc) 03544 register struct inode *ip; 03545 { 03546 register unsigned ds; 03547 register sep; 03548 register unsigned ts, ss; 03549 register i, overlay; 03550 long lsize; 03551 03552 /* 03553 * read in first few bytes 03554 * of file for segment 03555 * sizes: 03556 * ux_mag = 407/410/411/405 03557 * 407 is plain executable 03558 * 410 is RO text 03559 * 411 is separated ID 03560 * 405 is overlaid text 03561 */ 03562 03563 u.u_base = (caddr_t)&u.u_exdata; 03564 u.u_count = sizeof(u.u_exdata); 03565 u.u_offset = 0; 03566 u.u_segflg = 1; 03567 readi(ip); 03568 u.u_segflg = 0; 03569 if(u.u_error) 03570 goto bad; 03571 if (u.u_count!=0) { 03572 u.u_error = ENOEXEC; 03573 goto bad; 03574 } 03575 sep = 0; 03576 overlay = 0; 03577 if(u.u_exdata.ux_mag == 0407) { 03578 lsize = (long)u.u_exdata.ux_dsize + u.u_exdata.ux_tsize; 03579 u.u_exdata.ux_dsize = lsize; 03580 if (lsize != u.u_exdata.ux_dsize) { /* check overflow */ 03581 u.u_error = ENOMEM; 03582 goto bad; 03583 } 03584 u.u_exdata.ux_tsize = 0; 03585 } else if (u.u_exdata.ux_mag == 0411) 03586 sep++; 03587 else if (u.u_exdata.ux_mag == 0405) 03588 overlay++; 03589 else if (u.u_exdata.ux_mag != 0410) { 03590 u.u_error = ENOEXEC; 03591 goto bad; 03592 } 03593 if(u.u_exdata.ux_tsize!=0 && (ip->i_flag&ITEXT)==0 && ip->i_count!=1) { 03594 u.u_error = ETXTBSY; 03595 goto bad; 03596 } 03597 03598 /* 03599 * find text and data sizes 03600 * try them out for possible 03601 * overflow of max sizes 03602 */ 03603 ts = btoc(u.u_exdata.ux_tsize); 03604 lsize = (long)u.u_exdata.ux_dsize + u.u_exdata.ux_bsize; 03605 if (lsize != (unsigned)lsize) { 03606 u.u_error = ENOMEM; 03607 goto bad; 03608 } 03609 ds = btoc(lsize); 03610 ss = SSIZE + btoc(nargc); 03611 if (overlay) { 03612 if (u.u_sep==0 && ctos(ts) != ctos(u.u_tsize) || nargc) { 03613 u.u_error = ENOMEM; 03614 goto bad; 03615 } 03616 ds = u.u_dsize; 03617 ss = u.u_ssize; 03618 sep = u.u_sep; 03619 xfree(); 03620 xalloc(ip); 03621 u.u_ar0[PC] = u.u_exdata.ux_entloc & ~01; 03622 } else { 03623 if(estabur(ts, ds, ss, sep, RO)) 03624 goto bad; 03625 03626 /* 03627 * allocate and clear core 03628 * at this point, committed 03629 * to the new image 03630 */ 03631 03632 u.u_prof.pr_scale = 0; 03633 xfree(); 03634 i = USIZE+ds+ss; 03635 expand(i); 03636 while(--i >= USIZE) 03637 clearseg(u.u_procp->p_addr+i); 03638 xalloc(ip); 03639 03640 /* 03641 * read in data segment 03642 */ 03643 03644 estabur((unsigned)0, ds, (unsigned)0, 0, RO); 03645 u.u_base = 0; 03646 u.u_offset = sizeof(u.u_exdata)+u.u_exdata.ux_tsize; 03647 u.u_count = u.u_exdata.ux_dsize; 03648 readi(ip); 03649 /* 03650 * set SUID/SGID protections, if no tracing 03651 */ 03652 if ((u.u_procp->p_flag&STRC)==0) { 03653 if(ip->i_mode&ISUID) 03654 if(u.u_uid != 0) { 03655 u.u_uid = ip->i_uid; 03656 u.u_procp->p_uid = ip->i_uid; 03657 } 03658 if(ip->i_mode&ISGID) 03659 u.u_gid = ip->i_gid; 03660 } else 03661 psignal(u.u_procp, SIGTRC); 03662 } 03663 u.u_tsize = ts; 03664 u.u_dsize = ds; 03665 u.u_ssize = ss; 03666 u.u_sep = sep; 03667 estabur(ts, ds, ss, sep, RO); 03668 bad: 03669 return(overlay); 03670 } 03671 03672 /* 03673 * Clear registers on exec 03674 */ 03675 setregs() 03676 { 03677 register int *rp; 03678 register char *cp; 03679 register i; 03680 03681 for(rp = &u.u_signal[0]; rp < &u.u_signal[NSIG]; rp++) 03682 if((*rp & 1) == 0) 03683 *rp = 0; 03684 for(cp = &regloc[0]; cp < &regloc[6];) 03685 u.u_ar0[*cp++] = 0; 03686 u.u_ar0[PC] = u.u_exdata.ux_entloc & ~01; 03687 for(rp = (int *)&u.u_fps; rp < (int *)&u.u_fps.u_fpregs[6];) 03688 *rp++ = 0; 03689 for(i=0; i03690 if (u.u_pofile[i]&EXCLOSE) { 03691 closef(u.u_ofile[i]); 03692 u.u_ofile[i] = NULL; 03693 u.u_pofile[i] &= ~EXCLOSE; 03694 } 03695 } 03696 /* 03697 * Remember file name for accounting. 03698 */ 03699 u.u_acflag &= ~AFORK; 03700 bcopy((caddr_t)u.u_dbuf, (caddr_t)u.u_comm, DIRSIZ); 03701 } 03702 03703 /* 03704 * exit system call: 03705 * pass back caller's arg 03706 */ 03707 rexit() 03708 { 03709 register struct a { 03710 int rval; 03711 } *uap; 03712 03713 uap = (struct a *)u.u_ap; 03714 exit((uap->rval & 0377) << 8); 03715 } 03716 03717 /* 03718 * Release resources. 03719 * Save u. area for parent to look at. 03720 * Enter zombie state. 03721 * Wake up parent and init processes, 03722 * and dispose of children. 03723 */ 03724 exit(rv) 03725 { 03726 register int i; 03727 register struct proc *p, *q; 03728 register struct file *f; 03729 03730 p = u.u_procp; 03731 p->p_flag &= ~(STRC|SULOCK); 03732 p->p_clktim = 0; 03733 for(i=0; i03734 u.u_signal[i] = 1; 03735 for(i=0; i03736 f = u.u_ofile[i]; 03737 u.u_ofile[i] = NULL; 03738 closef(f); 03739 } 03740 plock(u.u_cdir); 03741 iput(u.u_cdir); 03742 if (u.u_rdir) { 03743 plock(u.u_rdir); 03744 iput(u.u_rdir); 03745 } 03746 xfree(); 03747 acct(); 03748 mfree(coremap, p->p_size, p->p_addr); 03749 p->p_stat = SZOMB; 03750 ((struct xproc *)p)->xp_xstat = rv; 03751 ((struct xproc *)p)->xp_utime = u.u_cutime + u.u_utime; 03752 ((struct xproc *)p)->xp_stime = u.u_cstime + u.u_stime; 03753 for(q = &proc[0]; q < &proc[NPROC]; q++) 03754 if(q->p_ppid == p->p_pid) { 03755 wakeup((caddr_t)&proc[1]); 03756 q->p_ppid = 1; 03757 if (q->p_stat==SSTOP) 03758 setrun(q); 03759 } 03760 for(q = &proc[0]; q < &proc[NPROC]; q++) 03761 if(p->p_ppid == q->p_pid) { 03762 wakeup((caddr_t)q); 03763 swtch(); 03764 /* no return */ 03765 } 03766 swtch(); 03767 } 03768 03769 /* 03770 * Wait system call. 03771 * Search for a terminated (zombie) child, 03772 * finally lay it to rest, and collect its status. 03773 * Look also for stopped (traced) children, 03774 * and pass back status from them. 03775 */ 03776 wait() 03777 { 03778 register f; 03779 register struct proc *p; 03780 03781 f = 0; 03782 03783 loop: 03784 for(p = &proc[0]; p < &proc[NPROC]; p++) 03785 if(p->p_ppid == u.u_procp->p_pid) { 03786 f++; 03787 if(p->p_stat == SZOMB) { 03788 u.u_r.r_val1 = p->p_pid; 03789 u.u_r.r_val2 = ((struct xproc *)p)->xp_xstat; 03790 u.u_cutime += ((struct xproc *)p)->xp_utime; 03791 u.u_cstime += ((struct xproc *)p)->xp_stime; 03792 p->p_pid = 0; 03793 p->p_ppid = 0; 03794 p->p_pgrp = 0; 03795 p->p_sig = 0; 03796 p->p_flag = 0; 03797 p->p_wchan = 0; 03798 p->p_stat = NULL; 03799 return; 03800 } 03801 if(p->p_stat == SSTOP) { 03802 if((p->p_flag&SWTED) == 0) { 03803 p->p_flag |= SWTED; 03804 u.u_r.r_val1 = p->p_pid; 03805 u.u_r.r_val2 = (fsig(p)<<8) | 0177; 03806 return; 03807 } 03808 continue; 03809 } 03810 } 03811 if(f) { 03812 sleep((caddr_t)u.u_procp, PWAIT); 03813 goto loop; 03814 } 03815 u.u_error = ECHILD; 03816 } 03817 03818 /* 03819 * fork system call. 03820 */ 03821 fork() 03822 { 03823 register struct proc *p1, *p2; 03824 register a; 03825 03826 /* 03827 * Make sure there's enough swap space for max 03828 * core image, thus reducing chances of running out 03829 */ 03830 if ((a = malloc(swapmap, ctod(MAXMEM))) == 0) { 03831 u.u_error = ENOMEM; 03832 goto out; 03833 } 03834 mfree(swapmap, ctod(MAXMEM), a); 03835 a = 0; 03836 p2 = NULL; 03837 for(p1 = &proc[0]; p1 < &proc[NPROC]; p1++) { 03838 if (p1->p_stat==NULL && p2==NULL) 03839 p2 = p1; 03840 else { 03841 if (p1->p_uid==u.u_uid && p1->p_stat!=NULL) 03842 a++; 03843 } 03844 } 03845 /* 03846 * Disallow if 03847 * No processes at all; 03848 * not su and too many procs owned; or 03849 * not su and would take last slot. 03850 */ 03851 if (p2==NULL || (u.u_uid!=0 && (p2==&proc[NPROC-1] || a>MAXUPRC))) { 03852 u.u_error = EAGAIN; 03853 goto out; 03854 } 03855 p1 = u.u_procp; 03856 if(newproc()) { 03857 u.u_r.r_val1 = p1->p_pid; 03858 u.u_start = time; 03859 u.u_cstime = 0; 03860 u.u_stime = 0; 03861 u.u_cutime = 0; 03862 u.u_utime = 0; 03863 u.u_acflag = AFORK; 03864 return; 03865 } 03866 u.u_r.r_val1 = p2->p_pid; 03867 03868 out: 03869 u.u_ar0[R7] += NBPW; 03870 } 03871 03872 /* 03873 * break system call. 03874 * -- bad planning: "break" is a dirty word in C. 03875 */ 03876 sbreak() 03877 { 03878 struct a { 03879 char *nsiz; 03880 }; 03881 register a, n, d; 03882 int i; 03883 03884 /* 03885 * set n to new data size 03886 * set d to new-old 03887 * set n to new total size 03888 */ 03889 03890 n = btoc((int)((struct a *)u.u_ap)->nsiz); 03891 if(!u.u_sep) 03892 n -= ctos(u.u_tsize) * stoc(1); 03893 if(n < 0) 03894 n = 0; 03895 d = n - u.u_dsize; 03896 n += USIZE+u.u_ssize; 03897 if(estabur(u.u_tsize, u.u_dsize+d, u.u_ssize, u.u_sep, RO)) 03898 return; 03899 u.u_dsize += d; 03900 if(d > 0) 03901 goto bigger; 03902 a = u.u_procp->p_addr + n - u.u_ssize; 03903 i = n; 03904 n = u.u_ssize; 03905 while(n--) { 03906 copyseg(a-d, a); 03907 a++; 03908 } 03909 expand(i); 03910 return; 03911 03912 bigger: 03913 expand(n); 03914 a = u.u_procp->p_addr + n; 03915 n = u.u_ssize; 03916 while(n--) { 03917 a--; 03918 copyseg(a-d, a); 03919 } 03920 while(d--) 03921 clearseg(--a); 03922 } 03923 03924 03925 03926 03927 03928 03929 03930 03931 03932 03933 03934 03935 03936 03937 03938 03939 03940 03941 03942 03943 03944 03945 03946 03947 03948 03949