Annotation of linux/kernel/sys.c, revision 1.1.1.10

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.