OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [uclinux/] [uClinux-2.0.x/] [kernel/] [sys.c] - Blame information for rev 199

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 199 simons
/*
2
 *  linux/kernel/sys.c
3
 *
4
 *  Copyright (C) 1991, 1992  Linus Torvalds
5
 */
6
 
7
#include <linux/config.h>
8
#include <linux/errno.h>
9
#include <linux/sched.h>
10
#include <linux/kernel.h>
11
#include <linux/times.h>
12
#include <linux/utsname.h>
13
#include <linux/param.h>
14
#include <linux/resource.h>
15
#include <linux/signal.h>
16
#include <linux/string.h>
17
#include <linux/ptrace.h>
18
#include <linux/stat.h>
19
#include <linux/mman.h>
20
#include <linux/mm.h>
21
#include <linux/fcntl.h>
22
#include <linux/acct.h>
23
#include <linux/tty.h>
24
#if defined(CONFIG_APM) && defined(CONFIG_APM_POWER_OFF)
25
#include <linux/apm_bios.h>
26
#endif
27
 
28
#include <asm/segment.h>
29
#include <asm/io.h>
30
 
31
/*
32
 * this indicates whether you can reboot with ctrl-alt-del: the default is yes
33
 */
34
int C_A_D = 1;
35
 
36
extern void adjust_clock(void);
37
extern void DAC960_Finalize(void);
38
extern void gdth_halt(void);
39
 
40
asmlinkage int sys_ni_syscall(void)
41
{
42
        return -ENOSYS;
43
}
44
 
45
static int proc_sel(struct task_struct *p, int which, int who)
46
{
47
        if(p->pid)
48
        {
49
                switch (which) {
50
                        case PRIO_PROCESS:
51
                                if (!who && p == current)
52
                                        return 1;
53
                                return(p->pid == who);
54
                        case PRIO_PGRP:
55
                                if (!who)
56
                                        who = current->pgrp;
57
                                return(p->pgrp == who);
58
                        case PRIO_USER:
59
                                if (!who)
60
                                        who = current->uid;
61
                                return(p->uid == who);
62
                }
63
        }
64
        return 0;
65
}
66
 
67
asmlinkage int sys_setpriority(int which, int who, int niceval)
68
{
69
        struct task_struct *p;
70
        int error = ESRCH;
71
        unsigned int priority;
72
 
73
        if (which > 2 || which < 0)
74
                return -EINVAL;
75
 
76
        /* normalize: avoid signed division (rounding problems) */
77
        priority = niceval;
78
        if (niceval < 0)
79
                priority = -niceval;
80
        if (priority > 20)
81
                priority = 20;
82
        priority = (priority * DEF_PRIORITY + 10) / 20 + DEF_PRIORITY;
83
 
84
        if (niceval >= 0) {
85
                priority = 2*DEF_PRIORITY - priority;
86
                if (!priority)
87
                        priority = 1;
88
        }
89
 
90
        for_each_task(p) {
91
                if (!proc_sel(p, which, who))
92
                        continue;
93
                if (p->uid != current->euid &&
94
                        p->uid != current->uid && !suser()) {
95
                        error = EPERM;
96
                        continue;
97
                }
98
                if (error == ESRCH)
99
                        error = 0;
100
                if (priority > p->priority && !suser())
101
                        error = EACCES;
102
                else
103
                        p->priority = priority;
104
        }
105
        return -error;
106
}
107
 
108
/*
109
 * Ugh. To avoid negative return values, "getpriority()" will
110
 * not return the normal nice-value, but a value that has been
111
 * offset by 20 (ie it returns 0..40 instead of -20..20)
112
 */
113
asmlinkage int sys_getpriority(int which, int who)
114
{
115
        struct task_struct *p;
116
        long max_prio = -ESRCH;
117
 
118
        if (which > 2 || which < 0)
119
                return -EINVAL;
120
 
121
        for_each_task (p) {
122
                if (!proc_sel(p, which, who))
123
                        continue;
124
                if (p->priority > max_prio)
125
                        max_prio = p->priority;
126
        }
127
 
128
        /* scale the priority from timeslice to 0..40 */
129
        if (max_prio > 0)
130
                max_prio = (max_prio * 20 + DEF_PRIORITY/2) / DEF_PRIORITY;
131
        return max_prio;
132
}
133
 
