]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/alpha/osf1/osf1_misc.c
Locking for the per-process resource limits structure.
[FreeBSD/FreeBSD.git] / sys / alpha / osf1 / osf1_misc.c
1 /*      $NetBSD: osf1_misc.c,v 1.14 1998/05/20 16:34:29 chs Exp $       */
2 /*
3  * Copyright (c) 1994, 1995 Carnegie-Mellon University.
4  * All rights reserved.
5  *
6  * Author: Chris G. Demetriou
7  *
8  * Permission to use, copy, modify and distribute this software and
9  * its documentation is hereby granted, provided that both the copyright
10  * notice and this permission notice appear in all copies of the
11  * software, derivative works or modified versions, and any portions
12  * thereof, and that both notices appear in supporting documentation.
13  *
14  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
15  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
16  * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
17  *
18  * Carnegie Mellon requests users of this software to return to
19  *
20  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
21  *  School of Computer Science
22  *  Carnegie Mellon University
23  *  Pittsburgh PA 15213-3890
24  *
25  * any improvements or extensions that they make and grant Carnegie the
26  * rights to redistribute these changes.
27  */
28 /*
29  * Additional Copyright (c) 1999 by Andrew Gallatin
30  */
31
32 #include <sys/cdefs.h>
33 __FBSDID("$FreeBSD$");
34
35 #include <sys/param.h>
36 #include <sys/systm.h>
37 #include <sys/bus.h>
38 #include <sys/exec.h>
39 #include <sys/fcntl.h>
40 #include <sys/filedesc.h>
41 #include <sys/imgact.h>
42 #include <sys/kernel.h>
43 #include <sys/lock.h>
44 #include <sys/malloc.h>
45 #include <sys/file.h>           /* Must come after sys/malloc.h */
46 #include <sys/mman.h>
47 #include <sys/module.h>
48 #include <sys/mount.h>
49 #include <sys/mutex.h>
50 #include <sys/namei.h>
51 #include <sys/param.h>
52 #include <sys/proc.h>
53 #include <sys/reboot.h>
54 #include <sys/resource.h>
55 #include <sys/resourcevar.h>
56 #include <sys/selinfo.h>
57 #include <sys/pipe.h>           /* Must come after sys/selinfo.h */
58 #include <sys/signal.h>
59 #include <sys/signalvar.h>
60 #include <sys/socket.h>
61 #include <sys/socketvar.h>
62 #include <sys/stat.h>
63 #include <sys/sysctl.h>
64 #include <sys/sysent.h>
65 #include <sys/sysproto.h>
66 #include <sys/systm.h>
67 #include <sys/unistd.h>
68 #include <sys/user.h>
69 #include <sys/utsname.h>
70 #include <sys/vnode.h>
71
72 #include <vm/vm.h>
73 #include <vm/vm_kern.h>
74 #include <vm/vm_param.h>
75 #include <vm/pmap.h>
76 #include <vm/vm_map.h>
77 #include <vm/vm_extern.h>
78
79 #include <machine/cpu.h>
80 #include <machine/cpuconf.h>
81 #include <machine/fpu.h>
82 #include <machine/md_var.h>
83 #include <machine/rpb.h>
84
85 #include <alpha/osf1/exec_ecoff.h>
86 #include <alpha/osf1/osf1_signal.h>
87 #include <alpha/osf1/osf1_proto.h>
88 #include <alpha/osf1/osf1_syscall.h>
89 #include <alpha/osf1/osf1_util.h>
90 #include <alpha/osf1/osf1.h>
91
92 static void cvtstat2osf1(struct stat *, struct osf1_stat *);
93 static int  osf2bsd_pathconf(int *);
94
95 static const char osf1_emul_path[] = "/compat/osf1";
96 /*
97  * [ taken from the linux emulator ]
98  * Search an alternate path before passing pathname arguments on
99  * to system calls. Useful for keeping a separate 'emulation tree'.
100  *
101  * If cflag is set, we check if an attempt can be made to create
102  * the named file, i.e. we check if the directory it should
103  * be in exists.
104  */
105 int
106 osf1_emul_find(td, sgp, prefix, path, pbuf, cflag)
107         struct thread   *td;
108         caddr_t         *sgp;          /* Pointer to stackgap memory */
109         const char      *prefix;
110         char            *path;
111         char            **pbuf;
112         int             cflag;
113 {
114         int                     error;
115         size_t                  len, sz;
116         char                    *buf, *cp, *ptr;
117         struct ucred            *ucred;
118         struct nameidata        nd;
119         struct nameidata        ndroot;
120         struct vattr            vat;
121         struct vattr            vatroot;
122
123         buf = (char *) malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
124         *pbuf = path;
125
126         for (ptr = buf; (*ptr = *prefix) != '\0'; ptr++, prefix++)
127                 continue;
128
129         sz = MAXPATHLEN - (ptr - buf);
130
131         /*
132          * If sgp is not given then the path is already in kernel space
133          */
134         if (sgp == NULL)
135                 error = copystr(path, ptr, sz, &len);
136         else
137                 error = copyinstr(path, ptr, sz, &len);
138
139         if (error) {
140                 free(buf, M_TEMP);
141                 return error;
142         }
143
144         if (*ptr != '/') {
145                 free(buf, M_TEMP);
146                 return EINVAL;
147         }
148
149         /*
150          *  We know that there is a / somewhere in this pathname.
151          *  Search backwards for it, to find the file's parent dir
152          *  to see if it exists in the alternate tree. If it does,
153          *  and we want to create a file (cflag is set). We don't
154          *  need to worry about the root comparison in this case.
155          */
156
157         if (cflag) {
158                 for (cp = &ptr[len] - 1; *cp != '/'; cp--)
159                         ;
160                 *cp = '\0';
161
162                 NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, buf, td);
163
164                 if ((error = namei(&nd)) != 0) {
165                         free(buf, M_TEMP);
166                         return error;
167                 }
168
169                 *cp = '/';
170         } else {
171                 NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, buf, td);
172
173                 if ((error = namei(&nd)) != 0) {
174                         free(buf, M_TEMP);
175                         return error;
176                 }
177
178                 /*
179                  * We now compare the vnode of the osf1_root to the one
180                  * vnode asked. If they resolve to be the same, then we
181                  * ignore the match so that the real root gets used.
182                  * This avoids the problem of traversing "../.." to find the
183                  * root directory and never finding it, because "/" resolves
184                  * to the emulation root directory. This is expensive :-(
185                  */
186                 NDINIT(&ndroot, LOOKUP, FOLLOW, UIO_SYSSPACE, osf1_emul_path,
187                     td);
188
189                 if ((error = namei(&ndroot)) != 0) {
190                         /* Cannot happen! */
191                         free(buf, M_TEMP);
192                         vrele(nd.ni_vp);
193                         return error;
194                 }
195
196                 ucred = td->td_ucred;
197                 if ((error = VOP_GETATTR(nd.ni_vp, &vat, ucred, td)) != 0) {
198                         goto bad;
199                 }
200
201                 if ((error = VOP_GETATTR(ndroot.ni_vp, &vatroot, ucred,
202                     td)) != 0) {
203                         goto bad;
204                 }
205
206                 if (vat.va_fsid == vatroot.va_fsid &&
207                     vat.va_fileid == vatroot.va_fileid) {
208                         error = ENOENT;
209                         goto bad;
210                 }
211
212         }
213         if (sgp == NULL)
214                 *pbuf = buf;
215         else {
216                 sz = &ptr[len] - buf;
217                 *pbuf = stackgap_alloc(sgp, sz + 1);
218                 error = copyout(buf, *pbuf, sz);
219                 free(buf, M_TEMP);
220         }
221
222         vrele(nd.ni_vp);
223         if (!cflag)
224                 vrele(ndroot.ni_vp);
225
226         return error;
227
228 bad:
229         vrele(ndroot.ni_vp);
230         vrele(nd.ni_vp);
231         free(buf, M_TEMP);
232         return error;
233 }
234
235
236 int
237 osf1_open(td, uap)
238         struct thread *td;
239         struct osf1_open_args *uap;
240 {
241         struct open_args /* {
242                 syscallarg(char *) path;
243                 syscallarg(int) flags;
244                 syscallarg(int) mode;
245         } */ a;
246         caddr_t sg;
247
248         sg = stackgap_init();
249         CHECKALTEXIST(td, &sg, uap->path);
250
251         a.path = uap->path;
252         a.flags = uap->flags;           /* XXX translate */
253         a.mode = uap->mode;
254
255         return open(td, &a);
256 }
257
258 extern long totalphysmem;
259
260 int
261 osf1_getsysinfo(td, uap)
262         struct thread *td;
263         struct osf1_getsysinfo_args *uap;
264 {
265         int error, retval;
266         int ncpus = 1;         /* XXX until SMP */
267         int ophysmem;
268         int unit;
269         long percpu;
270         long proctype;
271         struct osf1_cpu_info cpuinfo;
272
273         error = retval = 0;
274
275         switch(uap->op) {
276         case OSF_GET_MAX_UPROCS:
277                 error = copyout(&maxprocperuid, uap->buffer,
278                     sizeof(maxprocperuid));
279                 retval = 1;
280                 break;
281         case OSF_GET_PHYSMEM:
282                 ophysmem = totalphysmem * (PAGE_SIZE >> 10);    
283                 error = copyout(&ophysmem, uap->buffer,
284                     sizeof(ophysmem));
285                 retval = 1;
286                 break;
287         case OSF_GET_MAX_CPU:
288         case OSF_GET_CPUS_IN_BOX:
289                 error = copyout(&ncpus, uap->buffer,
290                     sizeof(ncpus));
291                 retval = 1;
292                 break;
293         case OSF_GET_IEEE_FP_CONTROL:
294                 error = copyout(&td->td_pcb->pcb_fp_control,uap->buffer,
295                     sizeof(td->td_pcb->pcb_fp_control));
296                 retval = 1;
297                 break;
298         case OSF_GET_CPU_INFO:
299
300                 if (uap->nbytes < sizeof(cpuinfo))
301                         error = EINVAL;
302                 else {
303                         bzero(&cpuinfo, sizeof(cpuinfo));
304                         unit = alpha_pal_whami();
305                         cpuinfo.current_cpu = unit;
306                         cpuinfo.cpus_in_box = ncpus;
307                         cpuinfo.cpu_type = 
308                             LOCATE_PCS(hwrpb, unit)->pcs_proc_type;
309                         cpuinfo.ncpus = ncpus;
310                         cpuinfo.cpus_present = ncpus;
311                         cpuinfo.cpus_running = ncpus;
312                         cpuinfo.cpu_binding = 1;
313                         cpuinfo.cpu_ex_binding = 0;
314                         cpuinfo.mhz = hwrpb->rpb_cc_freq / 1000000;
315                         error = copyout(&cpuinfo, uap->buffer,
316                             sizeof(cpuinfo));
317                         retval = 1;
318                 }
319                 break;
320         case OSF_GET_PROC_TYPE:
321                 if(uap->nbytes < sizeof(proctype))
322                         error = EINVAL;
323                 else {
324                         unit = alpha_pal_whami();
325                         proctype = LOCATE_PCS(hwrpb, unit)->pcs_proc_type;
326                         error = copyout (&proctype, uap->buffer,
327                             sizeof(percpu));
328                         retval = 1;
329                 }
330         break;
331         case OSF_GET_HWRPB: {  /* note -- osf/1 doesn't have rpb_tbhint[8] */
332                 unsigned long rpb_size;
333                 rpb_size = (unsigned long)&hwrpb->rpb_tbhint -
334                     (unsigned long)hwrpb;
335                 if(uap->nbytes < rpb_size){
336                         uprintf("nbytes = %ld, sizeof(struct rpb) = %ld\n",
337                             uap->nbytes, rpb_size);
338                         error = EINVAL;
339                 }
340                 else {
341                         error = copyout(hwrpb, uap->buffer, rpb_size);
342                         retval = 1;
343                 }
344         }
345                 break;
346         case OSF_GET_PLATFORM_NAME:
347                 error = copyout(platform.model, uap->buffer, 
348                     strlen(platform.model));
349                 retval = 1;
350                 break;
351         default:
352                 printf("osf1_getsysinfo called with unknown op=%ld\n", uap->op);
353                 return EINVAL;
354         }
355         td->td_retval[0] = retval;
356         return(error);
357 }
358
359
360 int
361 osf1_setsysinfo(td, uap)
362         struct thread *td;
363         struct osf1_setsysinfo_args *uap;
364 {
365         int error;
366
367         error = 0;
368
369         switch(uap->op) {
370         case OSF_SET_IEEE_FP_CONTROL:
371         {
372                 u_int64_t temp, *fp_control;
373
374                 if ((error = copyin(uap->buffer, &temp, sizeof(temp))))
375                         break;
376                 fp_control = &td->td_pcb->pcb_fp_control;
377                 *fp_control = temp & IEEE_TRAP_ENABLE_MASK;
378                 break;
379         }
380         default:
381                 uprintf("osf1_setsysinfo called with op=%ld\n", uap->op);
382                 /*error = EINVAL;*/
383         }
384         return (error);
385 }
386
387
388 int
389 osf1_getrlimit(td, uap)
390         struct thread *td;
391         struct osf1_getrlimit_args *uap;
392 {
393         struct rlimit bsd_rlim;
394         struct proc *p;
395         int which;
396
397         if (uap->which >= OSF1_RLIMIT_NLIMITS)
398                 return (EINVAL);
399
400         if (uap->which <= OSF1_RLIMIT_LASTCOMMON)
401                 which = uap->which;
402         else if (uap->which == OSF1_RLIMIT_NOFILE)
403                 which = RLIMIT_NOFILE;
404         else
405                 return (0);
406
407         p = td->td_proc;
408         PROC_LOCK(p);
409         lim_rlimit(p, which, &bsd_rlim);
410         PROC_UNLOCK(p);
411         return (copyout(&bsd_rlim, uap->rlp, sizeof(bsd_rlim)));
412 }
413
414
415 int
416 osf1_setrlimit(td, uap)
417         struct thread *td;
418         struct osf1_setrlimit_args  *uap;
419 {
420         struct rlimit bsd_rlim;
421         int error, which;
422
423         if (uap->which >= OSF1_RLIMIT_NLIMITS)
424                 return (EINVAL);
425
426         if (uap->which <= OSF1_RLIMIT_LASTCOMMON)
427                 which = uap->which;
428         else if (uap->which == OSF1_RLIMIT_NOFILE)
429                 which = RLIMIT_NOFILE;
430         else
431                 return (0);
432
433         error = copyin(uap->rlp, &bsd_rlim, sizeof(bsd_rlim));
434         if (error)
435                 return (error);
436
437         return (kern_setrlimit(td, which, &bsd_rlim));
438 }
439
440
441 /*
442  *  As linux says, this is a total guess.
443  */
444
445 int
446 osf1_set_program_attributes(td, uap)
447         struct thread *td;
448         struct osf1_set_program_attributes_args *uap;
449 {
450         struct vmspace *vm = td->td_proc->p_vmspace;
451
452         vm->vm_taddr = (caddr_t)uap->text_start;
453         vm->vm_tsize = btoc(round_page(uap->text_len));
454         vm->vm_daddr = (caddr_t)uap->bss_start;
455         vm->vm_dsize = btoc(round_page(uap->bss_len));
456
457         return(KERN_SUCCESS);
458 }
459
460
461 int
462 osf1_mmap(td, uap)
463         struct thread *td;
464         struct osf1_mmap_args *uap;
465 {
466         struct mmap_args /* {
467                 syscallarg(caddr_t) addr;
468                 syscallarg(size_t) len;
469                 syscallarg(int) prot;
470                 syscallarg(int) flags;
471                 syscallarg(int) fd;
472                 syscallarg(long) pad;
473                 syscallarg(off_t) pos;
474         } */ a;
475         int retval;
476         vm_map_t map;
477         vm_offset_t addr, len, newaddr;
478
479         GIANT_REQUIRED;
480
481         a.addr = uap->addr;
482         a.len = uap->len;
483         a.prot = uap->prot;
484         a.fd = uap->fd;
485         a.pad = 0;
486         a.pos = uap->pos;
487
488         a.flags = 0;
489
490         /*
491          *  OSF/1's mmap, unlike FreeBSD's, does its best to map memory at the
492          *  user's requested address, even if MAP_FIXED is not set.  Here we
493          *  try to replicate this behaviour as much as we can because some
494          *  applications (like /sbin/loader) depend on having things put as
495          *  close to where they've requested as possible.
496          */
497
498         if (uap->addr != NULL)
499                 addr = round_page((vm_offset_t)a.addr);
500         else
501         /*
502          *  Try to use the apparent OSF/1 default placement of 0x10000 for
503          *  NULL addrs, this helps to prevent non-64 bit clean binaries from
504          *  SEGV'ing.
505          */
506                 addr = round_page((vm_offset_t)0x10000UL);
507         len = (vm_offset_t)a.len;
508         map = &td->td_proc->p_vmspace->vm_map;
509         if (!vm_map_findspace(map, addr, len, &newaddr)) {
510                 a.addr = (caddr_t) newaddr;
511                 a.flags |= (MAP_FIXED);
512         }
513 #ifdef DEBUG
514         else
515                 uprintf("osf1_mmap:vm_map_findspace failed for: %p 0x%lx\n",
516                     (caddr_t)addr, len);
517 #endif
518         if (uap->flags & OSF1_MAP_SHARED)
519                 a.flags |= MAP_SHARED;
520         if (uap->flags & OSF1_MAP_PRIVATE)
521                 a.flags |= MAP_PRIVATE;
522
523         switch (uap->flags & OSF1_MAP_TYPE) {
524         case OSF1_MAP_ANONYMOUS:
525                 a.flags |= MAP_ANON;
526                 break;
527         case OSF1_MAP_FILE:
528                 a.flags |= MAP_FILE;
529                 break;
530         default:
531                 return (EINVAL);
532         }
533         if (uap->flags & OSF1_MAP_FIXED)
534                 a.flags |= MAP_FIXED;
535         if (uap->flags & OSF1_MAP_HASSEMAPHORE)
536                 a.flags |= MAP_HASSEMAPHORE;
537         if (uap->flags & OSF1_MAP_INHERIT)
538                 return (EINVAL);
539         if (uap->flags & OSF1_MAP_UNALIGNED)
540                 return (EINVAL);
541         /*
542          *  Emulate an osf/1 bug:  Apparently, mmap'ed segments are always
543          *  readable even if the user doesn't or in PROT_READ.  This causes
544          *  some buggy programs to segv.
545          */
546         a.prot |= PROT_READ;
547
548
549         retval = mmap(td, &a);
550 #ifdef DEBUG
551         uprintf(
552             "\nosf1_mmap: addr=%p (%p), len = 0x%lx, prot=0x%x, fd=%d, pad=0, pos=0x%lx",
553             uap->addr, a.addr,uap->len, uap->prot,
554             uap->fd, uap->pos);
555         printf(" flags = 0x%x\n",uap->flags);
556 #endif
557         return (retval);
558 }
559
560 int
561 osf1_msync(td, uap)
562         struct thread *td;
563         struct osf1_msync_args *uap;
564 {
565         struct msync_args a;
566
567         a.addr = uap->addr;
568         a.len  = uap->len;
569         a.flags = 0;
570         if(uap->flags & OSF1_MS_ASYNC)
571                 a.flags |= MS_ASYNC;
572         if(uap->flags & OSF1_MS_SYNC)
573                 a.flags |= MS_SYNC;
574         if(uap->flags & OSF1_MS_INVALIDATE)
575                 a.flags |= MS_INVALIDATE;
576         return(msync(td, &a));
577 }
578
579 struct osf1_stat {
580         int32_t         st_dev;
581         u_int32_t       st_ino;
582         u_int32_t       st_mode;
583         u_int16_t       st_nlink;
584         u_int32_t       st_uid;
585         u_int32_t       st_gid;
586         int32_t         st_rdev;
587         u_int64_t       st_size;
588         int32_t         st_atime_sec;
589         int32_t         st_spare1;
590         int32_t         st_mtime_sec;
591         int32_t         st_spare2;
592         int32_t         st_ctime_sec;
593         int32_t         st_spare3;
594         u_int32_t       st_blksize;
595         int32_t         st_blocks;
596         u_int32_t       st_flags;
597         u_int32_t       st_gen;
598 };
599
600 /*
601  *  Get file status; this version follows links.
602  */
603 /* ARGSUSED */
604 int
605 osf1_stat(td, uap)
606         struct thread *td;
607         struct osf1_stat_args *uap;
608 {
609         int error;
610         struct stat sb;
611         struct osf1_stat osb;
612         struct nameidata nd;
613         caddr_t sg;
614
615         sg = stackgap_init();
616
617         CHECKALTEXIST(td, &sg, uap->path);
618
619         NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
620             uap->path, td);
621         if ((error = namei(&nd)))
622                 return (error);
623         error = vn_stat(nd.ni_vp, &sb, td->td_ucred, NOCRED, td);
624         vput(nd.ni_vp);
625         if (error)
626                 return (error);
627         cvtstat2osf1(&sb, &osb);
628         error = copyout((caddr_t)&osb, (caddr_t)uap->ub, sizeof (osb));
629         return (error);
630 }
631
632
633 /*
634  *  Get file status; this version does not follow links.
635  */
636 /* ARGSUSED */
637 int
638 osf1_lstat(td, uap)
639         struct thread *td;
640         register struct osf1_lstat_args *uap;
641 {
642         struct stat sb;
643         struct osf1_stat osb;
644         int error;
645         struct nameidata nd;
646         caddr_t sg = stackgap_init();
647
648         CHECKALTEXIST(td, &sg, uap->path);
649
650         NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF, UIO_USERSPACE,
651             uap->path, td);
652         if ((error = namei(&nd)))
653                 return (error);
654         error = vn_stat(nd.ni_vp, &sb, td->td_ucred, NOCRED, td);
655         vput(nd.ni_vp);
656         if (error)
657                 return (error);
658         cvtstat2osf1(&sb, &osb);
659         error = copyout((caddr_t)&osb, (caddr_t)uap->ub, sizeof (osb));
660         return (error);
661 }
662
663
664 /*
665  *  Return status information about a file descriptor.
666  */
667 int
668 osf1_fstat(td, uap)
669         struct thread *td;
670         register struct osf1_fstat_args *uap;
671 {
672         struct file *fp;
673         struct stat ub;
674         struct osf1_stat oub;
675         int error;
676
677         if ((error = fget(td, uap->fd, &fp)) != 0)
678                 return (error);
679         error = fo_stat(fp, &ub, td->td_ucred, td);
680         fdrop(fp, td);
681         cvtstat2osf1(&ub, &oub);
682         if (error == 0)
683                 error = copyout((caddr_t)&oub, (caddr_t)uap->sb,
684                     sizeof (oub));
685         return (error);
686 }
687
688
689 #define bsd2osf_dev(dev)        (umajor(dev) << 20 | uminor(dev))
690 /*
691  * Convert from a stat structure to an osf1 stat structure.
692  */
693 static void
694 cvtstat2osf1(st, ost)
695         struct stat *st;
696         struct osf1_stat *ost;
697 {
698
699         ost->st_dev = bsd2osf_dev(st->st_dev);
700         ost->st_ino = st->st_ino;
701         ost->st_mode = st->st_mode;
702         ost->st_nlink = st->st_nlink;
703         ost->st_uid = st->st_uid == -2 ? (u_int16_t) -2 : st->st_uid;
704         ost->st_gid = st->st_gid == -2 ? (u_int16_t) -2 : st->st_gid;
705         ost->st_rdev = bsd2osf_dev(st->st_rdev);
706         ost->st_size = st->st_size;
707         ost->st_atime_sec = st->st_atime;
708         ost->st_spare1 = 0;
709         ost->st_mtime_sec = st->st_mtime;
710         ost->st_spare2 = 0;
711         ost->st_ctime_sec = st->st_ctime;
712         ost->st_spare3 = 0;
713         ost->st_blksize = st->st_blksize;
714         ost->st_blocks = st->st_blocks;
715         ost->st_flags = st->st_flags;
716         ost->st_gen = st->st_gen;
717 }
718
719
720 int
721 osf1_mknod(td, uap)
722         struct thread *td;
723         struct osf1_mknod_args *uap;
724 {
725
726         printf("osf1_mknod no longer implemented\n");
727         return ENOSYS;
728 }
729
730
731 int
732 osf1_access(td, uap)
733         struct thread *td;
734         struct osf1_access_args *uap;
735 {
736         caddr_t sg;
737
738         sg = stackgap_init();
739         CHECKALTEXIST(td, &sg, uap->path);
740
741         return access(td, (struct access_args *)uap);
742 }
743
744
745 struct osf1_flock   {
746         short   l_type;
747         short   l_whence;
748         off_t   l_start;
749         off_t   l_len;
750         pid_t   l_pid;
751         };
752
753 int
754 osf1_fcntl(td, uap)
755         struct thread *td;
756         struct osf1_fcntl_args *uap;
757 {
758         int error;
759         long tmp;
760         caddr_t oarg, sg;
761         struct fcntl_args a;
762         struct osf1_flock osf_flock;
763         struct flock bsd_flock;
764         struct flock *nflock;
765
766         error = 0;
767
768         switch (uap->cmd) {
769
770         case F_SETFL:
771                 a.fd = uap->fd;
772                 a.cmd = F_SETFL;
773                 /* need to translate flags here */
774                 tmp = 0;
775                 if ((long)uap->arg & OSF1_FNONBLOCK)
776                         tmp |= FNONBLOCK;
777                 if ((long)uap->arg & OSF1_FAPPEND)
778                         tmp |= FAPPEND;
779                 if ((long)uap->arg & OSF1_FDEFER)
780                         tmp |= FDEFER;
781                 if ((long)uap->arg & OSF1_FASYNC)
782                         tmp |= FASYNC;
783                 if ((long)uap->arg & OSF1_FCREAT)
784                         tmp |= O_CREAT;
785                 if ((long)uap->arg & OSF1_FTRUNC)
786                         tmp |= O_TRUNC;
787                 if ((long)uap->arg & OSF1_FEXCL)
788                         tmp |= O_EXCL;
789                 if ((long)uap->arg & OSF1_FNDELAY)
790                         tmp |= FNDELAY;
791                 if ((long)uap->arg & OSF1_FSYNC)
792                         tmp |= FFSYNC;
793                 a.arg = tmp;
794                 error = fcntl(td, &a);
795                 break;
796
797         case F_SETLK:
798         case F_SETLKW:
799         case F_GETLK:
800                 /*
801                  *  The OSF/1 flock stucture has a different order than
802                  *  the BSD one, but all else is the same.  We must
803                  *  reorder the one we've gotten so that flock() groks it.
804                  */
805                 if ((error = copyin(uap->arg, &osf_flock, sizeof(osf_flock))))
806                         return error;
807                 bsd_flock.l_type = osf_flock.l_type;
808                 bsd_flock.l_whence = osf_flock.l_whence;
809                 bsd_flock.l_start = osf_flock.l_start;
810                 bsd_flock.l_len = osf_flock.l_len;
811                 bsd_flock.l_pid = osf_flock.l_pid;
812                 sg = stackgap_init();
813                 nflock = stackgap_alloc(&sg, sizeof(struct flock));
814                 if ((error = copyout(&bsd_flock, nflock, sizeof(bsd_flock))) != 0)
815                         return error;
816                 oarg = uap->arg;
817                 uap->arg = nflock;
818                 error = fcntl(td, (struct fcntl_args *) uap);
819 /*              if (error) {
820                         printf("fcntl called with cmd=%d, args=0x%lx\n returns %d\n",uap->cmd,(long)uap->arg,error);
821                         printf("bsd_flock.l_type = 0x%x\n", bsd_flock.l_type);
822                         printf("bsd_flock.l_whence = 0x%x\n", bsd_flock.l_whence);
823                         printf("bsd_flock.l_start = 0x%lx\n", bsd_flock.l_start);
824                         printf("bsd_flock.l_len = 0x%lx\n", bsd_flock.l_len);
825                         printf("bsd_flock.l_pid = 0x%x\n", bsd_flock.l_pid);
826                 }
827 */
828                 if ((uap->cmd == F_GETLK) && !error) {
829                         osf_flock.l_type = F_UNLCK;
830                         if ((error = copyout(&osf_flock, oarg,
831                             sizeof(osf_flock))))
832                                 return error;
833                 }
834                 break;
835         default:
836                 error = fcntl(td, (struct fcntl_args *) uap);
837
838                 if ((uap->cmd == OSF1_F_GETFL) && !error ) {
839                         tmp = td->td_retval[0] & O_ACCMODE;
840                         if (td->td_retval[0] & FNONBLOCK)
841                                 tmp |= OSF1_FNONBLOCK;
842                         if (td->td_retval[0] & FAPPEND)
843                                 tmp |= OSF1_FAPPEND;
844                         if (td->td_retval[0] & FDEFER)
845                                 tmp |= OSF1_FDEFER;
846                         if (td->td_retval[0] & FASYNC)
847                                 tmp |= OSF1_FASYNC;
848                         if (td->td_retval[0] & O_CREAT)
849                                 tmp |= OSF1_FCREAT;
850                         if (td->td_retval[0] & O_TRUNC)
851                                 tmp |= OSF1_FTRUNC;
852                         if (td->td_retval[0] & O_EXCL)
853                                 tmp |= OSF1_FEXCL;
854                         if (td->td_retval[0] & FNDELAY)
855                                 tmp |= OSF1_FNDELAY;
856                         if (td->td_retval[0] & FFSYNC)
857                                 tmp |= OSF1_FSYNC;
858                         td->td_retval[0] = tmp;
859                 }
860         }
861
862         return (error);
863 }
864
865
866 #if 0
867 int
868 osf1_fcntl(td, uap)
869         struct thread *td;
870         struct osf1_fcntl_args *uap;
871 {
872         struct fcntl_args a;
873         long tmp;
874         int error;
875
876         a.fd = uap->fd;
877
878         switch (uap->cmd) {
879
880         case OSF1_F_DUPFD:
881                 a.cmd = F_DUPFD;
882                 a.arg = (long)uap->arg;
883                 break;
884
885         case OSF1_F_GETFD:
886                 a.cmd = F_GETFD;
887                 a.arg = (long)uap->arg;
888                 break;
889
890         case OSF1_F_SETFD:
891                 a.cmd = F_SETFD;
892                 a.arg = (long)uap->arg;
893                 break;
894
895         case OSF1_F_GETFL:
896                 a.cmd = F_GETFL;
897                 a.arg = (long)uap->arg;         /* ignored */
898                 break;
899
900         case OSF1_F_SETFL:
901                 a.cmd = F_SETFL;
902                 tmp = 0;
903                 if ((long)uap->arg & OSF1_FAPPEND)
904                         tmp |= FAPPEND;
905                 if ((long)uap->arg & OSF1_FNONBLOCK)
906                         tmp |= FNONBLOCK;
907                 if ((long)uap->arg & OSF1_FASYNC)
908                         tmp |= FASYNC;
909                 if ((long)uap->arg & OSF1_FSYNC)
910                         tmp |= FFSYNC;
911                 a.arg = tmp;
912                 break;
913
914         default:                                        /* XXX other cases */
915                 return (EINVAL);
916         }
917
918         error = fcntl(td, &a);
919
920         if (error)
921                 return error;
922
923         switch (uap->cmd) {
924         case OSF1_F_GETFL:
925                 /* XXX */
926                 break;
927         }
928
929         return error;
930 }
931 #endif
932
933 int
934 osf1_socket(td, uap)
935         struct thread *td;
936         struct osf1_socket_args *uap;
937 {
938         struct socket_args a;
939
940         if (uap->type > AF_LINK)
941                 return (EINVAL);        /* XXX After AF_LINK, divergence. */
942
943         a.domain = uap->domain;
944         a.type = uap->type;
945         a.protocol = uap->protocol;
946
947         return socket(td, &a);
948 }
949
950
951 int
952 osf1_sendto(td, uap)
953         struct thread *td;
954         register struct osf1_sendto_args *uap;
955 {
956         struct sendto_args a;
957
958         if (uap->flags & ~0x7f)         /* unsupported flags */
959                 return (EINVAL);
960
961         a.s = uap->s;
962         a.buf = uap->buf;
963         a.len = uap->len;
964         a.flags = uap->flags;
965         a.to = (caddr_t)uap->to;
966         a.tolen = uap->tolen;
967
968         return sendto(td, &a);
969 }
970
971
972 int
973 osf1_reboot(td, uap)
974         struct thread *td;
975         struct osf1_reboot_args *uap;
976 {
977         struct reboot_args a;
978
979         if (uap->opt & ~OSF1_RB_ALLFLAGS &&
980             uap->opt & (OSF1_RB_ALTBOOT|OSF1_RB_UNIPROC))
981                 return (EINVAL);
982
983         a.opt = 0;
984
985         if (uap->opt & OSF1_RB_ASKNAME)
986                 a.opt |= RB_ASKNAME;
987         if (uap->opt & OSF1_RB_SINGLE)
988                 a.opt |= RB_SINGLE;
989         if (uap->opt & OSF1_RB_NOSYNC)
990                 a.opt |= RB_NOSYNC;
991         if (uap->opt & OSF1_RB_HALT)
992                 a.opt |= RB_HALT;
993         if (uap->opt & OSF1_RB_INITNAME)
994                 a.opt |= RB_INITNAME;
995         if (uap->opt & OSF1_RB_DFLTROOT)
996                 a.opt |= RB_DFLTROOT;
997
998         return reboot(td, &a);
999 }
1000
1001
1002 int
1003 osf1_lseek(td, uap)
1004         struct thread *td;
1005         struct osf1_lseek_args *uap;
1006 {
1007         struct lseek_args a;
1008
1009         a.fd = uap->fd;
1010         a.pad = 0;
1011         a.offset = uap->offset;
1012         a.whence = uap->whence;
1013
1014         return lseek(td, &a);
1015 }
1016
1017
1018 /*
1019  *  OSF/1 defines _POSIX_SAVED_IDS, which means that our normal
1020  *  setuid() won't work.
1021  *
1022  *  Instead, by P1003.1b-1993, setuid() is supposed to work like:
1023  *      If the process has appropriate [super-user] privileges, the
1024  *          setuid() function sets the real user ID, effective user
1025  *          ID, and the saved set-user-ID to uid.
1026  *      If the process does not have appropriate privileges, but uid
1027  *          is equal to the real user ID or the saved set-user-ID, the
1028  *          setuid() function sets the effective user ID to uid; the
1029  *          real user ID and saved set-user-ID remain unchanged by
1030  *          this function call.
1031  */
1032 int
1033 osf1_setuid(td, uap)
1034         struct thread *td;
1035         struct osf1_setuid_args *uap;
1036 {
1037         struct proc *p;
1038         int error;
1039         uid_t uid;
1040         struct uidinfo *uip;
1041         struct ucred *newcred, *oldcred;
1042
1043         p = td->td_proc;
1044         uid = uap->uid;
1045         newcred = crget();
1046         uip = uifind(uid);
1047         PROC_LOCK(p);
1048         oldcred = p->p_ucred;
1049
1050         if ((error = suser_cred(p->p_ucred, PRISON_ROOT)) != 0 &&
1051             uid != oldcred->cr_ruid && uid != oldcred->cr_svuid) {
1052                 PROC_UNLOCK(p);
1053                 uifree(uip);
1054                 crfree(newcred);
1055                 return (error);
1056         }
1057
1058         crcopy(newcred, oldcred);
1059         if (error == 0) {
1060                 if (uid != oldcred->cr_ruid) {
1061                         change_ruid(newcred, uip);
1062                         setsugid(p);
1063                 }
1064                 if (oldcred->cr_svuid != uid) {
1065                         change_svuid(newcred, uid);
1066                         setsugid(p);
1067                 }
1068         }
1069         if (newcred->cr_uid != uid) {
1070                 change_euid(newcred, uip);
1071                 setsugid(p);
1072         }
1073         p->p_ucred = newcred;
1074         PROC_UNLOCK(p);
1075         uifree(uip);
1076         crfree(oldcred);
1077         return (0);
1078 }
1079
1080
1081 /*
1082  *  OSF/1 defines _POSIX_SAVED_IDS, which means that our normal
1083  *  setgid() won't work.
1084  *
1085  *  If you change "uid" to "gid" in the discussion, above, about
1086  *  setuid(), you'll get a correct description of setgid().
1087  */
1088 int
1089 osf1_setgid(td, uap)
1090         struct thread *td;
1091         struct osf1_setgid_args *uap;
1092 {
1093         struct proc *p;
1094         int error;
1095         gid_t gid;
1096         struct ucred *newcred, *oldcred;
1097
1098         p = td->td_proc;
1099         gid = uap->gid;
1100         newcred = crget();
1101         PROC_LOCK(p);
1102         oldcred = p->p_ucred;
1103
1104         if (((error = suser_cred(p->p_ucred, PRISON_ROOT)) != 0 ) &&
1105             gid != oldcred->cr_rgid && gid != oldcred->cr_svgid) {
1106                 PROC_UNLOCK(p);
1107                 crfree(newcred);
1108                 return (error);
1109         }
1110
1111         crcopy(newcred, oldcred);
1112         if (error == 0) {
1113                 if (gid != oldcred->cr_rgid) {
1114                         change_rgid(newcred, gid);
1115                         setsugid(p);
1116                 }
1117                 if (oldcred->cr_svgid != gid) {
1118                         change_svgid(newcred, gid);
1119                         setsugid(p);
1120                 }
1121         }
1122         if (newcred->cr_groups[0] != gid) {
1123                 change_egid(newcred, gid);
1124                 setsugid(p);
1125         }
1126         p->p_ucred = newcred;
1127         PROC_UNLOCK(p);
1128         crfree(oldcred);
1129         return (0);
1130 }
1131
1132
1133 /*
1134  *  The structures end up being the same... but we can't be sure that
1135  *  the other word of our iov_len is zero!
1136  */
1137 struct osf1_iovec {
1138         char    *iov_base;
1139         int     iov_len;
1140 };
1141 #define STACKGAPLEN     400
1142 int
1143 osf1_readv(td, uap)
1144         struct thread *td;
1145         struct osf1_readv_args *uap;
1146 {
1147         int error, osize, nsize, i;
1148         caddr_t sg;
1149         struct readv_args /* {
1150                 syscallarg(int) fd;
1151                 syscallarg(struct iovec *) iovp;
1152                 syscallarg(u_int) iovcnt;
1153         } */ a;
1154         struct osf1_iovec *oio;
1155         struct iovec *nio;
1156
1157         sg = stackgap_init();
1158
1159         if (uap->iovcnt > (STACKGAPLEN / sizeof (struct iovec)))
1160                 return (EINVAL);
1161
1162         osize = uap->iovcnt * sizeof (struct osf1_iovec);
1163         nsize = uap->iovcnt * sizeof (struct iovec);
1164
1165         oio = malloc(osize, M_TEMP, M_WAITOK);
1166         nio = malloc(nsize, M_TEMP, M_WAITOK);
1167
1168         error = 0;
1169         if ((error = copyin(uap->iovp, oio, osize)))
1170                 goto punt;
1171         for (i = 0; i < uap->iovcnt; i++) {
1172                 nio[i].iov_base = oio[i].iov_base;
1173                 nio[i].iov_len = oio[i].iov_len;
1174         }
1175
1176         a.fd = uap->fd;
1177         a.iovp = stackgap_alloc(&sg, nsize);
1178         a.iovcnt = uap->iovcnt;
1179
1180         if ((error = copyout(nio, (caddr_t)a.iovp, nsize)))
1181                 goto punt;
1182         error = readv(td, &a);
1183
1184 punt:
1185         free(oio, M_TEMP);
1186         free(nio, M_TEMP);
1187         return (error);
1188 }
1189
1190
1191 int
1192 osf1_writev(td, uap)
1193         struct thread *td;
1194         struct osf1_writev_args *uap;
1195 {
1196         int error, i, nsize, osize;
1197         caddr_t sg;
1198         struct writev_args /* {
1199                 syscallarg(int) fd;
1200                 syscallarg(struct iovec *) iovp;
1201                 syscallarg(u_int) iovcnt;
1202         } */ a;
1203         struct osf1_iovec *oio;
1204         struct iovec *nio;
1205
1206         sg = stackgap_init();
1207
1208         if (uap->iovcnt > (STACKGAPLEN / sizeof (struct iovec)))
1209                 return (EINVAL);
1210
1211         osize = uap->iovcnt * sizeof (struct osf1_iovec);
1212         nsize = uap->iovcnt * sizeof (struct iovec);
1213
1214         oio = malloc(osize, M_TEMP, M_WAITOK);
1215         nio = malloc(nsize, M_TEMP, M_WAITOK);
1216
1217         error = 0;
1218         if ((error = copyin(uap->iovp, oio, osize)))
1219                 goto punt;
1220         for (i = 0; i < uap->iovcnt; i++) {
1221                 nio[i].iov_base = oio[i].iov_base;
1222                 nio[i].iov_len = oio[i].iov_len;
1223         }
1224
1225         a.fd = uap->fd;
1226         a.iovp = stackgap_alloc(&sg, nsize);
1227         a.iovcnt = uap->iovcnt;
1228
1229         if ((error = copyout(nio, (caddr_t)a.iovp, nsize)))
1230                 goto punt;
1231         error = writev(td, &a);
1232
1233 punt:
1234         free(oio, M_TEMP);
1235         free(nio, M_TEMP);
1236         return (error);
1237 }
1238
1239
1240 /*
1241  *  More of the stupid off_t padding!
1242  */
1243 int
1244 osf1_truncate(td, uap)
1245         struct thread *td;
1246         struct osf1_truncate_args *uap;
1247 {
1248         caddr_t sg;
1249         struct truncate_args a;
1250
1251         sg = stackgap_init();
1252         CHECKALTEXIST(td, &sg, uap->path);
1253
1254         a.path = uap->path;
1255         a.pad = 0;
1256         a.length = uap->length;
1257
1258         return truncate(td, &a);
1259 }
1260
1261
1262 int
1263 osf1_ftruncate(td, uap)
1264         struct thread *td;
1265         struct osf1_ftruncate_args *uap;
1266 {
1267         struct ftruncate_args a;
1268
1269         a.fd = uap->fd;
1270         a.pad = 0;
1271         a.length = uap->length;
1272
1273         return ftruncate(td, &a);
1274 }
1275
1276
1277 static int
1278 osf2bsd_pathconf(name)
1279         int *name;
1280 {
1281
1282         switch (*name) {
1283         case _OSF1_PC_LINK_MAX:
1284         case _OSF1_PC_MAX_CANON:
1285         case _OSF1_PC_MAX_INPUT:
1286         case _OSF1_PC_NAME_MAX:
1287                 *name -= 10;
1288                 break;
1289
1290         case _OSF1_PC_PATH_MAX:
1291         case _OSF1_PC_PIPE_BUF:
1292                 *name -= 9;
1293
1294         case _OSF1_PC_NO_TRUNC:
1295                 *name = _PC_NO_TRUNC;
1296                 break;
1297
1298         case _OSF1_PC_CHOWN_RESTRICTED:
1299                 *name = _PC_CHOWN_RESTRICTED;
1300                 break;
1301
1302         case _OSF1_PC_VDISABLE:
1303                 *name = _PC_VDISABLE;
1304                 break;
1305
1306         default:
1307                 return (EINVAL);
1308         }
1309         return 0;
1310 }
1311
1312
1313 int
1314 osf1_pathconf(td, uap)
1315         struct thread *td;
1316         struct osf1_pathconf_args *uap;
1317 {
1318
1319         if (osf2bsd_pathconf(&uap->name))
1320                 return (EINVAL);
1321         else
1322                 return (pathconf(td, (void *)uap));
1323 }
1324
1325
1326 int
1327 osf1_fpathconf(td, uap)
1328         struct thread *td;
1329         struct osf1_fpathconf_args *uap;
1330 {
1331
1332         if (osf2bsd_pathconf(&uap->name))
1333                 return (EINVAL);
1334         else
1335                 return (fpathconf(td, (void *)uap));
1336 }
1337
1338
1339 int
1340 osf1_getrusage(td, uap)
1341         struct thread *td;
1342         struct osf1_getrusage_args *uap;
1343 {
1344         struct proc *p;
1345         struct rusage *rup;
1346         struct osf1_rusage oru;
1347
1348         p = td->td_proc;
1349         switch (uap->who) {
1350         case RUSAGE_SELF:
1351                 rup = &p->p_stats->p_ru;
1352                 mtx_lock_spin(&sched_lock);
1353                 calcru(p, &rup->ru_utime, &rup->ru_stime, NULL);
1354                 mtx_unlock_spin(&sched_lock);
1355                 break;
1356
1357         case RUSAGE_CHILDREN:
1358                 rup = &p->p_stats->p_cru;
1359                 break;
1360
1361         default:
1362                 return (EINVAL);
1363         }
1364         TV_CP(rup->ru_utime, oru.ru_utime);
1365         TV_CP(rup->ru_stime, oru.ru_stime);
1366         bcopy(&(rup->ru_first), &(oru.ru_first),
1367             (&(oru.ru_last) - &(oru.ru_first)));
1368
1369         return (copyout((caddr_t)&oru, (caddr_t)uap->rusage,
1370             sizeof (struct osf1_rusage)));
1371 }
1372
1373
1374 int
1375 osf1_wait4(td, uap)
1376         struct thread *td;
1377         struct osf1_wait4_args *uap;
1378 {
1379         int error;
1380         caddr_t sg;
1381         struct osf1_rusage *orusage, oru;
1382         struct rusage *rusage = NULL, ru;
1383
1384         orusage = uap->rusage;
1385         if (orusage) {
1386                 sg = stackgap_init();
1387                 rusage = stackgap_alloc(&sg, sizeof(struct rusage));
1388                 uap->rusage = (struct osf1_rusage *)rusage;
1389         }
1390         if ((error = wait4(td, (struct wait_args *)uap)))
1391                 return error;
1392         if (orusage && (error = copyin(rusage, &ru, sizeof(ru)) == 0)){
1393                 TV_CP(ru.ru_utime, oru.ru_utime);
1394                 TV_CP(ru.ru_stime, oru.ru_stime);
1395                 bcopy(&ru.ru_first, &oru.ru_first,
1396                     (&(oru.ru_last) - &(oru.ru_first)));
1397                 copyout(&oru, orusage, sizeof (struct osf1_rusage));
1398         }
1399         return (0);
1400 }
1401
1402
1403 int
1404 osf1_madvise(td, uap)
1405         struct thread *td;
1406         struct osf1_madvise_args *uap;
1407 {
1408
1409         /* XXX */
1410         return EINVAL;
1411 }
1412
1413
1414 int
1415 osf1_execve(td, uap)
1416         struct thread *td;
1417         struct osf1_execve_args *uap;
1418 {
1419         caddr_t sg;
1420         struct execve_args ap;
1421
1422         sg = stackgap_init();
1423         CHECKALTEXIST(td, &sg, uap->path);
1424
1425         ap.fname = uap->path;
1426         ap.argv = uap->argp;
1427         ap.envv = uap->envp;
1428
1429         return execve(td, &ap);
1430 }
1431
1432
1433 int
1434 osf1_usleep_thread(td, uap)
1435         struct thread *td;
1436         struct osf1_usleep_thread_args *uap;
1437 {
1438         int error, s, timo;
1439         struct osf1_timeval time;
1440         struct timeval difftv, endtv, sleeptv, tv;
1441
1442         if ((error = copyin(uap->sleep, &time, sizeof time)))
1443                 return (error);
1444
1445         sleeptv.tv_sec =  (u_long)time.tv_sec;
1446         sleeptv.tv_usec = (u_long)time.tv_usec;
1447         timo = tvtohz(&sleeptv);
1448
1449         /*
1450          *  Some callers use usleep(0) as a sort of thread-yield so make
1451          *  sure that the timeout is non-zero.
1452          */
1453
1454         if (timo == 0)
1455                 timo = 1;
1456         s = splclock();
1457         microtime(&tv);
1458         splx(s);
1459
1460         tsleep(td, PUSER|PCATCH, "OSF/1", timo);
1461
1462         if (uap->slept != NULL) {
1463                 s = splclock();
1464                 microtime(&endtv);
1465                 timersub(&time, &endtv, &difftv);
1466                 splx(s);
1467                 if (tv.tv_sec < 0 || tv.tv_usec < 0)
1468                         tv.tv_sec = tv.tv_usec = 0;
1469                 TV_CP(difftv, time)
1470                 error = copyout(&time, uap->slept, sizeof time);
1471         }
1472         return (error);
1473 }
1474
1475
1476 int osf1_gettimeofday(td, uap)
1477         struct thread *td;
1478         register struct osf1_gettimeofday_args *uap;
1479 {
1480         int error;
1481         struct timeval atv;
1482         struct timezone tz;
1483         struct osf1_timeval otv;
1484
1485         error = 0;
1486
1487         if (uap->tp) {
1488                 microtime(&atv);
1489                 otv.tv_sec = atv.tv_sec;
1490                 otv.tv_usec = atv.tv_usec;
1491                 if ((error = copyout((caddr_t)&otv, (caddr_t)uap->tp,
1492                     sizeof (otv))))
1493                         return (error);
1494         }
1495         if (uap->tzp) {
1496                 tz.tz_minuteswest = tz_minuteswest;
1497                 tz.tz_dsttime = tz_dsttime;
1498                 error = copyout((caddr_t)&tz, (caddr_t)uap->tzp, sizeof (tz));
1499         }
1500         return (error);
1501 }
1502
1503
1504 int osf1_select(td, uap)
1505         struct thread *td;
1506         register struct osf1_select_args *uap;
1507 {
1508         if (uap->tv) {
1509                 int error;
1510                 caddr_t sg;
1511                 struct osf1_timeval otv;
1512                 struct timeval tv;
1513
1514                 sg = stackgap_init();
1515
1516                 if ((error=copyin((caddr_t)uap->tv,(caddr_t)&otv,sizeof(otv))))
1517                         return(error);
1518                 TV_CP(otv,tv);
1519                 uap->tv = stackgap_alloc(&sg, sizeof(struct timeval));
1520                 if ((error=copyout((caddr_t)&tv, (caddr_t)uap->tv,sizeof(tv))))
1521                         return(error);
1522         }
1523         return(select(td, (struct select_args *)uap));
1524 }
1525
1526
1527 int
1528 osf1_setitimer(td, uap)
1529         struct thread *td;
1530         struct osf1_setitimer_args *uap;
1531 {
1532
1533         int error;
1534         caddr_t old_oitv, sg;
1535         struct itimerval itv;
1536         struct osf1_itimerval otv;
1537
1538         error = 0;
1539         old_oitv = (caddr_t)uap->oitv;
1540         sg = stackgap_init();
1541
1542         if ((error = copyin((caddr_t)uap->itv,(caddr_t)&otv,sizeof(otv)))) {
1543                 printf("%s(%d): error = %d\n", __FILE__, __LINE__, error);
1544                 return error;
1545         }
1546         TV_CP(otv.it_interval,itv.it_interval);
1547         TV_CP(otv.it_value,itv.it_value);
1548         uap->itv = stackgap_alloc(&sg, sizeof(struct itimerval));
1549         if ((error = copyout((caddr_t)&itv,(caddr_t)uap->itv,sizeof(itv)))) {
1550                 printf("%s(%d): error = %d\n", __FILE__, __LINE__, error);
1551                 return error;
1552         }
1553         uap->oitv = stackgap_alloc(&sg, sizeof(struct itimerval));
1554         if ((error = setitimer(td, (struct setitimer_args *)uap))) {
1555                 printf("%s(%d): error = %d\n", __FILE__, __LINE__, error);
1556                 return error;
1557         }
1558         if ((error = copyin((caddr_t)uap->oitv,(caddr_t)&itv,sizeof(itv)))) {
1559                 printf("%s(%d): error = %d\n", __FILE__, __LINE__, error);
1560                 return error;
1561         }
1562         TV_CP(itv.it_interval,otv.it_interval);
1563         TV_CP(itv.it_value,otv.it_value);
1564         if (old_oitv
1565             && (error = copyout((caddr_t)&otv, old_oitv, sizeof(otv)))) {
1566                 printf("%s(%d): error = %d\n", __FILE__, __LINE__, error);
1567         }
1568         return error;
1569 }
1570
1571
1572 int
1573 osf1_getitimer(td, uap)
1574         struct thread *td;
1575         struct osf1_getitimer_args *uap;
1576 {
1577         int error;
1578         caddr_t old_itv, sg;
1579         struct itimerval itv;
1580         struct osf1_itimerval otv;
1581
1582         error = 0;
1583         old_itv = (caddr_t)uap->itv;
1584         sg = stackgap_init();
1585
1586         uap->itv = stackgap_alloc(&sg, sizeof(struct itimerval));
1587         if ((error = getitimer(td, (struct getitimer_args *)uap))) {
1588                 printf("%s(%d): error = %d\n", __FILE__, __LINE__, error);
1589                 return error;
1590         }
1591         if ((error = copyin((caddr_t)uap->itv,(caddr_t)&itv,sizeof(itv)))) {
1592                 printf("%s(%d): error = %d\n", __FILE__, __LINE__, error);
1593                 return error;
1594         }
1595         TV_CP(itv.it_interval,otv.it_interval);
1596         TV_CP(itv.it_value,otv.it_value);
1597         if ((error = copyout((caddr_t)&otv, old_itv, sizeof(otv)))) {
1598                 printf("%s(%d): error = %d\n", __FILE__, __LINE__, error);
1599         }
1600         return error;
1601 }
1602
1603
1604 int
1605 osf1_proplist_syscall(td, uap)
1606         struct thread *td;
1607         struct osf1_proplist_syscall_args *uap;
1608 {
1609
1610         return(EOPNOTSUPP);
1611 }
1612
1613
1614 int
1615 osf1_ntpgettime(td, uap)
1616         struct thread *td;
1617         struct  osf1_ntpgettime_args *uap;
1618 {
1619
1620         return(ENOSYS);
1621 }
1622
1623
1624 int
1625 osf1_ntpadjtime(td, uap)
1626         struct thread *td;
1627         struct  osf1_ntpadjtime_args *uap;
1628 {
1629
1630         return(ENOSYS);
1631 }
1632
1633
1634 int
1635 osf1_setpgrp(td, uap)
1636         struct thread *td;
1637         struct  osf1_setpgrp_args *uap;
1638 {
1639
1640         return(setpgid(td, (struct setpgid_args *)uap));
1641 }
1642
1643
1644 int
1645 osf1_uswitch(td, uap)
1646         struct thread *td;
1647         struct osf1_uswitch_args *uap;
1648 {
1649         struct proc *p;
1650         int rv;
1651         vm_map_entry_t entry;
1652         vm_offset_t zero;
1653
1654         GIANT_REQUIRED;
1655         p = td->td_proc;
1656         zero = 0;
1657
1658         if (uap->cmd == OSF1_USC_GET) {
1659                 if (vm_map_lookup_entry(&(p->p_vmspace->vm_map), 0, &entry))
1660                         td->td_retval[0] =  OSF1_USW_NULLP;
1661                 else
1662                         td->td_retval[0] =  0;
1663                 return(KERN_SUCCESS);
1664         } else if (uap->cmd == OSF1_USC_SET)
1665                 if (uap->mask & OSF1_USW_NULLP) {
1666                         rv = vm_mmap(&(p->p_vmspace->vm_map), &zero, PAGE_SIZE,
1667                             VM_PROT_READ, VM_PROT_ALL,
1668                             MAP_PRIVATE | MAP_FIXED | MAP_ANON, NULL, 0);
1669                         if (!rv)
1670                                 return(KERN_SUCCESS);
1671                         else {
1672                                 printf(
1673                                     "osf1_uswitch:vm_mmap of zero page failed with status %d\n",
1674                                     rv);
1675                                 return(rv);
1676                         }
1677                 }
1678         return(EINVAL);
1679 }
1680
1681
1682 int
1683 osf1_classcntl(td, uap)
1684         struct thread *td;
1685         struct  osf1_classcntl_args *uap;
1686 {
1687
1688         return(EACCES); /* class scheduling not enabled */
1689 }
1690
1691
1692 struct osf1_tbl_loadavg
1693 {
1694         union {
1695                 long   l[3];
1696                 double d[3];
1697         } tl_avenrun;
1698         int  tl_lscale;
1699         long tl_mach_factor[3]; /* ???? */
1700 };
1701
1702 struct osf1_tbl_sysinfo {
1703         long si_user;
1704         long si_nice;
1705         long si_sys;
1706         long si_idle;
1707         long si_hz;
1708         long si_phz;
1709         long si_boottime;
1710         long wait;
1711 };
1712
1713 #define TBL_LOADAVG     3
1714 #define TBL_SYSINFO    12
1715
1716 int
1717 osf1_table(td, uap)
1718         struct thread *td;
1719         struct  osf1_table_args /*{
1720                                 long id;
1721                                 long index;
1722                                 void *addr;
1723                                 long nel;
1724                                 u_long lel;
1725                                 }*/ *uap;
1726 {
1727         int retval;
1728         struct osf1_tbl_loadavg ld;
1729         struct osf1_tbl_sysinfo si;
1730
1731         retval = 0;
1732
1733         switch(uap->id) {
1734         case TBL_LOADAVG: /* xemacs wants this */
1735                 if ((uap->index != 0) || (uap->nel != 1))
1736                         retval = EINVAL;
1737                 bcopy(&averunnable, &ld, sizeof(averunnable));
1738                 ld.tl_lscale = (u_int)averunnable.fscale;
1739                 retval = copyout(&ld, uap->addr, sizeof(ld));
1740                 break;
1741         case TBL_SYSINFO:
1742                 if ((uap->index != 0) || (uap->nel != 1))
1743                         retval = EINVAL;
1744                 bzero(&si, sizeof(si));
1745 #if 0
1746                 si.si_user = cp_time[CP_USER];
1747                 si.si_nice = cp_time[CP_NICE];
1748                 si.si_sys  = cp_time[CP_SYS];
1749                 si.si_idle = cp_time[CP_IDLE];
1750                 si.wait    = cp_time[CP_INTR];
1751 #endif
1752                 si.si_hz = hz;
1753                 si.si_phz = profhz;
1754                 si.si_boottime = boottime.tv_sec;
1755                 retval = copyout(&si, uap->addr, sizeof(si));
1756                 break;
1757         default:
1758                 printf("osf1_table: %ld, %ld, %p, %ld %ld\n",
1759                     uap->id, uap->index, uap->addr, uap->nel, uap->lel);
1760                 retval = EINVAL;
1761         }
1762         return retval;
1763 }
1764
1765
1766 /*
1767  * MPSAFE
1768  */
1769 int
1770 osf1_sysinfo(td, uap)
1771         struct thread *td;
1772         struct  osf1_sysinfo_args /*{
1773                                 int cmd;
1774                                 char *buf;
1775                                 long count;
1776                                 }*/ *uap;
1777 {
1778         int name[2], retval;
1779         size_t bytes, len;
1780         char *string;
1781
1782         string = NULL;
1783
1784         switch(uap->cmd) {
1785         case 1: /* OS */
1786                 string = "OSF1";
1787                 break;
1788         case 2: /* hostname, from ogethostname */
1789                 len = uap->count;
1790                 name[0] = CTL_KERN;
1791                 name[1] = KERN_HOSTNAME;
1792                 mtx_lock(&Giant);
1793                 retval = userland_sysctl(td, name, 2, uap->buf, &len,
1794                                         1, 0, 0, &bytes);
1795                 mtx_unlock(&Giant);
1796                 td->td_retval[0] =  bytes;
1797                 return(retval);
1798                 break;
1799         case 3: /* release of osf1 */
1800                 string = "V4.0";
1801                 break;
1802         case 4: /* minor version of osf1 */
1803                 string = "878";
1804                 break;
1805         case 5: /* machine or arch */
1806         case 6:
1807                 string = "alpha";
1808                 break;
1809         case 7: /* serial number, real osf1 returns 0! */
1810                 string = "0";
1811                 break;
1812         case 8: /* HW vendor */
1813                 string = "Digital";
1814                 break;
1815         case 9: /* dunno, this is what du does.. */
1816                 return(ENOSYS);
1817                 break;
1818         default:
1819                 return(EINVAL);
1820         }
1821         bytes = min(uap->count, strlen(string)+1);
1822         copyout(string, uap->buf, bytes);
1823         td->td_retval[0] =  bytes;
1824         return(0);
1825 }