root/arch/sparc/kernel/sys_sunos.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. get_sparc_unmapped_area
  2. sunos_mmap
  3. sunos_mctl
  4. sunos_msync
  5. sunos_brk
  6. sunos_sbrk
  7. sunos_sstk
  8. sunos_vadvise
  9. sunos_madvise
  10. sunos_mincore
  11. sunos_getdtablesize
  12. sunos_sigblock
  13. sunos_filldir
  14. sunos_getdents
  15. sunos_getdomainname
  16. sunos_uname
  17. sunos_nosys
  18. sunos_fpathconf
  19. sunos_pathconf
  20. sunos_select
  21. sunos_nop
  22. sunos_nfs_get_server_fd
  23. get_default
  24. sunos_nfs_mount
  25. sunos_mount
  26. sunos_setpgrp
  27. sunos_wait4
  28. sunos_killpg
  29. sunos_audit

   1 /* $Id: sys_sunos.c,v 1.20 1995/11/25 00:58:37 davem Exp $
   2  * sys_sunos.c: SunOS specific syscall compatability support.
   3  *
   4  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
   5  * Copyright (C) 1995 Miguel de Icaza (miguel@nuclecu.unam.mx)
   6  *
   7  * Based upon preliminary work which is:
   8  *
   9  * Copyright (C) 1995 Adrian M. Rodriguez (adrian@remus.rutgers.edu)
  10  */
  11 
  12 #include <linux/kernel.h>
  13 #include <linux/sched.h>
  14 #include <linux/types.h>
  15 #include <linux/mman.h>
  16 #include <linux/errno.h>
  17 #include <linux/mm.h>
  18 #include <linux/fs.h>
  19 #include <linux/resource.h>
  20 #include <linux/signal.h>
  21 #include <linux/uio.h>
  22 #include <linux/utsname.h>
  23 #include <linux/fs.h>
  24 #include <linux/major.h>
  25 
  26 #include <asm/page.h>
  27 #include <asm/pgtable.h>
  28 #include <asm/pconf.h>
  29 
  30 /* For the nfs mount emulation */
  31 #include <linux/socket.h>
  32 #include <linux/in.h>
  33 #include <linux/nfs.h>
  34 #include <linux/nfs_mount.h>
  35 
  36 /* for sunos_select */
  37 #include <linux/time.h>
  38 #include <linux/personality.h>
  39 
  40 static unsigned long get_sparc_unmapped_area(unsigned long len)
     /* [previous][next][first][last][top][bottom][index][help] */
  41 {
  42         unsigned long addr;
  43         struct vm_area_struct * vmm;
  44 
  45         if (len > TASK_SIZE)
  46                 return 0;
  47         addr = 0xE8000000UL;    /* To make it work on a sun4c. */
  48         for (vmm = current->mm->mmap; ; vmm = vmm->vm_next) {
  49                 if (TASK_SIZE - len < addr)
  50                         return 0;
  51                 if (!vmm)
  52                         return addr;
  53                 if (addr > vmm->vm_end)
  54                         continue;
  55                 if (addr + len > vmm->vm_start) {
  56                         addr = vmm->vm_end;
  57                         continue;
  58                 }
  59                 return addr;
  60         }
  61 }
  62 
  63 /* We use the SunOS mmap() semantics. */
  64 asmlinkage unsigned long sunos_mmap(unsigned long addr, unsigned long len,
     /* [previous][next][first][last][top][bottom][index][help] */
  65                                     unsigned long prot, unsigned long flags,
  66                                     unsigned long fd, unsigned long off)
  67 {
  68         struct file * file = NULL;
  69         unsigned long retval, ret_type;
  70 
  71         if(flags & MAP_NORESERVE) {
  72                 printk("%s: unimplemented SunOS MAP_NORESERVE mmap() flag\n",
  73                        current->comm);
  74                 flags &= ~MAP_NORESERVE;
  75         }
  76         if(!(flags & MAP_ANONYMOUS))
  77                 if (fd >= NR_OPEN || !(file = current->files->fd[fd]))
  78                         return -EBADF;
  79         if(!(flags & MAP_FIXED) && !addr) {
  80                 addr = get_sparc_unmapped_area(len);
  81                 if(!addr)
  82                         return -ENOMEM;
  83         }
  84         /* If this is ld.so or a shared library doing an mmap
  85          * of /dev/zero, transform it into an anonymous mapping.
  86          * SunOS is so stupid some times... hmph!
  87          */
  88         if(MAJOR(file->f_inode->i_rdev) == MEM_MAJOR &&
  89            MINOR(file->f_inode->i_rdev) == 5) {
  90                 flags |= MAP_ANONYMOUS;
  91                 file = 0;
  92         }
  93         ret_type = flags & _MAP_NEW;
  94         flags &= ~_MAP_NEW;
  95         retval = do_mmap(file, addr, len, prot, flags, off);
  96         if(ret_type)
  97                 return retval;
  98         else
  99                 return ((retval < KERNBASE) ? 0 : retval);
 100 }
 101 
 102 /* Weird SunOS mm control function.. */
 103 asmlinkage int sunos_mctl(unsigned long addr, unsigned long len, int function, char *arg)
     /* [previous][next][first][last][top][bottom][index][help] */
 104 {
 105         printk("%s: Call to sunos_mctl(addr<%08lx>, len<%08lx>, function<%d>, arg<%p>) "
 106                "is unsupported\n", current->comm, addr, len, function, arg);
 107         return -EAGAIN;
 108 }
 109 
 110 /* XXX This won't be necessary when I sync up to never kernel in 1.3.x series
 111  * XXX which has the sys_msync() system call implemented properly.
 112  */
 113 asmlinkage int sunos_msync(unsigned long addr, unsigned long len, unsigned long flags)
     /* [previous][next][first][last][top][bottom][index][help] */
 114 {
 115         printk("%s: Call to sunos_msync(addr<%08lx>, len<%08lx>, flags<%08lx>) "
 116                "is unsupported\n", current->comm, addr, len, flags);
 117         return -EINVAL;
 118 }
 119 
 120 /* SunOS is completely broken... it returns 0 on success, otherwise
 121  * ENOMEM.  For sys_sbrk() it wants the new brk value as a return
 122  * on success and ENOMEM as before on failure.
 123  */
 124 asmlinkage int sunos_brk(unsigned long brk)
     /* [previous][next][first][last][top][bottom][index][help] */
 125 {
 126         int freepages;
 127         unsigned long rlim;
 128         unsigned long newbrk, oldbrk;
 129 
 130         if (brk < current->mm->end_code)
 131                 return -ENOMEM;
 132 
 133         newbrk = PAGE_ALIGN(brk);
 134         oldbrk = PAGE_ALIGN(current->mm->brk);
 135         if (oldbrk == newbrk) {
 136                 current->mm->brk = brk;
 137                 return 0;
 138         }
 139 
 140         /*
 141          * Always allow shrinking brk
 142          */
 143         if (brk <= current->mm->brk) {
 144                 current->mm->brk = brk;
 145                 do_munmap(newbrk, oldbrk-newbrk);
 146                 return 0;
 147         }
 148         /*
 149          * Check against rlimit and stack..
 150          */
 151         rlim = current->rlim[RLIMIT_DATA].rlim_cur;
 152         if (rlim >= RLIM_INFINITY)
 153                 rlim = ~0;
 154         if (brk - current->mm->end_code > rlim)
 155                 return -ENOMEM;
 156 
 157         /*
 158          * Check against existing mmap mappings.
 159          */
 160         if (find_vma_intersection(current, oldbrk, newbrk+PAGE_SIZE))
 161                 return -ENOMEM;
 162 
 163         /*
 164          * stupid algorithm to decide if we have enough memory: while
 165          * simple, it hopefully works in most obvious cases.. Easy to
 166          * fool it, but this should catch most mistakes.
 167          */
 168         freepages = buffermem >> 12;
 169         freepages += nr_free_pages;
 170         freepages += nr_swap_pages;
 171         freepages -= MAP_NR(high_memory) >> 4;
 172         freepages -= (newbrk-oldbrk) >> 12;
 173         if (freepages < 0)
 174                 return -ENOMEM;
 175         /*
 176          * Ok, we have probably got enough memory - let it rip.
 177          */
 178         current->mm->brk = brk;
 179         do_mmap(NULL, oldbrk, newbrk-oldbrk,
 180                 PROT_READ|PROT_WRITE|PROT_EXEC,
 181                 MAP_FIXED|MAP_PRIVATE, 0);
 182         return 0;
 183 }
 184 
 185 asmlinkage unsigned long sunos_sbrk(int increment)
     /* [previous][next][first][last][top][bottom][index][help] */
 186 {
 187         int error;
 188 
 189         /* This should do it hopefully... */
 190         error = sunos_brk(((int) current->mm->brk) + increment);
 191         if(error == 0)
 192                 return current->mm->brk;
 193         else
 194                 return error;
 195 }
 196 
 197 /* XXX Completely undocumented, and completely magic...
 198  * XXX I belive it is to increase the size of the stack by
 199  * XXX argument 'increment' and return the new end of stack
 200  * XXX area.  Wheee...
 201  */
 202 asmlinkage unsigned long sunos_sstk(int increment)
     /* [previous][next][first][last][top][bottom][index][help] */
 203 {
 204         printk("%s: Call to sunos_sstk(increment<%d>) is unsupported\n",
 205                current->comm, increment);
 206         return -1;
 207 }
 208 
 209 /* Give hints to the kernel as to what paging strategy to use...
 210  * Completely bogus, don't remind me.
 211  */
 212 #define VA_NORMAL     0 /* Normal vm usage expected */
 213 #define VA_ABNORMAL   1 /* Abnormal/random vm usage probable */
 214 #define VA_SEQUENTIAL 2 /* Accesses will be of a sequential nature */
 215 #define VA_INVALIDATE 3 /* Page table entries should be flushed ??? */
 216 static char *vstrings[] = {
 217         "VA_NORMAL",
 218         "VA_ABNORMAL",
 219         "VA_SEQUENTIAL",
 220         "VA_INVALIDATE",
 221 };
 222 
 223 asmlinkage void sunos_vadvise(unsigned long strategy)
     /* [previous][next][first][last][top][bottom][index][help] */
 224 {
 225         /* I wanna see who uses this... */
 226         printk("%s: Advises us to use %s paging strategy\n",
 227                current->comm,
 228                strategy <= 3 ? vstrings[strategy] : "BOGUS");
 229         return; /* We don't do diddly... */
 230 }
 231 
 232 /* Same as vadvise, and just as bogus, but for a range of virtual
 233  * process address space.
 234  */
 235 #define MADV_NORMAL      0 /* Nothing special... */
 236 #define MADV_RANDOM      1 /* I am emacs... */
 237 #define MADV_SEQUENTIAL  2 /* I am researcher code... */
 238 #define MADV_WILLNEED    3 /* Pages in this range will be needed */
 239 #define MADV_DONTNEED    4 /* Pages in this range won't be needed */
 240 
 241 static char *mstrings[] = {
 242         "MADV_NORMAL",
 243         "MADV_RANDOM",
 244         "MADV_SEQUENTIAL",
 245         "MADV_WILLNEED",
 246         "MADV_DONTNEED",
 247 };
 248 
 249 asmlinkage void sunos_madvise(unsigned long address, unsigned long len,
     /* [previous][next][first][last][top][bottom][index][help] */
 250                               unsigned long strategy)
 251 {
 252         /* I wanna see who uses this... */
 253         printk("%s: Advises us to use %s paging strategy for addr<%08lx> len<%08lx>\n",
 254                current->comm,
 255                strategy <= 4 ? mstrings[strategy] : "BOGUS",
 256                address, len);
 257         return; /* We don't do diddly... */
 258 }
 259 
 260 /* Places into character array, the status of all the pages in the passed
 261  * range from 'addr' to 'addr + len'.  -1 on failure, 0 on success...
 262  * The encoding in each character is:
 263  * low-bit is zero == Page is not in physical ram right now
 264  * low-bit is one  == Page is currently residing in core
 265  * All other bits are undefined within the character so there...
 266  * Also, if you try to get stats on an area outside of the user vm area
 267  * *or* the passed base address is not aligned on a page boundry you
 268  * get an error.
 269  */
 270 asmlinkage int sunos_mincore(unsigned long addr, unsigned long len, char *array)
     /* [previous][next][first][last][top][bottom][index][help] */
 271 {
 272         pgd_t *pgdp;
 273         pmd_t *pmdp;
 274         pte_t *ptep;
 275         unsigned long limit;
 276         int num_pages, pnum;
 277 
 278         if(addr & (PAGE_SIZE - 1))
 279                 return -EINVAL;
 280 
 281         num_pages = (len / PAGE_SIZE);
 282         if(verify_area(VERIFY_WRITE, array, num_pages))
 283                 return -EFAULT; /* bum array, you lose... */
 284         if((addr >= KERNBASE) || ((addr + len) > KERNBASE))
 285                 return -ENOMEM; /* I'm sure you're curious about kernel mappings.. */
 286 
 287         /* Wheee, go through pte's */
 288         pnum = 0;
 289         for(limit = addr + len; addr < limit; addr += PAGE_SIZE, pnum++) {
 290                 pgdp = pgd_offset(current->mm, addr);
 291                 if(pgd_none(*pgdp))
 292                         return -ENOMEM; /* As per SunOS manpage */
 293                 pmdp = pmd_offset(pgdp, addr);
 294                 if(pmd_none(*pmdp))
 295                         return -ENOMEM; /* As per SunOS manpage */
 296                 ptep = pte_offset(pmdp, addr);
 297                 if(pte_none(*ptep))
 298                         return -ENOMEM; /* As per SunOS manpage */
 299                 /* Page in core or Swapped page? */
 300                 array[pnum] = pte_present(*ptep) ? 1 : 0;
 301         }
 302         return 0; /* Success... I think... */
 303 }
 304 
 305 /* This just wants the soft limit (ie. rlim_cur element) of the RLIMIT_NOFILE
 306  * resource limit and is for backwards compatability with older sunos
 307  * revs.
 308  */
 309 asmlinkage long sunos_getdtablesize(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 310 {
 311         return NR_OPEN;
 312 }
 313 #define _S(nr) (1<<((nr)-1))
 314 
 315 #define _BLOCKABLE (~(_S(SIGKILL) | _S(SIGSTOP)))
 316 
 317 asmlinkage unsigned long sunos_sigblock(unsigned long blk_mask)
     /* [previous][next][first][last][top][bottom][index][help] */
 318 {
 319         unsigned long old = current->blocked;
 320 
 321         current->blocked |= (blk_mask & _BLOCKABLE);
 322         return old;
 323 }
 324 
 325 /* SunOS getdents is very similar to the newer Linux (iBCS2 compliant)    */
 326 /* getdents system call, the format of the structure just has a different */
 327 /* layout (d_off+d_ino instead of d_ino+d_off) */
 328 struct sunos_dirent {
 329     long           d_off;
 330     unsigned long  d_ino;
 331     unsigned short d_reclen;
 332     unsigned short d_namlen;
 333     char           d_name[1];
 334 };
 335 
 336 struct sunos_dirent_callback {
 337     struct sunos_dirent *curr;
 338     struct sunos_dirent *previous;
 339     int count;
 340     int error;
 341 };
 342 
 343 #define NAME_OFFSET(de) ((int) ((de)->d_name - (char *) (de)))
 344 #define ROUND_UP(x) (((x)+sizeof(long)-1) & ~(sizeof(long)-1))
 345 
 346 static int sunos_filldir(void * __buf, const char * name, int namlen,
     /* [previous][next][first][last][top][bottom][index][help] */
 347                          off_t offset, ino_t ino)
 348 {
 349         struct sunos_dirent * dirent;
 350         struct sunos_dirent_callback * buf = (struct sunos_dirent_callback *) __buf;
 351         int reclen = ROUND_UP(NAME_OFFSET(dirent) + namlen + 1);
 352 
 353         buf->error = -EINVAL;   /* only used if we fail.. */
 354         if (reclen > buf->count)
 355                 return -EINVAL;
 356         dirent = buf->previous;
 357         if (dirent)
 358                 put_user(offset, &dirent->d_off);
 359         dirent = buf->curr;
 360         buf->previous = dirent;
 361         put_user(ino, &dirent->d_ino);
 362         put_user((strlen(name)), &dirent->d_namlen);
 363         put_user(reclen, &dirent->d_reclen);
 364         memcpy_tofs(dirent->d_name, name, namlen);
 365         put_user(0, dirent->d_name + namlen);
 366         ((char *) dirent) += reclen;
 367         buf->curr = dirent;
 368         buf->count -= reclen;
 369         return 0;
 370 }
 371 
 372 asmlinkage int sunos_getdents(unsigned int fd, void * dirent, int cnt)
     /* [previous][next][first][last][top][bottom][index][help] */
 373 {
 374         struct file * file;
 375         struct sunos_dirent * lastdirent;
 376         struct sunos_dirent_callback buf;
 377         int error;
 378 
 379         if (fd >= NR_OPEN || !(file = current->files->fd[fd]))
 380                 return -EBADF;
 381         if (!file->f_op || !file->f_op->readdir)
 382                 return -ENOTDIR;
 383         if(verify_area(VERIFY_WRITE, dirent, cnt))
 384                 return -EFAULT;
 385         if(cnt < (sizeof(struct sunos_dirent) + 255))
 386                 return -EINVAL;
 387 
 388         buf.curr = (struct sunos_dirent *) dirent;
 389         buf.previous = NULL;
 390         buf.count = cnt;
 391         buf.error = 0;
 392         error = file->f_op->readdir(file->f_inode, file, &buf, sunos_filldir);
 393         if (error < 0)
 394                 return error;
 395         lastdirent = buf.previous;
 396         if (!lastdirent)
 397                 return buf.error;
 398         put_user(file->f_pos, &lastdirent->d_off);
 399         return cnt - buf.count;
 400 }
 401 
 402 asmlinkage int sunos_getdomainname(char *name, int len)
     /* [previous][next][first][last][top][bottom][index][help] */
 403 {
 404         int error;
 405 
 406         if(len > __NEW_UTS_LEN)
 407                 return -EFAULT;
 408         error = verify_area(VERIFY_WRITE, name, len);
 409         if(error)
 410                 return -EFAULT;
 411         memcpy_tofs(name, system_utsname.domainname, len);
 412         return 0;
 413 }
 414 
 415 struct sunos_utsname {
 416         char sname[9];
 417         char nname[9];
 418         char nnext[56];
 419         char rel[9];
 420         char ver[9];
 421         char mach[9];
 422 };
 423 
 424 asmlinkage int sunos_uname(struct sunos_utsname *name)
     /* [previous][next][first][last][top][bottom][index][help] */
 425 {
 426         int error;
 427         if(!name)
 428                 return -EFAULT;
 429         error = verify_area(VERIFY_WRITE, name, sizeof *name);
 430         if(error)
 431                 return error;
 432         memcpy_tofs(&name->sname[0], &system_utsname.sysname[0],
 433                     sizeof(name->sname));
 434         memcpy_tofs(&name->nname[0], &system_utsname.nodename[0],
 435                     sizeof(name->nname));
 436         name->nname[8] = '\0';
 437         memcpy_tofs(&name->nnext[0], &system_utsname.nodename[9],
 438                     sizeof(name->nnext));
 439         memcpy_tofs(&name->rel[0], &system_utsname.release[0],
 440                     sizeof(name->rel));
 441         memcpy_tofs(&name->ver[0], &system_utsname.version[0],
 442                     sizeof(name->ver));
 443         memcpy_tofs(&name->mach[0], &system_utsname.machine[0],
 444                     sizeof(name->mach));
 445         return 0;
 446 }
 447 
 448 asmlinkage int sunos_nosys(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 449 {
 450         struct pt_regs *regs;
 451 
 452         regs = (struct pt_regs *) (((current->tss.ksp) & PAGE_MASK) +
 453                                    (PAGE_SIZE - TRACEREG_SZ));
 454         current->tss.sig_address = regs->pc;
 455         current->tss.sig_desc = regs->u_regs[UREG_G1];
 456         send_sig(SIGSYS, current, 1);
 457         printk("Process makes ni_syscall number %d, register dump:\n",
 458                (int) regs->u_regs[UREG_G1]);
 459         show_regs(regs);
 460         return -ENOSYS;
 461 }
 462 
 463 /* This is not a real and complete implementation yet, just to keep
 464  * the easy SunOS binaries happy.
 465  */
 466 asmlinkage int sunos_fpathconf(int fd, int name)
     /* [previous][next][first][last][top][bottom][index][help] */
 467 {
 468         switch(name) {
 469         case _PCONF_LINK:
 470                 return LINK_MAX;
 471         case _PCONF_CANON:
 472                 return MAX_CANON;
 473         case _PCONF_INPUT:
 474                 return MAX_INPUT;
 475         case _PCONF_NAME:
 476                 return NAME_MAX;
 477         case _PCONF_PATH:
 478                 return PATH_MAX;
 479         case _PCONF_PIPE:
 480                 return PIPE_BUF;
 481         case _PCONF_CHRESTRICT:
 482                 return 1; /* XXX Investigate XXX */
 483         case _PCONF_NOTRUNC:
 484                 return 0; /* XXX Investigate XXX */
 485         case _PCONF_VDISABLE:
 486                 return 30; /* XXX Investigate XXX */
 487         default:
 488                 return -EINVAL;
 489         }
 490 }
 491 
 492 asmlinkage int sunos_pathconf(char *path, int name)
     /* [previous][next][first][last][top][bottom][index][help] */
 493 {
 494         return sunos_fpathconf(0, name); /* XXX cheese XXX */
 495 }
 496 
 497 /* SunOS mount system call emulation */
 498 extern asmlinkage int
 499 sys_select(int n, fd_set *inp, fd_set *outp, fd_set *exp, struct timeval *tvp);
 500 
 501 asmlinkage int sunos_select(int width, fd_set *inp, fd_set *outp, fd_set *exp, struct timeval *tvp)
     /* [previous][next][first][last][top][bottom][index][help] */
 502 {
 503     /* SunOS binaries expect that select won't change the tvp contents */
 504     current->personality |= STICKY_TIMEOUTS;
 505     return sys_select (width, inp, outp, exp, tvp);
 506 }
 507 
 508 asmlinkage void sunos_nop(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 509 {
 510         return;
 511 }
 512 
 513 /* SunOS mount/umount. */
 514 #define SMNT_RDONLY       1
 515 #define SMNT_NOSUID       2
 516 #define SMNT_NEWTYPE      4
 517 #define SMNT_GRPID        8
 518 #define SMNT_REMOUNT      16
 519 #define SMNT_NOSUB        32
 520 #define SMNT_MULTI        64
 521 #define SMNT_SYS5         128
 522 
 523 struct ufs_mntargs {
 524         char *dev_name;
 525 };
 526 
 527 struct lo_mntargs {
 528         char *dev_name;
 529 };
 530 
 531 struct ext2_mntargs {
 532         char *dev_name;
 533 };
 534 
 535 struct iso9660_mntargs {
 536         char *dev_name;
 537 };
 538 
 539 struct minix_mntargs {
 540         char *dev_name;
 541 };
 542 
 543 struct ext_mntargs {
 544         char *dev_name;
 545 };
 546 
 547 struct msdos_mntargs {
 548         char *dev_name;
 549 };
 550 
 551 struct xiafs_mntargs {
 552         char *dev_name;
 553 };
 554 
 555 struct sunos_fh_t {
 556         char fh_data [NFS_FHSIZE];
 557 };
 558 
 559 struct sunos_nfs_mount_args {
 560         struct sockaddr_in  *addr; /* file server address */
 561         struct nfs_fh *fh;     /* File handle to be mounted */
 562         int        flags;      /* flags */
 563         int        wsize;      /* write size in bytes */
 564         int        rsize;      /* read size in bytes */
 565         int        timeo;      /* initial timeout in .1 secs */
 566         int        retrans;    /* times to retry send */
 567         char       *hostname;  /* server's hostname */
 568         int        acregmin;   /* attr cache file min secs */
 569         int        acregmax;   /* attr cache file max secs */
 570         int        acdirmin;   /* attr cache dir min secs */
 571         int        acdirmax;   /* attr cache dir max secs */
 572         char       *netname;   /* server's netname */
 573 };
 574 
 575 extern asmlinkage int sys_mount(char *, char *, char *, unsigned long, void *);
 576 
 577 extern int do_mount(dev_t, const char *, char *, int, void *);
 578 extern dev_t get_unnamed_dev(void);
 579 extern void put_unnamed_dev(dev_t);
 580 
 581 extern sys_mount (char * dev_name, char * dir_name, char * type,
 582                   unsigned long new_flags, void * data);
 583 
 584 extern asmlinkage int
 585 sys_connect(int fd, struct sockaddr *uservaddr, int addrlen);
 586 
 587 extern asmlinkage int
 588 sys_socket(int family, int type, int protocol);
 589 
 590 asmlinkage int
 591 sys_bind(int fd, struct sockaddr *umyaddr, int addrlen);
 592 
 593 
 594 /* Bind the socket on a local reserved port and connect it to the
 595  * remote server.  This on Linux/i386 is done by the mount program,
 596  * not by the kernel. 
 597  */
 598 static int
 599 sunos_nfs_get_server_fd (int fd, struct sockaddr_in *addr)
     /* [previous][next][first][last][top][bottom][index][help] */
 600 {
 601         struct sockaddr_in local;
 602         struct sockaddr_in server;
 603         int    try_port;
 604         int    ret;
 605         struct socket *socket;
 606         struct inode  *inode;
 607         struct file   *file;
 608 
 609         file = current->files->fd [fd];
 610         inode = file->f_inode;
 611         if (!inode || !inode->i_sock)
 612                 return 0;
 613 
 614         socket = &inode->u.socket_i;
 615         local.sin_family = AF_INET;
 616         local.sin_addr.s_addr = INADDR_ANY;
 617 
 618         /* IPPORT_RESERVED = 1024, can't find the definition in the kernel */
 619         try_port = 1024;
 620         do {
 621                 local.sin_port = htons (--try_port);
 622                 ret = socket->ops->bind(socket, (struct sockaddr*)&local,
 623                                         sizeof(local));
 624         } while (ret && try_port > (1024 / 2));
 625 
 626         if (ret)
 627                 return 0;
 628 
 629         server.sin_family = AF_INET;
 630         server.sin_addr = addr->sin_addr;
 631         server.sin_port = NFS_PORT;
 632 
 633         /* Call sys_connect */
 634         ret = socket->ops->connect (socket, (struct sockaddr *) &server,
 635                                     sizeof (server), file->f_flags);
 636         if (ret < 0)
 637                 return 0;
 638         return 1;
 639 }
 640 
 641 static int get_default (int value, int def_value)
     /* [previous][next][first][last][top][bottom][index][help] */
 642 {
 643     if (value)
 644         return value;
 645     else
 646         return def_value;
 647 }
 648 
 649 asmlinkage int sunos_nfs_mount(char *dir_name, int linux_flags, void *data)
     /* [previous][next][first][last][top][bottom][index][help] */
 650 {
 651         int  ret = -ENODEV, error;
 652         int  server_fd;
 653         char *the_name;
 654         struct nfs_mount_data linux_nfs_mount;
 655         struct sunos_nfs_mount_args *sunos_mount = data;
 656         dev_t dev;
 657         struct pt_regs *regs;
 658 
 659         error = verify_area(VERIFY_READ, data, sizeof (struct sunos_nfs_mount_args));
 660         if (error)
 661                 return error;
 662         /* Ok, here comes the fun part: Linux's nfs mount needs a
 663          * socket connection to the server, but SunOS mount does not
 664          * requiere this, so we use the information on the destination
 665          * address to create a socket and bind it to a reserved
 666          * port on this system
 667          */
 668         server_fd = sys_socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP);
 669         if (server_fd < 0)
 670                 return -ENXIO;
 671 
 672         if (!sunos_nfs_get_server_fd (server_fd, sunos_mount->addr)){
 673                 sys_close (server_fd);
 674                 return -ENXIO;
 675         }
 676 
 677         /* Now, bind it to a locally reserved port */
 678         linux_nfs_mount.version  = NFS_MOUNT_VERSION;
 679         linux_nfs_mount.flags    = sunos_mount->flags;
 680         linux_nfs_mount.addr     = *sunos_mount->addr;
 681         linux_nfs_mount.root     = *sunos_mount->fh;
 682         linux_nfs_mount.fd       = server_fd;
 683         
 684         linux_nfs_mount.rsize    = get_default (sunos_mount->rsize, 8192);
 685         linux_nfs_mount.wsize    = get_default (sunos_mount->wsize, 8192);
 686         linux_nfs_mount.timeo    = get_default (sunos_mount->timeo, 10);
 687         linux_nfs_mount.retrans  = sunos_mount->retrans;
 688         
 689         linux_nfs_mount.acregmin = sunos_mount->acregmin;
 690         linux_nfs_mount.acregmax = sunos_mount->acregmax;
 691         linux_nfs_mount.acdirmin = sunos_mount->acdirmin;
 692         linux_nfs_mount.acdirmax = sunos_mount->acdirmax;
 693 
 694         if (getname (sunos_mount->hostname, &the_name))
 695                 return -EFAULT;
 696 
 697         strncpy (linux_nfs_mount.hostname, the_name, 254);
 698         linux_nfs_mount.hostname [255] = 0;
 699         putname (the_name);
 700 
 701         dev = get_unnamed_dev ();
 702         
 703         ret = do_mount (dev, dir_name, "nfs", linux_flags, &linux_nfs_mount);
 704         if (ret)
 705             put_unnamed_dev(dev);
 706 
 707 #if 0
 708         /* Kill the process: the nfs directory is already mounted */
 709         regs = (struct pt_regs *) (((current->tss.ksp) & PAGE_MASK) +
 710                                    (PAGE_SIZE - TRACEREG_SZ));
 711         current->tss.sig_address = regs->pc;
 712         current->tss.sig_desc = regs->u_regs[UREG_G1];
 713         send_sig(SIGSYS, current, 1);
 714 #endif
 715         return ret;
 716 }
 717 
 718 asmlinkage int
 719 sunos_mount(char *type, char *dir, int flags, void *data)
     /* [previous][next][first][last][top][bottom][index][help] */
 720 {
 721         int linux_flags = MS_MGC_MSK; /* new semantics */
 722         int error;
 723         char *dev_fname = 0;
 724 
 725         /* We don't handle the integer fs type */
 726         if ((flags & SMNT_NEWTYPE) == 0)
 727                 return -EINVAL;
 728 
 729         /* Do not allow for those flags we don't support */
 730         if (flags & (SMNT_GRPID|SMNT_NOSUB|SMNT_MULTI|SMNT_SYS5))
 731                 return -EINVAL;
 732 
 733         if(flags & SMNT_REMOUNT)
 734                 linux_flags |= MS_REMOUNT;
 735         if(flags & SMNT_RDONLY)
 736                 linux_flags |= MS_RDONLY;
 737         if(flags & SMNT_NOSUID)
 738                 linux_flags |= MS_NOSUID;
 739         error = verify_area(VERIFY_READ, type, 16);
 740         if(error)
 741                 return error;
 742         if(strcmp(type, "ext2") == 0) {
 743                 dev_fname = (char *) data;;
 744         } else if(strcmp(type, "iso9660") == 0) {
 745                 dev_fname = (char *) data;
 746         } else if(strcmp(type, "minix") == 0) {
 747                 dev_fname = (char *) data;
 748         } else if(strcmp(type, "ext") == 0) {
 749                 dev_fname = (char *) data;
 750         } else if(strcmp(type, "xiafs") == 0) {
 751                 dev_fname = (char *) data;
 752         } else if(strcmp(type, "nfs") == 0) {
 753                 error = sunos_nfs_mount (dir, flags, data);
 754                 return error;
 755         } else if(strcmp(type, "ufs") == 0) {
 756                 printk("Warning: UFS filesystem mounts unsupported.\n");
 757                 return -ENODEV;
 758         } else if(strcmp(type, "proc")) {
 759                 return -ENODEV;
 760         }
 761         if(error)
 762                 return error;
 763         error = sys_mount(dev_fname, dir, type, linux_flags, NULL);
 764         printk("sys_mount(type<%s>, device<%s>) returns %d\n",
 765                type, dev_fname, error);
 766         return error;
 767 }
 768 
 769 extern asmlinkage int sys_setsid(void);
 770 extern asmlinkage int sys_setpgid(pid_t, pid_t);
 771 
 772 asmlinkage int sunos_setpgrp(pid_t pid, pid_t pgid)
     /* [previous][next][first][last][top][bottom][index][help] */
 773 {
 774         /* So stupid... */
 775         if((!pid || pid == current->pid) &&
 776            !pgid) {
 777                 sys_setsid();
 778                 return 0;
 779         } else {
 780                 return sys_setpgid(pid, pgid);
 781         }
 782 }
 783 
 784 /* So stupid... */
 785 extern asmlinkage int sys_wait4(pid_t, unsigned int *, int, struct rusage *);
 786 asmlinkage int sunos_wait4(pid_t pid, unsigned int *stat_addr, int options, struct rusage *ru)
     /* [previous][next][first][last][top][bottom][index][help] */
 787 {
 788         return sys_wait4((pid ? pid : -1), stat_addr, options, ru);
 789 }
 790 
 791 extern int kill_pg(int, int, int);
 792 asmlinkage int sunos_killpg(int pgrp, int sig)
     /* [previous][next][first][last][top][bottom][index][help] */
 793 {
 794         return kill_pg(pgrp, sig, 0);
 795 }
 796 
 797 extern asmlinkage sunos_audit ()
     /* [previous][next][first][last][top][bottom][index][help] */
 798 {
 799         printk ("sys_audit\n");
 800         return -1;
 801 }

/* [previous][next][first][last][top][bottom][index][help] */