134
#ifndef __alpha__
135
 
136
/*
137
 * Why do these exist?  Binary compatibility with some other standard?
138
 * If so, maybe they should be moved into the appropriate arch
139
 * directory.
140
 */
141
 
142
asmlinkage int sys_profil(void)
143
{
144
        return -ENOSYS;
145
}
146
 
147
asmlinkage int sys_ftime(void)
148
{
149
        return -ENOSYS;
150
}
151
 
152
asmlinkage int sys_break(void)
153
{
154
        return -ENOSYS;
155
}
156
 
157
asmlinkage int sys_stty(void)
158
{
159
        return -ENOSYS;
160
}
161
 
162
asmlinkage int sys_gtty(void)
163
{
164
        return -ENOSYS;
165
}
166
 
167
asmlinkage int sys_prof(void)
168
{
169
        return -ENOSYS;
170
}
171
 
172
#endif
173
 
174
extern void hard_reset_now(void);
175
extern asmlinkage int sys_kill(int, int);
176
 
177
/*
178
 * Reboot system call: for obvious reasons only root may call it,
179
 * and even root needs to set up some magic numbers in the registers
180
 * so that some mistake won't make this reboot the whole machine.
181
 * You can also set the meaning of the ctrl-alt-del-key here.
182
 *
183
 * reboot doesn't sync: do that yourself before calling this.
184
 */
185
asmlinkage int sys_reboot(int magic, int magic_too, int flag)
186
{
187
        if (!suser())
188
                return -EPERM;
189
        if (magic != 0xfee1dead || magic_too != 672274793)
190
                return -EINVAL;
191
        if (flag == 0x01234567) {
192
#ifdef CONFIG_BLK_DEV_DAC960
193
                DAC960_Finalize();
194
#endif
195
#ifdef CONFIG_SCSI_GDTH
196
                gdth_halt();
197
#endif
198
                hard_reset_now();
199
        } else if (flag == 0x89ABCDEF)
200
                C_A_D = 1;
201
        else if (!flag)
202
                C_A_D = 0;
203
        else if (flag == 0xCDEF0123) {
204
#ifdef CONFIG_BLK_DEV_DAC960
205
                DAC960_Finalize();
206
#endif
207
#ifdef CONFIG_SCSI_GDTH
208
                gdth_halt();
209
#endif
210
                printk(KERN_EMERG "System halted\n");
211
                sys_kill(-1, SIGKILL);
212
#if defined(CONFIG_APM) && defined(CONFIG_APM_POWER_OFF)
213
                apm_power_off();
214
#endif
215
                do_exit(0);
216
        } else
217
                return -EINVAL;
218
        return (0);
219
}
220
 
221
/*
222
 * This function gets called by ctrl-alt-del - ie the keyboard interrupt.
223
 * As it's called within an interrupt, it may NOT sync: the only choice
224
 * is whether to reboot at once, or just ignore the ctrl-alt-del.
225
 */
226
void ctrl_alt_del(void)
227
{
228
        if (C_A_D) {
229
#ifdef CONFIG_BLK_DEV_DAC960
230
                DAC960_Finalize();
231
#endif
232
#ifdef CONFIG_SCSI_GDTH
233
                gdth_halt();
234
#endif
235
                hard_reset_now();
236
        } else
237
                kill_proc(1, SIGINT, 1);
238
}
239
 
240
 
241
/*
242
 * Unprivileged users may change the real gid to the effective gid
243
 * or vice versa.  (BSD-style)
244
 *
245
 * If you set the real gid at all, or set the effective gid to a value not
246
 * equal to the real gid, then the saved gid is set to the new effective gid.
247
 *
248
 * This makes it possible for a setgid program to completely drop its
249
 * privileges, which is often a useful assertion to make when you are doing
250
 * a security 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
 */
