linux/arch/um/sys-i386/syscalls.c
<<
>>
Prefs
   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 * Perform the select(nd, in, out, ex, tv) and mmap() system
  16 * calls. Linux/i386 didn't use to be able to handle more than
  17 * 4 system call parameters, so these system calls used a memory
  18 * block for parameter passing..
  19 */
  20
  21struct mmap_arg_struct {
  22        unsigned long addr;
  23        unsigned long len;
  24        unsigned long prot;
  25        unsigned long flags;
  26        unsigned long fd;
  27        unsigned long offset;
  28};
  29
  30extern int old_mmap(unsigned long addr, unsigned long len,
  31                    unsigned long prot, unsigned long flags,
  32                    unsigned long fd, unsigned long offset);
  33
  34long old_mmap_i386(struct mmap_arg_struct __user *arg)
  35{
  36        struct mmap_arg_struct a;
  37        int err = -EFAULT;
  38
  39        if (copy_from_user(&a, arg, sizeof(a)))
  40                goto out;
  41
  42        err = old_mmap(a.addr, a.len, a.prot, a.flags, a.fd, a.offset);
  43 out:
  44        return err;
  45}
  46
  47struct sel_arg_struct {
  48        unsigned long n;
  49        fd_set __user *inp;
  50        fd_set __user *outp;
  51        fd_set __user *exp;
  52        struct timeval __user *tvp;
  53};
  54
  55long old_select(struct sel_arg_struct __user *arg)
  56{
  57        struct sel_arg_struct a;
  58
  59        if (copy_from_user(&a, arg, sizeof(a)))
  60                return -EFAULT;
  61        /* sys_select() does the appropriate kernel locking */
  62        return sys_select(a.n, a.inp, a.outp, a.exp, a.tvp);
  63}
  64
  65/*
  66 * The prototype on i386 is:
  67 *
  68 *     int clone(int flags, void * child_stack, int * parent_tidptr, struct user_desc * newtls, int * child_tidptr)
  69 *
  70 * and the "newtls" arg. on i386 is read by copy_thread directly from the
  71 * register saved on the stack.
  72 */
  73long sys_clone(unsigned long clone_flags, unsigned long newsp,
  74               int __user *parent_tid, void *newtls, int __user *child_tid)
  75{
  76        long ret;
  77
  78        if (!newsp)
  79                newsp = UPT_SP(&current->thread.regs.regs);
  80
  81        current->thread.forking = 1;
  82        ret = do_fork(clone_flags, newsp, &current->thread.regs, 0, parent_tid,
  83                      child_tid);
  84        current->thread.forking = 0;
  85        return ret;
  86}
  87
  88/*
  89 * sys_ipc() is the de-multiplexer for the SysV IPC calls..
  90 *
  91 * This is really horribly ugly.
  92 */
  93long sys_ipc (uint call, int first, int second,
  94             int third, void __user *ptr, long fifth)
  95{
  96        int version, ret;
  97
  98        version = call >> 16; /* hack for backward compatibility */
  99        call &= 0xffff;
 100
 101        switch (call) {
 102        case SEMOP:
 103                return sys_semtimedop(first, (struct sembuf __user *) ptr,
 104                                      second, NULL);
 105        case SEMTIMEDOP:
 106                return sys_semtimedop(first, (struct sembuf __user *) ptr,
 107                                      second,
 108                                      (const struct timespec __user *) fifth);
 109        case SEMGET:
 110                return sys_semget (first, second, third);
 111        case SEMCTL: {
 112                union semun fourth;
 113                if (!ptr)
 114                        return -EINVAL;
 115                if (get_user(fourth.__pad, (void __user * __user *) ptr))
 116                        return -EFAULT;
 117                return sys_semctl (first, second, third, fourth);
 118        }
 119
 120        case MSGSND:
 121                return sys_msgsnd (first, (struct msgbuf *) ptr,
 122                                   second, third);
 123        case MSGRCV:
 124                switch (version) {
 125                case 0: {
 126                        struct ipc_kludge tmp;
 127                        if (!ptr)
 128                                return -EINVAL;
 129
 130                        if (copy_from_user(&tmp,
 131                                           (struct ipc_kludge *) ptr,
 132                                           sizeof (tmp)))
 133                                return -EFAULT;
 134                        return sys_msgrcv (first, tmp.msgp, second,
 135                                           tmp.msgtyp, third);
 136                }
 137                default:
 138                        panic("msgrcv with version != 0");
 139                        return sys_msgrcv (first,
 140                                           (struct msgbuf *) ptr,
 141                                           second, fifth, third);
 142                }
 143        case MSGGET:
 144                return sys_msgget ((key_t) first, second);
 145        case MSGCTL:
 146                return sys_msgctl (first, second, (struct msqid_ds *) ptr);
 147
 148        case SHMAT:
 149                switch (version) {
 150                default: {
 151                        ulong raddr;
 152                        ret = do_shmat (first, (char *) ptr, second, &raddr);
 153                        if (ret)
 154                                return ret;
 155                        return put_user (raddr, (ulong *) third);
 156                }
 157                case 1: /* iBCS2 emulator entry point */
 158                        if (!segment_eq(get_fs(), get_ds()))
 159                                return -EINVAL;
 160                        return do_shmat (first, (char *) ptr, second, (ulong *) third);
 161                }
 162        case SHMDT:
 163                return sys_shmdt ((char *)ptr);
 164        case SHMGET:
 165                return sys_shmget (first, second, third);
 166        case SHMCTL:
 167                return sys_shmctl (first, second,
 168                                   (struct shmid_ds *) ptr);
 169        default:
 170                return -ENOSYS;
 171        }
 172}
 173
 174long sys_sigaction(int sig, const struct old_sigaction __user *act,
 175                         struct old_sigaction __user *oact)
 176{
 177        struct k_sigaction new_ka, old_ka;
 178        int ret;
 179
 180        if (act) {
 181                old_sigset_t mask;
 182                if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
 183                    __get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
 184                    __get_user(new_ka.sa.sa_restorer, &act->sa_restorer))
 185                        return -EFAULT;
 186                __get_user(new_ka.sa.sa_flags, &act->sa_flags);
 187                __get_user(mask, &act->sa_mask);
 188                siginitset(&new_ka.sa.sa_mask, mask);
 189        }
 190
 191        ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
 192
 193        if (!ret && oact) {
 194                if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
 195                    __put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
 196                    __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer))
 197                        return -EFAULT;
 198                __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
 199                __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
 200        }
 201
 202        return ret;
 203}
 204