1 /*
2 * Copyright (c) 1995 Steven Wallace
3 * Copyright (c) 1994, 1995 Scott Bartram
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 * from: Header: sun_misc.c,v 1.16 93/04/07 02:46:27 torek Exp
45 *
46 * @(#)sun_misc.c 8.1 (Berkeley) 6/18/93
47 *
48 * $FreeBSD: src/sys/i386/ibcs2/ibcs2_misc.c,v 1.10.2.4 1999/09/05 08:11:25 peter Exp $
49 */
50
51 /*
52 * IBCS2 compatibility module.
53 *
54 * IBCS2 system calls that are implemented differently in BSD are
55 * handled here.
56 */
57 #include <sys/param.h>
58 #include <sys/systm.h>
59 #include <sys/namei.h>
60 #include <sys/proc.h>
61 #include <sys/file.h>
62 #include <sys/filedesc.h>
63 #include <sys/ioctl.h>
64 #include <sys/kernel.h>
65 #include <sys/malloc.h>
66 #include <sys/mbuf.h>
67 #include <sys/mman.h>
68 #include <sys/mount.h>
69 #include <sys/reboot.h>
70 #include <sys/resource.h>
71 #include <sys/resourcevar.h>
72 #include <sys/socket.h>
73 #include <sys/stat.h>
74 #include <sys/dirent.h>
75 #include <sys/time.h>
76 #include <sys/times.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 #include <sys/sysproto.h>
85
86 #include <miscfs/specfs/specdev.h>
87
88 #include <vm/vm.h>
89 #include <sys/sysctl.h> /* must be included after vm.h */
90
91 #include <machine/cpu.h>
92 #include <machine/psl.h>
93 #include <machine/reg.h>
94
95 #include <i386/ibcs2/ibcs2_types.h>
96 #include <i386/ibcs2/ibcs2_dirent.h>
97 #include <i386/ibcs2/ibcs2_fcntl.h>
98 #include <i386/ibcs2/ibcs2_time.h>
99 #include <i386/ibcs2/ibcs2_signal.h>
100 #include <i386/ibcs2/ibcs2_unistd.h>
101 #include <i386/ibcs2/ibcs2_utsname.h>
102 #include <i386/ibcs2/ibcs2_util.h>
103 #include <i386/ibcs2/ibcs2_utime.h>
104 #include <i386/ibcs2/ibcs2_proto.h>
105 #include <i386/ibcs2/ibcs2_xenix.h>
106
107
108 int
109 ibcs2_ulimit(p, uap, retval)
110 struct proc *p;
111 struct ibcs2_ulimit_args *uap;
112 int *retval;
113 {
114 #ifdef notyet
115 int error;
116 struct rlimit rl;
117 struct setrlimit_args {
118 int resource;
119 struct rlimit *rlp;
120 } sra;
121 #endif
122 #define IBCS2_GETFSIZE 1
123 #define IBCS2_SETFSIZE 2
124 #define IBCS2_GETPSIZE 3
125 #define IBCS2_GETDTABLESIZE 4
126
127 switch (SCARG(uap, cmd)) {
128 case IBCS2_GETFSIZE:
129 *retval = p->p_rlimit[RLIMIT_FSIZE].rlim_cur;
130 if (*retval == -1) *retval = 0x7fffffff;
131 return 0;
132 case IBCS2_SETFSIZE: /* XXX - fix this */
133 #ifdef notyet
134 rl.rlim_cur = SCARG(uap, newlimit);
135 sra.resource = RLIMIT_FSIZE;
136 sra.rlp = &rl;
137 error = setrlimit(p, &sra, retval);
138 if (!error)
139 *retval = p->p_rlimit[RLIMIT_FSIZE].rlim_cur;
140 else
141 DPRINTF(("failed "));
142 return error;
143 #else
144 *retval = SCARG(uap, newlimit);
145 return 0;
146 #endif
147 case IBCS2_GETPSIZE:
148 *retval = p->p_rlimit[RLIMIT_RSS].rlim_cur; /* XXX */
149 return 0;
150 case IBCS2_GETDTABLESIZE:
151 uap->cmd = IBCS2_SC_OPEN_MAX;
152 return ibcs2_sysconf(p, (struct ibcs2_sysconf_args *)uap,
153 retval);
154 default:
155 return ENOSYS;
156 }
157 }
158
159 #define IBCS2_WSTOPPED 0177
160 #define IBCS2_STOPCODE(sig) ((sig) << 8 | IBCS2_WSTOPPED)
161 int
162 ibcs2_wait(p, uap, retval)
163 struct proc *p;
164 struct ibcs2_wait_args *uap;
165 int *retval;
166 {
167 int error, status;
168 struct wait_args w4;
169 struct trapframe *tf = (struct trapframe *)p->p_md.md_regs;
170
171 SCARG(&w4, rusage) = NULL;
172 if ((tf->tf_eflags & (PSL_Z|PSL_PF|PSL_N|PSL_V))
173 == (PSL_Z|PSL_PF|PSL_N|PSL_V)) {
174 /* waitpid */
175 SCARG(&w4, pid) = SCARG(uap, a1);
176 SCARG(&w4, status) = (int *)SCARG(uap, a2);
177 SCARG(&w4, options) = SCARG(uap, a3);
178 } else {
179 /* wait */
180 SCARG(&w4, pid) = WAIT_ANY;
181 SCARG(&w4, status) = (int *)SCARG(uap, a1);
182 SCARG(&w4, options) = 0;
183 }
184 if ((error = wait4(p, &w4, retval)) != 0)
185 return error;
186 if (SCARG(&w4, status)) { /* this is real iBCS brain-damage */
187 error = copyin((caddr_t)SCARG(&w4, status), (caddr_t)&status,
188 sizeof(SCARG(&w4, status)));
189 if(error)
190 return error;
191
192 /* convert status/signal result */
193 if(WIFSTOPPED(status))
194 status =
195 IBCS2_STOPCODE(bsd_to_ibcs2_sig[WSTOPSIG(status)]);
196 else if(WIFSIGNALED(status))
197 status = bsd_to_ibcs2_sig[WTERMSIG(status)];
198 /* else exit status -- identical */
199
200 /* record result/status */
201 retval[1] = status;
202 return copyout((caddr_t)&status, (caddr_t)SCARG(&w4, status),
203 sizeof(SCARG(&w4, status)));
204 }
205
206 return 0;
207 }
208
209 int
210 ibcs2_execv(p, uap, retval)
211 struct proc *p;
212 struct ibcs2_execv_args *uap;
213 int *retval;
214 {
215 struct execve_args ea;
216 caddr_t sg = stackgap_init();
217
218 CHECKALTEXIST(p, &sg, SCARG(uap, path));
219 SCARG(&ea, fname) = SCARG(uap, path);
220 SCARG(&ea, argv) = SCARG(uap, argp);
221 SCARG(&ea, envv) = NULL;
222 return execve(p, &ea, retval);
223 }
224
225 int
226 ibcs2_execve(p, uap, retval)
227 struct proc *p;
228 struct ibcs2_execve_args *uap;
229 int *retval;
230 {
231 caddr_t sg = stackgap_init();
232 CHECKALTEXIST(p, &sg, SCARG(uap, path));
233 return execve(p, (struct execve_args *)uap, retval);
234 }
235
236 int
237 ibcs2_umount(p, uap, retval)
238 struct proc *p;
239 struct ibcs2_umount_args *uap;
240 int *retval;
241 {
242 struct unmount_args um;
243
244 SCARG(&um, path) = SCARG(uap, name);
245 SCARG(&um, flags) = 0;
246 return unmount(p, &um, retval);
247 }
248
249 int
250 ibcs2_mount(p, uap, retval)
251 struct proc *p;
252 struct ibcs2_mount_args *uap;
253 int *retval;
254 {
255 #ifdef notyet
256 int oflags = SCARG(uap, flags), nflags, error;
257 char fsname[MFSNAMELEN];
258
259 if (oflags & (IBCS2_MS_NOSUB | IBCS2_MS_SYS5))
260 return (EINVAL);
261 if ((oflags & IBCS2_MS_NEWTYPE) == 0)
262 return (EINVAL);
263 nflags = 0;
264 if (oflags & IBCS2_MS_RDONLY)
265 nflags |= MNT_RDONLY;
266 if (oflags & IBCS2_MS_NOSUID)
267 nflags |= MNT_NOSUID;
268 if (oflags & IBCS2_MS_REMOUNT)
269 nflags |= MNT_UPDATE;
270 SCARG(uap, flags) = nflags;
271
272 if (error = copyinstr((caddr_t)SCARG(uap, type), fsname, sizeof fsname,
273 (u_int *)0))
274 return (error);
275
276 if (strcmp(fsname, "4.2") == 0) {
277 SCARG(uap, type) = (caddr_t)STACK_ALLOC();
278 if (error = copyout("ufs", SCARG(uap, type), sizeof("ufs")))
279 return (error);
280 } else if (strcmp(fsname, "nfs") == 0) {
281 struct ibcs2_nfs_args sna;
282 struct sockaddr_in sain;
283 struct nfs_args na;
284 struct sockaddr sa;
285
286 if (error = copyin(SCARG(uap, data), &sna, sizeof sna))
287 return (error);
288 if (error = copyin(sna.addr, &sain, sizeof sain))
289 return (error);
290 bcopy(&sain, &sa, sizeof sa);
291 sa.sa_len = sizeof(sain);
292 SCARG(uap, data) = (caddr_t)STACK_ALLOC();
293 na.addr = (struct sockaddr *)((int)SCARG(uap, data) + sizeof na);
294 na.sotype = SOCK_DGRAM;
295 na.proto = IPPROTO_UDP;
296 na.fh = (nfsv2fh_t *)sna.fh;
297 na.flags = sna.flags;
298 na.wsize = sna.wsize;
299 na.rsize = sna.rsize;
300 na.timeo = sna.timeo;
301 na.retrans = sna.retrans;
302 na.hostname = sna.hostname;
303
304 if (error = copyout(&sa, na.addr, sizeof sa))
305 return (error);
306 if (error = copyout(&na, SCARG(uap, data), sizeof na))
307 return (error);
308 }
309 return (mount(p, uap, retval));
310 #else
311 return EINVAL;
312 #endif
313 }
314
315 /*
316 * Read iBCS2-style directory entries. We suck them into kernel space so
317 * that they can be massaged before being copied out to user code. Like
318 * SunOS, we squish out `empty' entries.
319 *
320 * This is quite ugly, but what do you expect from compatibility code?
321 */
322
323 int
324 ibcs2_getdents(p, uap, retval)
325 struct proc *p;
326 register struct ibcs2_getdents_args *uap;
327 int *retval;
328 {
329 register struct vnode *vp;
330 register caddr_t inp, buf; /* BSD-format */
331 register int len, reclen; /* BSD-format */
332 register caddr_t outp; /* iBCS2-format */
333 register int resid; /* iBCS2-format */
334 struct file *fp;
335 struct uio auio;
336 struct iovec aiov;
337 struct ibcs2_dirent idb;
338 off_t off; /* true file offset */
339 int buflen, error, eofflag;
340 u_int *cookies = NULL, *cookiep;
341 int ncookies;
342 #define BSD_DIRENT(cp) ((struct dirent *)(cp))
343 #define IBCS2_RECLEN(reclen) (reclen + sizeof(u_short))
344
345 if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
346 return (error);
347 if ((fp->f_flag & FREAD) == 0)
348 return (EBADF);
349 vp = (struct vnode *)fp->f_data;
350 if (vp->v_type != VDIR) /* XXX vnode readdir op should do this */
351 return (EINVAL);
352
353 off = fp->f_offset;
354 #define DIRBLKSIZ 512 /* XXX we used to use ufs's DIRBLKSIZ */
355 buflen = max(DIRBLKSIZ, SCARG(uap, nbytes));
356 buflen = min(buflen, MAXBSIZE);
357 buf = malloc(buflen, M_TEMP, M_WAITOK);
358 VOP_LOCK(vp);
359 again:
360 aiov.iov_base = buf;
361 aiov.iov_len = buflen;
362 auio.uio_iov = &aiov;
363 auio.uio_iovcnt = 1;
364 auio.uio_rw = UIO_READ;
365 auio.uio_segflg = UIO_SYSSPACE;
366 auio.uio_procp = p;
367 auio.uio_resid = buflen;
368 auio.uio_offset = off;
369
370 if (cookies) {
371 free(cookies, M_TEMP);
372 cookies = NULL;
373 }
374
375 /*
376 * First we read into the malloc'ed buffer, then
377 * we massage it into user space, one record at a time.
378 */
379 if (error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, &ncookies, &cookies))
380 goto out;
381 inp = buf;
382 outp = SCARG(uap, buf);
383 resid = SCARG(uap, nbytes);
384 if ((len = buflen - auio.uio_resid) <= 0)
385 goto eof;
386
387 cookiep = cookies;
388
389 if (cookies) {
390 /*
391 * When using cookies, the vfs has the option of reading from
392 * a different offset than that supplied (UFS truncates the
393 * offset to a block boundary to make sure that it never reads
394 * partway through a directory entry, even if the directory
395 * has been compacted).
396 */
397 while (len > 0 && ncookies > 0 && *cookiep <= off) {
398 len -= BSD_DIRENT(inp)->d_reclen;
399 inp += BSD_DIRENT(inp)->d_reclen;
400 cookiep++;
401 ncookies--;
402 }
403 }
404
405 for (; len > 0; len -= reclen) {
406 if (cookiep && ncookies == 0)
407 break;
408 reclen = BSD_DIRENT(inp)->d_reclen;
409 if (reclen & 3) {
410 printf("ibcs2_getdents: reclen=%d\n", reclen);
411 error = EFAULT;
412 goto out;
413 }
414 if (BSD_DIRENT(inp)->d_fileno == 0) {
415 inp += reclen; /* it is a hole; squish it out */
416 if (cookiep) {
417 off = *cookiep++;
418 ncookies--;
419 } else
420 off += reclen;
421 continue;
422 }
423 if (reclen > len || resid < IBCS2_RECLEN(reclen)) {
424 /* entry too big for buffer, so just stop */
425 outp++;
426 break;
427 }
428 /*
429 * Massage in place to make a iBCS2-shaped dirent (otherwise
430 * we have to worry about touching user memory outside of
431 * the copyout() call).
432 */
433 idb.d_ino = (ibcs2_ino_t)BSD_DIRENT(inp)->d_fileno;
434 idb.d_off = (ibcs2_off_t)off;
435 idb.d_reclen = (u_short)IBCS2_RECLEN(reclen);
436 if ((error = copyout((caddr_t)&idb, outp, 10)) != 0 ||
437 (error = copyout(BSD_DIRENT(inp)->d_name, outp + 10,
438 BSD_DIRENT(inp)->d_namlen + 1)) != 0)
439 goto out;
440 /* advance past this real entry */
441 if (cookiep) {
442 off = *cookiep++;
443 ncookies--;
444 } else
445 off += reclen;
446 inp += reclen;
447 /* advance output past iBCS2-shaped entry */
448 outp += IBCS2_RECLEN(reclen);
449 resid -= IBCS2_RECLEN(reclen);
450 }
451 /* if we squished out the whole block, try again */
452 if (outp == SCARG(uap, buf))
453 goto again;
454 fp->f_offset = off; /* update the vnode offset */
455 eof:
456 *retval = SCARG(uap, nbytes) - resid;
457 out:
458 if (cookies)
459 free(cookies, M_TEMP);
460 VOP_UNLOCK(vp);
461 free(buf, M_TEMP);
462 return (error);
463 }
464
465 int
466 ibcs2_read(p, uap, retval)
467 struct proc *p;
468 struct ibcs2_read_args *uap;
469 int *retval;
470 {
471 register struct vnode *vp;
472 register caddr_t inp, buf; /* BSD-format */
473 register int len, reclen; /* BSD-format */
474 register caddr_t outp; /* iBCS2-format */
475 register int resid; /* iBCS2-format */
476 struct file *fp;
477 struct uio auio;
478 struct iovec aiov;
479 struct ibcs2_direct {
480 ibcs2_ino_t ino;
481 char name[14];
482 } idb;
483 off_t off; /* true file offset */
484 int buflen, error, eofflag, size;
485 u_int *cookies = NULL, *cookiep;
486 int ncookies;
487
488 if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) {
489 if (error == EINVAL)
490 return read(p, (struct read_args *)uap, retval);
491 else
492 return error;
493 }
494 if ((fp->f_flag & FREAD) == 0)
495 return (EBADF);
496 vp = (struct vnode *)fp->f_data;
497 if (vp->v_type != VDIR)
498 return read(p, (struct read_args *)uap, retval);
499
500 DPRINTF(("ibcs2_read: read directory\n"));
501
502 off = fp->f_offset;
503 buflen = max(DIRBLKSIZ, SCARG(uap, nbytes));
504 buflen = min(buflen, MAXBSIZE);
505 buf = malloc(buflen, M_TEMP, M_WAITOK);
506 VOP_LOCK(vp);
507 again:
508 aiov.iov_base = buf;
509 aiov.iov_len = buflen;
510 auio.uio_iov = &aiov;
511 auio.uio_iovcnt = 1;
512 auio.uio_rw = UIO_READ;
513 auio.uio_segflg = UIO_SYSSPACE;
514 auio.uio_procp = p;
515 auio.uio_resid = buflen;
516 auio.uio_offset = off;
517
518 if (cookies) {
519 free(cookies, M_TEMP);
520 cookies = NULL;
521 }
522
523 /*
524 * First we read into the malloc'ed buffer, then
525 * we massage it into user space, one record at a time.
526 */
527 if (error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, &ncookies, &cookies)) {
528 DPRINTF(("VOP_READDIR failed: %d\n", error));
529 goto out;
530 }
531 inp = buf;
532 outp = SCARG(uap, buf);
533 resid = SCARG(uap, nbytes);
534 if ((len = buflen - auio.uio_resid) <= 0)
535 goto eof;
536
537 cookiep = cookies;
538
539 if (cookies) {
540 /*
541 * When using cookies, the vfs has the option of reading from
542 * a different offset than that supplied (UFS truncates the
543 * offset to a block boundary to make sure that it never reads
544 * partway through a directory entry, even if the directory
545 * has been compacted).
546 */
547 while (len > 0 && ncookies > 0 && *cookiep <= off) {
548 len -= BSD_DIRENT(inp)->d_reclen;
549 inp += BSD_DIRENT(inp)->d_reclen;
550 cookiep++;
551 ncookies--;
552 }
553 }
554
555 for (; len > 0 && resid > 0; len -= reclen) {
556 if (cookiep && ncookies == 0)
557 break;
558 reclen = BSD_DIRENT(inp)->d_reclen;
559 if (reclen & 3) {
560 printf("ibcs2_read: reclen=%d\n", reclen);
561 error = EFAULT;
562 goto out;
563 }
564 if (BSD_DIRENT(inp)->d_fileno == 0) {
565 inp += reclen; /* it is a hole; squish it out */
566 if (cookiep) {
567 off = *cookiep++;
568 ncookies--;
569 } else
570 off += reclen;
571 continue;
572 }
573 if (reclen > len || resid < sizeof(struct ibcs2_direct)) {
574 /* entry too big for buffer, so just stop */
575 outp++;
576 break;
577 }
578 /*
579 * Massage in place to make a iBCS2-shaped dirent (otherwise
580 * we have to worry about touching user memory outside of
581 * the copyout() call).
582 *
583 * TODO: if length(filename) > 14, then break filename into
584 * multiple entries and set inode = 0xffff except last
585 */
586 idb.ino = (BSD_DIRENT(inp)->d_fileno > 0xfffe) ? 0xfffe :
587 BSD_DIRENT(inp)->d_fileno;
588 (void)copystr(BSD_DIRENT(inp)->d_name, idb.name, 14, &size);
589 bzero(idb.name + size, 14 - size);
590 if (error = copyout(&idb, outp, sizeof(struct ibcs2_direct)))
591 goto out;
592 /* advance past this real entry */
593 if (cookiep) {
594 off = *cookiep++;
595 ncookies--;
596 } else
597 off += reclen;
598 inp += reclen;
599 /* advance output past iBCS2-shaped entry */
600 outp += sizeof(struct ibcs2_direct);
601 resid -= sizeof(struct ibcs2_direct);
602 }
603 /* if we squished out the whole block, try again */
604 if (outp == SCARG(uap, buf))
605 goto again;
606 fp->f_offset = off; /* update the vnode offset */
607 eof:
608 *retval = SCARG(uap, nbytes) - resid;
609 out:
610 if (cookies)
611 free(cookies, M_TEMP);
612 VOP_UNLOCK(vp);
613 free(buf, M_TEMP);
614 return (error);
615 }
616
617 int
618 ibcs2_mknod(p, uap, retval)
619 struct proc *p;
620 struct ibcs2_mknod_args *uap;
621 int *retval;
622 {
623 caddr_t sg = stackgap_init();
624
625 CHECKALTCREAT(p, &sg, SCARG(uap, path));
626 if (S_ISFIFO(SCARG(uap, mode))) {
627 struct mkfifo_args ap;
628 SCARG(&ap, path) = SCARG(uap, path);
629 SCARG(&ap, mode) = SCARG(uap, mode);
630 return mkfifo(p, &ap, retval);
631 } else {
632 struct mknod_args ap;
633 SCARG(&ap, path) = SCARG(uap, path);
634 SCARG(&ap, mode) = SCARG(uap, mode);
635 SCARG(&ap, dev) = SCARG(uap, dev);
636 return mknod(p, &ap, retval);
637 }
638 }
639
640 int
641 ibcs2_getgroups(p, uap, retval)
642 struct proc *p;
643 struct ibcs2_getgroups_args *uap;
644 int *retval;
645 {
646 int error, i;
647 ibcs2_gid_t *iset;
648 struct getgroups_args sa;
649 gid_t *gp;
650 caddr_t sg = stackgap_init();
651
652 SCARG(&sa, gidsetsize) = SCARG(uap, gidsetsize);
653 if (SCARG(uap, gidsetsize)) {
654 SCARG(&sa, gidset) = stackgap_alloc(&sg, NGROUPS_MAX *
655 sizeof(gid_t *));
656 }
657 iset = stackgap_alloc(&sg, SCARG(uap, gidsetsize) *
658 sizeof(ibcs2_gid_t));
659 if (error = getgroups(p, &sa, retval))
660 return error;
661 if (SCARG(uap, gidsetsize) == 0)
662 return 0;
663 for (i = 0, gp = SCARG(&sa, gidset); i < retval[0]; i++)
664 iset[i] = (ibcs2_gid_t)*gp++;
665 if (retval[0] && (error = copyout((caddr_t)iset,
666 (caddr_t)SCARG(uap, gidset),
667 sizeof(ibcs2_gid_t) * retval[0])))
668 return error;
669 return 0;
670 }
671
672 int
673 ibcs2_setgroups(p, uap, retval)
674 struct proc *p;
675 struct ibcs2_setgroups_args *uap;
676 int *retval;
677 {
678 int error, i;
679 ibcs2_gid_t *iset;
680 struct setgroups_args sa;
681 gid_t *gp;
682 caddr_t sg = stackgap_init();
683
684 SCARG(&sa, gidsetsize) = SCARG(uap, gidsetsize);
685 SCARG(&sa, gidset) = stackgap_alloc(&sg, SCARG(&sa, gidsetsize) *
686 sizeof(gid_t *));
687 iset = stackgap_alloc(&sg, SCARG(&sa, gidsetsize) *
688 sizeof(ibcs2_gid_t *));
689 if (SCARG(&sa, gidsetsize)) {
690 if (error = copyin((caddr_t)SCARG(uap, gidset), (caddr_t)iset,
691 sizeof(ibcs2_gid_t *) *
692 SCARG(uap, gidsetsize)))
693 return error;
694 }
695 for (i = 0, gp = SCARG(&sa, gidset); i < SCARG(&sa, gidsetsize); i++)
696 *gp++ = (gid_t)iset[i];
697 return setgroups(p, &sa, retval);
698 }
699
700 int
701 ibcs2_setuid(p, uap, retval)
702 struct proc *p;
703 struct ibcs2_setuid_args *uap;
704 int *retval;
705 {
706 struct setuid_args sa;
707
708 SCARG(&sa, uid) = (uid_t)SCARG(uap, uid);
709 return setuid(p, &sa, retval);
710 }
711
712 int
713 ibcs2_setgid(p, uap, retval)
714 struct proc *p;
715 struct ibcs2_setgid_args *uap;
716 int *retval;
717 {
718 struct setgid_args sa;
719
720 SCARG(&sa, gid) = (gid_t)SCARG(uap, gid);
721 return setgid(p, &sa, retval);
722 }
723
724 int
725 ibcs2_time(p, uap, retval)
726 struct proc *p;
727 struct ibcs2_time_args *uap;
728 int *retval;
729 {
730 struct timeval tv;
731
732 microtime(&tv);
733 *retval = tv.tv_sec;
734 if (SCARG(uap, tp))
735 return copyout((caddr_t)&tv.tv_sec, (caddr_t)SCARG(uap, tp),
736 sizeof(ibcs2_time_t));
737 else
738 return 0;
739 }
740
741 int
742 ibcs2_pathconf(p, uap, retval)
743 struct proc *p;
744 struct ibcs2_pathconf_args *uap;
745 int *retval;
746 {
747 SCARG(uap, name)++; /* iBCS2 _PC_* defines are offset by one */
748 return pathconf(p, (struct pathconf_args *)uap, retval);
749 }
750
751 int
752 ibcs2_fpathconf(p, uap, retval)
753 struct proc *p;
754 struct ibcs2_fpathconf_args *uap;
755 int *retval;
756 {
757 SCARG(uap, name)++; /* iBCS2 _PC_* defines are offset by one */
758 return fpathconf(p, (struct fpathconf_args *)uap, retval);
759 }
760
761 int
762 ibcs2_sysconf(p, uap, retval)
763 struct proc *p;
764 struct ibcs2_sysconf_args *uap;
765 int *retval;
766 {
767 int mib[2], value, len, error;
768 struct sysctl_args sa;
769 struct __getrlimit_args ga;
770
771 switch(SCARG(uap, name)) {
772 case IBCS2_SC_ARG_MAX:
773 mib[1] = KERN_ARGMAX;
774 break;
775
776 case IBCS2_SC_CHILD_MAX:
777 {
778 caddr_t sg = stackgap_init();
779
780 SCARG(&ga, which) = RLIMIT_NPROC;
781 SCARG(&ga, rlp) = stackgap_alloc(&sg, sizeof(struct rlimit *));
782 if (error = getrlimit(p, &ga, retval))
783 return error;
784 *retval = SCARG(&ga, rlp)->rlim_cur;
785 return 0;
786 }
787
788 case IBCS2_SC_CLK_TCK:
789 *retval = hz;
790 return 0;
791
792 case IBCS2_SC_NGROUPS_MAX:
793 mib[1] = KERN_NGROUPS;
794 break;
795
796 case IBCS2_SC_OPEN_MAX:
797 {
798 caddr_t sg = stackgap_init();
799
800 SCARG(&ga, which) = RLIMIT_NOFILE;
801 SCARG(&ga, rlp) = stackgap_alloc(&sg, sizeof(struct rlimit *));
802 if (error = getrlimit(p, &ga, retval))
803 return error;
804 *retval = SCARG(&ga, rlp)->rlim_cur;
805 return 0;
806 }
807
808 case IBCS2_SC_JOB_CONTROL:
809 mib[1] = KERN_JOB_CONTROL;
810 break;
811
812 case IBCS2_SC_SAVED_IDS:
813 mib[1] = KERN_SAVED_IDS;
814 break;
815
816 case IBCS2_SC_VERSION:
817 mib[1] = KERN_POSIX1;
818 break;
819
820 case IBCS2_SC_PASS_MAX:
821 *retval = 128; /* XXX - should we create PASS_MAX ? */
822 return 0;
823
824 case IBCS2_SC_XOPEN_VERSION:
825 *retval = 2; /* XXX: What should that be? */
826 return 0;
827
828 default:
829 return EINVAL;
830 }
831
832 mib[0] = CTL_KERN;
833 len = sizeof(value);
834 SCARG(&sa, name) = mib;
835 SCARG(&sa, namelen) = 2;
836 SCARG(&sa, old) = &value;
837 SCARG(&sa, oldlenp) = &len;
838 SCARG(&sa, new) = NULL;
839 SCARG(&sa, newlen) = 0;
840 if (error = __sysctl(p, &sa, retval))
841 return error;
842 *retval = value;
843 return 0;
844 }
845
846 int
847 ibcs2_alarm(p, uap, retval)
848 struct proc *p;
849 struct ibcs2_alarm_args *uap;
850 int *retval;
851 {
852 int error;
853 struct itimerval *itp, *oitp;
854 struct setitimer_args sa;
855 caddr_t sg = stackgap_init();
856
857 itp = stackgap_alloc(&sg, sizeof(*itp));
858 oitp = stackgap_alloc(&sg, sizeof(*oitp));
859 timerclear(&itp->it_interval);
860 itp->it_value.tv_sec = SCARG(uap, sec);
861 itp->it_value.tv_usec = 0;
862
863 SCARG(&sa, which) = ITIMER_REAL;
864 SCARG(&sa, itv) = itp;
865 SCARG(&sa, oitv) = oitp;
866 error = setitimer(p, &sa, retval);
867 if (error)
868 return error;
869 if (oitp->it_value.tv_usec)
870 oitp->it_value.tv_sec++;
871 *retval = oitp->it_value.tv_sec;
872 return 0;
873 }
874
875 int
876 ibcs2_times(p, uap, retval)
877 struct proc *p;
878 struct ibcs2_times_args *uap;
879 int *retval;
880 {
881 int error;
882 struct getrusage_args ga;
883 struct tms tms;
884 struct timeval t;
885 caddr_t sg = stackgap_init();
886 struct rusage *ru = stackgap_alloc(&sg, sizeof(*ru));
887 #define CONVTCK(r) (r.tv_sec * hz + r.tv_usec / (1000000 / hz))
888
889 SCARG(&ga, who) = RUSAGE_SELF;
890 SCARG(&ga, rusage) = ru;
891 error = getrusage(p, &ga, retval);
892 if (error)
893 return error;
894 tms.tms_utime = CONVTCK(ru->ru_utime);
895 tms.tms_stime = CONVTCK(ru->ru_stime);
896
897 SCARG(&ga, who) = RUSAGE_CHILDREN;
898 error = getrusage(p, &ga, retval);
899 if (error)
900 return error;
901 tms.tms_cutime = CONVTCK(ru->ru_utime);
902 tms.tms_cstime = CONVTCK(ru->ru_stime);
903
904 microtime(&t);
905 *retval = CONVTCK(t);
906
907 return copyout((caddr_t)&tms, (caddr_t)SCARG(uap, tp),
908 sizeof(struct tms));
909 }
910
911 int
912 ibcs2_stime(p, uap, retval)
913 struct proc *p;
914 struct ibcs2_stime_args *uap;
915 int *retval;
916 {
917 int error;
918 struct settimeofday_args sa;
919 caddr_t sg = stackgap_init();
920
921 SCARG(&sa, tv) = stackgap_alloc(&sg, sizeof(*SCARG(&sa, tv)));
922 SCARG(&sa, tzp) = NULL;
923 if (error = copyin((caddr_t)SCARG(uap, timep),
924 &(SCARG(&sa, tv)->tv_sec), sizeof(long)))
925 return error;
926 SCARG(&sa, tv)->tv_usec = 0;
927 if (error = settimeofday(p, &sa, retval))
928 return EPERM;
929 return 0;
930 }
931
932 int
933 ibcs2_utime(p, uap, retval)
934 struct proc *p;
935 struct ibcs2_utime_args *uap;
936 int *retval;
937 {
938 int error;
939 struct utimes_args sa;
940 struct timeval *tp;
941 caddr_t sg = stackgap_init();
942
943 CHECKALTEXIST(p, &sg, SCARG(uap, path));
944 SCARG(&sa, path) = SCARG(uap, path);
945 if (SCARG(uap, buf)) {
946 struct ibcs2_utimbuf ubuf;
947
948 if (error = copyin((caddr_t)SCARG(uap, buf), (caddr_t)&ubuf,
949 sizeof(ubuf)))
950 return error;
951 SCARG(&sa, tptr) = stackgap_alloc(&sg,
952 2 * sizeof(struct timeval *));
953 tp = (struct timeval *)SCARG(&sa, tptr);
954 tp->tv_sec = ubuf.actime;
955 tp->tv_usec = 0;
956 tp++;
957 tp->tv_sec = ubuf.modtime;
958 tp->tv_usec = 0;
959 } else
960 SCARG(&sa, tptr) = NULL;
961 return utimes(p, &sa, retval);
962 }
963
964 int
965 ibcs2_nice(p, uap, retval)
966 struct proc *p;
967 struct ibcs2_nice_args *uap;
968 int *retval;
969 {
970 int error;
971 struct setpriority_args sa;
972
973 SCARG(&sa, which) = PRIO_PROCESS;
974 SCARG(&sa, who) = 0;
975 SCARG(&sa, prio) = p->p_nice + SCARG(uap, incr);
976 if (error = setpriority(p, &sa, retval))
977 return EPERM;
978 *retval = p->p_nice;
979 return 0;
980 }
981
982 /*
983 * iBCS2 getpgrp, setpgrp, setsid, and setpgid
984 */
985
986 int
987 ibcs2_pgrpsys(p, uap, retval)
988 struct proc *p;
989 struct ibcs2_pgrpsys_args *uap;
990 int *retval;
991 {
992 switch (SCARG(uap, type)) {
993 case 0: /* getpgrp */
994 *retval = p->p_pgrp->pg_id;
995 return 0;
996
997 case 1: /* setpgrp */
998 {
999 struct setpgid_args sa;
1000
1001 SCARG(&sa, pid) = 0;
1002 SCARG(&sa, pgid) = 0;
1003 setpgid(p, &sa, retval);
1004 *retval = p->p_pgrp->pg_id;
1005 return 0;
1006 }
1007
1008 case 2: /* setpgid */
1009 {
1010 struct setpgid_args sa;
1011
1012 SCARG(&sa, pid) = SCARG(uap, pid);
1013 SCARG(&sa, pgid) = SCARG(uap, pgid);
1014 return setpgid(p, &sa, retval);
1015 }
1016
1017 case 3: /* setsid */
1018 return setsid(p, NULL, retval);
1019
1020 default:
1021 return EINVAL;
1022 }
1023 }
1024
1025 /*
1026 * XXX - need to check for nested calls
1027 */
1028
1029 int
1030 ibcs2_plock(p, uap, retval)
1031 struct proc *p;
1032 struct ibcs2_plock_args *uap;
1033 int *retval;
1034 {
1035 int error;
1036 #define IBCS2_UNLOCK 0
1037 #define IBCS2_PROCLOCK 1
1038 #define IBCS2_TEXTLOCK 2
1039 #define IBCS2_DATALOCK 4
1040
1041
1042 if (error = suser(p->p_ucred, &p->p_acflag))
1043 return EPERM;
1044 switch(SCARG(uap, cmd)) {
1045 case IBCS2_UNLOCK:
1046 case IBCS2_PROCLOCK:
1047 case IBCS2_TEXTLOCK:
1048 case IBCS2_DATALOCK:
1049 return 0; /* XXX - TODO */
1050 }
1051 return EINVAL;
1052 }
1053
1054 int
1055 ibcs2_uadmin(p, uap, retval)
1056 struct proc *p;
1057 struct ibcs2_uadmin_args *uap;
1058 int *retval;
1059 {
1060 #define SCO_A_REBOOT 1
1061 #define SCO_A_SHUTDOWN 2
1062 #define SCO_A_REMOUNT 4
1063 #define SCO_A_CLOCK 8
1064 #define SCO_A_SETCONFIG 128
1065 #define SCO_A_GETDEV 130
1066
1067 #define SCO_AD_HALT 0
1068 #define SCO_AD_BOOT 1
1069 #define SCO_AD_IBOOT 2
1070 #define SCO_AD_PWRDOWN 3
1071 #define SCO_AD_PWRNAP 4
1072
1073 #define SCO_AD_PANICBOOT 1
1074
1075 #define SCO_AD_GETBMAJ 0
1076 #define SCO_AD_GETCMAJ 1
1077
1078 if (suser(p->p_ucred, &p->p_acflag))
1079 return EPERM;
1080
1081 switch(SCARG(uap, cmd)) {
1082 case SCO_A_REBOOT:
1083 case SCO_A_SHUTDOWN:
1084 switch(SCARG(uap, func)) {
1085 struct reboot_args r;
1086 case SCO_AD_HALT:
1087 case SCO_AD_PWRDOWN:
1088 case SCO_AD_PWRNAP:
1089 r.opt = RB_HALT;
1090 reboot(p, &r, retval);
1091 case SCO_AD_BOOT:
1092 case SCO_AD_IBOOT:
1093 r.opt = RB_AUTOBOOT;
1094 reboot(p, &r, retval);
1095 }
1096 return EINVAL;
1097 case SCO_A_REMOUNT:
1098 case SCO_A_CLOCK:
1099 case SCO_A_SETCONFIG:
1100 return 0;
1101 case SCO_A_GETDEV:
1102 return EINVAL; /* XXX - TODO */
1103 }
1104 return EINVAL;
1105 }
1106
1107 int
1108 ibcs2_sysfs(p, uap, retval)
1109 struct proc *p;
1110 struct ibcs2_sysfs_args *uap;
1111 int *retval;
1112 {
1113 #define IBCS2_GETFSIND 1
1114 #define IBCS2_GETFSTYP 2
1115 #define IBCS2_GETNFSTYP 3
1116
1117 switch(SCARG(uap, cmd)) {
1118 case IBCS2_GETFSIND:
1119 case IBCS2_GETFSTYP:
1120 case IBCS2_GETNFSTYP:
1121 }
1122 return EINVAL; /* XXX - TODO */
1123 }
1124
1125 int
1126 ibcs2_unlink(p, uap, retval)
1127 struct proc *p;
1128 struct ibcs2_unlink_args *uap;
1129 int *retval;
1130 {
1131 caddr_t sg = stackgap_init();
1132
1133 CHECKALTEXIST(p, &sg, SCARG(uap, path));
1134 return unlink(p, (struct unlink_args *)uap, retval);
1135 }
1136
1137 int
1138 ibcs2_chdir(p, uap, retval)
1139 struct proc *p;
1140 struct ibcs2_chdir_args *uap;
1141 int *retval;
1142 {
1143 caddr_t sg = stackgap_init();
1144
1145 CHECKALTEXIST(p, &sg, SCARG(uap, path));
1146 return chdir(p, (struct chdir_args *)uap, retval);
1147 }
1148
1149 int
1150 ibcs2_chmod(p, uap, retval)
1151 struct proc *p;
1152 struct ibcs2_chmod_args *uap;
1153 int *retval;
1154 {
1155 caddr_t sg = stackgap_init();
1156
1157 CHECKALTEXIST(p, &sg, SCARG(uap, path));
1158 return chmod(p, (struct chmod_args *)uap, retval);
1159 }
1160
1161 int
1162 ibcs2_chown(p, uap, retval)
1163 struct proc *p;
1164 struct ibcs2_chown_args *uap;
1165 int *retval;
1166 {
1167 caddr_t sg = stackgap_init();
1168
1169 CHECKALTEXIST(p, &sg, SCARG(uap, path));
1170 return chown(p, (struct chown_args *)uap, retval);
1171 }
1172
1173 int
1174 ibcs2_rmdir(p, uap, retval)
1175 struct proc *p;
1176 struct ibcs2_rmdir_args *uap;
1177 int *retval;
1178 {
1179 caddr_t sg = stackgap_init();
1180
1181 CHECKALTEXIST(p, &sg, SCARG(uap, path));
1182 return rmdir(p, (struct rmdir_args *)uap, retval);
1183 }
1184
1185 int
1186 ibcs2_mkdir(p, uap, retval)
1187 struct proc *p;
1188 struct ibcs2_mkdir_args *uap;
1189 int *retval;
1190 {
1191 caddr_t sg = stackgap_init();
1192
1193 CHECKALTCREAT(p, &sg, SCARG(uap, path));
1194 return mkdir(p, (struct mkdir_args *)uap, retval);
1195 }
1196
1197 int
1198 ibcs2_symlink(p, uap, retval)
1199 struct proc *p;
1200 struct ibcs2_symlink_args *uap;
1201 int *retval;
1202 {
1203 caddr_t sg = stackgap_init();
1204
1205 CHECKALTEXIST(p, &sg, SCARG(uap, path));
1206 CHECKALTCREAT(p, &sg, SCARG(uap, link));
1207 return symlink(p, (struct symlink_args *)uap, retval);
1208 }
1209
1210 int
1211 ibcs2_rename(p, uap, retval)
1212 struct proc *p;
1213 struct ibcs2_rename_args *uap;
1214 int *retval;
1215 {
1216 caddr_t sg = stackgap_init();
1217
1218 CHECKALTEXIST(p, &sg, SCARG(uap, from));
1219 CHECKALTCREAT(p, &sg, SCARG(uap, to));
1220 return rename(p, (struct rename_args *)uap, retval);
1221 }
1222
1223 int
1224 ibcs2_readlink(p, uap, retval)
1225 struct proc *p;
1226 struct ibcs2_readlink_args *uap;
1227 int *retval;
1228 {
1229 caddr_t sg = stackgap_init();
1230
1231 CHECKALTEXIST(p, &sg, SCARG(uap, path));
1232 return readlink(p, (struct readlink_args *) uap, retval);
1233 }
Cache object: 3fa14910682f9b3d677f4a43082948f7
|