256
asmlinkage int sys_setregid(gid_t rgid, gid_t egid)
257
{
258
        int old_rgid = current->gid;
259
        int old_egid = current->egid;
260
 
261
        if (rgid != (gid_t) -1) {
262
                if ((old_rgid == rgid) ||
263
                    (current->egid==rgid) ||
264
                    suser())
265
                        current->gid = rgid;
266
                else
267
                        return(-EPERM);
268
        }
269
        if (egid != (gid_t) -1) {
270
                if ((old_rgid == egid) ||
271
                    (current->egid == egid) ||
272
                    (current->sgid == egid) ||
273
                    suser())
274
                        current->fsgid = current->egid = egid;
275
                else {
276
                        current->gid = old_rgid;
277
                        return(-EPERM);
278
                }
279
        }
280
        if (rgid != (gid_t) -1 ||
281
            (egid != (gid_t) -1 && egid != old_rgid))
282
                current->sgid = current->egid;
283
        current->fsgid = current->egid;
284
        if (current->egid != old_egid)
285
                current->dumpable = 0;
286
        return 0;
287
}
288
 
289
/*
290
 * setgid() is implemented like SysV w/ SAVED_IDS
291
 */
292
asmlinkage int sys_setgid(gid_t gid)
293
{
294
        int old_egid = current->egid;
295
 
296
        if (suser())
297
                current->gid = current->egid = current->sgid = current->fsgid = gid;
298
        else if ((gid == current->gid) || (gid == current->sgid))
299
                current->egid = current->fsgid = gid;
300
        else
301
                return -EPERM;
302
        if (current->egid != old_egid)
303
                current->dumpable = 0;
304
        return 0;
305
}
306
 
307
static char acct_active = 0;
308
static struct file acct_file;
309
 
310
int acct_process(long exitcode)
311
{
312
   struct acct ac;
313
   unsigned short fs;
314
 
315
   if (acct_active) {
316
      strncpy(ac.ac_comm, current->comm, ACCT_COMM);
317
      ac.ac_comm[ACCT_COMM-1] = '\0';
318
      ac.ac_utime = current->utime;
319
      ac.ac_stime = current->stime;
320
      ac.ac_btime = CT_TO_SECS(current->start_time) + (xtime.tv_sec - (jiffies / HZ));
321
      ac.ac_etime = CURRENT_TIME - ac.ac_btime;
322
      ac.ac_uid   = current->uid;
323
      ac.ac_gid   = current->gid;
324
      ac.ac_tty   = (current)->tty == NULL ? -1 :
325
          kdev_t_to_nr(current->tty->device);
326
      ac.ac_flag  = 0;
327
      if (current->flags & PF_FORKNOEXEC)
328
         ac.ac_flag |= AFORK;
329
      if (current->flags & PF_SUPERPRIV)
330
         ac.ac_flag |= ASU;
331
      if (current->flags & PF_DUMPCORE)
332
         ac.ac_flag |= ACORE;
333
      if (current->flags & PF_SIGNALED)
334
         ac.ac_flag |= AXSIG;
335
      ac.ac_minflt = current->min_flt;
336
      ac.ac_majflt = current->maj_flt;
337
      ac.ac_exitcode = exitcode;
338
 
339
      /* Kernel segment override */
340
      fs = get_fs();
341
      set_fs(KERNEL_DS);
342
 
343
      acct_file.f_op->write(acct_file.f_inode, &acct_file,
344
                             (char *)&ac, sizeof(struct acct));
345
 
346
      set_fs(fs);
347
   }
348
   return 0;
349
}
350
 
