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