Import 2.3.10pre5
[davej-history.git] / arch / sparc64 / kernel / sys_sunos32.c
blob8b01df62d8a87e1a1527889a68b75a9a2ba42706
1 /* $Id: sys_sunos32.c,v 1.28 1999/06/29 12:34:04 davem Exp $
2 * sys_sunos32.c: SunOS binary compatability layer on sparc64.
4 * Copyright (C) 1995, 1996, 1997 David S. Miller (davem@caip.rutgers.edu)
5 * Copyright (C) 1995 Miguel de Icaza (miguel@nuclecu.unam.mx)
7 * Based upon preliminary work which is:
9 * Copyright (C) 1995 Adrian M. Rodriguez (adrian@remus.rutgers.edu)
12 #include <linux/kernel.h>
13 #include <linux/sched.h>
14 #include <linux/types.h>
15 #include <linux/mman.h>
16 #include <linux/mm.h>
17 #include <linux/swap.h>
18 #include <linux/fs.h>
19 #include <linux/file.h>
20 #include <linux/resource.h>
21 #include <linux/ipc.h>
22 #include <linux/shm.h>
23 #include <linux/msg.h>
24 #include <linux/sem.h>
25 #include <linux/signal.h>
26 #include <linux/uio.h>
27 #include <linux/utsname.h>
28 #include <linux/major.h>
29 #include <linux/stat.h>
30 #include <linux/malloc.h>
31 #include <linux/pagemap.h>
32 #include <linux/errno.h>
33 #include <linux/smp.h>
34 #include <linux/smp_lock.h>
36 #include <asm/uaccess.h>
37 #include <asm/page.h>
38 #include <asm/pgtable.h>
39 #include <asm/pconf.h>
40 #include <asm/idprom.h> /* for gethostid() */
41 #include <asm/unistd.h>
42 #include <asm/system.h>
44 /* For the nfs mount emulation */
45 #include <linux/socket.h>
46 #include <linux/in.h>
47 #include <linux/nfs.h>
48 #include <linux/nfs_mount.h>
50 /* for sunos_select */
51 #include <linux/time.h>
52 #include <linux/personality.h>
54 /* Use this to get at 32-bit user passed pointers. */
55 #define A(__x) \
56 ({ unsigned long __ret; \
57 __asm__ ("srl %0, 0, %0" \
58 : "=r" (__ret) \
59 : "0" (__x)); \
60 __ret; \
63 #define SUNOS_NR_OPEN 256
65 asmlinkage u32 sunos_mmap(u32 addr, u32 len, u32 prot, u32 flags, u32 fd, u32 off)
67 struct file *file = NULL;
68 unsigned long retval, ret_type;
70 down(&current->mm->mmap_sem);
71 lock_kernel();
72 current->personality |= PER_BSD;
73 if(flags & MAP_NORESERVE) {
74 printk("%s: unimplemented SunOS MAP_NORESERVE mmap() flag\n",
75 current->comm);
76 flags &= ~MAP_NORESERVE;
78 retval = -EBADF;
79 if(!(flags & MAP_ANONYMOUS)) {
80 if(fd >= SUNOS_NR_OPEN)
81 goto out;
82 file = fget(fd);
83 if (!file)
84 goto out;
85 if (file->f_dentry && file->f_dentry->d_inode) {
86 struct inode * inode = file->f_dentry->d_inode;
87 if(MAJOR(inode->i_rdev) == MEM_MAJOR &&
88 MINOR(inode->i_rdev) == 5) {
89 flags |= MAP_ANONYMOUS;
90 fput(file);
91 file = NULL;
96 retval = -ENOMEM;
97 if(!(flags & MAP_FIXED) && !addr) {
98 unsigned long attempt = get_unmapped_area(addr, len);
99 if(!attempt || (attempt >= 0xf0000000UL))
100 goto out_putf;
101 addr = (u32) attempt;
103 if(!(flags & MAP_FIXED))
104 addr = 0;
105 ret_type = flags & _MAP_NEW;
106 flags &= ~_MAP_NEW;
108 flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
109 retval = do_mmap(file,
110 (unsigned long) addr, (unsigned long) len,
111 (unsigned long) prot, (unsigned long) flags,
112 (unsigned long) off);
113 if(!ret_type)
114 retval = ((retval < 0xf0000000) ? 0 : retval);
115 out_putf:
116 if (file)
117 fput(file);
118 out:
119 unlock_kernel();
120 up(&current->mm->mmap_sem);
121 return (u32) retval;
124 asmlinkage int sunos_mctl(u32 addr, u32 len, int function, u32 arg)
126 return 0;
129 asmlinkage int sunos_brk(u32 baddr)
131 int freepages, retval = -ENOMEM;
132 unsigned long rlim;
133 unsigned long newbrk, oldbrk, brk = (unsigned long) baddr;
135 down(&current->mm->mmap_sem);
136 if (brk < current->mm->end_code)
137 goto out;
138 newbrk = PAGE_ALIGN(brk);
139 oldbrk = PAGE_ALIGN(current->mm->brk);
140 retval = 0;
141 if (oldbrk == newbrk) {
142 current->mm->brk = brk;
143 goto out;
145 /* Always allow shrinking brk. */
146 if (brk <= current->mm->brk) {
147 current->mm->brk = brk;
148 do_munmap(newbrk, oldbrk-newbrk);
149 goto out;
151 /* Check against rlimit and stack.. */
152 retval = -ENOMEM;
153 rlim = current->rlim[RLIMIT_DATA].rlim_cur;
154 if (rlim >= RLIM_INFINITY)
155 rlim = ~0;
156 if (brk - current->mm->end_code > rlim)
157 goto out;
158 /* Check against existing mmap mappings. */
159 if (find_vma_intersection(current->mm, oldbrk, newbrk+PAGE_SIZE))
160 goto out;
161 /* stupid algorithm to decide if we have enough memory: while
162 * simple, it hopefully works in most obvious cases.. Easy to
163 * fool it, but this should catch most mistakes.
165 freepages = atomic_read(&buffermem) >> PAGE_SHIFT;
166 freepages += atomic_read(&page_cache_size);
167 freepages >>= 1;
168 freepages += nr_free_pages;
169 freepages += nr_swap_pages;
170 freepages -= num_physpages >> 4;
171 freepages -= (newbrk-oldbrk) >> PAGE_SHIFT;
172 if (freepages < 0)
173 goto out;
174 /* Ok, we have probably got enough memory - let it rip. */
175 current->mm->brk = brk;
176 do_brk(oldbrk, newbrk-oldbrk);
177 retval = 0;
178 out:
179 up(&current->mm->mmap_sem);
180 return retval;
183 asmlinkage u32 sunos_sbrk(int increment)
185 int error, oldbrk;
187 /* This should do it hopefully... */
188 lock_kernel();
189 oldbrk = (int)current->mm->brk;
190 error = sunos_brk(((int) current->mm->brk) + increment);
191 if(!error)
192 error = oldbrk;
193 unlock_kernel();
194 return error;
197 asmlinkage u32 sunos_sstk(int increment)
199 lock_kernel();
200 printk("%s: Call to sunos_sstk(increment<%d>) is unsupported\n",
201 current->comm, increment);
202 unlock_kernel();
203 return (u32)-1;
206 /* Give hints to the kernel as to what paging strategy to use...
207 * Completely bogus, don't remind me.
209 #define VA_NORMAL 0 /* Normal vm usage expected */
210 #define VA_ABNORMAL 1 /* Abnormal/random vm usage probable */
211 #define VA_SEQUENTIAL 2 /* Accesses will be of a sequential nature */
212 #define VA_INVALIDATE 3 /* Page table entries should be flushed ??? */
213 static char *vstrings[] = {
214 "VA_NORMAL",
215 "VA_ABNORMAL",
216 "VA_SEQUENTIAL",
217 "VA_INVALIDATE",
220 asmlinkage void sunos_vadvise(u32 strategy)
222 /* I wanna see who uses this... */
223 lock_kernel();
224 printk("%s: Advises us to use %s paging strategy\n",
225 current->comm,
226 strategy <= 3 ? vstrings[strategy] : "BOGUS");
227 unlock_kernel();
230 /* Same as vadvise, and just as bogus, but for a range of virtual
231 * process address space.
233 #define MADV_NORMAL 0 /* Nothing special... */
234 #define MADV_RANDOM 1 /* I am emacs... */
235 #define MADV_SEQUENTIAL 2 /* I am researcher code... */
236 #define MADV_WILLNEED 3 /* Pages in this range will be needed */
237 #define MADV_DONTNEED 4 /* Pages in this range won't be needed */
239 static char *mstrings[] = {
240 "MADV_NORMAL",
241 "MADV_RANDOM",
242 "MADV_SEQUENTIAL",
243 "MADV_WILLNEED",
244 "MADV_DONTNEED",
247 asmlinkage void sunos_madvise(u32 address, u32 len, u32 strategy)
249 /* I wanna see who uses this... */
250 lock_kernel();
251 printk("%s: Advises us to use %s paging strategy for addr<%08x> len<%08x>\n",
252 current->comm, strategy <= 4 ? mstrings[strategy] : "BOGUS",
253 address, len);
254 unlock_kernel();
257 /* Places into character array, the status of all the pages in the passed
258 * range from 'addr' to 'addr + len'. -1 on failure, 0 on success...
259 * The encoding in each character is:
260 * low-bit is zero == Page is not in physical ram right now
261 * low-bit is one == Page is currently residing in core
262 * All other bits are undefined within the character so there...
263 * Also, if you try to get stats on an area outside of the user vm area
264 * *or* the passed base address is not aligned on a page boundary you
265 * get an error.
267 asmlinkage int sunos_mincore(u32 __addr, u32 len, u32 u_array)
269 pgd_t *pgdp;
270 pmd_t *pmdp;
271 pte_t *ptep;
272 unsigned long limit, addr = (unsigned long)__addr;
273 int num_pages, pnum, retval = -EINVAL;
274 char *array = (char *)A(u_array);
276 lock_kernel();
277 if(addr & ~(4096))
278 goto out;
279 num_pages = (len / 4096);
280 retval = -EFAULT;
281 if(verify_area(VERIFY_WRITE, array, num_pages))
282 goto out;
283 retval = -ENOMEM;
284 if((addr >= 0xf0000000) || ((addr + len) > 0xf0000000))
285 goto out; /* I'm sure you're curious about kernel mappings.. */
286 /* Wheee, go through pte's */
287 pnum = 0;
288 for(limit = addr + len; addr < limit; addr += 4096, pnum++) {
289 pgdp = pgd_offset(current->mm, addr);
290 if(pgd_none(*pgdp))
291 goto out; /* As per SunOS manpage */
292 pmdp = pmd_offset(pgdp, addr);
293 if(pmd_none(*pmdp))
294 goto out; /* As per SunOS manpage */
295 ptep = pte_offset(pmdp, addr);
296 if(pte_none(*ptep))
297 goto out; /* As per SunOS manpage */
298 /* Page in core or Swapped page? */
299 __put_user((pte_present(*ptep) ? 1 : 0), &array[pnum]);
301 retval = 0; /* Success... I think... */
302 out:
303 unlock_kernel();
304 return retval;
307 /* This just wants the soft limit (ie. rlim_cur element) of the RLIMIT_NOFILE
308 * resource limit and is for backwards compatibility with older sunos
309 * revs.
311 asmlinkage int sunos_getdtablesize(void)
313 return SUNOS_NR_OPEN;
317 #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
319 asmlinkage u32 sunos_sigblock(u32 blk_mask)
321 u32 old;
323 spin_lock_irq(&current->sigmask_lock);
324 old = (u32) current->blocked.sig[0];
325 current->blocked.sig[0] |= (blk_mask & _BLOCKABLE);
326 spin_unlock_irq(&current->sigmask_lock);
327 return old;
330 asmlinkage u32 sunos_sigsetmask(u32 newmask)
332 u32 retval;
334 spin_lock_irq(&current->sigmask_lock);
335 retval = (u32) current->blocked.sig[0];
336 current->blocked.sig[0] = (newmask & _BLOCKABLE);
337 spin_unlock_irq(&current->sigmask_lock);
338 return retval;
341 /* SunOS getdents is very similar to the newer Linux (iBCS2 compliant) */
342 /* getdents system call, the format of the structure just has a different */
343 /* layout (d_off+d_ino instead of d_ino+d_off) */
344 struct sunos_dirent {
345 s32 d_off;
346 u32 d_ino;
347 u16 d_reclen;
348 u16 d_namlen;
349 char d_name[1];
352 struct sunos_dirent_callback {
353 struct sunos_dirent *curr;
354 struct sunos_dirent *previous;
355 int count;
356 int error;
359 #define NAME_OFFSET(de) ((int) ((de)->d_name - (char *) (de)))
360 #define ROUND_UP(x) (((x)+sizeof(s32)-1) & ~(sizeof(s32)-1))
362 static int sunos_filldir(void * __buf, const char * name, int namlen,
363 off_t offset, ino_t ino)
365 struct sunos_dirent * dirent;
366 struct sunos_dirent_callback * buf = (struct sunos_dirent_callback *) __buf;
367 int reclen = ROUND_UP(NAME_OFFSET(dirent) + namlen + 1);
369 buf->error = -EINVAL; /* only used if we fail.. */
370 if (reclen > buf->count)
371 return -EINVAL;
372 dirent = buf->previous;
373 if (dirent)
374 put_user(offset, &dirent->d_off);
375 dirent = buf->curr;
376 buf->previous = dirent;
377 put_user(ino, &dirent->d_ino);
378 put_user(namlen, &dirent->d_namlen);
379 put_user(reclen, &dirent->d_reclen);
380 copy_to_user(dirent->d_name, name, namlen);
381 put_user(0, dirent->d_name + namlen);
382 ((char *) dirent) += reclen;
383 buf->curr = dirent;
384 buf->count -= reclen;
385 return 0;
388 asmlinkage int sunos_getdents(unsigned int fd, u32 u_dirent, int cnt)
390 struct file * file;
391 struct inode * inode;
392 struct sunos_dirent * lastdirent;
393 struct sunos_dirent_callback buf;
394 int error = -EBADF;
395 void *dirent = (void *)A(u_dirent);
397 lock_kernel();
398 if(fd >= SUNOS_NR_OPEN)
399 goto out;
401 file = fget(fd);
402 if(!file)
403 goto out;
405 error = -ENOTDIR;
406 if (!file->f_op || !file->f_op->readdir)
407 goto out_putf;
409 error = -EINVAL;
410 if(cnt < (sizeof(struct sunos_dirent) + 255))
411 goto out_putf;
413 buf.curr = (struct sunos_dirent *) dirent;
414 buf.previous = NULL;
415 buf.count = cnt;
416 buf.error = 0;
418 inode = file->f_dentry->d_inode;
419 down(&inode->i_sem);
420 error = file->f_op->readdir(file, &buf, sunos_filldir);
421 up(&inode->i_sem);
422 if (error < 0)
423 goto out_putf;
425 lastdirent = buf.previous;
426 error = buf.error;
427 if (lastdirent) {
428 put_user(file->f_pos, &lastdirent->d_off);
429 error = cnt - buf.count;
432 out_putf:
433 fput(file);
434 out:
435 unlock_kernel();
436 return error;
439 /* Old sunos getdirentries, severely broken compatibility stuff here. */
440 struct sunos_direntry {
441 u32 d_ino;
442 u16 d_reclen;
443 u16 d_namlen;
444 char d_name[1];
447 struct sunos_direntry_callback {
448 struct sunos_direntry *curr;
449 struct sunos_direntry *previous;
450 int count;
451 int error;
454 static int sunos_filldirentry(void * __buf, const char * name, int namlen,
455 off_t offset, ino_t ino)
457 struct sunos_direntry * dirent;
458 struct sunos_direntry_callback * buf = (struct sunos_direntry_callback *) __buf;
459 int reclen = ROUND_UP(NAME_OFFSET(dirent) + namlen + 1);
461 buf->error = -EINVAL; /* only used if we fail.. */
462 if (reclen > buf->count)
463 return -EINVAL;
464 dirent = buf->previous;
465 dirent = buf->curr;
466 buf->previous = dirent;
467 put_user(ino, &dirent->d_ino);
468 put_user(namlen, &dirent->d_namlen);
469 put_user(reclen, &dirent->d_reclen);
470 copy_to_user(dirent->d_name, name, namlen);
471 put_user(0, dirent->d_name + namlen);
472 ((char *) dirent) += reclen;
473 buf->curr = dirent;
474 buf->count -= reclen;
475 return 0;
478 asmlinkage int sunos_getdirentries(unsigned int fd, u32 u_dirent,
479 int cnt, u32 u_basep)
481 void *dirent = (void *) A(u_dirent);
482 unsigned int *basep = (unsigned int *)A(u_basep);
483 struct file * file;
484 struct inode * inode;
485 struct sunos_direntry * lastdirent;
486 int error = -EBADF;
487 struct sunos_direntry_callback buf;
489 lock_kernel();
490 if(fd >= SUNOS_NR_OPEN)
491 goto out;
493 file = fget(fd);
494 if(!file)
495 goto out;
497 error = -ENOTDIR;
498 if (!file->f_op || !file->f_op->readdir)
499 goto out_putf;
501 error = -EINVAL;
502 if(cnt < (sizeof(struct sunos_direntry) + 255))
503 goto out_putf;
505 buf.curr = (struct sunos_direntry *) dirent;
506 buf.previous = NULL;
507 buf.count = cnt;
508 buf.error = 0;
510 inode = file->f_dentry->d_inode;
511 down(&inode->i_sem);
512 error = file->f_op->readdir(file, &buf, sunos_filldirentry);
513 up(&inode->i_sem);
514 if (error < 0)
515 goto out_putf;
517 lastdirent = buf.previous;
518 error = buf.error;
519 if (lastdirent) {
520 put_user(file->f_pos, basep);
521 error = cnt - buf.count;
524 out_putf:
525 fput(file);
526 out:
527 unlock_kernel();
528 return error;
531 struct sunos_utsname {
532 char sname[9];
533 char nname[9];
534 char nnext[56];
535 char rel[9];
536 char ver[9];
537 char mach[9];
540 asmlinkage int sunos_uname(struct sunos_utsname *name)
542 int ret;
544 down(&uts_sem);
545 ret = copy_to_user(&name->sname[0], &system_utsname.sysname[0], sizeof(name->sname) - 1);
546 ret |= copy_to_user(&name->nname[0], &system_utsname.nodename[0], sizeof(name->nname) - 1);
547 ret |= put_user('\0', &name->nname[8]);
548 ret |= copy_to_user(&name->rel[0], &system_utsname.release[0], sizeof(name->rel) - 1);
549 ret |= copy_to_user(&name->ver[0], &system_utsname.version[0], sizeof(name->ver) - 1);
550 ret |= copy_to_user(&name->mach[0], &system_utsname.machine[0], sizeof(name->mach) - 1);
551 up(&uts_sem);
552 return ret;
555 asmlinkage int sunos_nosys(void)
557 struct pt_regs *regs;
559 lock_kernel();
560 regs = current->tss.kregs;
561 current->tss.sig_address = regs->tpc;
562 current->tss.sig_desc = regs->u_regs[UREG_G1];
563 send_sig(SIGSYS, current, 1);
564 printk("Process makes ni_syscall number %d, register dump:\n",
565 (int) regs->u_regs[UREG_G1]);
566 show_regs(regs);
567 unlock_kernel();
568 return -ENOSYS;
571 /* This is not a real and complete implementation yet, just to keep
572 * the easy SunOS binaries happy.
574 asmlinkage int sunos_fpathconf(int fd, int name)
576 int ret;
578 lock_kernel();
579 switch(name) {
580 case _PCONF_LINK:
581 ret = LINK_MAX;
582 break;
583 case _PCONF_CANON:
584 ret = MAX_CANON;
585 break;
586 case _PCONF_INPUT:
587 ret = MAX_INPUT;
588 break;
589 case _PCONF_NAME:
590 ret = NAME_MAX;
591 break;
592 case _PCONF_PATH:
593 ret = PATH_MAX;
594 break;
595 case _PCONF_PIPE:
596 ret = PIPE_BUF;
597 break;
598 case _PCONF_CHRESTRICT: /* XXX Investigate XXX */
599 ret = 1;
600 break;
601 case _PCONF_NOTRUNC: /* XXX Investigate XXX */
602 case _PCONF_VDISABLE:
603 ret = 0;
604 break;
605 default:
606 ret = -EINVAL;
607 break;
609 unlock_kernel();
610 return ret;
613 asmlinkage int sunos_pathconf(u32 u_path, int name)
615 int ret;
617 lock_kernel();
618 ret = sunos_fpathconf(0, name); /* XXX cheese XXX */
619 unlock_kernel();
620 return ret;
623 /* SunOS mount system call emulation */
624 extern asmlinkage int
625 sys32_select(int n, u32 inp, u32 outp, u32 exp, u32 tvp);
627 struct timeval32
629 int tv_sec, tv_usec;
632 asmlinkage int sunos_select(int width, u32 inp, u32 outp, u32 exp, u32 tvp_x)
634 int ret;
636 /* SunOS binaries expect that select won't change the tvp contents */
637 lock_kernel();
638 current->personality |= STICKY_TIMEOUTS;
639 ret = sys32_select (width, inp, outp, exp, tvp_x);
640 if (ret == -EINTR && tvp_x) {
641 struct timeval32 *tvp = (struct timeval32 *)A(tvp_x);
642 time_t sec, usec;
644 __get_user(sec, &tvp->tv_sec);
645 __get_user(usec, &tvp->tv_usec);
646 if (sec == 0 && usec == 0)
647 ret = 0;
649 unlock_kernel();
650 return ret;
653 asmlinkage void sunos_nop(void)
655 return;
658 /* XXXXXXXXXX SunOS mount/umount. XXXXXXXXXXX */
659 #define SMNT_RDONLY 1
660 #define SMNT_NOSUID 2
661 #define SMNT_NEWTYPE 4
662 #define SMNT_GRPID 8
663 #define SMNT_REMOUNT 16
664 #define SMNT_NOSUB 32
665 #define SMNT_MULTI 64
666 #define SMNT_SYS5 128
668 struct sunos_fh_t {
669 char fh_data [NFS_FHSIZE];
672 struct sunos_nfs_mount_args {
673 struct sockaddr_in *addr; /* file server address */
674 struct nfs_fh *fh; /* File handle to be mounted */
675 int flags; /* flags */
676 int wsize; /* write size in bytes */
677 int rsize; /* read size in bytes */
678 int timeo; /* initial timeout in .1 secs */
679 int retrans; /* times to retry send */
680 char *hostname; /* server's hostname */
681 int acregmin; /* attr cache file min secs */
682 int acregmax; /* attr cache file max secs */
683 int acdirmin; /* attr cache dir min secs */
684 int acdirmax; /* attr cache dir max secs */
685 char *netname; /* server's netname */
688 extern int do_mount(kdev_t, const char *, const char *, char *, int, void *);
689 extern dev_t get_unnamed_dev(void);
690 extern void put_unnamed_dev(dev_t);
691 extern asmlinkage int sys_mount(char *, char *, char *, unsigned long, void *);
692 extern asmlinkage int sys_connect(int fd, struct sockaddr *uservaddr, int addrlen);
693 extern asmlinkage int sys_socket(int family, int type, int protocol);
694 extern asmlinkage int sys_bind(int fd, struct sockaddr *umyaddr, int addrlen);
697 /* Bind the socket on a local reserved port and connect it to the
698 * remote server. This on Linux/i386 is done by the mount program,
699 * not by the kernel.
701 /* XXXXXXXXXXXXXXXXXXXX */
702 static int
703 sunos_nfs_get_server_fd (int fd, struct sockaddr_in *addr)
705 struct sockaddr_in local;
706 struct sockaddr_in server;
707 int try_port;
708 int ret;
709 struct socket *socket;
710 struct dentry *dentry;
711 struct inode *inode;
712 struct file *file;
714 file = fcheck(fd);
715 if(!file)
716 return 0;
718 dentry = file->f_dentry;
719 if(!dentry)
720 return 0;
722 inode = dentry->d_inode;
723 if(!inode)
724 return 0;
726 socket = &inode->u.socket_i;
727 local.sin_family = AF_INET;
728 local.sin_addr.s_addr = INADDR_ANY;
730 /* IPPORT_RESERVED = 1024, can't find the definition in the kernel */
731 try_port = 1024;
732 do {
733 local.sin_port = htons (--try_port);
734 ret = socket->ops->bind(socket, (struct sockaddr*)&local,
735 sizeof(local));
736 } while (ret && try_port > (1024 / 2));
738 if (ret)
739 return 0;
741 server.sin_family = AF_INET;
742 server.sin_addr = addr->sin_addr;
743 server.sin_port = NFS_PORT;
745 /* Call sys_connect */
746 ret = socket->ops->connect (socket, (struct sockaddr *) &server,
747 sizeof (server), file->f_flags);
748 if (ret < 0)
749 return 0;
750 return 1;
753 /* XXXXXXXXXXXXXXXXXXXX */
754 static int get_default (int value, int def_value)
756 if (value)
757 return value;
758 else
759 return def_value;
762 /* XXXXXXXXXXXXXXXXXXXX */
763 asmlinkage int sunos_nfs_mount(char *dir_name, int linux_flags, void *data)
765 int ret = -ENODEV;
766 int server_fd;
767 char *the_name;
768 struct nfs_mount_data linux_nfs_mount;
769 struct sunos_nfs_mount_args *sunos_mount = data;
770 dev_t dev;
772 /* Ok, here comes the fun part: Linux's nfs mount needs a
773 * socket connection to the server, but SunOS mount does not
774 * require this, so we use the information on the destination
775 * address to create a socket and bind it to a reserved
776 * port on this system
778 server_fd = sys_socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP);
779 if (server_fd < 0)
780 return -ENXIO;
782 if (!sunos_nfs_get_server_fd (server_fd, sunos_mount->addr)){
783 sys_close (server_fd);
784 return -ENXIO;
787 /* Now, bind it to a locally reserved port */
788 linux_nfs_mount.version = NFS_MOUNT_VERSION;
789 linux_nfs_mount.flags = sunos_mount->flags;
790 linux_nfs_mount.addr = *sunos_mount->addr;
791 linux_nfs_mount.root = *sunos_mount->fh;
792 linux_nfs_mount.fd = server_fd;
794 linux_nfs_mount.rsize = get_default (sunos_mount->rsize, 8192);
795 linux_nfs_mount.wsize = get_default (sunos_mount->wsize, 8192);
796 linux_nfs_mount.timeo = get_default (sunos_mount->timeo, 10);
797 linux_nfs_mount.retrans = sunos_mount->retrans;
799 linux_nfs_mount.acregmin = sunos_mount->acregmin;
800 linux_nfs_mount.acregmax = sunos_mount->acregmax;
801 linux_nfs_mount.acdirmin = sunos_mount->acdirmin;
802 linux_nfs_mount.acdirmax = sunos_mount->acdirmax;
804 the_name = getname(sunos_mount->hostname);
805 if(IS_ERR(the_name))
806 return -EFAULT;
808 strncpy (linux_nfs_mount.hostname, the_name, 254);
809 linux_nfs_mount.hostname [255] = 0;
810 putname (the_name);
812 dev = get_unnamed_dev ();
814 ret = do_mount (dev, "", dir_name, "nfs", linux_flags, &linux_nfs_mount);
815 if (ret)
816 put_unnamed_dev(dev);
818 return ret;
821 /* XXXXXXXXXXXXXXXXXXXX */
822 asmlinkage int
823 sunos_mount(char *type, char *dir, int flags, void *data)
825 int linux_flags = MS_MGC_MSK; /* new semantics */
826 int ret = -EINVAL;
827 char *dev_fname = 0;
829 if (!capable (CAP_SYS_ADMIN))
830 return -EPERM;
831 lock_kernel();
832 /* We don't handle the integer fs type */
833 if ((flags & SMNT_NEWTYPE) == 0)
834 goto out;
836 /* Do not allow for those flags we don't support */
837 if (flags & (SMNT_GRPID|SMNT_NOSUB|SMNT_MULTI|SMNT_SYS5))
838 goto out;
840 if(flags & SMNT_REMOUNT)
841 linux_flags |= MS_REMOUNT;
842 if(flags & SMNT_RDONLY)
843 linux_flags |= MS_RDONLY;
844 if(flags & SMNT_NOSUID)
845 linux_flags |= MS_NOSUID;
846 if(strcmp(type, "ext2") == 0) {
847 dev_fname = (char *) data;
848 } else if(strcmp(type, "iso9660") == 0) {
849 dev_fname = (char *) data;
850 } else if(strcmp(type, "minix") == 0) {
851 dev_fname = (char *) data;
852 } else if(strcmp(type, "nfs") == 0) {
853 ret = sunos_nfs_mount (dir, flags, data);
854 goto out;
855 } else if(strcmp(type, "ufs") == 0) {
856 printk("Warning: UFS filesystem mounts unsupported.\n");
857 ret = -ENODEV;
858 goto out;
859 } else if(strcmp(type, "proc")) {
860 ret = -ENODEV;
861 goto out;
863 ret = sys_mount(dev_fname, dir, type, linux_flags, NULL);
864 out:
865 unlock_kernel();
866 return ret;
869 extern asmlinkage int sys_setsid(void);
870 extern asmlinkage int sys_setpgid(pid_t, pid_t);
872 asmlinkage int sunos_setpgrp(pid_t pid, pid_t pgid)
874 int ret;
876 /* So stupid... */
877 lock_kernel();
878 if((!pid || pid == current->pid) &&
879 !pgid) {
880 sys_setsid();
881 ret = 0;
882 } else {
883 ret = sys_setpgid(pid, pgid);
885 unlock_kernel();
886 return ret;
889 /* So stupid... */
890 extern asmlinkage int sys32_wait4(__kernel_pid_t32 pid,
891 u32 stat_addr, int options, u32 ru);
893 asmlinkage int sunos_wait4(__kernel_pid_t32 pid, u32 stat_addr, int options, u32 ru)
895 int ret;
897 lock_kernel();
898 ret = sys32_wait4((pid ? pid : ((__kernel_pid_t32)-1)),
899 stat_addr, options, ru);
900 unlock_kernel();
901 return ret;
904 extern int kill_pg(int, int, int);
905 asmlinkage int sunos_killpg(int pgrp, int sig)
907 int ret;
909 lock_kernel();
910 ret = kill_pg(pgrp, sig, 0);
911 unlock_kernel();
912 return ret;
915 asmlinkage int sunos_audit(void)
917 lock_kernel();
918 printk ("sys_audit\n");
919 unlock_kernel();
920 return -1;
923 extern asmlinkage u32 sunos_gethostid(void)
925 u32 ret;
927 lock_kernel();
928 ret = (((u32)idprom->id_machtype << 24) | ((u32)idprom->id_sernum));
929 unlock_kernel();
930 return ret;
933 /* sysconf options, for SunOS compatibility */
934 #define _SC_ARG_MAX 1
935 #define _SC_CHILD_MAX 2
936 #define _SC_CLK_TCK 3
937 #define _SC_NGROUPS_MAX 4
938 #define _SC_OPEN_MAX 5
939 #define _SC_JOB_CONTROL 6
940 #define _SC_SAVED_IDS 7
941 #define _SC_VERSION 8
943 extern asmlinkage s32 sunos_sysconf (int name)
945 s32 ret;
947 lock_kernel();
948 switch (name){
949 case _SC_ARG_MAX:
950 ret = ARG_MAX;
951 break;
952 case _SC_CHILD_MAX:
953 ret = CHILD_MAX;
954 break;
955 case _SC_CLK_TCK:
956 ret = HZ;
957 break;
958 case _SC_NGROUPS_MAX:
959 ret = NGROUPS_MAX;
960 break;
961 case _SC_OPEN_MAX:
962 ret = OPEN_MAX;
963 break;
964 case _SC_JOB_CONTROL:
965 ret = 1; /* yes, we do support job control */
966 break;
967 case _SC_SAVED_IDS:
968 ret = 1; /* yes, we do support saved uids */
969 break;
970 case _SC_VERSION:
971 /* mhm, POSIX_VERSION is in /usr/include/unistd.h
972 * should it go on /usr/include/linux?
974 ret = 199009;
975 break;
976 default:
977 ret = -1;
978 break;
980 unlock_kernel();
981 return ret;
984 extern asmlinkage int sys_semctl (int semid, int semnum, int cmd, union semun arg);
985 extern asmlinkage int sys_semget (key_t key, int nsems, int semflg);
986 extern asmlinkage int sys_semop (int semid, struct sembuf *tsops, unsigned nsops);
988 asmlinkage int sunos_semsys(int op, u32 arg1, u32 arg2, u32 arg3, u32 ptr)
990 union semun arg4;
991 int ret;
993 lock_kernel();
994 switch (op) {
995 case 0:
996 /* Most arguments match on a 1:1 basis but cmd doesn't */
997 switch(arg3) {
998 case 4:
999 arg3=GETPID; break;
1000 case 5:
1001 arg3=GETVAL; break;
1002 case 6:
1003 arg3=GETALL; break;
1004 case 3:
1005 arg3=GETNCNT; break;
1006 case 7:
1007 arg3=GETZCNT; break;
1008 case 8:
1009 arg3=SETVAL; break;
1010 case 9:
1011 arg3=SETALL; break;
1013 /* sys_semctl(): */
1014 arg4.__pad=(void *)A(ptr); /* value to modify semaphore to */
1015 ret = sys_semctl((int)arg1, (int)arg2, (int)arg3, arg4);
1016 break;
1017 case 1:
1018 /* sys_semget(): */
1019 ret = sys_semget((key_t)arg1, (int)arg2, (int)arg3);
1020 break;
1021 case 2:
1022 /* sys_semop(): */
1023 ret = sys_semop((int)arg1, (struct sembuf *)A(arg2), (unsigned)arg3);
1024 break;
1025 default:
1026 ret = -EINVAL;
1027 break;
1029 unlock_kernel();
1030 return ret;
1033 struct msgbuf32 {
1034 s32 mtype;
1035 char mtext[1];
1038 struct ipc_perm32
1040 key_t key;
1041 __kernel_uid_t32 uid;
1042 __kernel_gid_t32 gid;
1043 __kernel_uid_t32 cuid;
1044 __kernel_gid_t32 cgid;
1045 __kernel_mode_t32 mode;
1046 unsigned short seq;
1049 struct msqid_ds32
1051 struct ipc_perm32 msg_perm;
1052 u32 msg_first;
1053 u32 msg_last;
1054 __kernel_time_t32 msg_stime;
1055 __kernel_time_t32 msg_rtime;
1056 __kernel_time_t32 msg_ctime;
1057 u32 wwait;
1058 u32 rwait;
1059 unsigned short msg_cbytes;
1060 unsigned short msg_qnum;
1061 unsigned short msg_qbytes;
1062 __kernel_ipc_pid_t32 msg_lspid;
1063 __kernel_ipc_pid_t32 msg_lrpid;
1066 static inline int sunos_msqid_get(struct msqid_ds32 *user,
1067 struct msqid_ds *kern)
1069 if(get_user(kern->msg_perm.key, &user->msg_perm.key) ||
1070 __get_user(kern->msg_perm.uid, &user->msg_perm.uid) ||
1071 __get_user(kern->msg_perm.gid, &user->msg_perm.gid) ||
1072 __get_user(kern->msg_perm.cuid, &user->msg_perm.cuid) ||
1073 __get_user(kern->msg_perm.cgid, &user->msg_perm.cgid) ||
1074 __get_user(kern->msg_stime, &user->msg_stime) ||
1075 __get_user(kern->msg_rtime, &user->msg_rtime) ||
1076 __get_user(kern->msg_ctime, &user->msg_ctime) ||
1077 __get_user(kern->msg_ctime, &user->msg_cbytes) ||
1078 __get_user(kern->msg_ctime, &user->msg_qnum) ||
1079 __get_user(kern->msg_ctime, &user->msg_qbytes) ||
1080 __get_user(kern->msg_ctime, &user->msg_lspid) ||
1081 __get_user(kern->msg_ctime, &user->msg_lrpid))
1082 return -EFAULT;
1083 return 0;
1086 static inline int sunos_msqid_put(struct msqid_ds32 *user,
1087 struct msqid_ds *kern)
1089 if(put_user(kern->msg_perm.key, &user->msg_perm.key) ||
1090 __put_user(kern->msg_perm.uid, &user->msg_perm.uid) ||
1091 __put_user(kern->msg_perm.gid, &user->msg_perm.gid) ||
1092 __put_user(kern->msg_perm.cuid, &user->msg_perm.cuid) ||
1093 __put_user(kern->msg_perm.cgid, &user->msg_perm.cgid) ||
1094 __put_user(kern->msg_stime, &user->msg_stime) ||
1095 __put_user(kern->msg_rtime, &user->msg_rtime) ||
1096 __put_user(kern->msg_ctime, &user->msg_ctime) ||
1097 __put_user(kern->msg_ctime, &user->msg_cbytes) ||
1098 __put_user(kern->msg_ctime, &user->msg_qnum) ||
1099 __put_user(kern->msg_ctime, &user->msg_qbytes) ||
1100 __put_user(kern->msg_ctime, &user->msg_lspid) ||
1101 __put_user(kern->msg_ctime, &user->msg_lrpid))
1102 return -EFAULT;
1103 return 0;
1106 static inline int sunos_msgbuf_get(struct msgbuf32 *user, struct msgbuf *kern, int len)
1108 if(get_user(kern->mtype, &user->mtype) ||
1109 __copy_from_user(kern->mtext, &user->mtext, len))
1110 return -EFAULT;
1111 return 0;
1114 static inline int sunos_msgbuf_put(struct msgbuf32 *user, struct msgbuf *kern, int len)
1116 if(put_user(kern->mtype, &user->mtype) ||
1117 __copy_to_user(user->mtext, kern->mtext, len))
1118 return -EFAULT;
1119 return 0;
1122 extern asmlinkage int sys_msgget (key_t key, int msgflg);
1123 extern asmlinkage int sys_msgrcv (int msqid, struct msgbuf *msgp,
1124 size_t msgsz, long msgtyp, int msgflg);
1125 extern asmlinkage int sys_msgsnd (int msqid, struct msgbuf *msgp,
1126 size_t msgsz, int msgflg);
1127 extern asmlinkage int sys_msgctl (int msqid, int cmd, struct msqid_ds *buf);
1129 asmlinkage int sunos_msgsys(int op, u32 arg1, u32 arg2, u32 arg3, u32 arg4)
1131 struct sparc_stackf32 *sp;
1132 struct msqid_ds kds;
1133 struct msgbuf *kmbuf;
1134 mm_segment_t old_fs = get_fs();
1135 u32 arg5;
1136 int rval;
1138 lock_kernel();
1139 switch(op) {
1140 case 0:
1141 rval = sys_msgget((key_t)arg1, (int)arg2);
1142 break;
1143 case 1:
1144 if(!sunos_msqid_get((struct msqid_ds32 *)A(arg3), &kds)) {
1145 set_fs(KERNEL_DS);
1146 rval = sys_msgctl((int)arg1, (int)arg2,
1147 (struct msqid_ds *)A(arg3));
1148 set_fs(old_fs);
1149 if(!rval)
1150 rval = sunos_msqid_put((struct msqid_ds32 *)A(arg3),
1151 &kds);
1152 } else
1153 rval = -EFAULT;
1154 break;
1155 case 2:
1156 rval = -EFAULT;
1157 kmbuf = (struct msgbuf *)kmalloc(sizeof(struct msgbuf) + arg3,
1158 GFP_KERNEL);
1159 if(!kmbuf)
1160 break;
1161 sp = (struct sparc_stackf32 *)
1162 (current->tss.kregs->u_regs[UREG_FP] & 0xffffffffUL);
1163 if(get_user(arg5, &sp->xxargs[0])) {
1164 rval = -EFAULT;
1165 break;
1167 set_fs(KERNEL_DS);
1168 rval = sys_msgrcv((int)arg1, kmbuf, (size_t)arg3,
1169 (long)arg4, (int)arg5);
1170 set_fs(old_fs);
1171 if(!rval)
1172 rval = sunos_msgbuf_put((struct msgbuf32 *)A(arg2),
1173 kmbuf, arg3);
1174 kfree(kmbuf);
1175 break;
1176 case 3:
1177 rval = -EFAULT;
1178 kmbuf = (struct msgbuf *)kmalloc(sizeof(struct msgbuf) + arg3,
1179 GFP_KERNEL);
1180 if(!kmbuf || sunos_msgbuf_get((struct msgbuf32 *)A(arg2),
1181 kmbuf, arg3))
1182 break;
1183 set_fs(KERNEL_DS);
1184 rval = sys_msgsnd((int)arg1, kmbuf, (size_t)arg3, (int)arg4);
1185 set_fs(old_fs);
1186 kfree(kmbuf);
1187 break;
1188 default:
1189 rval = -EINVAL;
1190 break;
1192 unlock_kernel();
1193 return rval;
1196 struct shmid_ds32 {
1197 struct ipc_perm32 shm_perm;
1198 int shm_segsz;
1199 __kernel_time_t32 shm_atime;
1200 __kernel_time_t32 shm_dtime;
1201 __kernel_time_t32 shm_ctime;
1202 __kernel_ipc_pid_t32 shm_cpid;
1203 __kernel_ipc_pid_t32 shm_lpid;
1204 unsigned short shm_nattch;
1207 static inline int sunos_shmid_get(struct shmid_ds32 *user,
1208 struct shmid_ds *kern)
1210 if(get_user(kern->shm_perm.key, &user->shm_perm.key) ||
1211 __get_user(kern->shm_perm.uid, &user->shm_perm.uid) ||
1212 __get_user(kern->shm_perm.gid, &user->shm_perm.gid) ||
1213 __get_user(kern->shm_perm.cuid, &user->shm_perm.cuid) ||
1214 __get_user(kern->shm_perm.cgid, &user->shm_perm.cgid) ||
1215 __get_user(kern->shm_segsz, &user->shm_segsz) ||
1216 __get_user(kern->shm_atime, &user->shm_atime) ||
1217 __get_user(kern->shm_dtime, &user->shm_dtime) ||
1218 __get_user(kern->shm_ctime, &user->shm_ctime) ||
1219 __get_user(kern->shm_cpid, &user->shm_cpid) ||
1220 __get_user(kern->shm_lpid, &user->shm_lpid) ||
1221 __get_user(kern->shm_nattch, &user->shm_nattch))
1222 return -EFAULT;
1223 return 0;
1226 static inline int sunos_shmid_put(struct shmid_ds32 *user,
1227 struct shmid_ds *kern)
1229 if(put_user(kern->shm_perm.key, &user->shm_perm.key) ||
1230 __put_user(kern->shm_perm.uid, &user->shm_perm.uid) ||
1231 __put_user(kern->shm_perm.gid, &user->shm_perm.gid) ||
1232 __put_user(kern->shm_perm.cuid, &user->shm_perm.cuid) ||
1233 __put_user(kern->shm_perm.cgid, &user->shm_perm.cgid) ||
1234 __put_user(kern->shm_segsz, &user->shm_segsz) ||
1235 __put_user(kern->shm_atime, &user->shm_atime) ||
1236 __put_user(kern->shm_dtime, &user->shm_dtime) ||
1237 __put_user(kern->shm_ctime, &user->shm_ctime) ||
1238 __put_user(kern->shm_cpid, &user->shm_cpid) ||
1239 __put_user(kern->shm_lpid, &user->shm_lpid) ||
1240 __put_user(kern->shm_nattch, &user->shm_nattch))
1241 return -EFAULT;
1242 return 0;
1245 extern asmlinkage int sys_shmat (int shmid, char *shmaddr, int shmflg, ulong *raddr);
1246 extern asmlinkage int sys_shmctl (int shmid, int cmd, struct shmid_ds *buf);
1247 extern asmlinkage int sys_shmdt (char *shmaddr);
1248 extern asmlinkage int sys_shmget (key_t key, int size, int shmflg);
1250 asmlinkage int sunos_shmsys(int op, u32 arg1, u32 arg2, u32 arg3)
1252 struct shmid_ds ksds;
1253 unsigned long raddr;
1254 mm_segment_t old_fs = get_fs();
1255 int rval;
1257 lock_kernel();
1258 switch(op) {
1259 case 0:
1260 /* sys_shmat(): attach a shared memory area */
1261 rval = sys_shmat((int)arg1,(char *)A(arg2),(int)arg3,&raddr);
1262 if(!rval)
1263 rval = (int) raddr;
1264 break;
1265 case 1:
1266 /* sys_shmctl(): modify shared memory area attr. */
1267 if(!sunos_shmid_get((struct shmid_ds32 *)A(arg3), &ksds)) {
1268 set_fs(KERNEL_DS);
1269 rval = sys_shmctl((int)arg1,(int)arg2, &ksds);
1270 set_fs(old_fs);
1271 if(!rval)
1272 rval = sunos_shmid_put((struct shmid_ds32 *)A(arg3),
1273 &ksds);
1274 } else
1275 rval = -EFAULT;
1276 break;
1277 case 2:
1278 /* sys_shmdt(): detach a shared memory area */
1279 rval = sys_shmdt((char *)A(arg1));
1280 break;
1281 case 3:
1282 /* sys_shmget(): get a shared memory area */
1283 rval = sys_shmget((key_t)arg1,(int)arg2,(int)arg3);
1284 break;
1285 default:
1286 rval = -EINVAL;
1287 break;
1289 unlock_kernel();
1290 return rval;
1293 asmlinkage int sunos_open(u32 filename, int flags, int mode)
1295 int ret;
1297 lock_kernel();
1298 current->personality |= PER_BSD;
1299 ret = sys_open ((char *)A(filename), flags, mode);
1300 unlock_kernel();
1301 return ret;
1304 #define SUNOS_EWOULDBLOCK 35
1306 /* see the sunos man page read(2v) for an explanation
1307 of this garbage. We use O_NDELAY to mark
1308 file descriptors that have been set non-blocking
1309 using 4.2BSD style calls. (tridge) */
1311 static inline int check_nonblock(int ret, int fd)
1313 if (ret == -EAGAIN) {
1314 struct file * file = fcheck(fd);
1315 if (file && (file->f_flags & O_NDELAY))
1316 ret = -SUNOS_EWOULDBLOCK;
1318 return ret;
1321 extern asmlinkage int sys_read(unsigned int fd, char *buf, unsigned long count);
1322 extern asmlinkage int sys_write(unsigned int fd, char *buf, unsigned long count);
1323 extern asmlinkage int sys_recv(int fd, void *ubuf, size_t size, unsigned flags);
1324 extern asmlinkage int sys_send(int fd, void *buff, size_t len, unsigned flags);
1325 extern asmlinkage int sys_accept(int fd, struct sockaddr *sa, int *addrlen);
1326 extern asmlinkage int sys32_readv(u32 fd, u32 vector, s32 count);
1327 extern asmlinkage int sys32_writev(u32 fd, u32 vector, s32 count);
1329 asmlinkage int sunos_read(unsigned int fd, u32 buf, u32 count)
1331 int ret;
1333 lock_kernel();
1334 ret = check_nonblock(sys_read(fd, (char *)A(buf), count), fd);
1335 unlock_kernel();
1336 return ret;
1339 asmlinkage int sunos_readv(u32 fd, u32 vector, s32 count)
1341 int ret;
1343 lock_kernel();
1344 ret = check_nonblock(sys32_readv(fd, vector, count), fd);
1345 unlock_kernel();
1346 return ret;
1349 asmlinkage int sunos_write(unsigned int fd, u32 buf, u32 count)
1351 int ret;
1353 lock_kernel();
1354 ret = check_nonblock(sys_write(fd, (char *)A(buf), count), fd);
1355 unlock_kernel();
1356 return ret;
1359 asmlinkage int sunos_writev(u32 fd, u32 vector, s32 count)
1361 int ret;
1363 lock_kernel();
1364 ret = check_nonblock(sys32_writev(fd, vector, count), fd);
1365 unlock_kernel();
1366 return ret;
1369 asmlinkage int sunos_recv(int fd, u32 ubuf, int size, unsigned flags)
1371 int ret;
1373 lock_kernel();
1374 ret = check_nonblock(sys_recv(fd, (void *)A(ubuf), size, flags), fd);
1375 unlock_kernel();
1376 return ret;
1379 asmlinkage int sunos_send(int fd, u32 buff, int len, unsigned flags)
1381 int ret;
1383 lock_kernel();
1384 ret = check_nonblock(sys_send(fd, (void *)A(buff), len, flags), fd);
1385 unlock_kernel();
1386 return ret;
1389 extern asmlinkage int sys_setsockopt(int fd, int level, int optname,
1390 char *optval, int optlen);
1392 asmlinkage int sunos_socket(int family, int type, int protocol)
1394 int ret, one = 1;
1396 lock_kernel();
1397 ret = sys_socket(family, type, protocol);
1398 if (ret < 0)
1399 goto out;
1401 sys_setsockopt(ret, SOL_SOCKET, SO_BSDCOMPAT,
1402 (char *)&one, sizeof(one));
1403 out:
1404 unlock_kernel();
1405 return ret;
1408 asmlinkage int sunos_accept(int fd, u32 sa, u32 addrlen)
1410 int ret, one = 1;
1412 lock_kernel();
1413 while (1) {
1414 ret = check_nonblock(sys_accept(fd, (struct sockaddr *)A(sa),
1415 (int *)A(addrlen)), fd);
1416 if (ret != -ENETUNREACH && ret != -EHOSTUNREACH)
1417 break;
1419 if (ret < 0)
1420 goto out;
1422 sys_setsockopt(ret, SOL_SOCKET, SO_BSDCOMPAT,
1423 (char *)&one, sizeof(one));
1424 out:
1425 unlock_kernel();
1426 return ret;
1429 #define SUNOS_SV_INTERRUPT 2
1431 asmlinkage int sunos_sigaction (int sig, u32 act, u32 oact)
1433 struct k_sigaction new_ka, old_ka;
1434 int ret;
1436 current->personality |= PER_BSD;
1438 if (act) {
1439 old_sigset_t32 mask;
1441 if (get_user((long)new_ka.sa.sa_handler, &((struct old_sigaction32 *)A(act))->sa_handler) ||
1442 __get_user(new_ka.sa.sa_flags, &((struct old_sigaction32 *)A(act))->sa_flags))
1443 return -EFAULT;
1444 __get_user(mask, &((struct old_sigaction32 *)A(act))->sa_mask);
1445 new_ka.sa.sa_restorer = NULL;
1446 new_ka.ka_restorer = NULL;
1447 siginitset(&new_ka.sa.sa_mask, mask);
1448 new_ka.sa.sa_flags ^= SUNOS_SV_INTERRUPT;
1451 ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
1453 if (!ret && oact) {
1454 old_ka.sa.sa_flags ^= SUNOS_SV_INTERRUPT;
1455 if (put_user((long)old_ka.sa.sa_handler, &((struct old_sigaction32 *)A(oact))->sa_handler) ||
1456 __put_user(old_ka.sa.sa_flags, &((struct old_sigaction32 *)A(oact))->sa_flags))
1457 return -EFAULT;
1458 __put_user(old_ka.sa.sa_mask.sig[0], &((struct old_sigaction32 *)A(oact))->sa_mask);
1461 return ret;
1464 extern asmlinkage int sys_setsockopt(int fd, int level, int optname,
1465 char *optval, int optlen);
1466 extern asmlinkage int sys32_getsockopt(int fd, int level, int optname,
1467 u32 optval, u32 optlen);
1469 asmlinkage int sunos_setsockopt(int fd, int level, int optname, u32 optval,
1470 int optlen)
1472 int tr_opt = optname;
1473 int ret;
1475 lock_kernel();
1476 if (level == SOL_IP) {
1477 /* Multicast socketopts (ttl, membership) */
1478 if (tr_opt >=2 && tr_opt <= 6)
1479 tr_opt += 30;
1481 ret = sys_setsockopt(fd, level, tr_opt, (char *)A(optval), optlen);
1482 unlock_kernel();
1483 return ret;
1486 asmlinkage int sunos_getsockopt(int fd, int level, int optname,
1487 u32 optval, u32 optlen)
1489 int tr_opt = optname;
1490 int ret;
1492 lock_kernel();
1493 if (level == SOL_IP) {
1494 /* Multicast socketopts (ttl, membership) */
1495 if (tr_opt >=2 && tr_opt <= 6)
1496 tr_opt += 30;
1498 ret = sys32_getsockopt(fd, level, tr_opt, optval, optlen);
1499 unlock_kernel();
1500 return ret;