351
asmlinkage int sys_acct(const char *name)
352
{
353
   struct inode *inode = (struct inode *)0;
354
   char *tmp;
355
   int error;
356
 
357
   if (!suser())
358
      return -EPERM;
359
 
360
   if (name == (char *)0) {
361
      if (acct_active) {
362
         if (acct_file.f_op->release)
363
            acct_file.f_op->release(acct_file.f_inode, &acct_file);
364
 
365
         if (acct_file.f_inode != (struct inode *) 0)
366
            iput(acct_file.f_inode);
367
 
368
         acct_active = 0;
369
      }
370
      return 0;
371
   } else {
372
      if (!acct_active) {
373
 
374
         if ((error = getname(name, &tmp)) != 0)
375
            return (error);
376
 
377
         error = open_namei(tmp, O_RDWR, 0600, &inode, 0);
378
         putname(tmp);
379
 
380
         if (error)
381
            return (error);
382
 
383
         if (!S_ISREG(inode->i_mode)) {
384
            iput(inode);
385
            return -EACCES;
386
         }
387
 
388
         if (!inode->i_op || !inode->i_op->default_file_ops ||
389
             !inode->i_op->default_file_ops->write) {
390
            iput(inode);
391
            return -EIO;
392
         }
393
 
394
         acct_file.f_mode = 3;
395
         acct_file.f_flags = 0;
396
         acct_file.f_count = 1;
397
         acct_file.f_inode = inode;
398
         acct_file.f_pos = inode->i_size;
399
         acct_file.f_reada = 0;
400
         acct_file.f_op = inode->i_op->default_file_ops;
401
 
402
         if (acct_file.f_op->open)
403
            if (acct_file.f_op->open(acct_file.f_inode, &acct_file)) {
404
               iput(inode);
405
               return -EIO;
406
            }
407
 
408
         acct_active = 1;
409
         return 0;
410
      } else
411
         return -EBUSY;
412
   }
413
}
414
 
415
#ifndef __alpha__
416
 
417
/*
418
 * Why do these exist?  Binary compatibility with some other standard?
419
 * If so, maybe they should be moved into the appropriate arch
420
 * directory.
421
 */
422
 
423
asmlinkage int sys_phys(void)
424
{
425
        return -ENOSYS;
426
}
427
 
428
asmlinkage int sys_lock(void)
429
{
430
        return -ENOSYS;
431
}
432
 
433
asmlinkage int sys_mpx(void)
434
{
435
        return -ENOSYS;
436
}
437
 
438
asmlinkage int sys_ulimit(void)
439
{
440
        return -ENOSYS;
441
}
442
 
443
asmlinkage int sys_old_syscall(void)
444
{
445
        return -ENOSYS;
446
}
447
 
448
#endif
449
 
450
/*
451
 * Unprivileged users may change the real uid to the effective uid
452
 * or vice versa.  (BSD-style)
453
 *
454
 * If you set the real uid at all, or set the effective uid to a value not
455
 * equal to the real uid, then the saved uid is set to the new effective uid.
456
 *
457
 * This makes it possible for a setuid program to completely drop its
458
 * privileges, which is often a useful assertion to make when you are doing
459
 * a security audit over a program.
460
 *
461
 * The general idea is that a program which uses just setreuid() will be
462
 * 100% compatible with BSD.  A program which uses just setuid() will be
463
 * 100% compatible with POSIX w/ Saved ID's.
464
 */
465
asmlinkage int sys_setreuid(uid_t ruid, uid_t euid)
466
{
467
        int old_ruid = current->uid;
468
        int old_euid = current->euid;
469
 
470
        if (ruid != (uid_t) -1) {
471
                if ((old_ruid == ruid) ||
472
                    (current->euid==ruid) ||
473
                    suser())
474
                        current->uid = ruid;
475
                else
476
                        return(-EPERM);
477
        }
478
        if (euid != (uid_t) -1) {
479
                if ((old_ruid == euid) ||
480
                    (current->euid == euid) ||
481
                    (current->suid == euid) ||
482
                    suser())
483
                        current->fsuid = current->euid = euid;
484
                else {
485
                        current->uid = old_ruid;
486
                        return(-EPERM);
487
                }
488
        }
489
        if (ruid != (uid_t) -1 ||
490
            (euid != (uid_t) -1 && euid != old_ruid))
491
                current->suid = current->euid;
492
        current->fsuid = current->euid;
493
        if (current->euid != old_euid)
494
                current->dumpable = 0;
495
        return 0;
496
}
497
 
498
/*
499
 * setuid() is implemented like SysV w/ SAVED_IDS
500
 *
501
 * Note that SAVED_ID's is deficient in that a setuid root program
502
 * like sendmail, for example, cannot set its uid to be a normal
503
 * user and then switch back, because if you're root, setuid() sets
504
 * the saved uid too.  If you don't like this, blame the bright people
505
 * in the POSIX committee and/or USG.  Note that the BSD-style setreuid()
506
 * will allow a root program to temporarily drop privileges and be able to
507
 * regain them by swapping the real and effective uid.
508
 */
