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