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_brk
  5. sunos_sbrk
  6. sunos_sstk
  7. sunos_vadvise
  8. sunos_madvise
  9. sunos_mincore
  10. sunos_getdtablesize
  11. sunos_sigblock
  12. sunos_sigsetmask
  13. sunos_filldir
  14. sunos_getdents
  15. sunos_filldirentry
  16. sunos_getdirentries
  17. sunos_getdomainname
  18. sunos_uname
  19. sunos_nosys
  20. sunos_fpathconf
  21. sunos_pathconf
  22. sunos_select
  23. sunos_nop
  24. sunos_nfs_get_server_fd
  25. get_default
  26. sunos_nfs_mount
  27. sunos_mount
  28. sunos_setpgrp
  29. sunos_wait4
  30. sunos_killpg
  31. sunos_audit
  32. sunos_gethostid
  33. sunos_sysconf

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

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