509
asmlinkage int sys_setuid(uid_t uid)
510
{
511
        int old_euid = current->euid;
512
 
513
        if (suser())
514
                current->uid = current->euid = current->suid = current->fsuid = uid;
515
        else if ((uid == current->uid) || (uid == current->suid))
516
                current->fsuid = current->euid = uid;
517
        else
518
                return -EPERM;
519
        if (current->euid != old_euid)
520
                current->dumpable = 0;
521
        return(0);
522
}
523
 
524
/*
525
 * "setfsuid()" sets the fsuid - the uid used for filesystem checks. This
526
 * is used for "access()" and for the NFS daemon (letting nfsd stay at
527
 * whatever uid it wants to). It normally shadows "euid", except when
528
 * explicitly set by setfsuid() or for access..
529
 */
530
asmlinkage int sys_setfsuid(uid_t uid)
531
{
532
        int old_fsuid = current->fsuid;
533
 
534
        if (uid == current->uid || uid == current->euid ||
535
            uid == current->suid || uid == current->fsuid || suser())
536
                current->fsuid = uid;
537
        if (current->fsuid != old_fsuid)
538
                current->dumpable = 0;
539
        return old_fsuid;
540
}
541
 
542
/*
543
 * Samma på svenska..
544
 */
545
asmlinkage int sys_setfsgid(gid_t gid)
546
{
547
        int old_fsgid = current->fsgid;
548
 
549
        if (gid == current->gid || gid == current->egid ||
550
            gid == current->sgid || gid == current->fsgid || suser())
551
                current->fsgid = gid;
552
        if (current->fsgid != old_fsgid)
553
                current->dumpable = 0;
554
        return old_fsgid;
555
}
556
 
557
asmlinkage long sys_times(struct tms * tbuf)
558
{
559
        if (tbuf) {
560
                int error = verify_area(VERIFY_WRITE,tbuf,sizeof *tbuf);
561
                if (error)
562
                        return error;
563
                put_user(current->utime,&tbuf->tms_utime);
564
                put_user(current->stime,&tbuf->tms_stime);
565
                put_user(current->cutime,&tbuf->tms_cutime);
566
                put_user(current->cstime,&tbuf->tms_cstime);
567
        }
568
        return jiffies;
569
}
570
 
571
/*
572
 * This needs some heavy checking ...
573
 * I just haven't the stomach for it. I also don't fully
574
 * understand sessions/pgrp etc. Let somebody who does explain it.
575
 *
576
 * OK, I think I have the protection semantics right.... this is really
577
 * only important on a multi-user system anyway, to make sure one user
578
 * can't send a signal to a process owned by another.  -TYT, 12/12/91
579
 *
580
 * Auch. Had to add the 'did_exec' flag to conform completely to POSIX.
581
 * LBT 04.03.94
582
 */
583
asmlinkage int sys_setpgid(pid_t pid, pid_t pgid)
584
{
585
        struct task_struct * p;
586
 
587
        if (!pid)
588
                pid = current->pid;
589
        if (!pgid)
590
                pgid = pid;
591
        if (pgid < 0)
592
                return -EINVAL;
593
        for_each_task(p) {
594
                if (p->pid == pid)
595
                        goto found_task;
596
        }
597
        return -ESRCH;
598
 
599
found_task:
600
        if (p->p_pptr == current || p->p_opptr == current) {
601
                if (p->session != current->session)
602
                        return -EPERM;
603
                if (p->did_exec)
604
                        return -EACCES;
605
        } else if (p != current)
606
                return -ESRCH;
607
        if (p->leader)
608
                return -EPERM;
609
        if (pgid != pid) {
610
                struct task_struct * tmp;
611
                for_each_task (tmp) {
612
                        if (tmp->pgrp == pgid &&
613
                         tmp->session == current->session)
614
                                goto ok_pgid;
615
                }
616
                return -EPERM;
617
        }
618
 
619
ok_pgid:
620
        p->pgrp = pgid;
621
        return 0;
622
}
623
 
