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