d0aa8f125ee67ad85e9b7ee32d5a7c16c64cb9ad
[safe/jmp/linux-2.6] / arch / um / sys-i386 / syscalls.c
1 /* 
2  * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com)
3  * Licensed under the GPL
4  */
5
6 #include "linux/sched.h"
7 #include "linux/shm.h"
8 #include "linux/ipc.h"
9 #include "linux/syscalls.h"
10 #include "asm/mman.h"
11 #include "asm/uaccess.h"
12 #include "asm/unistd.h"
13
14 /*
15  * The prototype on i386 is:
16  *
17  *     int clone(int flags, void * child_stack, int * parent_tidptr, struct user_desc * newtls, int * child_tidptr)
18  *
19  * and the "newtls" arg. on i386 is read by copy_thread directly from the
20  * register saved on the stack.
21  */
22 long sys_clone(unsigned long clone_flags, unsigned long newsp,
23                int __user *parent_tid, void *newtls, int __user *child_tid)
24 {
25         long ret;
26
27         if (!newsp)
28                 newsp = UPT_SP(&current->thread.regs.regs);
29
30         current->thread.forking = 1;
31         ret = do_fork(clone_flags, newsp, &current->thread.regs, 0, parent_tid,
32                       child_tid);
33         current->thread.forking = 0;
34         return ret;
35 }
36
37 /*
38  * sys_ipc() is the de-multiplexer for the SysV IPC calls..
39  *
40  * This is really horribly ugly.
41  */
42 long sys_ipc (uint call, int first, int second,
43              int third, void __user *ptr, long fifth)
44 {
45         int version, ret;
46
47         version = call >> 16; /* hack for backward compatibility */
48         call &= 0xffff;
49
50         switch (call) {
51         case SEMOP:
52                 return sys_semtimedop(first, (struct sembuf __user *) ptr,
53                                       second, NULL);
54         case SEMTIMEDOP:
55                 return sys_semtimedop(first, (struct sembuf __user *) ptr,
56                                       second,
57                                       (const struct timespec __user *) fifth);
58         case SEMGET:
59                 return sys_semget (first, second, third);
60         case SEMCTL: {
61                 union semun fourth;
62                 if (!ptr)
63                         return -EINVAL;
64                 if (get_user(fourth.__pad, (void __user * __user *) ptr))
65                         return -EFAULT;
66                 return sys_semctl (first, second, third, fourth);
67         }
68
69         case MSGSND:
70                 return sys_msgsnd (first, (struct msgbuf *) ptr,
71                                    second, third);
72         case MSGRCV:
73                 switch (version) {
74                 case 0: {
75                         struct ipc_kludge tmp;
76                         if (!ptr)
77                                 return -EINVAL;
78
79                         if (copy_from_user(&tmp,
80                                            (struct ipc_kludge *) ptr,
81                                            sizeof (tmp)))
82                                 return -EFAULT;
83                         return sys_msgrcv (first, tmp.msgp, second,
84                                            tmp.msgtyp, third);
85                 }
86                 default:
87                         panic("msgrcv with version != 0");
88                         return sys_msgrcv (first,
89                                            (struct msgbuf *) ptr,
90                                            second, fifth, third);
91                 }
92         case MSGGET:
93                 return sys_msgget ((key_t) first, second);
94         case MSGCTL:
95                 return sys_msgctl (first, second, (struct msqid_ds *) ptr);
96
97         case SHMAT:
98                 switch (version) {
99                 default: {
100                         ulong raddr;
101                         ret = do_shmat (first, (char *) ptr, second, &raddr);
102                         if (ret)
103                                 return ret;
104                         return put_user (raddr, (ulong *) third);
105                 }
106                 case 1: /* iBCS2 emulator entry point */
107                         if (!segment_eq(get_fs(), get_ds()))
108                                 return -EINVAL;
109                         return do_shmat (first, (char *) ptr, second, (ulong *) third);
110                 }
111         case SHMDT:
112                 return sys_shmdt ((char *)ptr);
113         case SHMGET:
114                 return sys_shmget (first, second, third);
115         case SHMCTL:
116                 return sys_shmctl (first, second,
117                                    (struct shmid_ds *) ptr);
118         default:
119                 return -ENOSYS;
120         }
121 }
122
123 long sys_sigaction(int sig, const struct old_sigaction __user *act,
124                          struct old_sigaction __user *oact)
125 {
126         struct k_sigaction new_ka, old_ka;
127         int ret;
128
129         if (act) {
130                 old_sigset_t mask;
131                 if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
132                     __get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
133                     __get_user(new_ka.sa.sa_restorer, &act->sa_restorer))
134                         return -EFAULT;
135                 __get_user(new_ka.sa.sa_flags, &act->sa_flags);
136                 __get_user(mask, &act->sa_mask);
137                 siginitset(&new_ka.sa.sa_mask, mask);
138         }
139
140         ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
141
142         if (!ret && oact) {
143                 if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
144                     __put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
145                     __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer))
146                         return -EFAULT;
147                 __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
148                 __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
149         }
150
151         return ret;
152 }