624
asmlinkage int sys_getpgid(pid_t pid)
625
{
626
        struct task_struct * p;
627
 
628
        if (!pid)
629
                return current->pgrp;
630
        for_each_task(p) {
631
                if (p->pid == pid)
632
                        return p->pgrp;
633
        }
634
        return -ESRCH;
635
}
636
 
637
asmlinkage int sys_getpgrp(void)
638
{
639
        return current->pgrp;
640
}
641
 
642
asmlinkage int sys_getsid(pid_t pid)
643
{
644
        struct task_struct * p;
645
 
646
        if (!pid)
647
                return current->session;
648
        for_each_task(p) {
649
                if (p->pid == pid)
650
                        return p->session;
651
        }
652
        return -ESRCH;
653
}
654
 
655
asmlinkage int sys_setsid(void)
656
{
657
        struct task_struct * p;
658
 
659
        for_each_task(p) {
660
                if (p->pgrp == current->pid)
661
                        return -EPERM;
662
        }
663
 
664
        current->leader = 1;
665
        current->session = current->pgrp = current->pid;
666
        current->tty = NULL;
667
        current->tty_old_pgrp = 0;
668
        return current->pgrp;
669
}
670
 
671
/*
672
 * Supplementary group ID's
673
 */
674
asmlinkage int sys_getgroups(int gidsetsize, gid_t *grouplist)
675
{
676
        int i;
677
        int * groups;
678
 
679
        /* Avoid an integer overflow on systems with 32 bit gid_t (Alpha) */
680
        if (gidsetsize & ~0x3FFFFFFF)
681
                return -EINVAL;
682
        groups = current->groups;
683
        for (i = 0 ; i < NGROUPS ; i++) {
684
                if (groups[i] == NOGROUP)
685
                        break;
686
        }
687
        if (gidsetsize) {
688
                int error;
689
                error = verify_area(VERIFY_WRITE, grouplist, sizeof(gid_t) * gidsetsize);
690
                if (error)
691
                        return error;
692
                if (i > gidsetsize)
693
                        return -EINVAL;
694
 
695
                for (i = 0 ; i < NGROUPS ; i++) {
696
                        if (groups[i] == NOGROUP)
697
                                break;
698
                        put_user(groups[i], grouplist);
699
                        grouplist++;
700
                }
701
        }
702
        return i;
703
}
704
 
705
asmlinkage int sys_setgroups(int gidsetsize, gid_t *grouplist)
706
{
707
        int     i;
708
 
709
        if (!suser())
710
                return -EPERM;
711
        if (gidsetsize > NGROUPS)
712
                return -EINVAL;
713
        i = verify_area(VERIFY_READ, grouplist, sizeof(gid_t) * gidsetsize);
714
        if (i)
715
                return i;
716
        for (i = 0; i < gidsetsize; i++, grouplist++) {
717
                current->groups[i] = get_user(grouplist);
718
        }
719
        if (i < NGROUPS)
720
                current->groups[i] = NOGROUP;
721
        return 0;
722
}
723
 
724
int in_group_p(gid_t grp)
725
{
726
        int     i;
727
 
728
        if (grp == current->fsgid)
729
                return 1;
730
 
731
        for (i = 0; i < NGROUPS; i++) {
732
                if (current->groups[i] == NOGROUP)
733
                        break;
734
                if (current->groups[i] == grp)
735
                        return 1;
736
        }
737
        return 0;
738
}
739
 
740
asmlinkage int sys_newuname(struct new_utsname * name)
741
{
742
        int error;
743
 
744
        if (!name)
745
                return -EFAULT;
746
        error = verify_area(VERIFY_WRITE, name, sizeof *name);
747
        if (!error)
748
                memcpy_tofs(name,&system_utsname,sizeof *name);
749
        return error;
750
}
751
 
752
#ifndef __alpha__
753
 
754
/*
755
 * Move these to arch dependent dir since they are for
756
 * backward compatibility only?
757
 */
