ultrix_misc.c revision 1.5 1 /* $NetBSD: ultrix_misc.c,v 1.5 1994/06/29 06:30:42 cgd Exp $ */
2
3 /*
4 * Copyright (c) 1992, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * This software was developed by the Computer Systems Engineering group
8 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
9 * contributed to Berkeley.
10 *
11 * All advertising materials mentioning features or use of this software
12 * must display the following acknowledgement:
13 * This product includes software developed by the University of
14 * California, Lawrence Berkeley Laboratory.
15 *
16 * Redistribution and use in source and binary forms, with or without
17 * modification, are permitted provided that the following conditions
18 * are met:
19 * 1. Redistributions of source code must retain the above copyright
20 * notice, this list of conditions and the following disclaimer.
21 * 2. Redistributions in binary form must reproduce the above copyright
22 * notice, this list of conditions and the following disclaimer in the
23 * documentation and/or other materials provided with the distribution.
24 * 3. All advertising materials mentioning features or use of this software
25 * must display the following acknowledgement:
26 * This product includes software developed by the University of
27 * California, Berkeley and its contributors.
28 * 4. Neither the name of the University nor the names of its contributors
29 * may be used to endorse or promote products derived from this software
30 * without specific prior written permission.
31 *
32 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
33 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
34 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
35 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
36 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
37 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
38 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
39 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
40 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
41 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
42 * SUCH DAMAGE.
43 *
44 *
45 * @(#)sun_misc.c 8.1 (Berkeley) 6/18/93
46 *
47 * from: Header: sun_misc.c,v 1.16 93/04/07 02:46:27 torek Exp
48 */
49
50 /*
51 * SunOS compatibility module.
52 *
53 * SunOS system calls that are implemented differently in BSD are
54 * handled here.
55 */
56
57 #include <sys/param.h>
58 #include <sys/systm.h>
59 #include <sys/namei.h>
60 #include <sys/dir.h>
61 #include <sys/proc.h>
62 #include <sys/file.h>
63 #include <sys/stat.h>
64 #include <sys/filedesc.h>
65 #include <sys/ioctl.h>
66 #include <sys/kernel.h>
67 #include <sys/exec.h>
68 #include <sys/malloc.h>
69 #include <sys/mbuf.h>
70 #include <sys/mman.h>
71 #include <sys/mount.h>
72 #include <sys/resource.h>
73 #include <sys/resourcevar.h>
74 #include <sys/signal.h>
75 #include <sys/signalvar.h>
76 #include <sys/socket.h>
77 #include <sys/vnode.h>
78 #include <sys/uio.h>
79 #include <sys/wait.h>
80 #include <sys/utsname.h>
81 #include <sys/unistd.h>
82
83 #include <netinet/in.h>
84
85 #include <miscfs/specfs/specdev.h>
86
87 #include <nfs/rpcv2.h>
88 #include <nfs/nfsv2.h>
89 #include <nfs/nfs.h>
90
91 #include <vm/vm.h>
92
93 struct ultrix_waitpid_args {
94 int pid;
95 int *status;
96 int options;
97 struct rusage *rusage;
98 };
99 ultrix_waitpid(p, uap, retval)
100 struct proc *p;
101 struct ultrix_waitpid_args *uap;
102 int *retval;
103 {
104
105 uap->rusage = 0;
106 return (wait4(p, uap, retval));
107 }
108 struct sun_wait4_args {
109 int pid;
110 int *status;
111 int options;
112 struct rusage *rusage;
113 int compat;
114 };
115 sun_wait4(p, uap, retval)
116 struct proc *p;
117 struct sun_wait4_args *uap;
118 int *retval;
119 {
120
121 if (uap->pid == 0)
122 uap->pid = WAIT_ANY;
123 return (wait4(p, uap, retval));
124 }
125
126 struct sun_wait3_args {
127 int *status;
128 int options;
129 struct rusage *rusage;
130 };
131
132 sun_wait3(p, uap, retval)
133 struct proc *p;
134 struct sun_wait3_args *uap;
135 int *retval;
136 {
137 struct sun_wait4_args ua;
138
139 if (uap == NULL)
140 panic("uap == NULL");
141 ua.pid = -1;
142 ua.status = uap->status;
143 ua.options = uap->options;
144 ua.rusage = uap->rusage;
145
146 return (wait4(p, &ua, retval));
147 }
148
149 struct sun_creat_args {
150 char *fname;
151 int fmode;
152 };
153 sun_creat(p, uap, retval)
154 struct proc *p;
155 struct sun_creat_args *uap;
156 int *retval;
157 {
158 struct args {
159 char *fname;
160 int mode;
161 int crtmode;
162 } openuap;
163
164 openuap.fname = uap->fname;
165 openuap.crtmode = uap->fmode;
166 openuap.mode = O_WRONLY | O_CREAT | O_TRUNC;
167 return (open(p, &openuap, retval));
168 }
169
170 struct sun_execv_args {
171 char *fname;
172 char **argp;
173 char **envp; /* pseudo */
174 };
175 sun_execv(p, uap, retval)
176 struct proc *p;
177 struct sun_execv_args *uap;
178 int *retval;
179 {
180
181 uap->envp = NULL;
182 return (execve(p, uap, retval));
183 }
184
185 struct sun_omsync_args {
186 caddr_t addr;
187 int len;
188 int flags;
189 };
190 sun_omsync(p, uap, retval)
191 struct proc *p;
192 struct sun_omsync_args *uap;
193 int *retval;
194 {
195
196 if (uap->flags)
197 return (EINVAL);
198 return (msync(p, uap, retval));
199 }
200
201 struct sun_unmount_args {
202 char *name;
203 int flags; /* pseudo */
204 };
205 sun_unmount(p, uap, retval)
206 struct proc *p;
207 struct sun_unmount_args *uap;
208 int *retval;
209 {
210
211 uap->flags = 0;
212 return (unmount(p, uap, retval));
213 }
214
215 #define SUNM_RDONLY 0x01 /* mount fs read-only */
216 #define SUNM_NOSUID 0x02 /* mount fs with setuid disallowed */
217 #define SUNM_NEWTYPE 0x04 /* type is string (char *), not int */
218 #define SUNM_GRPID 0x08 /* (bsd semantics; ignored) */
219 #define SUNM_REMOUNT 0x10 /* update existing mount */
220 #define SUNM_NOSUB 0x20 /* prevent submounts (rejected) */
221 #define SUNM_MULTI 0x40 /* (ignored) */
222 #define SUNM_SYS5 0x80 /* Sys 5-specific semantics (rejected) */
223
224 struct sun_nfs_args {
225 struct sockaddr_in *addr; /* file server address */
226 caddr_t fh; /* file handle to be mounted */
227 int flags; /* flags */
228 int wsize; /* write size in bytes */
229 int rsize; /* read size in bytes */
230 int timeo; /* initial timeout in .1 secs */
231 int retrans; /* times to retry send */
232 char *hostname; /* server's hostname */
233 int acregmin; /* attr cache file min secs */
234 int acregmax; /* attr cache file max secs */
235 int acdirmin; /* attr cache dir min secs */
236 int acdirmax; /* attr cache dir max secs */
237 char *netname; /* server's netname */
238 struct pathcnf *pathconf; /* static pathconf kludge */
239 };
240
241 struct sun_mount_args {
242 char *type;
243 char *dir;
244 int flags;
245 caddr_t data;
246 };
247 sun_mount(p, uap, retval)
248 struct proc *p;
249 struct sun_mount_args *uap;
250 int *retval;
251 {
252 int oflags = uap->flags, nflags, error;
253 extern char sigcode[], esigcode[];
254 char fsname[MFSNAMELEN];
255
256 #define szsigcode (esigcode - sigcode)
257
258 if (oflags & (SUNM_NOSUB | SUNM_SYS5))
259 return (EINVAL);
260 if ((oflags & SUNM_NEWTYPE) == 0)
261 return (EINVAL);
262 nflags = 0;
263 if (oflags & SUNM_RDONLY)
264 nflags |= MNT_RDONLY;
265 if (oflags & SUNM_NOSUID)
266 nflags |= MNT_NOSUID;
267 if (oflags & SUNM_REMOUNT)
268 nflags |= MNT_UPDATE;
269 uap->flags = nflags;
270
271 if (error = copyinstr((caddr_t)uap->type, fsname, sizeof fsname, (u_int *)0))
272 return (error);
273
274 if (strcmp(fsname, "4.2") == 0) {
275 uap->type = (caddr_t)ALIGN(PS_STRINGS - szsigcode - STACKGAPLEN);
276 if (error = copyout("ufs", uap->type, sizeof("ufs")))
277 return (error);
278 } else if (strcmp(fsname, "nfs") == 0) {
279 struct sun_nfs_args sna;
280 struct sockaddr_in sain;
281 struct nfs_args na;
282 struct sockaddr sa;
283
284 if (error = copyin(uap->data, &sna, sizeof sna))
285 return (error);
286 if (error = copyin(sna.addr, &sain, sizeof sain))
287 return (error);
288 bcopy(&sain, &sa, sizeof sa);
289 sa.sa_len = sizeof(sain);
290 uap->data = (caddr_t)ALIGN(PS_STRINGS - szsigcode - STACKGAPLEN);
291 na.addr = (struct sockaddr *)((int)uap->data + sizeof na);
292 na.sotype = SOCK_DGRAM;
293 na.proto = IPPROTO_UDP;
294 na.fh = (nfsv2fh_t *)sna.fh;
295 na.flags = sna.flags;
296 na.wsize = sna.wsize;
297 na.rsize = sna.rsize;
298 na.timeo = sna.timeo;
299 na.retrans = sna.retrans;
300 na.hostname = sna.hostname;
301
302 if (error = copyout(&sa, na.addr, sizeof sa))
303 return (error);
304 if (error = copyout(&na, uap->data, sizeof na))
305 return (error);
306 }
307 return (mount(p, uap, retval));
308 }
309
310 #if defined(NFSCLIENT)
311 async_daemon(p, uap, retval)
312 struct proc *p;
313 void *uap;
314 int *retval;
315 {
316 struct nfssvc_args {
317 int flag;
318 caddr_t argp;
319 } args;
320
321 args.flag = NFSSVC_BIOD;
322 return nfssvc(p, &args, retval);
323 }
324 #endif /* NFSCLIENT */
325
326 struct sun_sigpending_args {
327 int *mask;
328 };
329 sun_sigpending(p, uap, retval)
330 struct proc *p;
331 struct sun_sigpending_args *uap;
332 int *retval;
333 {
334 int mask = p->p_siglist & p->p_sigmask;
335
336 return (copyout((caddr_t)&mask, (caddr_t)uap->mask, sizeof(int)));
337 }
338
339 #if 0
340 /* XXX: Temporary until sys/dir.h, include/dirent.h and sys/dirent.h are fixed */
341 struct dirent {
342 u_long d_fileno; /* file number of entry */
343 u_short d_reclen; /* length of this record */
344 u_short d_namlen; /* length of string in d_name */
345 char d_name[255 + 1]; /* name must be no longer than this */
346 };
347 #endif
348
349 /*
350 * Here is the sun layout. (Compare the BSD layout in <sys/dirent.h>.)
351 * We can assume big-endian, so the BSD d_type field is just the high
352 * byte of the SunOS d_namlen field, after adjusting for the extra "long".
353 */
354 struct sun_dirent {
355 long d_off;
356 u_long d_fileno;
357 u_short d_reclen;
358 u_short d_namlen;
359 char d_name[256];
360 };
361
362 /*
363 * Read Sun-style directory entries. We suck them into kernel space so
364 * that they can be massaged before being copied out to user code. Like
365 * SunOS, we squish out `empty' entries.
366 *
367 * This is quite ugly, but what do you expect from compatibility code?
368 */
369 struct sun_getdents_args {
370 int fd;
371 char *buf;
372 int nbytes;
373 };
374 sun_getdents(p, uap, retval)
375 struct proc *p;
376 register struct sun_getdents_args *uap;
377 int *retval;
378 {
379 register struct vnode *vp;
380 register caddr_t inp, buf; /* BSD-format */
381 register int len, reclen; /* BSD-format */
382 register caddr_t outp; /* Sun-format */
383 register int resid; /* Sun-format */
384 struct file *fp;
385 struct uio auio;
386 struct iovec aiov;
387 off_t off; /* true file offset */
388 long soff; /* Sun file offset */
389 int buflen, error, eofflag;
390 #define BSD_DIRENT(cp) ((struct dirent *)(cp))
391 #define SUN_RECLEN(reclen) (reclen + sizeof(long))
392
393 if ((error = getvnode(p->p_fd, uap->fd, &fp)) != 0)
394 return (error);
395 if ((fp->f_flag & FREAD) == 0)
396 return (EBADF);
397 vp = (struct vnode *)fp->f_data;
398 if (vp->v_type != VDIR) /* XXX vnode readdir op should do this */
399 return (EINVAL);
400 buflen = min(MAXBSIZE, uap->nbytes);
401 buf = malloc(buflen, M_TEMP, M_WAITOK);
402 VOP_LOCK(vp);
403 off = fp->f_offset;
404 again:
405 aiov.iov_base = buf;
406 aiov.iov_len = buflen;
407 auio.uio_iov = &aiov;
408 auio.uio_iovcnt = 1;
409 auio.uio_rw = UIO_READ;
410 auio.uio_segflg = UIO_SYSSPACE;
411 auio.uio_procp = p;
412 auio.uio_resid = buflen;
413 auio.uio_offset = off;
414 /*
415 * First we read into the malloc'ed buffer, then
416 * we massage it into user space, one record at a time.
417 */
418 if (error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, (u_long *)0,
419 0))
420 goto out;
421 inp = buf;
422 outp = uap->buf;
423 resid = uap->nbytes;
424 if ((len = buflen - auio.uio_resid) == 0)
425 goto eof;
426 for (; len > 0; len -= reclen) {
427 reclen = ((struct dirent *)inp)->d_reclen;
428 if (reclen & 3)
429 panic("sun_getdents");
430 off += reclen; /* each entry points to next */
431 if (BSD_DIRENT(inp)->d_fileno == 0) {
432 inp += reclen; /* it is a hole; squish it out */
433 continue;
434 }
435 if (reclen > len || resid < SUN_RECLEN(reclen)) {
436 /* entry too big for buffer, so just stop */
437 outp++;
438 break;
439 }
440 /*
441 * Massage in place to make a Sun-shaped dirent (otherwise
442 * we have to worry about touching user memory outside of
443 * the copyout() call).
444 */
445 BSD_DIRENT(inp)->d_reclen = SUN_RECLEN(reclen);
446 #if notdef
447 BSD_DIRENT(inp)->d_type = 0; /* 4.4 specific */
448 #endif
449 soff = off;
450 if ((error = copyout((caddr_t)&soff, outp, sizeof soff)) != 0 ||
451 (error = copyout(inp, outp + sizeof soff, reclen)) != 0)
452 goto out;
453 /* advance past this real entry */
454 inp += reclen;
455 /* advance output past Sun-shaped entry */
456 outp += SUN_RECLEN(reclen);
457 resid -= SUN_RECLEN(reclen);
458 }
459 /* if we squished out the whole block, try again */
460 if (outp == uap->buf)
461 goto again;
462 fp->f_offset = off; /* update the vnode offset */
463 eof:
464 *retval = uap->nbytes - resid;
465 out:
466 VOP_UNLOCK(vp);
467 free(buf, M_TEMP);
468 return (error);
469 }
470
471 #define SUN__MAP_NEW 0x80000000 /* if not, old mmap & cannot handle */
472
473 struct sun_mmap_args {
474 caddr_t addr;
475 size_t len;
476 int prot;
477 int flags;
478 int fd;
479 long off; /* not off_t! */
480 off_t qoff; /* created here and fed to mmap() */
481 };
482 sun_mmap(p, uap, retval)
483 register struct proc *p;
484 register struct sun_mmap_args *uap;
485 int *retval;
486 {
487 register struct filedesc *fdp;
488 register struct file *fp;
489 register struct vnode *vp;
490
491 /*
492 * Verify the arguments.
493 */
494 if (uap->prot & ~(PROT_READ|PROT_WRITE|PROT_EXEC))
495 return (EINVAL); /* XXX still needed? */
496
497 if ((uap->flags & SUN__MAP_NEW) == 0)
498 return (EINVAL);
499 uap->flags &= ~SUN__MAP_NEW;
500
501 if ((uap->flags & MAP_FIXED) == 0 &&
502 uap->addr != 0 &&
503 uap->addr < (caddr_t)round_page(p->p_vmspace->vm_daddr+MAXDSIZ))
504 uap->addr = (caddr_t)round_page(p->p_vmspace->vm_daddr+MAXDSIZ);
505
506 /*
507 * Special case: if fd refers to /dev/zero, map as MAP_ANON. (XXX)
508 */
509 fdp = p->p_fd;
510 if ((unsigned)uap->fd < fdp->fd_nfiles && /*XXX*/
511 (fp = fdp->fd_ofiles[uap->fd]) != NULL && /*XXX*/
512 fp->f_type == DTYPE_VNODE && /*XXX*/
513 (vp = (struct vnode *)fp->f_data)->v_type == VCHR && /*XXX*/
514 iszerodev(vp->v_rdev)) { /*XXX*/
515 uap->flags |= MAP_ANON;
516 uap->fd = -1;
517 }
518
519 uap->qoff = uap->off;
520 return (mmap(p, uap, retval));
521 }
522
523 #define MC_SYNC 1
524 #define MC_LOCK 2
525 #define MC_UNLOCK 3
526 #define MC_ADVISE 4
527 #define MC_LOCKAS 5
528 #define MC_UNLOCKAS 6
529
530 struct sun_mctl_args {
531 caddr_t addr;
532 size_t len;
533 int func;
534 void *arg;
535 };
536 sun_mctl(p, uap, retval)
537 register struct proc *p;
538 register struct sun_mctl_args *uap;
539 int *retval;
540 {
541
542 switch (uap->func) {
543
544 case MC_ADVISE: /* ignore for now */
545 return (0);
546
547 case MC_SYNC: /* translate to msync */
548 return (msync(p, uap, retval));
549
550 default:
551 return (EINVAL);
552 }
553 }
554
555 struct sun_setsockopt_args {
556 int s;
557 int level;
558 int name;
559 caddr_t val;
560 int valsize;
561 };
562 sun_setsockopt(p, uap, retval)
563 struct proc *p;
564 register struct sun_setsockopt_args *uap;
565 int *retval;
566 {
567 struct file *fp;
568 struct mbuf *m = NULL;
569 int error;
570
571 if (error = getsock(p->p_fd, uap->s, &fp))
572 return (error);
573 #define SO_DONTLINGER (~SO_LINGER)
574 if (uap->name == SO_DONTLINGER) {
575 m = m_get(M_WAIT, MT_SOOPTS);
576 if (m == NULL)
577 return (ENOBUFS);
578 mtod(m, struct linger *)->l_onoff = 0;
579 m->m_len = sizeof(struct linger);
580 return (sosetopt((struct socket *)fp->f_data, uap->level,
581 SO_LINGER, m));
582 }
583 if (uap->valsize > MLEN)
584 return (EINVAL);
585 if (uap->val) {
586 m = m_get(M_WAIT, MT_SOOPTS);
587 if (m == NULL)
588 return (ENOBUFS);
589 if (error = copyin(uap->val, mtod(m, caddr_t),
590 (u_int)uap->valsize)) {
591 (void) m_free(m);
592 return (error);
593 }
594 m->m_len = uap->valsize;
595 }
596 return (sosetopt((struct socket *)fp->f_data, uap->level,
597 uap->name, m));
598 }
599
600 struct sun_fchroot_args {
601 int fdes;
602 };
603 sun_fchroot(p, uap, retval)
604 register struct proc *p;
605 register struct sun_fchroot_args *uap;
606 int *retval;
607 {
608 register struct filedesc *fdp = p->p_fd;
609 register struct vnode *vp;
610 struct file *fp;
611 int error;
612
613 if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
614 return (error);
615 if ((error = getvnode(fdp, uap->fdes, &fp)) != 0)
616 return (error);
617 vp = (struct vnode *)fp->f_data;
618 VOP_LOCK(vp);
619 if (vp->v_type != VDIR)
620 error = ENOTDIR;
621 else
622 error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p);
623 VOP_UNLOCK(vp);
624 if (error)
625 return (error);
626 VREF(vp);
627 if (fdp->fd_rdir != NULL)
628 vrele(fdp->fd_rdir);
629 fdp->fd_rdir = vp;
630 return (0);
631 }
632
633 /*
634 * XXX: This needs cleaning up.
635 */
636 sun_auditsys(...)
637 {
638 return 0;
639 }
640
641 struct sun_utsname {
642 char sysname[9];
643 char nodename[9];
644 char nodeext[65-9];
645 char release[9];
646 char version[9];
647 char machine[9];
648 };
649
650 struct sun_uname_args {
651 struct sun_utsname *name;
652 };
653 sun_uname(p, uap, retval)
654 struct proc *p;
655 struct sun_uname_args *uap;
656 int *retval;
657 {
658 struct sun_utsname sut;
659 extern char ostype[], machine[], osrelease[];
660
661 bzero(&sut, sizeof(sut));
662
663 bcopy(ostype, sut.sysname, sizeof(sut.sysname) - 1);
664 bcopy(hostname, sut.nodename, sizeof(sut.nodename));
665 sut.nodename[sizeof(sut.nodename)-1] = '\0';
666 bcopy(osrelease, sut.release, sizeof(sut.release) - 1);
667 bcopy("1", sut.version, sizeof(sut.version) - 1);
668 bcopy(machine, sut.machine, sizeof(sut.machine) - 1);
669
670 return copyout((caddr_t)&sut, (caddr_t)uap->name, sizeof(struct sun_utsname));
671 }
672
673 struct sun_setpgid_args {
674 int pid; /* target process id */
675 int pgid; /* target pgrp id */
676 };
677 int
678 sun_setpgid(p, uap, retval)
679 struct proc *p;
680 struct sun_setpgid_args *uap;
681 int *retval;
682 {
683 /*
684 * difference to our setpgid call is to include backwards
685 * compatibility to pre-setsid() binaries. Do setsid()
686 * instead of setpgid() in those cases where the process
687 * tries to create a new session the old way.
688 */
689 if (!uap->pgid && (!uap->pid || uap->pid == p->p_pid))
690 return setsid(p, uap, retval);
691 else
692 return setpgid(p, uap, retval);
693 }
694
695 struct sun_open_args {
696 char *fname;
697 int fmode;
698 int crtmode;
699 };
700 sun_open(p, uap, retval)
701 struct proc *p;
702 struct sun_open_args *uap;
703 int *retval;
704 {
705 int l, r;
706 int noctty = uap->fmode & 0x8000;
707 int ret;
708
709 /* convert mode into NetBSD mode */
710 l = uap->fmode;
711 r = (l & (0x0001 | 0x0002 | 0x0008 | 0x0040 | 0x0200 | 0x0400 | 0x0800));
712 r |= ((l & (0x0004 | 0x1000 | 0x4000)) ? O_NONBLOCK : 0);
713 r |= ((l & 0x0080) ? O_SHLOCK : 0);
714 r |= ((l & 0x0100) ? O_EXLOCK : 0);
715 r |= ((l & 0x2000) ? O_FSYNC : 0);
716
717 uap->fmode = r;
718 ret = open(p, uap, retval);
719
720 if (!ret && !noctty && SESS_LEADER(p) && !(p->p_flag & P_CONTROLT)) {
721 struct filedesc *fdp = p->p_fd;
722 struct file *fp = fdp->fd_ofiles[*retval];
723
724 /* ignore any error, just give it a try */
725 if (fp->f_type == DTYPE_VNODE)
726 (fp->f_ops->fo_ioctl)(fp, TIOCSCTTY, (caddr_t) 0, p);
727 }
728 return ret;
729 }
730
731 #if defined (NFSSERVER)
732 struct nfssvc_args {
733 int fd;
734 caddr_t mskval;
735 int msklen;
736 caddr_t mtchval;
737 int mtchlen;
738 };
739 struct sun_nfssvc_args {
740 int fd;
741 };
742 sun_nfssvc(p, uap, retval)
743 struct proc *p;
744 struct sun_nfssvc_args *uap;
745 int *retval;
746 {
747 struct nfssvc_args outuap;
748 struct sockaddr sa;
749 int error;
750 extern char sigcode[], esigcode[];
751
752 bzero(&outuap, sizeof outuap);
753 outuap.fd = uap->fd;
754 outuap.mskval = (caddr_t)ALIGN(PS_STRINGS - szsigcode - STACKGAPLEN);
755 outuap.msklen = sizeof sa;
756 outuap.mtchval = outuap.mskval + sizeof sa;
757 outuap.mtchlen = sizeof sa;
758
759 bzero(&sa, sizeof sa);
760 if (error = copyout(&sa, outuap.mskval, outuap.msklen))
761 return (error);
762 if (error = copyout(&sa, outuap.mtchval, outuap.mtchlen))
763 return (error);
764
765 return nfssvc(p, &outuap, retval);
766 }
767 #endif /* NFSSERVER */
768
769 struct sun_ustat {
770 daddr_t f_tfree; /* total free */
771 ino_t f_tinode; /* total inodes free */
772 char f_fname[6]; /* filsys name */
773 char f_fpack[6]; /* filsys pack name */
774 };
775 struct sun_ustat_args {
776 int dev;
777 struct sun_ustat *buf;
778 };
779 sun_ustat(p, uap, retval)
780 struct proc *p;
781 struct sun_ustat_args *uap;
782 int *retval;
783 {
784 struct sun_ustat us;
785 int error;
786
787 bzero(&us, sizeof us);
788
789 /*
790 * XXX: should set f_tfree and f_tinode at least
791 * How do we translate dev -> fstat? (and then to sun_ustat)
792 */
793
794 if (error = copyout(&us, uap->buf, sizeof us))
795 return (error);
796 return 0;
797 }
798
799 struct sun_quotactl_args {
800 int cmd;
801 char *special;
802 int uid;
803 caddr_t addr;
804 };
805 sun_quotactl(p, uap, retval)
806 struct proc *p;
807 struct sun_quotactl_args *uap;
808 int *retval;
809 {
810 return EINVAL;
811 }
812
813 sun_vhangup(p, uap, retval)
814 struct proc *p;
815 void *uap;
816 int *retval;
817 {
818 return 0;
819 }
820
821 struct sun_statfs {
822 long f_type; /* type of info, zero for now */
823 long f_bsize; /* fundamental file system block size */
824 long f_blocks; /* total blocks in file system */
825 long f_bfree; /* free blocks */
826 long f_bavail; /* free blocks available to non-super-user */
827 long f_files; /* total file nodes in file system */
828 long f_ffree; /* free file nodes in fs */
829 fsid_t f_fsid; /* file system id */
830 long f_spare[7]; /* spare for later */
831 };
832 static
833 sunstatfs(sp, buf)
834 struct statfs *sp;
835 caddr_t buf;
836 {
837 struct sun_statfs ssfs;
838
839 bzero(&ssfs, sizeof ssfs);
840 ssfs.f_type = 0;
841 ssfs.f_bsize = sp->f_bsize;
842 ssfs.f_blocks = sp->f_blocks;
843 ssfs.f_bfree = sp->f_bfree;
844 ssfs.f_bavail = sp->f_bavail;
845 ssfs.f_files = sp->f_files;
846 ssfs.f_ffree = sp->f_ffree;
847 ssfs.f_fsid = sp->f_fsid;
848 return copyout((caddr_t)&ssfs, buf, sizeof ssfs);
849 }
850
851 struct sun_statfs_args {
852 char *path;
853 struct sun_statfs *buf;
854 };
855 sun_statfs(p, uap, retval)
856 struct proc *p;
857 struct sun_statfs_args *uap;
858 int *retval;
859 {
860 register struct mount *mp;
861 register struct statfs *sp;
862 int error;
863 struct nameidata nd;
864
865 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p);
866 if (error = namei(&nd))
867 return (error);
868 mp = nd.ni_vp->v_mount;
869 sp = &mp->mnt_stat;
870 vrele(nd.ni_vp);
871 if (error = VFS_STATFS(mp, sp, p))
872 return (error);
873 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
874 return sunstatfs(sp, (caddr_t)uap->buf);
875 }
876
877 struct sun_fstatfs_args {
878 int fd;
879 struct sun_statfs *buf;
880 };
881 sun_fstatfs(p, uap, retval)
882 struct proc *p;
883 struct sun_fstatfs_args *uap;
884 int *retval;
885 {
886 struct file *fp;
887 struct mount *mp;
888 register struct statfs *sp;
889 int error;
890
891 if (error = getvnode(p->p_fd, uap->fd, &fp))
892 return (error);
893 mp = ((struct vnode *)fp->f_data)->v_mount;
894 sp = &mp->mnt_stat;
895 if (error = VFS_STATFS(mp, sp, p))
896 return (error);
897 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
898 return sunstatfs(sp, (caddr_t)uap->buf);
899 }
900
901 struct sun_exportfs_args {
902 char *path;
903 char *ex; /* struct sun_export * */
904 };
905 sun_exportfs(p, uap, retval)
906 struct proc *p;
907 struct sun_exportfs_args *uap;
908 int *retval;
909 {
910 /*
911 * XXX: should perhaps translate into a mount(2)
912 * with MOUNT_EXPORT?
913 */
914 return 0;
915 }
916
917 struct sun_mknod_args {
918 char *fname;
919 int fmode;
920 int dev;
921 };
922
923 sun_mknod(p, uap, retval)
924 struct proc *p;
925 struct sun_mknod_args *uap;
926 int *retval;
927 {
928 if (S_ISFIFO(uap->fmode))
929 return mkfifo(p, uap, retval);
930
931 return mknod(p, uap, retval);
932 }
933
934 #define SUN_SC_ARG_MAX 1
935 #define SUN_SC_CHILD_MAX 2
936 #define SUN_SC_CLK_TCK 3
937 #define SUN_SC_NGROUPS_MAX 4
938 #define SUN_SC_OPEN_MAX 5
939 #define SUN_SC_JOB_CONTROL 6
940 #define SUN_SC_SAVED_IDS 7
941 #define SUN_SC_VERSION 8
942
943 struct sun_sysconf_args {
944 int name;
945 };
946
947 sun_sysconf(p, uap, retval)
948 struct proc *p;
949 struct sun_sysconf_args *uap;
950 int *retval;
951 {
952 extern int maxfiles;
953
954 switch(uap->name) {
955 case SUN_SC_ARG_MAX:
956 *retval = ARG_MAX;
957 break;
958 case SUN_SC_CHILD_MAX:
959 *retval = maxproc;
960 break;
961 case SUN_SC_CLK_TCK:
962 *retval = 60; /* should this be `hz', ie. 100? */
963 break;
964 case SUN_SC_NGROUPS_MAX:
965 *retval = NGROUPS_MAX;
966 break;
967 case SUN_SC_OPEN_MAX:
968 *retval = maxfiles;
969 break;
970 case SUN_SC_JOB_CONTROL:
971 *retval = 1;
972 break;
973 case SUN_SC_SAVED_IDS:
974 #ifdef _POSIX_SAVED_IDS
975 *retval = 1;
976 #else
977 *retval = 0;
978 #endif
979 break;
980 case SUN_SC_VERSION:
981 *retval = 198808;
982 break;
983 default:
984 return EINVAL;
985 }
986 return 0;
987 }
988
989 #define SUN_RLIMIT_NOFILE 6 /* Other RLIMIT_* are the same */
990 #define SUN_RLIM_NLIMITS 7
991
992 struct sun_getrlimit_args {
993 int which;
994 struct orlimit *rlp;
995 };
996
997 sun_getrlimit(p, uap, retval)
998 struct proc *p;
999 struct sun_getrlimit_args *uap;
1000 int *retval;
1001 {
1002 if (uap->which >= SUN_RLIM_NLIMITS)
1003 return EINVAL;
1004
1005 if (uap->which == SUN_RLIMIT_NOFILE)
1006 uap->which = RLIMIT_NOFILE;
1007
1008 return ogetrlimit(p, uap, retval);
1009 }
1010
1011 struct sun_setrlimit_args {
1012 int which;
1013 struct orlimit *rlp;
1014 };
1015
1016 sun_setrlimit(p, uap, retval)
1017 struct proc *p;
1018 struct sun_getrlimit_args *uap;
1019 int *retval;
1020 {
1021 if (uap->which >= SUN_RLIM_NLIMITS)
1022 return EINVAL;
1023
1024 if (uap->which == SUN_RLIMIT_NOFILE)
1025 uap->which = RLIMIT_NOFILE;
1026
1027 return osetrlimit(p, uap, retval);
1028 }
1029