home *** CD-ROM | disk | FTP | other *** search
/ Whiteline: Alpha / Whiteline Alpha.iso / linux / atari / source / source.lzh / atari-linux-0.01pl3 / kernel / sys.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-06-05  |  17.9 KB  |  778 lines

  1. /*
  2.  *  linux/kernel/sys.c
  3.  *
  4.  *  Copyright (C) 1991, 1992  Linus Torvalds
  5.  *
  6.  * This file is subject to the terms and conditions of the GNU General Public
  7.  * License.  See the file README.legal in the main directory of this archive
  8.  * for more details.
  9.  */
  10.  
  11. #include <asm/system.h>
  12. #include <asm/segment.h>
  13.  
  14. #include <linux/config.h>
  15. #include <linux/errno.h>
  16. #include <linux/sched.h>
  17. #include <linux/tty.h>
  18. #include <linux/kernel.h>
  19. #include <linux/times.h>
  20. #include <linux/utsname.h>
  21. #include <linux/param.h>
  22. #include <linux/resource.h>
  23. #include <linux/signal.h>
  24. #include <linux/string.h>
  25. #include <linux/ptrace.h>
  26. #include <linux/stat.h>
  27. #include <linux/mman.h>
  28.  
  29.  
  30. /*
  31.  * this indicates wether you can reboot with ctrl-alt-del: the default is yes
  32.  */
  33. static int C_A_D = 1;
  34.  
  35. extern void adjust_clock(void);
  36.  
  37. #define PZERO    15
  38.  
  39. static int proc_sel(struct task_struct *p, int which, int who)
  40. {
  41.     switch (which) {
  42.         case PRIO_PROCESS:
  43.             if (!who && p == current)
  44.                 return 1;
  45.             return(p->pid == who);
  46.         case PRIO_PGRP:
  47.             if (!who)
  48.                 who = current->pgrp;
  49.             return(p->pgrp == who);
  50.         case PRIO_USER:
  51.             if (!who)
  52.                 who = current->uid;
  53.             return(p->uid == who);
  54.     }
  55.     return 0;
  56. }
  57.  
  58. asmlinkage int sys_setpriority(int which, int who, int niceval)
  59. {
  60.     struct task_struct **p;
  61.     int error = ESRCH;
  62.     int priority;
  63.  
  64.     if (which > 2 || which < 0)
  65.         return -EINVAL;
  66.  
  67.     if ((priority = PZERO - niceval) <= 0)
  68.         priority = 1;
  69.  
  70.     for(p = &LAST_TASK; p > &FIRST_TASK; --p) {
  71.         if (!*p || !proc_sel(*p, which, who))
  72.             continue;
  73.         if ((*p)->uid != current->euid &&
  74.             (*p)->uid != current->uid && !suser()) {
  75.             error = EPERM;
  76.             continue;
  77.         }
  78.         if (error == ESRCH)
  79.             error = 0;
  80.         if (priority > (*p)->priority && !suser())
  81.             error = EACCES;
  82.         else
  83.             (*p)->priority = priority;
  84.     }
  85.     return -error;
  86. }
  87.  
  88. asmlinkage int sys_getpriority(int which, int who)
  89. {
  90.     struct task_struct **p;
  91.     int max_prio = 0;
  92.  
  93.     if (which > 2 || which < 0)
  94.         return -EINVAL;
  95.  
  96.     for(p = &LAST_TASK; p > &FIRST_TASK; --p) {
  97.         if (!*p || !proc_sel(*p, which, who))
  98.             continue;
  99.         if ((*p)->priority > max_prio)
  100.             max_prio = (*p)->priority;
  101.     }
  102.     return(max_prio ? max_prio : -ESRCH);
  103. }
  104.  
  105. asmlinkage int sys_profil(void)
  106. {
  107.     return -ENOSYS;
  108. }
  109.  
  110. asmlinkage int sys_ftime(void)
  111. {
  112.     return -ENOSYS;
  113. }
  114.  
  115. asmlinkage int sys_break(void)
  116. {
  117.     return -ENOSYS;
  118. }
  119.  
  120. asmlinkage int sys_stty(void)
  121. {
  122.     return -ENOSYS;
  123. }
  124.  
  125. asmlinkage int sys_gtty(void)
  126. {
  127.     return -ENOSYS;
  128. }
  129.  
  130. asmlinkage int sys_prof(void)
  131. {
  132.     return -ENOSYS;
  133. }
  134.  
  135. asmlinkage int sys_unimp(void)
  136. {
  137.     return -ENOSYS;
  138. }
  139.  
  140. asmlinkage unsigned long save_v86_state(struct vm86_regs * regs)
  141. {
  142. #ifdef __i386__
  143.     unsigned long stack;
  144.  
  145.     if (!current->vm86_info) {
  146.         printk("no vm86_info: BAD\n");
  147.         do_exit(SIGSEGV);
  148.     }
  149.     memcpy_tofs(&(current->vm86_info->regs),regs,sizeof(*regs));
  150.     put_fs_long(current->screen_bitmap,&(current->vm86_info->screen_bitmap));
  151.     stack = current->tss.esp0;
  152.     current->tss.esp0 = current->saved_kernel_stack;
  153.     current->saved_kernel_stack = 0;
  154.     return stack;
  155. #else
  156.     return -ENOSYS;
  157. #endif
  158. }
  159.  
  160. #ifdef __i386__
  161. static void mark_screen_rdonly(struct task_struct * tsk)
  162. {
  163.     unsigned long tmp;
  164.     unsigned long *pg_table;
  165.  
  166.     if ((tmp = tsk->tss.crp) != 0) {
  167.         tmp = *(unsigned long *) tmp;
  168.         if (tmp & PAGE_PRESENT) {
  169.             tmp &= PAGE_MASK;
  170.             pg_table = (0xA0000 >> PAGE_SHIFT) + (unsigned long *) tmp;
  171.             tmp = 32;
  172.             while (tmp--) {
  173.                 if (PAGE_PRESENT & *pg_table)
  174.                     *pg_table &= ~PAGE_RW;
  175.                 pg_table++;
  176.             }
  177.         }
  178.     }
  179. }
  180. #endif
  181.  
  182. asmlinkage int sys_vm86(struct vm86_struct * v86)
  183. {
  184. #ifdef __i386__
  185.     struct vm86_struct info;
  186.     struct pt_regs * pt_regs = (struct pt_regs *) &v86;
  187.  
  188.     if (current->saved_kernel_stack)
  189.         return -EPERM;
  190.     memcpy_fromfs(&info,v86,sizeof(info));
  191. /*
  192.  * make sure the vm86() system call doesn't try to do anything silly
  193.  */
  194.     info.regs.__null_ds = 0;
  195.     info.regs.__null_es = 0;
  196.     info.regs.__null_fs = 0;
  197.     info.regs.__null_gs = 0;
  198. /*
  199.  * The eflags register is also special: we cannot trust that the user
  200.  * has set it up safely, so this makes sure interrupt etc flags are
  201.  * inherited from protected mode.
  202.  */
  203.     info.regs.eflags &= 0x00000dd5;
  204.     info.regs.eflags |= ~0x00000dd5 & pt_regs->eflags;
  205.     info.regs.eflags |= VM_MASK;
  206.     current->saved_kernel_stack = current->tss.esp0;
  207.     current->tss.esp0 = (unsigned long) pt_regs;
  208.     current->vm86_info = v86;
  209.     current->screen_bitmap = info.screen_bitmap;
  210.     if (info.flags & VM86_SCREEN_BITMAP)
  211.         mark_screen_rdonly(current);
  212.     __asm__ __volatile__("movl %0,%%esp\n\t"
  213.         "pushl $ret_from_sys_call\n\t"
  214.         "ret"
  215.         : /* no outputs */
  216.         :"g" ((long) &(info.regs)),"a" (info.regs.eax));
  217.     return 0;
  218. #else
  219.     return -ENOSYS;
  220. #endif
  221. }
  222.  
  223. /*
  224.  * Reboot system call: for obvious reasons only root may call it,
  225.  * and even root needs to set up some magic numbers in the registers
  226.  * so that some mistake won't make this reboot the whole machine.
  227.  * You can also set the meaning of the ctrl-alt-del-key here.
  228.  *
  229.  * reboot doesn't sync: do that yourself before calling this.
  230.  */
  231. asmlinkage int sys_reboot(int magic, int magic_too, int flag)
  232. {
  233.     if (!suser())
  234.         return -EPERM;
  235.     if (magic != 0xfee1dead || magic_too != 672274793)
  236.         return -EINVAL;
  237.  
  238.     if (flag == 0x01234567)
  239.         if (mach_reset) mach_reset();
  240.     else if (flag == 0x89ABCDEF)
  241.         C_A_D = 1;
  242.     else if (!flag)
  243.         C_A_D = 0;
  244.     else
  245.         return -EINVAL;
  246.     return (0);
  247. }
  248.  
  249. /*
  250.  * This function gets called by ctrl-alt-del - ie the keyboard interrupt.
  251.  * As it's called within an interrupt, it may NOT sync: the only choice
  252.  * is wether to reboot at once, or just ignore the ctrl-alt-del.
  253.  */
  254. void ctrl_alt_del(void)
  255. {
  256.     if (C_A_D)
  257.         if (mach_reset) mach_reset();
  258.     else
  259.         send_sig(SIGINT,task[1],1);
  260. }
  261.  
  262.  
  263. /*
  264.  * This is done BSD-style, with no consideration of the saved gid, except
  265.  * that if you set the effective gid, it sets the saved gid too.  This
  266.  * makes it possible for a setgid program to completely drop its privileges,
  267.  * which is often a useful assertion to make when you are doing a security
  268.  * audit over a program.
  269.  *
  270.  * The general idea is that a program which uses just setregid() will be
  271.  * 100% compatible with BSD.  A program which uses just setgid() will be
  272.  * 100% compatible with POSIX w/ Saved ID's.
  273.  */
  274. asmlinkage int sys_setregid(gid_t rgid, gid_t egid)
  275. {
  276.     int old_rgid = current->gid;
  277.  
  278.     if (rgid != (gid_t) -1) {
  279.         if ((current->egid==rgid) ||
  280.             (old_rgid == rgid) ||
  281.             suser())
  282.             current->gid = rgid;
  283.         else
  284.             return(-EPERM);
  285.     }
  286.     if (egid != (gid_t) -1) {
  287.         if ((old_rgid == egid) ||
  288.             (current->egid == egid) ||
  289.             suser()) {
  290.             current->egid = egid;
  291.             current->sgid = egid;
  292.         } else {
  293.             current->gid = old_rgid;
  294.             return(-EPERM);
  295.         }
  296.     }
  297.     return 0;
  298. }
  299.  
  300. /*
  301.  * setgid() is implemeneted like SysV w/ SAVED_IDS
  302.  */
  303. asmlinkage int sys_setgid(gid_t gid)
  304. {
  305.     if (suser())
  306.         current->gid = current->egid = current->sgid = gid;
  307.     else if ((gid == current->gid) || (gid == current->sgid))
  308.         current->egid = gid;
  309.     else
  310.         return -EPERM;
  311.     return 0;
  312. }
  313.  
  314. asmlinkage int sys_acct(void)
  315. {
  316.     return -ENOSYS;
  317. }
  318.  
  319. asmlinkage int sys_phys(void)
  320. {
  321.     return -ENOSYS;
  322. }
  323.  
  324. asmlinkage int sys_lock(void)
  325. {
  326.     return -ENOSYS;
  327. }
  328.  
  329. asmlinkage int sys_mpx(void)
  330. {
  331.     return -ENOSYS;
  332. }
  333.  
  334. asmlinkage int sys_ulimit(void)
  335. {
  336.     return -ENOSYS;
  337. }
  338.  
  339. asmlinkage int sys_old_syscall(void)
  340. {
  341.     return -ENOSYS;
  342. }
  343.  
  344. /*
  345.  * Unprivileged users may change the real user id to the effective uid
  346.  * or vice versa.  (BSD-style)
  347.  *
  348.  * When you set the effective uid, it sets the saved uid too.  This
  349.  * makes it possible for a setuid program to completely drop its privileges,
  350.  * which is often a useful assertion to make when you are doing a security
  351.  * audit over a program.
  352.  *
  353.  * The general idea is that a program which uses just setreuid() will be
  354.  * 100% compatible with BSD.  A program which uses just setuid() will be
  355.  * 100% compatible with POSIX w/ Saved ID's.
  356.  */
  357. asmlinkage int sys_setreuid(uid_t ruid, uid_t euid)
  358. {
  359.     int old_ruid = current->uid;
  360.  
  361.     if (ruid != (uid_t) -1) {
  362.         if ((current->euid==ruid) ||
  363.             (old_ruid == ruid) ||
  364.             suser())
  365.             current->uid = ruid;
  366.         else
  367.             return(-EPERM);
  368.     }
  369.     if (euid != (uid_t) -1) {
  370.         if ((old_ruid == euid) ||
  371.             (current->euid == euid) ||
  372.             suser()) {
  373.             current->euid = euid;
  374.             current->suid = euid;
  375.         } else {
  376.             current->uid = old_ruid;
  377.             return(-EPERM);
  378.         }
  379.     }
  380.     return 0;
  381. }
  382.  
  383. /*
  384.  * setuid() is implemeneted like SysV w/ SAVED_IDS
  385.  *
  386.  * Note that SAVED_ID's is deficient in that a setuid root program
  387.  * like sendmail, for example, cannot set its uid to be a normal
  388.  * user and then switch back, because if you're root, setuid() sets
  389.  * the saved uid too.  If you don't like this, blame the bright people
  390.  * in the POSIX commmittee and/or USG.    Note that the BSD-style setreuid()
  391.  * will allow a root program to temporarily drop privileges and be able to
  392.  * regain them by swapping the real and effective uid.
  393.  */
  394. asmlinkage int sys_setuid(uid_t uid)
  395. {
  396.     if (suser())
  397.         current->uid = current->euid = current->suid = uid;
  398.     else if ((uid == current->uid) || (uid == current->suid))
  399.         current->euid = uid;
  400.     else
  401.         return -EPERM;
  402.     return(0);
  403. }
  404.  
  405. asmlinkage int sys_times(struct tms * tbuf)
  406. {
  407.     if (tbuf) {
  408.         int error = verify_area(VERIFY_WRITE,tbuf,sizeof *tbuf);
  409.         if (error)
  410.             return error;
  411.         put_fs_long(current->utime,(unsigned long *)&tbuf->tms_utime);
  412.         put_fs_long(current->stime,(unsigned long *)&tbuf->tms_stime);
  413.         put_fs_long(current->cutime,(unsigned long *)&tbuf->tms_cutime);
  414.         put_fs_long(current->cstime,(unsigned long *)&tbuf->tms_cstime);
  415.     }
  416.     return jiffies;
  417. }
  418.  
  419. asmlinkage int sys_brk(unsigned long brk)
  420. {
  421.     int freepages;
  422.     unsigned long rlim;
  423.     unsigned long newbrk, oldbrk;
  424.  
  425.  
  426.     if (brk < current->end_code)
  427.         return current->brk;
  428.     newbrk = PAGE_ALIGN(brk);
  429.     oldbrk = PAGE_ALIGN(current->brk);
  430.     if (oldbrk == newbrk)
  431.         return current->brk = brk;
  432.  
  433.     /*
  434.      * Always allow shrinking brk
  435.      */
  436.     if (brk <= current->brk) {
  437.         current->brk = brk;
  438.         do_munmap(newbrk, oldbrk-newbrk);
  439.         return brk;
  440.     }
  441.     /*
  442.      * Check against rlimit and stack..
  443.      */
  444.     rlim = current->rlim[RLIMIT_DATA].rlim_cur;
  445.     if (rlim >= RLIM_INFINITY)
  446.         rlim = ~0;
  447.     if (brk - current->end_code > rlim || brk >= current->start_stack - 16384)
  448.         return current->brk;
  449.  
  450. #if 0
  451.     /*
  452.      * stupid algorithm to decide if we have enough memory: while
  453.      * simple, it hopefully works in most obvious cases.. Easy to
  454.      * fool it, but this should catch most mistakes.
  455.      */
  456.     freepages = buffermem >> 12;
  457.     freepages += nr_free_pages;
  458.     freepages += nr_swap_pages;
  459.     freepages -= (high_memory - (KSTART_ADDR + 0x100000)) >> 16;
  460.     freepages -= (newbrk-oldbrk) >> 12;
  461.     if (freepages < 0)
  462.         return current->brk;
  463. #endif
  464. #if 0
  465.     freepages += current->rss;
  466.     freepages -= oldbrk >> 12;
  467.     if (freepages < 0)
  468.         return current->brk;
  469. #endif
  470.     /*
  471.      * Ok, we have probably got enough memory - let it rip.
  472.      */
  473.     current->brk = brk;
  474.     do_mmap(NULL, oldbrk, newbrk-oldbrk,
  475.         PROT_READ|PROT_WRITE|PROT_EXEC,
  476.         MAP_FIXED|MAP_PRIVATE, 0);
  477.     return brk;
  478. }
  479.  
  480. /*
  481.  * This needs some heave checking ...
  482.  * I just haven't get the stomach for it. I also don't fully
  483.  * understand sessions/pgrp etc. Let somebody who does explain it.
  484.  *
  485.  * OK, I think I have the protection semantics right.... this is really
  486.  * only important on a multi-user system anyway, to make sure one user
  487.  * can't send a signal to a process owned by another.  -TYT, 12/12/91
  488.  */
  489. asmlinkage int sys_setpgid(pid_t pid, pid_t pgid)
  490. {
  491.     int i;
  492.  
  493.     if (!pid)
  494.         pid = current->pid;
  495.     if (!pgid)
  496.         pgid = current->pid;
  497.     if (pgid < 0)
  498.         return -EINVAL;
  499.     for (i=0 ; i<NR_TASKS ; i++)
  500.         if (task[i] && (task[i]->pid == pid) &&
  501.             ((task[i]->p_pptr == current) ||
  502.              (task[i]->p_opptr == current) || 
  503.              (task[i] == current))) {
  504.             if (task[i]->leader)
  505.                 return -EPERM;
  506.             if ((task[i]->session != current->session) ||
  507.                 ((pgid != pid) &&
  508.                  (session_of_pgrp(pgid) != current->session)))
  509.                 return -EPERM;
  510.             task[i]->pgrp = pgid;
  511.             return 0;
  512.         }
  513.     return -ESRCH;
  514. }
  515.  
  516. asmlinkage int sys_getpgrp(void)
  517. {
  518.     return current->pgrp;
  519. }
  520.  
  521. asmlinkage int sys_setsid(void)
  522. {
  523.     if (current->leader && !suser())
  524.         return -EPERM;
  525.     current->leader = 1;
  526.     current->session = current->pgrp = current->pid;
  527.     current->tty = -1;
  528.     return current->pgrp;
  529. }
  530.  
  531. /*
  532.  * Supplementary group ID's
  533.  */
  534. asmlinkage int sys_getgroups(int gidsetsize, gid_t *grouplist)
  535. {
  536.     int i;
  537.  
  538.     if (gidsetsize) {
  539.         i = verify_area(VERIFY_WRITE, grouplist, sizeof(gid_t) * gidsetsize);
  540.         if (i)
  541.             return i;
  542.     }
  543.     for (i = 0 ; (i < NGROUPS) && (current->groups[i] != NOGROUP) ; i++) {
  544.         if (!gidsetsize)
  545.             continue;
  546.         if (i >= gidsetsize)
  547.             break;
  548.         put_fs_word(current->groups[i], (short *) grouplist);
  549.         grouplist++;
  550.     }
  551.     return(i);
  552. }
  553.  
  554. asmlinkage int sys_setgroups(int gidsetsize, gid_t *grouplist)
  555. {
  556.     int    i;
  557.  
  558.     if (!suser())
  559.         return -EPERM;
  560.     if (gidsetsize > NGROUPS)
  561.         return -EINVAL;
  562.     for (i = 0; i < gidsetsize; i++, grouplist++) {
  563.         current->groups[i] = get_fs_word((unsigned short *) grouplist);
  564.     }
  565.     if (i < NGROUPS)
  566.         current->groups[i] = NOGROUP;
  567.     return 0;
  568. }
  569.  
  570. int in_group_p(gid_t grp)
  571. {
  572.     int    i;
  573.  
  574.     if (grp == current->egid)
  575.         return 1;
  576.  
  577.     for (i = 0; i < NGROUPS; i++) {
  578.         if (current->groups[i] == NOGROUP)
  579.             break;
  580.         if (current->groups[i] == grp)
  581.             return 1;
  582.     }
  583.     return 0;
  584. }
  585.  
  586. asmlinkage int sys_newuname(struct new_utsname * name)
  587. {
  588.     int error;
  589.  
  590.     if (!name)
  591.         return -EFAULT;
  592.     error = verify_area(VERIFY_WRITE, name, sizeof *name);
  593.     if (!error)
  594.         memcpy_tofs(name,&system_utsname,sizeof *name);
  595.     return error;
  596. }
  597.  
  598. asmlinkage int sys_uname(struct old_utsname * name)
  599. {
  600.     int error;
  601.     if (!name)
  602.         return -EFAULT;
  603.     error = verify_area(VERIFY_WRITE, name,sizeof *name);
  604.     if (error)
  605.         return error;
  606.     memcpy_tofs(&name->sysname,&system_utsname.sysname,
  607.         sizeof (system_utsname.sysname));
  608.     memcpy_tofs(&name->nodename,&system_utsname.nodename,
  609.         sizeof (system_utsname.nodename));
  610.     memcpy_tofs(&name->release,&system_utsname.release,
  611.         sizeof (system_utsname.release));
  612.     memcpy_tofs(&name->version,&system_utsname.version,
  613.         sizeof (system_utsname.version));
  614.     memcpy_tofs(&name->machine,&system_utsname.machine,
  615.         sizeof (system_utsname.machine));
  616.     return 0;
  617. }
  618.  
  619. asmlinkage int sys_olduname(struct oldold_utsname * name)
  620. {
  621.     int error;
  622.     if (!name)
  623.         return -EFAULT;
  624.     error = verify_area(VERIFY_WRITE, name,sizeof *name);
  625.     if (error)
  626.         return error;
  627.     memcpy_tofs(&name->sysname,&system_utsname.sysname,__OLD_UTS_LEN);
  628.     put_fs_byte(0,name->sysname+__OLD_UTS_LEN);
  629.     memcpy_tofs(&name->nodename,&system_utsname.nodename,__OLD_UTS_LEN);
  630.     put_fs_byte(0,name->nodename+__OLD_UTS_LEN);
  631.     memcpy_tofs(&name->release,&system_utsname.release,__OLD_UTS_LEN);
  632.     put_fs_byte(0,name->release+__OLD_UTS_LEN);
  633.     memcpy_tofs(&name->version,&system_utsname.version,__OLD_UTS_LEN);
  634.     put_fs_byte(0,name->version+__OLD_UTS_LEN);
  635.     memcpy_tofs(&name->machine,&system_utsname.machine,__OLD_UTS_LEN);
  636.     put_fs_byte(0,name->machine+__OLD_UTS_LEN);
  637.     return 0;
  638. }
  639.  
  640. /*
  641.  * Only sethostname; gethostname can be implemented by calling uname()
  642.  */
  643. asmlinkage int sys_sethostname(char *name, int len)
  644. {
  645.     int    i;
  646.  
  647.     if (!suser())
  648.         return -EPERM;
  649.     if (len > __NEW_UTS_LEN)
  650.         return -EINVAL;
  651.     for (i=0; i < len; i++) {
  652.         if ((system_utsname.nodename[i] = get_fs_byte(name+i)) == 0)
  653.             return 0;
  654.     }
  655.     system_utsname.nodename[i] = 0;
  656.     return 0;
  657. }
  658.  
  659. /*
  660.  * Only setdomainname; getdomainname can be implemented by calling
  661.  * uname()
  662.  */
  663. asmlinkage int sys_setdomainname(char *name, int len)
  664. {
  665.     int    i;
  666.  
  667.     if (!suser())
  668.         return -EPERM;
  669.     if (len > __NEW_UTS_LEN)
  670.         return -EINVAL;
  671.     for (i=0; i < len; i++) {
  672.         if ((system_utsname.domainname[i] = get_fs_byte(name+i)) == 0)
  673.             return 0;
  674.     }
  675.     system_utsname.domainname[i] = 0;
  676.     return 0;
  677. }
  678.  
  679. asmlinkage int sys_getrlimit(unsigned int resource, struct rlimit *rlim)
  680. {
  681.     int error;
  682.  
  683.     if (resource >= RLIM_NLIMITS)
  684.         return -EINVAL;
  685.     error = verify_area(VERIFY_WRITE,rlim,sizeof *rlim);
  686.     if (error)
  687.         return error;
  688.     put_fs_long(current->rlim[resource].rlim_cur,
  689.             (unsigned long *) rlim);
  690.     put_fs_long(current->rlim[resource].rlim_max,
  691.             ((unsigned long *) rlim)+1);
  692.     return 0;
  693. }
  694.  
  695. asmlinkage int sys_setrlimit(unsigned int resource, struct rlimit *rlim)
  696. {
  697.     struct rlimit new_rlim, *old_rlim;
  698.  
  699.     if (resource >= RLIM_NLIMITS)
  700.         return -EINVAL;
  701.     old_rlim = current->rlim + resource;
  702.     new_rlim.rlim_cur = get_fs_long((unsigned long *) rlim);
  703.     new_rlim.rlim_max = get_fs_long(((unsigned long *) rlim)+1);
  704.     if (((new_rlim.rlim_cur > old_rlim->rlim_max) ||
  705.          (new_rlim.rlim_max > old_rlim->rlim_max)) &&
  706.         !suser())
  707.         return -EPERM;
  708.     *old_rlim = new_rlim;
  709.     return 0;
  710. }
  711.  
  712. /*
  713.  * It would make sense to put struct rusuage in the task_struct,
  714.  * except that would make the task_struct be *really big*.  After
  715.  * task_struct gets moved into malloc'ed memory, it would
  716.  * make sense to do this.  It will make moving the rest of the information
  717.  * a lot simpler!  (Which we're not doing right now because we're not
  718.  * measuring them yet).
  719.  */
  720. int getrusage(struct task_struct *p, int who, struct rusage *ru)
  721. {
  722.     int error;
  723.     struct rusage r;
  724.     unsigned long    *lp, *lpend, *dest;
  725.  
  726.     error = verify_area(VERIFY_WRITE, ru, sizeof *ru);
  727.     if (error)
  728.         return error;
  729.     memset((char *) &r, 0, sizeof(r));
  730.     switch (who) {
  731.         case RUSAGE_SELF:
  732.             r.ru_utime.tv_sec = CT_TO_SECS(p->utime);
  733.             r.ru_utime.tv_usec = CT_TO_USECS(p->utime);
  734.             r.ru_stime.tv_sec = CT_TO_SECS(p->stime);
  735.             r.ru_stime.tv_usec = CT_TO_USECS(p->stime);
  736.             r.ru_minflt = p->min_flt;
  737.             r.ru_majflt = p->maj_flt;
  738.             break;
  739.         case RUSAGE_CHILDREN:
  740.             r.ru_utime.tv_sec = CT_TO_SECS(p->cutime);
  741.             r.ru_utime.tv_usec = CT_TO_USECS(p->cutime);
  742.             r.ru_stime.tv_sec = CT_TO_SECS(p->cstime);
  743.             r.ru_stime.tv_usec = CT_TO_USECS(p->cstime);
  744.             r.ru_minflt = p->cmin_flt;
  745.             r.ru_majflt = p->cmaj_flt;
  746.             break;
  747.         default:
  748.             r.ru_utime.tv_sec = CT_TO_SECS(p->utime + p->cutime);
  749.             r.ru_utime.tv_usec = CT_TO_USECS(p->utime + p->cutime);
  750.             r.ru_stime.tv_sec = CT_TO_SECS(p->stime + p->cstime);
  751.             r.ru_stime.tv_usec = CT_TO_USECS(p->stime + p->cstime);
  752.             r.ru_minflt = p->min_flt + p->cmin_flt;
  753.             r.ru_majflt = p->maj_flt + p->cmaj_flt;
  754.             break;
  755.     }
  756.     lp = (unsigned long *) &r;
  757.     lpend = (unsigned long *) (&r+1);
  758.     dest = (unsigned long *) ru;
  759.     for (; lp < lpend; lp++, dest++)
  760.         put_fs_long(*lp, dest);
  761.     return 0;
  762. }
  763.  
  764. asmlinkage int sys_getrusage(int who, struct rusage *ru)
  765. {
  766.     if (who != RUSAGE_SELF && who != RUSAGE_CHILDREN)
  767.         return -EINVAL;
  768.     return getrusage(current, who, ru);
  769. }
  770.  
  771. asmlinkage int sys_umask(int mask)
  772. {
  773.     int old = current->umask;
  774.  
  775.     current->umask = mask & S_IRWXUGO;
  776.     return (old);
  777. }
  778.