758
asmlinkage int sys_uname(struct old_utsname * name)
759
{
760
        int error;
761
        if (!name)
762
                return -EFAULT;
763
        error = verify_area(VERIFY_WRITE, name,sizeof *name);
764
        if (error)
765
                return error;
766
        memcpy_tofs(&name->sysname,&system_utsname.sysname,
767
                sizeof (system_utsname.sysname));
768
        memcpy_tofs(&name->nodename,&system_utsname.nodename,
769
                sizeof (system_utsname.nodename));
770
        memcpy_tofs(&name->release,&system_utsname.release,
771
                sizeof (system_utsname.release));
772
        memcpy_tofs(&name->version,&system_utsname.version,
773
                sizeof (system_utsname.version));
774
        memcpy_tofs(&name->machine,&system_utsname.machine,
775
                sizeof (system_utsname.machine));
776
        return 0;
777
}
778
 
779
asmlinkage int sys_olduname(struct oldold_utsname * name)
780
{
781
        int error;
782
        if (!name)
783
                return -EFAULT;
784
        error = verify_area(VERIFY_WRITE, name,sizeof *name);
785
        if (error)
786
                return error;
787
        memcpy_tofs(&name->sysname,&system_utsname.sysname,__OLD_UTS_LEN);
788
        put_user(0,name->sysname+__OLD_UTS_LEN);
789
        memcpy_tofs(&name->nodename,&system_utsname.nodename,__OLD_UTS_LEN);
790
        put_user(0,name->nodename+__OLD_UTS_LEN);
791
        memcpy_tofs(&name->release,&system_utsname.release,__OLD_UTS_LEN);
792
        put_user(0,name->release+__OLD_UTS_LEN);
793
        memcpy_tofs(&name->version,&system_utsname.version,__OLD_UTS_LEN);
794
        put_user(0,name->version+__OLD_UTS_LEN);
795
        memcpy_tofs(&name->machine,&system_utsname.machine,__OLD_UTS_LEN);
796
        put_user(0,name->machine+__OLD_UTS_LEN);
797
        return 0;
798
}
799
 
800
#endif
801
 
802
asmlinkage int sys_sethostname(char *name, int len)
803
{
804
        int error;
805
 
806
        if (!suser())
807
                return -EPERM;
808
        if (len < 0 || len > __NEW_UTS_LEN)
809
                return -EINVAL;
810
        error = verify_area(VERIFY_READ, name, len);
811
        if (error)
812
                return error;
813
        memcpy_fromfs(system_utsname.nodename, name, len);
814
        system_utsname.nodename[len] = 0;
815
        return 0;
816
}
817
 
818
asmlinkage int sys_gethostname(char *name, int len)
819
{
820
        int i;
821
 
822
        if (len < 0)
823
                return -EINVAL;
824
        i = verify_area(VERIFY_WRITE, name, len);
825
        if (i)
826
                return i;
827
        i = 1+strlen(system_utsname.nodename);
828
        if (i > len)
829
                i = len;
830
        memcpy_tofs(name, system_utsname.nodename, i);
831
        return 0;
832
}
833
 
834
/*
835
 * Only setdomainname; getdomainname can be implemented by calling
836
 * uname()
837
 */
838
asmlinkage int sys_setdomainname(char *name, int len)
839
{
840
        int error;
841
 
842
        if (!suser())
843
                return -EPERM;
844
        if (len < 0 || len > __NEW_UTS_LEN)
845
                return -EINVAL;
846
        error = verify_area(VERIFY_READ, name, len);
847
        if (error)
848
                return error;
849
        memcpy_fromfs(system_utsname.domainname, name, len);
850
        system_utsname.domainname[len] = 0;
851
        return 0;
852
}
853
 
854
asmlinkage int sys_getrlimit(unsigned int resource, struct rlimit *rlim)
855
{
856
        int error;
857
 
858
        if (resource >= RLIM_NLIMITS)
859
                return -EINVAL;
860
        error = verify_area(VERIFY_WRITE,rlim,sizeof *rlim);
861
        if (error)
862
                return error;
863
        memcpy_tofs(rlim, current->rlim + resource, sizeof(*rlim));
864
        return 0;
865
}
866
 
