Remove the FreeBSD 3.x signal code. This includes osendsig(),
[dragonfly.git] / sys / emulation / linux / linux_misc.c
1 /*-
2  * Copyright (c) 1994-1995 Søren Schmidt
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer
10  *    in this position and unchanged.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  * 3. The name of the author may not be used to endorse or promote products
15  *    derived from this software withough specific prior written permission
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  *
28  * $FreeBSD: src/sys/compat/linux/linux_misc.c,v 1.85.2.9 2002/09/24 08:11:41 mdodd Exp $
29  * $DragonFly: src/sys/emulation/linux/linux_misc.c,v 1.14 2003/09/23 05:03:51 dillon Exp $
30  */
31
32 #include "opt_compat.h"
33
34 #include <sys/param.h>
35 #include <sys/systm.h>
36 #include <sys/fcntl.h>
37 #include <sys/imgact_aout.h>
38 #include <sys/kernel.h>
39 #include <sys/lock.h>
40 #include <sys/mman.h>
41 #include <sys/mount.h>
42 #include <sys/poll.h>
43 #include <sys/proc.h>
44 #include <sys/namei.h>
45 #include <sys/blist.h>
46 #include <sys/reboot.h>
47 #include <sys/resourcevar.h>
48 #include <sys/signalvar.h>
49 #include <sys/stat.h>
50 #include <sys/sysctl.h>
51 #include <sys/sysproto.h>
52 #include <sys/time.h>
53 #include <sys/unistd.h>
54 #include <sys/vmmeter.h>
55 #include <sys/vnode.h>
56 #include <sys/wait.h>
57
58 #include <vm/vm.h>
59 #include <vm/pmap.h>
60 #include <vm/vm_kern.h>
61 #include <vm/vm_map.h>
62 #include <vm/vm_extern.h>
63 #include <vm/vm_object.h>
64 #include <vm/vm_zone.h>
65 #include <vm/swap_pager.h>
66
67 #include <machine/frame.h>
68 #include <machine/limits.h>
69 #include <machine/psl.h>
70 #include <machine/sysarch.h>
71 #ifdef __i386__
72 #include <machine/segments.h>
73 #endif
74
75 #include <emulation/posix4/sched.h>
76
77 #include <arch_linux/linux.h>
78 #include <arch_linux/linux_proto.h>
79 #include "linux_mib.h"
80 #include "linux_util.h"
81
82 #ifdef __alpha__
83 #define BSD_TO_LINUX_SIGNAL(sig)       (sig)
84 #else
85 #define BSD_TO_LINUX_SIGNAL(sig)        \
86         (((sig) <= LINUX_SIGTBLSZ) ? bsd_to_linux_signal[_SIG_IDX(sig)] : sig)
87 #endif
88
89 #ifndef __alpha__
90 static unsigned int linux_to_bsd_resource[LINUX_RLIM_NLIMITS] = {
91         RLIMIT_CPU, RLIMIT_FSIZE, RLIMIT_DATA, RLIMIT_STACK,
92         RLIMIT_CORE, RLIMIT_RSS, RLIMIT_NPROC, RLIMIT_NOFILE,
93         RLIMIT_MEMLOCK, -1
94 };
95 #endif /*!__alpha__*/
96
97 struct l_sysinfo {
98         l_long          uptime;         /* Seconds since boot */
99         l_ulong         loads[3];       /* 1, 5, and 15 minute load averages */
100         l_ulong         totalram;       /* Total usable main memory size */
101         l_ulong         freeram;        /* Available memory size */
102         l_ulong         sharedram;      /* Amount of shared memory */
103         l_ulong         bufferram;      /* Memory used by buffers */
104         l_ulong         totalswap;      /* Total swap space size */
105         l_ulong         freeswap;       /* swap space still available */
106         l_ushort        procs;          /* Number of current processes */
107         char            _f[22];         /* Pads structure to 64 bytes */
108 };
109 #ifndef __alpha__
110 int
111 linux_sysinfo(struct linux_sysinfo_args *args)
112 {
113         struct l_sysinfo sysinfo;
114         vm_object_t object;
115         int i;
116         struct timespec ts;
117
118         /* Uptime is copied out of print_uptime() in kern_shutdown.c */
119         getnanouptime(&ts);
120         i = 0;
121         if (ts.tv_sec >= 86400) {
122                 ts.tv_sec %= 86400;
123                 i = 1;
124         }
125         if (i || ts.tv_sec >= 3600) {
126                 ts.tv_sec %= 3600;
127                 i = 1;
128         }
129         if (i || ts.tv_sec >= 60) {
130                 ts.tv_sec %= 60;
131                 i = 1;
132         }
133         sysinfo.uptime=ts.tv_sec;
134
135         /* Use the information from the mib to get our load averages */
136         for (i = 0; i < 3; i++)
137                 sysinfo.loads[i] = averunnable.ldavg[i];
138
139         sysinfo.totalram = physmem * PAGE_SIZE;
140         sysinfo.freeram = sysinfo.totalram - vmstats.v_wire_count * PAGE_SIZE;
141
142         sysinfo.sharedram = 0;
143         for (object = TAILQ_FIRST(&vm_object_list); object != NULL;
144              object = TAILQ_NEXT(object, object_list))
145                 if (object->shadow_count > 1)
146                         sysinfo.sharedram += object->resident_page_count;
147
148         sysinfo.sharedram *= PAGE_SIZE;
149         sysinfo.bufferram = 0;
150
151         if (swapblist == NULL) {
152                 sysinfo.totalswap= 0;
153                 sysinfo.freeswap = 0;
154         } else {
155                 sysinfo.totalswap = swapblist->bl_blocks * 1024;
156                 sysinfo.freeswap = swapblist->bl_root->u.bmu_avail * PAGE_SIZE;
157         }
158
159         sysinfo.procs = 20; /* Hack */
160
161         return copyout(&sysinfo, (caddr_t)args->info, sizeof(sysinfo));
162 }
163 #endif /*!__alpha__*/
164
165 #ifndef __alpha__
166 int
167 linux_alarm(struct linux_alarm_args *args)
168 {
169         struct thread *td = curthread;
170         struct proc *p = td->td_proc;
171         struct itimerval it, old_it;
172         struct timeval tv;
173         int s;
174
175         KKASSERT(p);
176
177 #ifdef DEBUG
178         if (ldebug(alarm))
179                 printf(ARGS(alarm, "%u"), args->secs);
180 #endif
181
182         if (args->secs > 100000000)
183                 return EINVAL;
184
185         it.it_value.tv_sec = (long)args->secs;
186         it.it_value.tv_usec = 0;
187         it.it_interval.tv_sec = 0;
188         it.it_interval.tv_usec = 0;
189         s = splsoftclock();
190         old_it = p->p_realtimer;
191         getmicrouptime(&tv);
192         if (timevalisset(&old_it.it_value))
193                 untimeout(realitexpire, (caddr_t)p, p->p_ithandle);
194         if (it.it_value.tv_sec != 0) {
195                 p->p_ithandle = timeout(realitexpire, (caddr_t)p,
196                     tvtohz(&it.it_value));
197                 timevaladd(&it.it_value, &tv);
198         }
199         p->p_realtimer = it;
200         splx(s);
201         if (timevalcmp(&old_it.it_value, &tv, >)) {
202                 timevalsub(&old_it.it_value, &tv);
203                 if (old_it.it_value.tv_usec != 0)
204                         old_it.it_value.tv_sec++;
205                 args->sysmsg_result = old_it.it_value.tv_sec;
206         }
207         return 0;
208 }
209 #endif /*!__alpha__*/
210
211 int
212 linux_brk(struct linux_brk_args *args)
213 {
214         struct thread *td = curthread;
215         struct proc *p = td->td_proc;
216         struct vmspace *vm;
217         vm_offset_t new, old;
218         struct obreak_args bsd_args;
219
220         KKASSERT(p);
221         vm = p->p_vmspace;
222 #ifdef DEBUG
223         if (ldebug(brk))
224                 printf(ARGS(brk, "%p"), (void *)args->dsend);
225 #endif
226         old = (vm_offset_t)vm->vm_daddr + ctob(vm->vm_dsize);
227         new = (vm_offset_t)args->dsend;
228         bsd_args.sysmsg_result = 0;
229         bsd_args.nsize = (char *) new;
230         bsd_args.sysmsg_result = 0;
231         if (((caddr_t)new > vm->vm_daddr) && !obreak(&bsd_args))
232                 args->sysmsg_result = (long)new;
233         else
234                 args->sysmsg_result = (long)old;
235
236         return 0;
237 }
238
239 int
240 linux_uselib(struct linux_uselib_args *args)
241 {
242         struct thread *td = curthread;
243         struct proc *p;
244         struct nameidata ni;
245         struct vnode *vp;
246         struct exec *a_out;
247         struct vattr attr;
248         vm_offset_t vmaddr;
249         unsigned long file_offset;
250         vm_offset_t buffer;
251         unsigned long bss_size;
252         int error;
253         caddr_t sg;
254         int locked;
255
256         KKASSERT(td->td_proc);
257         p = td->td_proc;
258
259         sg = stackgap_init();
260         CHECKALTEXIST(&sg, args->library);
261
262 #ifdef DEBUG
263         if (ldebug(uselib))
264                 printf(ARGS(uselib, "%s"), args->library);
265 #endif
266
267         a_out = NULL;
268         locked = 0;
269         vp = NULL;
270
271         NDINIT(&ni, NAMEI_LOOKUP, CNP_FOLLOW | CNP_LOCKLEAF,
272                 UIO_USERSPACE, args->library, td);
273         error = namei(&ni);
274         if (error)
275                 goto cleanup;
276
277         vp = ni.ni_vp;
278         /*
279          * XXX - This looks like a bogus check. A LOCKLEAF namei should not
280          * succeed without returning a vnode.
281          */
282         if (vp == NULL) {
283                 error = ENOEXEC;        /* ?? */
284                 goto cleanup;
285         }
286         NDFREE(&ni, NDF_ONLY_PNBUF);
287
288         /*
289          * From here on down, we have a locked vnode that must be unlocked.
290          */
291         locked++;
292
293         /* Writable? */
294         if (vp->v_writecount) {
295                 error = ETXTBSY;
296                 goto cleanup;
297         }
298
299         /* Executable? */
300         error = VOP_GETATTR(vp, &attr, td);
301         if (error)
302                 goto cleanup;
303
304         if ((vp->v_mount->mnt_flag & MNT_NOEXEC) ||
305             ((attr.va_mode & 0111) == 0) || (attr.va_type != VREG)) {
306                 error = ENOEXEC;
307                 goto cleanup;
308         }
309
310         /* Sensible size? */
311         if (attr.va_size == 0) {
312                 error = ENOEXEC;
313                 goto cleanup;
314         }
315
316         /* Can we access it? */
317         error = VOP_ACCESS(vp, VEXEC, p->p_ucred, td);
318         if (error)
319                 goto cleanup;
320
321         error = VOP_OPEN(vp, FREAD, p->p_ucred, td);
322         if (error)
323                 goto cleanup;
324
325         /*
326          * Lock no longer needed
327          */
328         VOP_UNLOCK(vp, 0, td);
329         locked = 0;
330
331         /* Pull in executable header into kernel_map */
332         error = vm_mmap(kernel_map, (vm_offset_t *)&a_out, PAGE_SIZE,
333             VM_PROT_READ, VM_PROT_READ, 0, (caddr_t)vp, 0);
334         if (error)
335                 goto cleanup;
336
337         /* Is it a Linux binary ? */
338         if (((a_out->a_magic >> 16) & 0xff) != 0x64) {
339                 error = ENOEXEC;
340                 goto cleanup;
341         }
342
343         /*
344          * While we are here, we should REALLY do some more checks
345          */
346
347         /* Set file/virtual offset based on a.out variant. */
348         switch ((int)(a_out->a_magic & 0xffff)) {
349         case 0413:      /* ZMAGIC */
350                 file_offset = 1024;
351                 break;
352         case 0314:      /* QMAGIC */
353                 file_offset = 0;
354                 break;
355         default:
356                 error = ENOEXEC;
357                 goto cleanup;
358         }
359
360         bss_size = round_page(a_out->a_bss);
361
362         /* Check various fields in header for validity/bounds. */
363         if (a_out->a_text & PAGE_MASK || a_out->a_data & PAGE_MASK) {
364                 error = ENOEXEC;
365                 goto cleanup;
366         }
367
368         /* text + data can't exceed file size */
369         if (a_out->a_data + a_out->a_text > attr.va_size) {
370                 error = EFAULT;
371                 goto cleanup;
372         }
373
374         /*
375          * text/data/bss must not exceed limits
376          * XXX - this is not complete. it should check current usage PLUS
377          * the resources needed by this library.
378          */
379         if (a_out->a_text > maxtsiz ||
380             a_out->a_data + bss_size > p->p_rlimit[RLIMIT_DATA].rlim_cur) {
381                 error = ENOMEM;
382                 goto cleanup;
383         }
384
385         /* prevent more writers */
386         vp->v_flag |= VTEXT;
387
388         /*
389          * Check if file_offset page aligned. Currently we cannot handle
390          * misalinged file offsets, and so we read in the entire image
391          * (what a waste).
392          */
393         if (file_offset & PAGE_MASK) {
394 #ifdef DEBUG
395                 printf("uselib: Non page aligned binary %lu\n", file_offset);
396 #endif
397                 /* Map text+data read/write/execute */
398
399                 /* a_entry is the load address and is page aligned */
400                 vmaddr = trunc_page(a_out->a_entry);
401
402                 /* get anon user mapping, read+write+execute */
403                 error = vm_map_find(&p->p_vmspace->vm_map, NULL, 0,
404                     &vmaddr, a_out->a_text + a_out->a_data, FALSE, VM_PROT_ALL,
405                     VM_PROT_ALL, 0);
406                 if (error)
407                         goto cleanup;
408
409                 /* map file into kernel_map */
410                 error = vm_mmap(kernel_map, &buffer,
411                     round_page(a_out->a_text + a_out->a_data + file_offset),
412                     VM_PROT_READ, VM_PROT_READ, 0, (caddr_t)vp,
413                     trunc_page(file_offset));
414                 if (error)
415                         goto cleanup;
416
417                 /* copy from kernel VM space to user space */
418                 error = copyout((caddr_t)(uintptr_t)(buffer + file_offset),
419                     (caddr_t)vmaddr, a_out->a_text + a_out->a_data);
420
421                 /* release temporary kernel space */
422                 vm_map_remove(kernel_map, buffer, buffer +
423                     round_page(a_out->a_text + a_out->a_data + file_offset));
424
425                 if (error)
426                         goto cleanup;
427         } else {
428 #ifdef DEBUG
429                 printf("uselib: Page aligned binary %lu\n", file_offset);
430 #endif
431                 /*
432                  * for QMAGIC, a_entry is 20 bytes beyond the load address
433                  * to skip the executable header
434                  */
435                 vmaddr = trunc_page(a_out->a_entry);
436
437                 /*
438                  * Map it all into the process's space as a single
439                  * copy-on-write "data" segment.
440                  */
441                 error = vm_mmap(&p->p_vmspace->vm_map, &vmaddr,
442                     a_out->a_text + a_out->a_data, VM_PROT_ALL, VM_PROT_ALL,
443                     MAP_PRIVATE | MAP_FIXED, (caddr_t)vp, file_offset);
444                 if (error)
445                         goto cleanup;
446         }
447 #ifdef DEBUG
448         printf("mem=%08lx = %08lx %08lx\n", (long)vmaddr, ((long*)vmaddr)[0],
449             ((long*)vmaddr)[1]);
450 #endif
451         if (bss_size != 0) {
452                 /* Calculate BSS start address */
453                 vmaddr = trunc_page(a_out->a_entry) + a_out->a_text +
454                     a_out->a_data;
455
456                 /* allocate some 'anon' space */
457                 error = vm_map_find(&p->p_vmspace->vm_map, NULL, 0,
458                     &vmaddr, bss_size, FALSE, VM_PROT_ALL, VM_PROT_ALL, 0);
459                 if (error)
460                         goto cleanup;
461         }
462
463 cleanup:
464         /* Unlock vnode if needed */
465         if (locked)
466                 VOP_UNLOCK(vp, 0, td);
467
468         /* Release the kernel mapping. */
469         if (a_out)
470                 vm_map_remove(kernel_map, (vm_offset_t)a_out,
471                     (vm_offset_t)a_out + PAGE_SIZE);
472
473         return error;
474 }
475
476 int
477 linux_select(struct linux_select_args *args)
478 {
479         struct select_args bsa;
480         struct timeval tv0, tv1, utv, *tvp;
481         caddr_t sg;
482         int error;
483
484 #ifdef DEBUG
485         if (ldebug(select))
486                 printf(ARGS(select, "%d, %p, %p, %p, %p"), args->nfds,
487                     (void *)args->readfds, (void *)args->writefds,
488                     (void *)args->exceptfds, (void *)args->timeout);
489 #endif
490
491         error = 0;
492         bsa.sysmsg_result = 0;
493         bsa.nd = args->nfds;
494         bsa.in = args->readfds;
495         bsa.ou = args->writefds;
496         bsa.ex = args->exceptfds;
497         bsa.tv = (struct timeval *)args->timeout;
498
499         /*
500          * Store current time for computation of the amount of
501          * time left.
502          */
503         if (args->timeout) {
504                 if ((error = copyin((caddr_t)args->timeout, &utv,
505                     sizeof(utv))))
506                         goto select_out;
507 #ifdef DEBUG
508                 if (ldebug(select))
509                         printf(LMSG("incoming timeout (%ld/%ld)"),
510                             utv.tv_sec, utv.tv_usec);
511 #endif
512
513                 if (itimerfix(&utv)) {
514                         /*
515                          * The timeval was invalid.  Convert it to something
516                          * valid that will act as it does under Linux.
517                          */
518                         sg = stackgap_init();
519                         tvp = stackgap_alloc(&sg, sizeof(utv));
520                         utv.tv_sec += utv.tv_usec / 1000000;
521                         utv.tv_usec %= 1000000;
522                         if (utv.tv_usec < 0) {
523                                 utv.tv_sec -= 1;
524                                 utv.tv_usec += 1000000;
525                         }
526                         if (utv.tv_sec < 0)
527                                 timevalclear(&utv);
528                         if ((error = copyout(&utv, tvp, sizeof(utv))))
529                                 goto select_out;
530                         bsa.tv = tvp;
531                 }
532                 microtime(&tv0);
533         }
534
535         error = select(&bsa);
536         args->sysmsg_result = bsa.sysmsg_result;
537 #ifdef DEBUG
538         if (ldebug(select))
539                 printf(LMSG("real select returns %d"), error);
540 #endif
541         if (error) {
542                 /*
543                  * See fs/select.c in the Linux kernel.  Without this,
544                  * Maelstrom doesn't work.
545                  */
546                 if (error == ERESTART)
547                         error = EINTR;
548                 goto select_out;
549         }
550
551         if (args->timeout) {
552                 if (args->sysmsg_result) {
553                         /*
554                          * Compute how much time was left of the timeout,
555                          * by subtracting the current time and the time
556                          * before we started the call, and subtracting
557                          * that result from the user-supplied value.
558                          */
559                         microtime(&tv1);
560                         timevalsub(&tv1, &tv0);
561                         timevalsub(&utv, &tv1);
562                         if (utv.tv_sec < 0)
563                                 timevalclear(&utv);
564                 } else
565                         timevalclear(&utv);
566 #ifdef DEBUG
567                 if (ldebug(select))
568                         printf(LMSG("outgoing timeout (%ld/%ld)"),
569                             utv.tv_sec, utv.tv_usec);
570 #endif
571                 if ((error = copyout(&utv, (caddr_t)args->timeout,
572                     sizeof(utv))))
573                         goto select_out;
574         }
575
576 select_out:
577 #ifdef DEBUG
578         if (ldebug(select))
579                 printf(LMSG("select_out -> %d"), error);
580 #endif
581         return error;
582 }
583
584 int     
585 linux_mremap(struct linux_mremap_args *args)
586 {
587         struct munmap_args bsd_args; 
588         int error = 0;
589
590 #ifdef DEBUG
591         if (ldebug(mremap))
592                 printf(ARGS(mremap, "%p, %08lx, %08lx, %08lx"),
593                     (void *)args->addr, 
594                     (unsigned long)args->old_len, 
595                     (unsigned long)args->new_len,
596                     (unsigned long)args->flags);
597 #endif
598         args->new_len = round_page(args->new_len);
599         args->old_len = round_page(args->old_len);
600
601         if (args->new_len > args->old_len) {
602                 args->sysmsg_result = 0;
603                 return ENOMEM;
604         }
605
606         if (args->new_len < args->old_len) {
607                 bsd_args.sysmsg_result = 0;
608                 bsd_args.addr = (caddr_t)(args->addr + args->new_len);
609                 bsd_args.len = args->old_len - args->new_len;
610                 error = munmap(&bsd_args);
611         }
612
613         args->sysmsg_resultp = error ? NULL : (void *)args->addr;
614         return error;
615 }
616
617 #define LINUX_MS_ASYNC          0x0001
618 #define LINUX_MS_INVALIDATE     0x0002
619 #define LINUX_MS_SYNC           0x0004
620
621 int
622 linux_msync(struct linux_msync_args *args)
623 {
624         struct msync_args bsd_args;
625         int error;
626
627         bsd_args.addr = (caddr_t)args->addr;
628         bsd_args.len = args->len;
629         bsd_args.flags = args->fl & ~LINUX_MS_SYNC;
630         bsd_args.sysmsg_result = 0;
631
632         error = msync(&bsd_args);
633         args->sysmsg_result = bsd_args.sysmsg_result;
634         return(error);
635 }
636
637 #ifndef __alpha__
638 int
639 linux_time(struct linux_time_args *args)
640 {
641         struct timeval tv;
642         l_time_t tm;
643         int error;
644
645 #ifdef DEBUG
646         if (ldebug(time))
647                 printf(ARGS(time, "*"));
648 #endif
649
650         microtime(&tv);
651         tm = tv.tv_sec;
652         if (args->tm && (error = copyout(&tm, (caddr_t)args->tm, sizeof(tm))))
653                 return error;
654         args->sysmsg_lresult = tm;
655         return 0;
656 }
657 #endif  /*!__alpha__*/
658
659 struct l_times_argv {
660         l_long          tms_utime;
661         l_long          tms_stime;
662         l_long          tms_cutime;
663         l_long          tms_cstime;
664 };
665
666 #ifdef __alpha__
667 #define CLK_TCK 1024    /* Linux uses 1024 on alpha */
668 #else
669 #define CLK_TCK 100     /* Linux uses 100 */
670 #endif
671
672 #define CONVTCK(r)      (r.tv_sec * CLK_TCK + r.tv_usec / (1000000 / CLK_TCK))
673
674 int
675 linux_times(struct linux_times_args *args)
676 {
677         struct thread *td = curthread;
678         struct proc *p = td->td_proc;
679         struct timeval tv;
680         struct l_times_argv tms;
681         struct rusage ru;
682         int error;
683
684         KKASSERT(p);
685 #ifdef DEBUG
686         if (ldebug(times))
687                 printf(ARGS(times, "*"));
688 #endif
689
690         calcru(p, &ru.ru_utime, &ru.ru_stime, NULL);
691
692         tms.tms_utime = CONVTCK(ru.ru_utime);
693         tms.tms_stime = CONVTCK(ru.ru_stime);
694
695         tms.tms_cutime = CONVTCK(p->p_stats->p_cru.ru_utime);
696         tms.tms_cstime = CONVTCK(p->p_stats->p_cru.ru_stime);
697
698         if ((error = copyout(&tms, (caddr_t)args->buf, sizeof(tms))))
699                 return error;
700
701         microuptime(&tv);
702         args->sysmsg_result = (int)CONVTCK(tv);
703         return 0;
704 }
705
706 int
707 linux_newuname(struct linux_newuname_args *args)
708 {
709         struct thread *td = curthread;
710         struct l_new_utsname utsname;
711         char *osrelease, *osname;
712
713 #ifdef DEBUG
714         if (ldebug(newuname))
715                 printf(ARGS(newuname, "*"));
716 #endif
717
718         osname = linux_get_osname(td);
719         osrelease = linux_get_osrelease(td);
720
721         bzero(&utsname, sizeof(utsname));
722         strncpy(utsname.sysname, osname, LINUX_MAX_UTSNAME-1);
723         strncpy(utsname.nodename, hostname, LINUX_MAX_UTSNAME-1);
724         strncpy(utsname.release, osrelease, LINUX_MAX_UTSNAME-1);
725         strncpy(utsname.version, version, LINUX_MAX_UTSNAME-1);
726         strncpy(utsname.machine, machine, LINUX_MAX_UTSNAME-1);
727         strncpy(utsname.domainname, domainname, LINUX_MAX_UTSNAME-1);
728
729         return (copyout(&utsname, (caddr_t)args->buf, sizeof(utsname)));
730 }
731
732 #if defined(__i386__)
733 struct l_utimbuf {
734         l_time_t l_actime;
735         l_time_t l_modtime;
736 };
737
738 int
739 linux_utime(struct linux_utime_args *args)
740 {
741         struct utimes_args /* {
742                 char    *path;
743                 struct  timeval *tptr;
744         } */ bsdutimes;
745         struct timeval tv[2], *tvp;
746         struct l_utimbuf lut;
747         int error;
748         caddr_t sg;
749
750         sg = stackgap_init();
751         CHECKALTEXIST(&sg, args->fname);
752
753 #ifdef DEBUG
754         if (ldebug(utime))
755                 printf(ARGS(utime, "%s, *"), args->fname);
756 #endif
757
758         if (args->times) {
759                 if ((error = copyin((caddr_t)args->times, &lut, sizeof lut)))
760                         return error;
761                 tv[0].tv_sec = lut.l_actime;
762                 tv[0].tv_usec = 0;
763                 tv[1].tv_sec = lut.l_modtime;
764                 tv[1].tv_usec = 0;
765                 /* so that utimes can copyin */
766                 tvp = (struct timeval *)stackgap_alloc(&sg, sizeof(tv));
767                 if (tvp == NULL)
768                         return (ENAMETOOLONG);
769                 if ((error = copyout(tv, tvp, sizeof(tv))))
770                         return error;
771                 bsdutimes.tptr = tvp;
772         } else
773                 bsdutimes.tptr = NULL;
774
775         bsdutimes.path = args->fname;
776         bsdutimes.sysmsg_result = 0;
777         error = utimes(&bsdutimes);
778         args->sysmsg_result = bsdutimes.sysmsg_result;
779         return(error);
780 }
781 #endif /* __i386__ */
782
783 #define __WCLONE 0x80000000
784
785 #ifndef __alpha__
786 int
787 linux_waitpid(struct linux_waitpid_args *args)
788 {
789         struct wait_args bsd_args;
790         int error, tmpstat;
791
792 #ifdef DEBUG
793         if (ldebug(waitpid))
794                 printf(ARGS(waitpid, "%d, %p, %d"),
795                     args->pid, (void *)args->status, args->options);
796 #endif
797
798         bsd_args.sysmsg_result = 0;
799         bsd_args.pid = args->pid;
800         bsd_args.status = args->status;
801         bsd_args.options = (args->options & (WNOHANG | WUNTRACED));
802         /* WLINUXCLONE should be equal to __WCLONE, but we make sure */
803         if (args->options & __WCLONE)
804                 bsd_args.options |= WLINUXCLONE;
805         bsd_args.rusage = NULL;
806
807         if ((error = wait4(&bsd_args)) != 0)
808                 return error;
809         args->sysmsg_result = bsd_args.sysmsg_result;
810
811         if (args->status) {
812                 if ((error = copyin((caddr_t)args->status, &tmpstat,
813                     sizeof(int))) != 0)
814                         return error;
815                 tmpstat &= 0xffff;
816                 if (WIFSIGNALED(tmpstat))
817                         tmpstat = (tmpstat & 0xffffff80) |
818                             BSD_TO_LINUX_SIGNAL(WTERMSIG(tmpstat));
819                 else if (WIFSTOPPED(tmpstat))
820                         tmpstat = (tmpstat & 0xffff00ff) |
821                             (BSD_TO_LINUX_SIGNAL(WSTOPSIG(tmpstat)) << 8);
822                 return copyout(&tmpstat, (caddr_t)args->status, sizeof(int));
823         }
824
825         return 0;
826 }
827 #endif  /*!__alpha__*/
828
829 int
830 linux_wait4(struct linux_wait4_args *args)
831 {
832         struct thread *td = curthread;
833         struct proc *p = td->td_proc;
834         struct wait_args bsd_args;
835         int error, tmpstat;
836
837         KKASSERT(p);
838
839 #ifdef DEBUG
840         if (ldebug(wait4))
841                 printf(ARGS(wait4, "%d, %p, %d, %p"),
842                     args->pid, (void *)args->status, args->options,
843                     (void *)args->rusage);
844 #endif
845
846         bsd_args.sysmsg_result = 0;
847         bsd_args.pid = args->pid;
848         bsd_args.status = args->status;
849         bsd_args.options = (args->options & (WNOHANG | WUNTRACED));
850         /* WLINUXCLONE should be equal to __WCLONE, but we make sure */
851         if (args->options & __WCLONE)
852                 bsd_args.options |= WLINUXCLONE;
853         bsd_args.rusage = (struct rusage *)args->rusage;
854
855         if ((error = wait4(&bsd_args)) != 0)
856                 return error;
857         args->sysmsg_result = bsd_args.sysmsg_result;
858
859         SIGDELSET(p->p_siglist, SIGCHLD);
860
861         if (args->status) {
862                 if ((error = copyin((caddr_t)args->status, &tmpstat,
863                     sizeof(int))) != 0)
864                         return error;
865                 tmpstat &= 0xffff;
866                 if (WIFSIGNALED(tmpstat))
867                         tmpstat = (tmpstat & 0xffffff80) |
868                             BSD_TO_LINUX_SIGNAL(WTERMSIG(tmpstat));
869                 else if (WIFSTOPPED(tmpstat))
870                         tmpstat = (tmpstat & 0xffff00ff) |
871                             (BSD_TO_LINUX_SIGNAL(WSTOPSIG(tmpstat)) << 8);
872                 return copyout(&tmpstat, (caddr_t)args->status, sizeof(int));
873         }
874
875         return 0;
876 }
877
878 int
879 linux_mknod(struct linux_mknod_args *args)
880 {
881         int error;
882         caddr_t sg;
883         struct mknod_args bsd_mknod;
884         struct mkfifo_args bsd_mkfifo;
885
886         sg = stackgap_init();
887
888         CHECKALTCREAT(&sg, args->path);
889
890 #ifdef DEBUG
891         if (ldebug(mknod))
892                 printf(ARGS(mknod, "%s, %d, %d"),
893                     args->path, args->mode, args->dev);
894 #endif
895
896         if (args->mode & S_IFIFO) {
897                 bsd_mkfifo.path = args->path;
898                 bsd_mkfifo.mode = args->mode;
899                 bsd_mkfifo.sysmsg_result = 0;
900                 error = mkfifo(&bsd_mkfifo);
901                 args->sysmsg_result = bsd_mkfifo.sysmsg_result;
902         } else {
903                 bsd_mknod.path = args->path;
904                 bsd_mknod.mode = args->mode;
905                 bsd_mknod.dev = args->dev;
906                 bsd_mknod.sysmsg_result = 0;
907                 error = mknod(&bsd_mknod);
908                 args->sysmsg_result = bsd_mknod.sysmsg_result;
909         }
910         return(error);
911 }
912
913 /*
914  * UGH! This is just about the dumbest idea I've ever heard!!
915  */
916 int
917 linux_personality(struct linux_personality_args *args)
918 {
919 #ifdef DEBUG
920         if (ldebug(personality))
921                 printf(ARGS(personality, "%d"), args->per);
922 #endif
923 #ifndef __alpha__
924         if (args->per != 0)
925                 return EINVAL;
926 #endif
927
928         /* Yes Jim, it's still a Linux... */
929         args->sysmsg_result = 0;
930         return 0;
931 }
932
933 /*
934  * Wrappers for get/setitimer for debugging..
935  */
936 int
937 linux_setitimer(struct linux_setitimer_args *args)
938 {
939         struct setitimer_args bsa;
940         struct itimerval foo;
941         int error;
942
943 #ifdef DEBUG
944         if (ldebug(setitimer))
945                 printf(ARGS(setitimer, "%p, %p"),
946                     (void *)args->itv, (void *)args->oitv);
947 #endif
948         bsa.which = args->which;
949         bsa.itv = (struct itimerval *)args->itv;
950         bsa.oitv = (struct itimerval *)args->oitv;
951         bsa.sysmsg_result = 0;
952         if (args->itv) {
953             if ((error = copyin((caddr_t)args->itv, &foo, sizeof(foo))))
954                 return error;
955 #ifdef DEBUG
956             if (ldebug(setitimer)) {
957                 printf("setitimer: value: sec: %ld, usec: %ld\n",
958                     foo.it_value.tv_sec, foo.it_value.tv_usec);
959                 printf("setitimer: interval: sec: %ld, usec: %ld\n",
960                     foo.it_interval.tv_sec, foo.it_interval.tv_usec);
961             }
962 #endif
963         }
964         error = setitimer(&bsa);
965         args->sysmsg_result = bsa.sysmsg_result;
966         return(error);
967 }
968
969 int
970 linux_getitimer(struct linux_getitimer_args *args)
971 {
972         struct getitimer_args bsa;
973         int error;
974 #ifdef DEBUG
975         if (ldebug(getitimer))
976                 printf(ARGS(getitimer, "%p"), (void *)args->itv);
977 #endif
978         bsa.which = args->which;
979         bsa.itv = (struct itimerval *)args->itv;
980         bsa.sysmsg_result = 0;
981         error = getitimer(&bsa);
982         args->sysmsg_result = bsa.sysmsg_result;
983         return(error);
984 }
985
986 #ifndef __alpha__
987 int
988 linux_nice(struct linux_nice_args *args)
989 {
990         struct setpriority_args bsd_args;
991         int error;
992
993         bsd_args.which = PRIO_PROCESS;
994         bsd_args.who = 0;       /* current process */
995         bsd_args.prio = args->inc;
996         bsd_args.sysmsg_result = 0;
997         error = setpriority(&bsd_args);
998         args->sysmsg_result = bsd_args.sysmsg_result;
999         return(error);
1000 }
1001 #endif  /*!__alpha__*/
1002
1003 int
1004 linux_setgroups(struct linux_setgroups_args *args)
1005 {
1006         struct thread *td = curthread;
1007         struct proc *p = td->td_proc;
1008         struct ucred *newcred, *oldcred;
1009         l_gid_t linux_gidset[NGROUPS];
1010         gid_t *bsd_gidset;
1011         int ngrp, error;
1012
1013         KKASSERT(p);
1014
1015         ngrp = args->gidsetsize;
1016         oldcred = p->p_ucred;
1017
1018         /*
1019          * cr_groups[0] holds egid. Setting the whole set from
1020          * the supplied set will cause egid to be changed too.
1021          * Keep cr_groups[0] unchanged to prevent that.
1022          */
1023
1024         if ((error = suser_cred(oldcred, PRISON_ROOT)) != 0)
1025                 return (error);
1026
1027         if (ngrp >= NGROUPS)
1028                 return (EINVAL);
1029
1030         newcred = crdup(oldcred);
1031         if (ngrp > 0) {
1032                 error = copyin((caddr_t)args->grouplist, linux_gidset,
1033                                ngrp * sizeof(l_gid_t));
1034                 if (error)
1035                         return (error);
1036
1037                 newcred->cr_ngroups = ngrp + 1;
1038
1039                 bsd_gidset = newcred->cr_groups;
1040                 ngrp--;
1041                 while (ngrp >= 0) {
1042                         bsd_gidset[ngrp + 1] = linux_gidset[ngrp];
1043                         ngrp--;
1044                 }
1045         } else {
1046                 newcred->cr_ngroups = 1;
1047         }
1048
1049         setsugid();
1050         p->p_ucred = newcred;
1051         crfree(oldcred);
1052         return (0);
1053 }
1054
1055 int
1056 linux_getgroups(struct linux_getgroups_args *args)
1057 {
1058         struct thread *td = curthread;
1059         struct proc *p = td->td_proc;
1060         struct ucred *cred;
1061         l_gid_t linux_gidset[NGROUPS];
1062         gid_t *bsd_gidset;
1063         int bsd_gidsetsz, ngrp, error;
1064
1065         KKASSERT(p);
1066
1067         cred = p->p_ucred;
1068         bsd_gidset = cred->cr_groups;
1069         bsd_gidsetsz = cred->cr_ngroups - 1;
1070
1071         /*
1072          * cr_groups[0] holds egid. Returning the whole set
1073          * here will cause a duplicate. Exclude cr_groups[0]
1074          * to prevent that.
1075          */
1076
1077         if ((ngrp = args->gidsetsize) == 0) {
1078                 args->sysmsg_result = bsd_gidsetsz;
1079                 return (0);
1080         }
1081
1082         if (ngrp < bsd_gidsetsz)
1083                 return (EINVAL);
1084
1085         ngrp = 0;
1086         while (ngrp < bsd_gidsetsz) {
1087                 linux_gidset[ngrp] = bsd_gidset[ngrp + 1];
1088                 ngrp++;
1089         }
1090
1091         if ((error = copyout(linux_gidset, (caddr_t)args->grouplist,
1092             ngrp * sizeof(l_gid_t))))
1093                 return (error);
1094
1095         args->sysmsg_result = ngrp;
1096         return (0);
1097 }
1098
1099 #ifndef __alpha__
1100 int
1101 linux_setrlimit(struct linux_setrlimit_args *args)
1102 {
1103         struct __setrlimit_args bsd;
1104         struct l_rlimit rlim;
1105         int error;
1106         caddr_t sg = stackgap_init();
1107
1108 #ifdef DEBUG
1109         if (ldebug(setrlimit))
1110                 printf(ARGS(setrlimit, "%d, %p"),
1111                     args->resource, (void *)args->rlim);
1112 #endif
1113
1114         if (args->resource >= LINUX_RLIM_NLIMITS)
1115                 return (EINVAL);
1116
1117         bsd.which = linux_to_bsd_resource[args->resource];
1118         if (bsd.which == -1)
1119                 return (EINVAL);
1120
1121         error = copyin((caddr_t)args->rlim, &rlim, sizeof(rlim));
1122         if (error)
1123                 return (error);
1124
1125         bsd.rlp = stackgap_alloc(&sg, sizeof(struct rlimit));
1126         bsd.rlp->rlim_cur = (rlim_t)rlim.rlim_cur;
1127         bsd.rlp->rlim_max = (rlim_t)rlim.rlim_max;
1128         bsd.sysmsg_result = 0;
1129         error = setrlimit(&bsd);
1130         args->sysmsg_result = bsd.sysmsg_result;
1131         return(error);
1132 }
1133
1134 int
1135 linux_old_getrlimit(struct linux_old_getrlimit_args *args)
1136 {
1137         struct __getrlimit_args bsd;
1138         struct l_rlimit rlim;
1139         int error;
1140         caddr_t sg = stackgap_init();
1141
1142 #ifdef DEBUG
1143         if (ldebug(old_getrlimit))
1144                 printf(ARGS(old_getrlimit, "%d, %p"),
1145                     args->resource, (void *)args->rlim);
1146 #endif
1147
1148         if (args->resource >= LINUX_RLIM_NLIMITS)
1149                 return (EINVAL);
1150
1151         bsd.which = linux_to_bsd_resource[args->resource];
1152         if (bsd.which == -1)
1153                 return (EINVAL);
1154
1155         bsd.rlp = stackgap_alloc(&sg, sizeof(struct rlimit));
1156         bsd.sysmsg_result = 0;
1157         error = getrlimit(&bsd);
1158         if (error)
1159                 return (error);
1160         args->sysmsg_result = bsd.sysmsg_result;
1161         rlim.rlim_cur = (unsigned long)bsd.rlp->rlim_cur;
1162         if (rlim.rlim_cur == ULONG_MAX)
1163                 rlim.rlim_cur = LONG_MAX;
1164         rlim.rlim_max = (unsigned long)bsd.rlp->rlim_max;
1165         if (rlim.rlim_max == ULONG_MAX)
1166                 rlim.rlim_max = LONG_MAX;
1167         return (copyout(&rlim, (caddr_t)args->rlim, sizeof(rlim)));
1168 }
1169
1170 int
1171 linux_getrlimit(struct linux_getrlimit_args *args)
1172 {
1173         struct __getrlimit_args bsd;
1174         struct l_rlimit rlim;
1175         int error;
1176         caddr_t sg = stackgap_init();
1177
1178 #ifdef DEBUG
1179         if (ldebug(getrlimit))
1180                 printf(ARGS(getrlimit, "%d, %p"),
1181                     args->resource, (void *)args->rlim);
1182 #endif
1183
1184         if (args->resource >= LINUX_RLIM_NLIMITS)
1185                 return (EINVAL);
1186
1187         bsd.which = linux_to_bsd_resource[args->resource];
1188         if (bsd.which == -1)
1189                 return (EINVAL);
1190
1191         bsd.rlp = stackgap_alloc(&sg, sizeof(struct rlimit));
1192         bsd.sysmsg_result = 0;
1193         error = getrlimit(&bsd);
1194         if (error)
1195                 return (error);
1196         args->sysmsg_result = bsd.sysmsg_result;
1197
1198         rlim.rlim_cur = (l_ulong)bsd.rlp->rlim_cur;
1199         rlim.rlim_max = (l_ulong)bsd.rlp->rlim_max;
1200         return (copyout(&rlim, (caddr_t)args->rlim, sizeof(rlim)));
1201 }
1202 #endif /*!__alpha__*/
1203
1204 int
1205 linux_sched_setscheduler(struct linux_sched_setscheduler_args *args)
1206 {
1207         struct sched_setscheduler_args bsd;
1208         int error;
1209
1210 #ifdef DEBUG
1211         if (ldebug(sched_setscheduler))
1212                 printf(ARGS(sched_setscheduler, "%d, %d, %p"),
1213                     args->pid, args->policy, (const void *)args->param);
1214 #endif
1215
1216         switch (args->policy) {
1217         case LINUX_SCHED_OTHER:
1218                 bsd.policy = SCHED_OTHER;
1219                 break;
1220         case LINUX_SCHED_FIFO:
1221                 bsd.policy = SCHED_FIFO;
1222                 break;
1223         case LINUX_SCHED_RR:
1224                 bsd.policy = SCHED_RR;
1225                 break;
1226         default:
1227                 return EINVAL;
1228         }
1229
1230         bsd.pid = args->pid;
1231         bsd.param = (struct sched_param *)args->param;
1232         bsd.sysmsg_result = 0;
1233
1234         error = sched_setscheduler(&bsd);
1235         args->sysmsg_result = bsd.sysmsg_result;
1236         return(error);
1237 }
1238
1239 int
1240 linux_sched_getscheduler(struct linux_sched_getscheduler_args *args)
1241 {
1242         struct sched_getscheduler_args bsd;
1243         int error;
1244
1245 #ifdef DEBUG
1246         if (ldebug(sched_getscheduler))
1247                 printf(ARGS(sched_getscheduler, "%d"), args->pid);
1248 #endif
1249
1250         bsd.sysmsg_result = 0;
1251         bsd.pid = args->pid;
1252         error = sched_getscheduler(&bsd);
1253         args->sysmsg_result = bsd.sysmsg_result;
1254
1255         switch (args->sysmsg_result) {
1256         case SCHED_OTHER:
1257                 args->sysmsg_result = LINUX_SCHED_OTHER;
1258                 break;
1259         case SCHED_FIFO:
1260                 args->sysmsg_result = LINUX_SCHED_FIFO;
1261                 break;
1262         case SCHED_RR:
1263                 args->sysmsg_result = LINUX_SCHED_RR;
1264                 break;
1265         }
1266         return error;
1267 }
1268
1269 int
1270 linux_sched_get_priority_max(struct linux_sched_get_priority_max_args *args)
1271 {
1272         struct sched_get_priority_max_args bsd;
1273         int error;
1274
1275 #ifdef DEBUG
1276         if (ldebug(sched_get_priority_max))
1277                 printf(ARGS(sched_get_priority_max, "%d"), args->policy);
1278 #endif
1279
1280         switch (args->policy) {
1281         case LINUX_SCHED_OTHER:
1282                 bsd.policy = SCHED_OTHER;
1283                 break;
1284         case LINUX_SCHED_FIFO:
1285                 bsd.policy = SCHED_FIFO;
1286                 break;
1287         case LINUX_SCHED_RR:
1288                 bsd.policy = SCHED_RR;
1289                 break;
1290         default:
1291                 return EINVAL;
1292         }
1293         bsd.sysmsg_result = 0;
1294
1295         error = sched_get_priority_max(&bsd);
1296         args->sysmsg_result = bsd.sysmsg_result;
1297         return(error);
1298 }
1299
1300 int
1301 linux_sched_get_priority_min(struct linux_sched_get_priority_min_args *args)
1302 {
1303         struct sched_get_priority_min_args bsd;
1304         int error;
1305
1306 #ifdef DEBUG
1307         if (ldebug(sched_get_priority_min))
1308                 printf(ARGS(sched_get_priority_min, "%d"), args->policy);
1309 #endif
1310
1311         switch (args->policy) {
1312         case LINUX_SCHED_OTHER:
1313                 bsd.policy = SCHED_OTHER;
1314                 break;
1315         case LINUX_SCHED_FIFO:
1316                 bsd.policy = SCHED_FIFO;
1317                 break;
1318         case LINUX_SCHED_RR:
1319                 bsd.policy = SCHED_RR;
1320                 break;
1321         default:
1322                 return EINVAL;
1323         }
1324         bsd.sysmsg_result = 0;
1325
1326         error = sched_get_priority_min(&bsd);
1327         args->sysmsg_result = bsd.sysmsg_result;
1328         return(error);
1329 }
1330
1331 #define REBOOT_CAD_ON   0x89abcdef
1332 #define REBOOT_CAD_OFF  0
1333 #define REBOOT_HALT     0xcdef0123
1334
1335 int
1336 linux_reboot(struct linux_reboot_args *args)
1337 {
1338         struct reboot_args bsd_args;
1339         int error;
1340
1341 #ifdef DEBUG
1342         if (ldebug(reboot))
1343                 printf(ARGS(reboot, "0x%x"), args->cmd);
1344 #endif
1345         if (args->cmd == REBOOT_CAD_ON || args->cmd == REBOOT_CAD_OFF)
1346                 return (0);
1347         bsd_args.opt = (args->cmd == REBOOT_HALT) ? RB_HALT : 0;
1348         bsd_args.sysmsg_result = 0;
1349
1350         error = reboot(&bsd_args);
1351         args->sysmsg_result = bsd_args.sysmsg_result;
1352         return(error);
1353 }
1354
1355 #ifndef __alpha__
1356
1357 /*
1358  * The FreeBSD native getpid(2), getgid(2) and getuid(2) also modify
1359  * p->p_retval[1] when COMPAT_43 or COMPAT_SUNOS is defined. This
1360  * globbers registers that are assumed to be preserved. The following
1361  * lightweight syscalls fixes this. See also linux_getgid16() and
1362  * linux_getuid16() in linux_uid16.c.
1363  *
1364  * linux_getpid() - MP SAFE
1365  * linux_getgid() - MP SAFE
1366  * linux_getuid() - MP SAFE
1367  */
1368
1369 int
1370 linux_getpid(struct linux_getpid_args *args)
1371 {
1372         struct thread *td = curthread;
1373         struct proc *p = td->td_proc;
1374
1375         KKASSERT(p);
1376
1377         args->sysmsg_result = p->p_pid;
1378         return (0);
1379 }
1380
1381 int
1382 linux_getgid(struct linux_getgid_args *args)
1383 {
1384         struct thread *td = curthread;
1385         struct proc *p = td->td_proc;
1386
1387         KKASSERT(p);
1388
1389         args->sysmsg_result = p->p_ucred->cr_rgid;
1390         return (0);
1391 }
1392
1393 int
1394 linux_getuid(struct linux_getuid_args *args)
1395 {
1396         struct thread *td = curthread;
1397         struct proc *p = td->td_proc;
1398
1399         KKASSERT(p);
1400
1401         args->sysmsg_result = p->p_ucred->cr_ruid;
1402         return (0);
1403 }
1404
1405 #endif /*!__alpha__*/
1406
1407 int
1408 linux_getsid(struct linux_getsid_args *args)
1409 {
1410         struct getsid_args bsd;
1411         int error;
1412
1413         bsd.sysmsg_result = 0;
1414         bsd.pid = args->pid;
1415         error = getsid(&bsd);
1416         args->sysmsg_result = bsd.sysmsg_result;
1417         return(error);
1418 }
1419