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