867
asmlinkage int sys_setrlimit(unsigned int resource, struct rlimit *rlim)
868
{
869
        struct rlimit new_rlim, *old_rlim;
870
        int err;
871
 
872
        if (resource >= RLIM_NLIMITS)
873
                return -EINVAL;
874
        err = verify_area(VERIFY_READ, rlim, sizeof(*rlim));
875
        if (err)
876
                return err;
877
        memcpy_fromfs(&new_rlim, rlim, sizeof(*rlim));
878
        if (new_rlim.rlim_cur < 0 || new_rlim.rlim_max < 0)
879
                return -EINVAL;
880
        old_rlim = current->rlim + resource;
881
        if (((new_rlim.rlim_cur > old_rlim->rlim_max) ||
882
             (new_rlim.rlim_max > old_rlim->rlim_max)) &&
883
            !suser())
884
                return -EPERM;
885
        if (resource == RLIMIT_NOFILE) {
886
                if (new_rlim.rlim_cur > NR_OPEN || new_rlim.rlim_max > NR_OPEN)
887
                        return -EPERM;
888
        }
889
        *old_rlim = new_rlim;
890
        return 0;
891
}
892
 
893
/*
894
 * It would make sense to put struct rusage in the task_struct,
895
 * except that would make the task_struct be *really big*.  After
896
 * task_struct gets moved into malloc'ed memory, it would
897
 * make sense to do this.  It will make moving the rest of the information
898
 * a lot simpler!  (Which we're not doing right now because we're not
899
 * measuring them yet).
900
 */
901
int getrusage(struct task_struct *p, int who, struct rusage *ru)
902
{
903
        int error;
904
        struct rusage r;
905
 
906
        error = verify_area(VERIFY_WRITE, ru, sizeof *ru);
907
        if (error)
908
                return error;
909
        memset((char *) &r, 0, sizeof(r));
910
        switch (who) {
911
                case RUSAGE_SELF:
912
                        r.ru_utime.tv_sec = CT_TO_SECS(p->utime);
913
                        r.ru_utime.tv_usec = CT_TO_USECS(p->utime);
914
                        r.ru_stime.tv_sec = CT_TO_SECS(p->stime);
915
                        r.ru_stime.tv_usec = CT_TO_USECS(p->stime);
916
                        r.ru_minflt = p->min_flt;
917
                        r.ru_majflt = p->maj_flt;
918
                        r.ru_nswap = p->nswap;
919
                        break;
920
                case RUSAGE_CHILDREN:
921
                        r.ru_utime.tv_sec = CT_TO_SECS(p->cutime);
922
                        r.ru_utime.tv_usec = CT_TO_USECS(p->cutime);
923
                        r.ru_stime.tv_sec = CT_TO_SECS(p->cstime);
924
                        r.ru_stime.tv_usec = CT_TO_USECS(p->cstime);
925
                        r.ru_minflt = p->cmin_flt;
926
                        r.ru_majflt = p->cmaj_flt;
927
                        r.ru_nswap = p->cnswap;
928
                        break;
929
                default:
930
                        r.ru_utime.tv_sec = CT_TO_SECS(p->utime + p->cutime);
931
                        r.ru_utime.tv_usec = CT_TO_USECS(p->utime + p->cutime);
932
                        r.ru_stime.tv_sec = CT_TO_SECS(p->stime + p->cstime);
933
                        r.ru_stime.tv_usec = CT_TO_USECS(p->stime + p->cstime);
934
                        r.ru_minflt = p->min_flt + p->cmin_flt;
935
                        r.ru_majflt = p->maj_flt + p->cmaj_flt;
936
                        r.ru_nswap = p->nswap + p->cnswap;
937
                        break;
938
        }
939
        memcpy_tofs(ru, &r, sizeof(r));
940
        return 0;
941
}
942
 
943
asmlinkage int sys_getrusage(int who, struct rusage *ru)
944
{
945
        if (who != RUSAGE_SELF && who != RUSAGE_CHILDREN)
946
                return -EINVAL;
947
        return getrusage(current, who, ru);
948
}
949
 
950
asmlinkage int sys_umask(int mask)
951
{
952
        int old = current->fs->umask;
953
 
954
        current->fs->umask = mask & S_IRWXUGO;
955
        return (old);
956
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.