This source file includes following definitions.
- sunos_mmap
- sunos_mctl
- sunos_brk
- sunos_sbrk
- sunos_sstk
- sunos_vadvise
- sunos_madvise
- sunos_mincore
- sunos_getdtablesize
- sunos_sigblock
- sunos_sigsetmask
- sunos_filldir
- sunos_getdents
- sunos_filldirentry
- sunos_getdirentries
- sunos_getdomainname
- sunos_uname
- sunos_nosys
- sunos_fpathconf
- sunos_pathconf
- sunos_select
- sunos_nop
- sunos_nfs_get_server_fd
- get_default
- sunos_nfs_mount
- sunos_mount
- sunos_setpgrp
- sunos_wait4
- sunos_killpg
- sunos_audit
- sunos_gethostid
- sunos_sysconf
- free_wait
- check
- sunos_poll
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29 #include <linux/config.h>
30 #include <linux/kernel.h>
31 #include <linux/sched.h>
32 #include <linux/types.h>
33 #include <linux/mman.h>
34 #include <linux/mm.h>
35 #include <linux/swap.h>
36 #include <linux/fs.h>
37 #include <linux/resource.h>
38 #include <linux/signal.h>
39 #include <linux/uio.h>
40 #include <linux/utsname.h>
41 #include <linux/fs.h>
42 #include <linux/major.h>
43 #include <linux/stat.h>
44 #include <linux/malloc.h>
45 #include <linux/pagemap.h>
46
47 #include <asm/segment.h>
48 #ifndef KERNEL_DS
49 #include <linux/segment.h>
50 #endif
51
52 #include <asm/page.h>
53 #include <asm/pgtable.h>
54 #include <asm/pconf.h>
55 #include <asm/idprom.h>
56 #include <asm/unistd.h>
57 #include <asm/system.h>
58
59
60 #include <linux/socket.h>
61 #include <linux/in.h>
62 #include <linux/nfs.h>
63 #include <linux/nfs_mount.h>
64
65
66 #include <linux/time.h>
67 #include <linux/personality.h>
68
69 extern unsigned long get_sparc_unmapped_area(unsigned long len);
70
71
72 asmlinkage unsigned long sunos_mmap(unsigned long addr, unsigned long len,
73 unsigned long prot, unsigned long flags,
74 unsigned long fd, unsigned long off)
75 {
76 struct file * file = NULL;
77 unsigned long retval, ret_type;
78
79 if(flags & MAP_NORESERVE) {
80 printk("%s: unimplemented SunOS MAP_NORESERVE mmap() flag\n",
81 current->comm);
82 flags &= ~MAP_NORESERVE;
83 }
84 if(!(flags & MAP_ANONYMOUS))
85 if (fd >= NR_OPEN || !(file = current->files->fd[fd]))
86 return -EBADF;
87 if(!(flags & MAP_FIXED) && !addr) {
88 addr = get_sparc_unmapped_area(len);
89 if(!addr)
90 return -ENOMEM;
91 }
92
93
94
95
96 if(MAJOR(file->f_inode->i_rdev) == MEM_MAJOR &&
97 MINOR(file->f_inode->i_rdev) == 5) {
98 flags |= MAP_ANONYMOUS;
99 file = 0;
100 }
101 ret_type = flags & _MAP_NEW;
102 flags &= ~_MAP_NEW;
103 retval = do_mmap(file, addr, len, prot, flags, off);
104 if(ret_type)
105 return retval;
106 else
107 return ((retval < KERNBASE) ? 0 : retval);
108 }
109
110
111 asmlinkage int sunos_mctl(unsigned long addr, unsigned long len, int function, char *arg)
112 {
113 return 0;
114 }
115
116
117
118
119
120 asmlinkage int sunos_brk(unsigned long brk)
121 {
122 int freepages;
123 unsigned long rlim;
124 unsigned long newbrk, oldbrk;
125
126 if (brk < current->mm->end_code)
127 return -ENOMEM;
128
129 newbrk = PAGE_ALIGN(brk);
130 oldbrk = PAGE_ALIGN(current->mm->brk);
131 if (oldbrk == newbrk) {
132 current->mm->brk = brk;
133 return 0;
134 }
135
136
137
138
139 if (brk <= current->mm->brk) {
140 current->mm->brk = brk;
141 do_munmap(newbrk, oldbrk-newbrk);
142 return 0;
143 }
144
145
146
147 rlim = current->rlim[RLIMIT_DATA].rlim_cur;
148 if (rlim >= RLIM_INFINITY)
149 rlim = ~0;
150 if (brk - current->mm->end_code > rlim)
151 return -ENOMEM;
152
153
154
155
156 if (find_vma_intersection(current, oldbrk, newbrk+PAGE_SIZE))
157 return -ENOMEM;
158
159
160
161
162
163
164 freepages = buffermem >> PAGE_SHIFT;
165 freepages += page_cache_size;
166 freepages >>= 1;
167 freepages += nr_free_pages;
168 freepages += nr_swap_pages;
169 freepages -= MAP_NR(high_memory) >> 4;
170 freepages -= (newbrk-oldbrk) >> PAGE_SHIFT;
171 if (freepages < 0)
172 return -ENOMEM;
173
174
175
176 current->mm->brk = brk;
177 do_mmap(NULL, oldbrk, newbrk-oldbrk,
178 PROT_READ|PROT_WRITE|PROT_EXEC,
179 MAP_FIXED|MAP_PRIVATE, 0);
180 return 0;
181 }
182
183 asmlinkage unsigned long sunos_sbrk(int increment)
184 {
185 int error;
186
187
188 error = sunos_brk(((int) current->mm->brk) + increment);
189 if(error)
190 return error;
191 else
192 return current->mm->brk;
193 }
194
195
196
197
198
199
200 asmlinkage unsigned long sunos_sstk(int increment)
201 {
202 printk("%s: Call to sunos_sstk(increment<%d>) is unsupported\n",
203 current->comm, increment);
204 return -1;
205 }
206
207
208
209
210 #define VA_NORMAL 0
211 #define VA_ABNORMAL 1
212 #define VA_SEQUENTIAL 2
213 #define VA_INVALIDATE 3
214 static char *vstrings[] = {
215 "VA_NORMAL",
216 "VA_ABNORMAL",
217 "VA_SEQUENTIAL",
218 "VA_INVALIDATE",
219 };
220
221 asmlinkage void sunos_vadvise(unsigned long strategy)
222 {
223
224 printk("%s: Advises us to use %s paging strategy\n",
225 current->comm,
226 strategy <= 3 ? vstrings[strategy] : "BOGUS");
227 return;
228 }
229
230
231
232
233 #define MADV_NORMAL 0
234 #define MADV_RANDOM 1
235 #define MADV_SEQUENTIAL 2
236 #define MADV_WILLNEED 3
237 #define MADV_DONTNEED 4
238
239 static char *mstrings[] = {
240 "MADV_NORMAL",
241 "MADV_RANDOM",
242 "MADV_SEQUENTIAL",
243 "MADV_WILLNEED",
244 "MADV_DONTNEED",
245 };
246
247 asmlinkage void sunos_madvise(unsigned long address, unsigned long len,
248 unsigned long strategy)
249 {
250
251 printk("%s: Advises us to use %s paging strategy for addr<%08lx> len<%08lx>\n",
252 current->comm,
253 strategy <= 4 ? mstrings[strategy] : "BOGUS",
254 address, len);
255 return;
256 }
257
258
259
260
261
262
263
264
265
266
267
268 asmlinkage int sunos_mincore(unsigned long addr, unsigned long len, char *array)
269 {
270 pgd_t *pgdp;
271 pmd_t *pmdp;
272 pte_t *ptep;
273 unsigned long limit;
274 int num_pages, pnum;
275
276 if(addr & (PAGE_SIZE - 1))
277 return -EINVAL;
278
279 num_pages = (len / PAGE_SIZE);
280 if(verify_area(VERIFY_WRITE, array, num_pages))
281 return -EFAULT;
282 if((addr >= KERNBASE) || ((addr + len) > KERNBASE))
283 return -ENOMEM;
284
285
286 pnum = 0;
287 for(limit = addr + len; addr < limit; addr += PAGE_SIZE, pnum++) {
288 pgdp = pgd_offset(current->mm, addr);
289 if(pgd_none(*pgdp))
290 return -ENOMEM;
291 pmdp = pmd_offset(pgdp, addr);
292 if(pmd_none(*pmdp))
293 return -ENOMEM;
294 ptep = pte_offset(pmdp, addr);
295 if(pte_none(*ptep))
296 return -ENOMEM;
297
298 array[pnum] = pte_present(*ptep) ? 1 : 0;
299 }
300 return 0;
301 }
302
303
304
305
306
307 asmlinkage long sunos_getdtablesize(void)
308 {
309 return NR_OPEN;
310 }
311 #define _S(nr) (1<<((nr)-1))
312
313 #define _BLOCKABLE (~(_S(SIGKILL) | _S(SIGSTOP)))
314
315 asmlinkage unsigned long sunos_sigblock(unsigned long blk_mask)
316 {
317 unsigned long flags;
318 unsigned long old;
319
320 save_flags(flags); cli();
321 old = current->blocked;
322 current->blocked |= (blk_mask & _BLOCKABLE);
323 restore_flags(flags);
324 return old;
325 }
326
327 asmlinkage unsigned long sunos_sigsetmask(unsigned long newmask)
328 {
329 unsigned long flags;
330 unsigned long retval;
331
332 save_flags(flags); cli();
333 retval = current->blocked;
334 current->blocked = newmask & _BLOCKABLE;
335 restore_flags(flags);
336 return retval;
337 }
338
339
340
341
342 struct sunos_dirent {
343 long d_off;
344 unsigned long d_ino;
345 unsigned short d_reclen;
346 unsigned short d_namlen;
347 char d_name[1];
348 };
349
350 struct sunos_dirent_callback {
351 struct sunos_dirent *curr;
352 struct sunos_dirent *previous;
353 int count;
354 int error;
355 };
356
357 #define NAME_OFFSET(de) ((int) ((de)->d_name - (char *) (de)))
358 #define ROUND_UP(x) (((x)+sizeof(long)-1) & ~(sizeof(long)-1))
359
360 static int sunos_filldir(void * __buf, const char * name, int namlen,
361 off_t offset, ino_t ino)
362 {
363 struct sunos_dirent * dirent;
364 struct sunos_dirent_callback * buf = (struct sunos_dirent_callback *) __buf;
365 int reclen = ROUND_UP(NAME_OFFSET(dirent) + namlen + 1);
366
367 buf->error = -EINVAL;
368 if (reclen > buf->count)
369 return -EINVAL;
370 dirent = buf->previous;
371 if (dirent)
372 put_user(offset, &dirent->d_off);
373 dirent = buf->curr;
374 buf->previous = dirent;
375 put_user(ino, &dirent->d_ino);
376 put_user(namlen, &dirent->d_namlen);
377 put_user(reclen, &dirent->d_reclen);
378 memcpy_tofs(dirent->d_name, name, namlen);
379 put_user(0, dirent->d_name + namlen);
380 ((char *) dirent) += reclen;
381 buf->curr = dirent;
382 buf->count -= reclen;
383 return 0;
384 }
385
386 asmlinkage int sunos_getdents(unsigned int fd, void * dirent, int cnt)
387 {
388 struct file * file;
389 struct sunos_dirent * lastdirent;
390 struct sunos_dirent_callback buf;
391 int error;
392
393 if (fd >= NR_OPEN || !(file = current->files->fd[fd]))
394 return -EBADF;
395 if (!file->f_op || !file->f_op->readdir)
396 return -ENOTDIR;
397 if(verify_area(VERIFY_WRITE, dirent, cnt))
398 return -EFAULT;
399 if(cnt < (sizeof(struct sunos_dirent) + 255))
400 return -EINVAL;
401
402 buf.curr = (struct sunos_dirent *) dirent;
403 buf.previous = NULL;
404 buf.count = cnt;
405 buf.error = 0;
406 error = file->f_op->readdir(file->f_inode, file, &buf, sunos_filldir);
407 if (error < 0)
408 return error;
409 lastdirent = buf.previous;
410 if (!lastdirent)
411 return buf.error;
412 put_user(file->f_pos, &lastdirent->d_off);
413 return cnt - buf.count;
414 }
415
416
417 struct sunos_direntry {
418 unsigned long d_ino;
419 unsigned short d_reclen;
420 unsigned short d_namlen;
421 char d_name[1];
422 };
423
424 struct sunos_direntry_callback {
425 struct sunos_direntry *curr;
426 struct sunos_direntry *previous;
427 int count;
428 int error;
429 };
430
431 static int sunos_filldirentry(void * __buf, const char * name, int namlen,
432 off_t offset, ino_t ino)
433 {
434 struct sunos_direntry * dirent;
435 struct sunos_direntry_callback * buf = (struct sunos_direntry_callback *) __buf;
436 int reclen = ROUND_UP(NAME_OFFSET(dirent) + namlen + 1);
437
438 buf->error = -EINVAL;
439 if (reclen > buf->count)
440 return -EINVAL;
441 dirent = buf->previous;
442 dirent = buf->curr;
443 buf->previous = dirent;
444 put_user(ino, &dirent->d_ino);
445 put_user(namlen, &dirent->d_namlen);
446 put_user(reclen, &dirent->d_reclen);
447 memcpy_tofs(dirent->d_name, name, namlen);
448 put_user(0, dirent->d_name + namlen);
449 ((char *) dirent) += reclen;
450 buf->curr = dirent;
451 buf->count -= reclen;
452 return 0;
453 }
454
455 asmlinkage int sunos_getdirentries(unsigned int fd, void * dirent, int cnt, unsigned int *basep)
456 {
457 struct file * file;
458 struct sunos_direntry * lastdirent;
459 struct sunos_direntry_callback buf;
460 int error;
461
462 if (fd >= NR_OPEN || !(file = current->files->fd[fd]))
463 return -EBADF;
464 if (!file->f_op || !file->f_op->readdir)
465 return -ENOTDIR;
466 if(verify_area(VERIFY_WRITE, dirent, cnt) ||
467 verify_area(VERIFY_WRITE, basep, sizeof(unsigned int)))
468 return -EFAULT;
469 if(cnt < (sizeof(struct sunos_direntry) + 255))
470 return -EINVAL;
471
472 buf.curr = (struct sunos_direntry *) dirent;
473 buf.previous = NULL;
474 buf.count = cnt;
475 buf.error = 0;
476 error = file->f_op->readdir(file->f_inode, file, &buf, sunos_filldirentry);
477 if (error < 0)
478 return error;
479 lastdirent = buf.previous;
480 if (!lastdirent)
481 return buf.error;
482 put_user(file->f_pos, basep);
483 return cnt - buf.count;
484 }
485
486 asmlinkage int sunos_getdomainname(char *name, int len)
487 {
488 int error;
489
490 if(len > __NEW_UTS_LEN)
491 return -EFAULT;
492 error = verify_area(VERIFY_WRITE, name, len);
493 if(error)
494 return -EFAULT;
495 memcpy_tofs(name, system_utsname.domainname, len);
496 return 0;
497 }
498
499 struct sunos_utsname {
500 char sname[9];
501 char nname[9];
502 char nnext[56];
503 char rel[9];
504 char ver[9];
505 char mach[9];
506 };
507
508 asmlinkage int sunos_uname(struct sunos_utsname *name)
509 {
510 int error;
511 if(!name)
512 return -EFAULT;
513 error = verify_area(VERIFY_WRITE, name, sizeof *name);
514 if(error)
515 return error;
516 memcpy_tofs(&name->sname[0], &system_utsname.sysname[0],
517 sizeof(name->sname) - 1);
518 memcpy_tofs(&name->nname[0], &system_utsname.nodename[0],
519 sizeof(name->nname) - 1);
520 name->nname[8] = '\0';
521 memcpy_tofs(&name->rel[0], &system_utsname.release[0],
522 sizeof(name->rel) - 1);
523 memcpy_tofs(&name->ver[0], &system_utsname.version[0],
524 sizeof(name->ver) - 1);
525 memcpy_tofs(&name->mach[0], &system_utsname.machine[0],
526 sizeof(name->mach) - 1);
527 return 0;
528 }
529
530 asmlinkage int sunos_nosys(void)
531 {
532 struct pt_regs *regs;
533
534 regs = (struct pt_regs *) (current->saved_kernel_stack +
535 sizeof(struct reg_window));
536 current->tss.sig_address = regs->pc;
537 current->tss.sig_desc = regs->u_regs[UREG_G1];
538 send_sig(SIGSYS, current, 1);
539 printk("Process makes ni_syscall number %d, register dump:\n",
540 (int) regs->u_regs[UREG_G1]);
541 show_regs(regs);
542 return -ENOSYS;
543 }
544
545
546
547
548 asmlinkage int sunos_fpathconf(int fd, int name)
549 {
550 switch(name) {
551 case _PCONF_LINK:
552 return LINK_MAX;
553 case _PCONF_CANON:
554 return MAX_CANON;
555 case _PCONF_INPUT:
556 return MAX_INPUT;
557 case _PCONF_NAME:
558 return NAME_MAX;
559 case _PCONF_PATH:
560 return PATH_MAX;
561 case _PCONF_PIPE:
562 return PIPE_BUF;
563 case _PCONF_CHRESTRICT:
564 return 1;
565 case _PCONF_NOTRUNC:
566 return 0;
567 case _PCONF_VDISABLE:
568 return 30;
569 default:
570 return -EINVAL;
571 }
572 }
573
574 asmlinkage int sunos_pathconf(char *path, int name)
575 {
576 return sunos_fpathconf(0, name);
577 }
578
579
580 extern asmlinkage int
581 sys_select(int n, fd_set *inp, fd_set *outp, fd_set *exp, struct timeval *tvp);
582
583 asmlinkage int sunos_select(int width, fd_set *inp, fd_set *outp, fd_set *exp, struct timeval *tvp)
584 {
585
586 current->personality |= STICKY_TIMEOUTS;
587 return sys_select (width, inp, outp, exp, tvp);
588 }
589
590 asmlinkage void sunos_nop(void)
591 {
592 return;
593 }
594
595
596 #define SMNT_RDONLY 1
597 #define SMNT_NOSUID 2
598 #define SMNT_NEWTYPE 4
599 #define SMNT_GRPID 8
600 #define SMNT_REMOUNT 16
601 #define SMNT_NOSUB 32
602 #define SMNT_MULTI 64
603 #define SMNT_SYS5 128
604
605 struct sunos_fh_t {
606 char fh_data [NFS_FHSIZE];
607 };
608
609 struct sunos_nfs_mount_args {
610 struct sockaddr_in *addr;
611 struct nfs_fh *fh;
612 int flags;
613 int wsize;
614 int rsize;
615 int timeo;
616 int retrans;
617 char *hostname;
618 int acregmin;
619 int acregmax;
620 int acdirmin;
621 int acdirmax;
622 char *netname;
623 };
624
625
626 extern int do_mount(kdev_t, const char *, const char *, char *, int, void *);
627 extern dev_t get_unnamed_dev(void);
628 extern void put_unnamed_dev(dev_t);
629 extern asmlinkage int sys_mount(char *, char *, char *, unsigned long, void *);
630 extern asmlinkage int sys_connect(int fd, struct sockaddr *uservaddr, int addrlen);
631 extern asmlinkage int sys_socket(int family, int type, int protocol);
632 extern asmlinkage int sys_bind(int fd, struct sockaddr *umyaddr, int addrlen);
633
634
635
636
637
638
639 static int
640 sunos_nfs_get_server_fd (int fd, struct sockaddr_in *addr)
641 {
642 struct sockaddr_in local;
643 struct sockaddr_in server;
644 int try_port;
645 int ret;
646 struct socket *socket;
647 struct inode *inode;
648 struct file *file;
649
650 file = current->files->fd [fd];
651 inode = file->f_inode;
652 if (!inode || !inode->i_sock)
653 return 0;
654
655 socket = &inode->u.socket_i;
656 local.sin_family = AF_INET;
657 local.sin_addr.s_addr = INADDR_ANY;
658
659
660 try_port = 1024;
661 do {
662 local.sin_port = htons (--try_port);
663 ret = socket->ops->bind(socket, (struct sockaddr*)&local,
664 sizeof(local));
665 } while (ret && try_port > (1024 / 2));
666
667 if (ret)
668 return 0;
669
670 server.sin_family = AF_INET;
671 server.sin_addr = addr->sin_addr;
672 server.sin_port = NFS_PORT;
673
674
675 ret = socket->ops->connect (socket, (struct sockaddr *) &server,
676 sizeof (server), file->f_flags);
677 if (ret < 0)
678 return 0;
679 return 1;
680 }
681
682 static int get_default (int value, int def_value)
683 {
684 if (value)
685 return value;
686 else
687 return def_value;
688 }
689
690 asmlinkage int sunos_nfs_mount(char *dir_name, int linux_flags, void *data)
691 {
692 int ret = -ENODEV, error;
693 int server_fd;
694 char *the_name;
695 struct nfs_mount_data linux_nfs_mount;
696 struct sunos_nfs_mount_args *sunos_mount = data;
697 dev_t dev;
698
699 error = verify_area(VERIFY_READ, data, sizeof (struct sunos_nfs_mount_args));
700 if (error)
701 return error;
702
703
704
705
706
707
708 server_fd = sys_socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP);
709 if (server_fd < 0)
710 return -ENXIO;
711
712 if (!sunos_nfs_get_server_fd (server_fd, sunos_mount->addr)){
713 sys_close (server_fd);
714 return -ENXIO;
715 }
716
717
718 linux_nfs_mount.version = NFS_MOUNT_VERSION;
719 linux_nfs_mount.flags = sunos_mount->flags;
720 linux_nfs_mount.addr = *sunos_mount->addr;
721 linux_nfs_mount.root = *sunos_mount->fh;
722 linux_nfs_mount.fd = server_fd;
723
724 linux_nfs_mount.rsize = get_default (sunos_mount->rsize, 8192);
725 linux_nfs_mount.wsize = get_default (sunos_mount->wsize, 8192);
726 linux_nfs_mount.timeo = get_default (sunos_mount->timeo, 10);
727 linux_nfs_mount.retrans = sunos_mount->retrans;
728
729 linux_nfs_mount.acregmin = sunos_mount->acregmin;
730 linux_nfs_mount.acregmax = sunos_mount->acregmax;
731 linux_nfs_mount.acdirmin = sunos_mount->acdirmin;
732 linux_nfs_mount.acdirmax = sunos_mount->acdirmax;
733
734 if (getname (sunos_mount->hostname, &the_name))
735 return -EFAULT;
736
737 strncpy (linux_nfs_mount.hostname, the_name, 254);
738 linux_nfs_mount.hostname [255] = 0;
739 putname (the_name);
740
741 dev = get_unnamed_dev ();
742
743 ret = do_mount (dev, "", dir_name, "nfs", linux_flags, &linux_nfs_mount);
744 if (ret)
745 put_unnamed_dev(dev);
746
747 return ret;
748 }
749
750 asmlinkage int
751 sunos_mount(char *type, char *dir, int flags, void *data)
752 {
753 int linux_flags = MS_MGC_MSK;
754 int error;
755 char *dev_fname = 0;
756
757
758 if ((flags & SMNT_NEWTYPE) == 0)
759 return -EINVAL;
760
761
762 if (flags & (SMNT_GRPID|SMNT_NOSUB|SMNT_MULTI|SMNT_SYS5))
763 return -EINVAL;
764
765 if(flags & SMNT_REMOUNT)
766 linux_flags |= MS_REMOUNT;
767 if(flags & SMNT_RDONLY)
768 linux_flags |= MS_RDONLY;
769 if(flags & SMNT_NOSUID)
770 linux_flags |= MS_NOSUID;
771 error = verify_area(VERIFY_READ, type, 16);
772 if(error)
773 return error;
774 if(strcmp(type, "ext2") == 0) {
775 dev_fname = (char *) data;
776 } else if(strcmp(type, "iso9660") == 0) {
777 dev_fname = (char *) data;
778 } else if(strcmp(type, "minix") == 0) {
779 dev_fname = (char *) data;
780 } else if(strcmp(type, "ext") == 0) {
781 dev_fname = (char *) data;
782 } else if(strcmp(type, "xiafs") == 0) {
783 dev_fname = (char *) data;
784 } else if(strcmp(type, "nfs") == 0) {
785 error = sunos_nfs_mount (dir, flags, data);
786 return error;
787 } else if(strcmp(type, "ufs") == 0) {
788 printk("Warning: UFS filesystem mounts unsupported.\n");
789 return -ENODEV;
790 } else if(strcmp(type, "proc")) {
791 return -ENODEV;
792 }
793 if(error)
794 return error;
795 error = sys_mount(dev_fname, dir, type, linux_flags, NULL);
796 return error;
797 }
798
799 extern asmlinkage int sys_setsid(void);
800 extern asmlinkage int sys_setpgid(pid_t, pid_t);
801
802 asmlinkage int sunos_setpgrp(pid_t pid, pid_t pgid)
803 {
804
805 if((!pid || pid == current->pid) &&
806 !pgid) {
807 sys_setsid();
808 return 0;
809 } else {
810 return sys_setpgid(pid, pgid);
811 }
812 }
813
814
815 extern asmlinkage int sys_wait4(pid_t, unsigned int *, int, struct rusage *);
816 asmlinkage int sunos_wait4(pid_t pid, unsigned int *stat_addr, int options, struct rusage *ru)
817 {
818 return sys_wait4((pid ? pid : -1), stat_addr, options, ru);
819 }
820
821 extern int kill_pg(int, int, int);
822 asmlinkage int sunos_killpg(int pgrp, int sig)
823 {
824 return kill_pg(pgrp, sig, 0);
825 }
826
827 asmlinkage int sunos_audit(void)
828 {
829 printk ("sys_audit\n");
830 return -1;
831 }
832
833 extern asmlinkage unsigned long sunos_gethostid(void)
834 {
835 return (unsigned long) idprom->id_sernum;
836 }
837
838 extern asmlinkage long sunos_sysconf (int name)
839 {
840 switch (name){
841 case _SC_ARG_MAX:
842 return ARG_MAX;
843 case _SC_CHILD_MAX:
844 return CHILD_MAX;
845 case _SC_CLK_TCK:
846 return HZ;
847 case _SC_NGROUPS_MAX:
848 return NGROUPS_MAX;
849 case _SC_OPEN_MAX:
850 return OPEN_MAX;
851 case _SC_JOB_CONTROL:
852 return 1;
853 case _SC_SAVED_IDS:
854 return 1;
855 case _SC_VERSION:
856
857
858
859 return 199009L;
860 }
861 return -1;
862 }
863
864 #define POLL_ROUND_UP(x,y) (((x)+(y)-1)/(y))
865
866 #define POLLIN 1
867 #define POLLPRI 2
868 #define POLLOUT 4
869 #define POLLERR 8
870 #define POLLHUP 16
871 #define POLLNVAL 32
872 #define POLLRDNORM 64
873 #define POLLWRNORM POLLOUT
874 #define POLLRDBAND 128
875 #define POLLWRBAND 256
876
877 #define LINUX_POLLIN (POLLRDNORM | POLLRDBAND | POLLIN)
878 #define LINUX_POLLOUT (POLLWRBAND | POLLWRNORM | POLLOUT)
879 #define LINUX_POLLERR (POLLERR)
880
881 static inline void free_wait(select_table * p)
882 {
883 struct select_table_entry * entry = p->entry + p->nr;
884
885 while (p->nr > 0) {
886 p->nr--;
887 entry--;
888 remove_wait_queue(entry->wait_address,&entry->wait);
889 }
890 }
891
892
893
894 static int check(int flag, select_table * wait, struct file * file)
895 {
896 struct inode * inode;
897 struct file_operations *fops;
898 int (*select) (struct inode *, struct file *, int, select_table *);
899
900 inode = file->f_inode;
901 if ((fops = file->f_op) && (select = fops->select))
902 return select(inode, file, flag, wait)
903 || (wait && select(inode, file, flag, NULL));
904 if (S_ISREG(inode->i_mode))
905 return 1;
906 return 0;
907 }
908
909 struct poll {
910 int fd;
911 short events;
912 short revents;
913 };
914
915 int sunos_poll(struct poll * ufds, size_t nfds, int timeout)
916 {
917 int i,j, count, fdcount, error, retflag;
918 struct poll * fdpnt;
919 struct poll * fds, *fds1;
920 select_table wait_table, *wait;
921 struct select_table_entry *entry;
922
923 if ((error = verify_area(VERIFY_READ, ufds, nfds*sizeof(struct poll))))
924 return error;
925
926 if (nfds > NR_OPEN)
927 return -EINVAL;
928
929 if (!(entry = (struct select_table_entry*)__get_free_page(GFP_KERNEL))
930 || !(fds = (struct poll *)kmalloc(nfds*sizeof(struct poll), GFP_KERNEL)))
931 return -ENOMEM;
932
933 memcpy_fromfs(fds, ufds, nfds*sizeof(struct poll));
934
935 if (timeout < 0)
936 current->timeout = 0x7fffffff;
937 else {
938 current->timeout = jiffies + POLL_ROUND_UP(timeout, (1000/HZ));
939 if (current->timeout <= jiffies)
940 current->timeout = 0;
941 }
942
943 count = 0;
944 wait_table.nr = 0;
945 wait_table.entry = entry;
946 wait = &wait_table;
947
948 for(fdpnt = fds, j = 0; j < (int)nfds; j++, fdpnt++) {
949 i = fdpnt->fd;
950 fdpnt->revents = 0;
951 if (!current->files->fd[i] || !current->files->fd[i]->f_inode)
952 fdpnt->revents = POLLNVAL;
953 }
954 repeat:
955 current->state = TASK_INTERRUPTIBLE;
956 for(fdpnt = fds, j = 0; j < (int)nfds; j++, fdpnt++) {
957 i = fdpnt->fd;
958
959 if(i < 0) continue;
960 if (!current->files->fd[i] || !current->files->fd[i]->f_inode) continue;
961
962 if ((fdpnt->events & LINUX_POLLIN)
963 && check(SEL_IN, wait, current->files->fd[i])) {
964 if (fdpnt->events & POLLIN)
965 retflag = POLLIN;
966 if (fdpnt->events & POLLRDNORM)
967 retflag = POLLRDNORM;
968 fdpnt->revents |= retflag;
969 count++;
970 wait = NULL;
971 }
972
973 if ((fdpnt->events & LINUX_POLLOUT) &&
974 check(SEL_OUT, wait, current->files->fd[i])) {
975 fdpnt->revents |= (LINUX_POLLOUT & fdpnt->events);
976 count++;
977 wait = NULL;
978 }
979
980 if (check(SEL_EX, wait, current->files->fd[i])) {
981 fdpnt->revents |= POLLHUP;
982 count++;
983 wait = NULL;
984 }
985 }
986
987 if ((current->signal & (~current->blocked)))
988 return -EINTR;
989
990 wait = NULL;
991 if (!count && current->timeout > jiffies) {
992 schedule();
993 goto repeat;
994 }
995
996 free_wait(&wait_table);
997 free_page((unsigned long) entry);
998
999
1000 fds1 = fds;
1001 fdcount = 0;
1002 for(i=0; i < (int)nfds; i++, ufds++, fds++) {
1003 if (fds->revents) {
1004 fdcount++;
1005 }
1006 put_fs_word(fds->revents, &ufds->revents);
1007 }
1008 kfree(fds1);
1009 current->timeout = 0;
1010 current->state = TASK_RUNNING;
1011 return fdcount;
1012 }
1013