home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / sys / hp300 / hpux / hpux_compat.c next >
Encoding:
C/C++ Source or Header  |  1991-06-17  |  36.1 KB  |  1,735 lines

  1. /*
  2.  * Copyright (c) 1988 University of Utah.
  3.  * Copyright (c) 1990 The Regents of the University of California.
  4.  * All rights reserved.
  5.  *
  6.  * This code is derived from software contributed to Berkeley by
  7.  * the Systems Programming Group of the University of Utah Computer
  8.  * Science Department.
  9.  *
  10.  * Redistribution and use in source and binary forms, with or without
  11.  * modification, are permitted provided that the following conditions
  12.  * are met:
  13.  * 1. Redistributions of source code must retain the above copyright
  14.  *    notice, this list of conditions and the following disclaimer.
  15.  * 2. Redistributions in binary form must reproduce the above copyright
  16.  *    notice, this list of conditions and the following disclaimer in the
  17.  *    documentation and/or other materials provided with the distribution.
  18.  * 3. All advertising materials mentioning features or use of this software
  19.  *    must display the following acknowledgement:
  20.  *    This product includes software developed by the University of
  21.  *    California, Berkeley and its contributors.
  22.  * 4. Neither the name of the University nor the names of its contributors
  23.  *    may be used to endorse or promote products derived from this software
  24.  *    without specific prior written permission.
  25.  *
  26.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  27.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  28.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  29.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  30.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  31.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  32.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  33.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  34.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  35.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  36.  * SUCH DAMAGE.
  37.  *
  38.  * from: Utah $Hdr: hpux_compat.c 1.41 91/04/06$
  39.  *
  40.  *    @(#)hpux_compat.c    7.16 (Berkeley) 5/30/91
  41.  */
  42.  
  43. /*
  44.  * Various HPUX compatibility routines
  45.  */
  46.  
  47. #ifdef HPUXCOMPAT
  48.  
  49. #include "param.h"
  50. #include "systm.h"
  51. #include "signalvar.h"
  52. #include "kernel.h"
  53. #include "filedesc.h"
  54. #include "proc.h"
  55. #include "buf.h"
  56. #include "wait.h"
  57. #include "file.h"
  58. #include "namei.h"
  59. #include "vnode.h"
  60. #include "ioctl.h"
  61. #include "ptrace.h"
  62. #include "stat.h"
  63. #include "syslog.h"
  64. #include "malloc.h"
  65. #include "mount.h"
  66. #include "ipc.h"
  67. #include "user.h"
  68.  
  69. #include "machine/cpu.h"
  70. #include "machine/reg.h"
  71. #include "machine/psl.h"
  72. #include "machine/vmparam.h"
  73. #include "hpux.h"
  74. #include "hpux_termio.h"
  75.  
  76. #ifdef DEBUG
  77. int unimpresponse = 0;
  78. #endif
  79.  
  80. /* SYS5 style UTSNAME info */
  81. struct hpuxutsname protoutsname = {
  82.     "4.4bsd", "", "2.0", "B", "9000/3?0", ""
  83. };
  84.  
  85. /* 6.0 and later style context */
  86. #ifdef FPCOPROC
  87. char hpuxcontext[] =
  88.     "standalone HP-MC68881 HP-MC68020 HP-MC68010 localroot default";
  89. #else
  90. char hpuxcontext[] =
  91.     "standalone HP-MC68020 HP-MC68010 localroot default";
  92. #endif
  93.  
  94. /* YP domainname */
  95. char    domainname[MAXHOSTNAMELEN] = "unknown";
  96. int    domainnamelen = 7;
  97.  
  98. #define NERR    79
  99. #define BERR    1000
  100.  
  101. /* indexed by BSD errno */
  102. short bsdtohpuxerrnomap[NERR] = {
  103. /*00*/      0,   1,   2,   3,   4,   5,   6,   7,   8,   9,
  104. /*10*/     10,  45,  12,  13,  14,  15,  16,  17,  18,  19,
  105. /*20*/     20,  21,  22,  23,  24,  25,  26,  27,  28,  29,
  106. /*30*/     30,  31,  32,  33,  34, 246, 245, 244, 216, 217,
  107. /*40*/    218, 219, 220, 221, 222, 223, 224, 225, 226, 227,
  108. /*50*/    228, 229, 230, 231, 232, 233, 234, 235, 236, 237,
  109. /*60*/    238, 239, 249, 248, 241, 242, 247,BERR,BERR,BERR,
  110. /*70*/   70,  71,BERR,BERR,BERR,BERR,BERR,  46,BERR
  111. };
  112.  
  113. notimp(p, uap, retval, code, nargs)
  114.     struct proc *p;
  115.     int *uap, *retval;
  116.     int code, nargs;
  117. {
  118.     int error = 0;
  119. #ifdef DEBUG
  120.     register int *argp = uap;
  121.     extern char *hpuxsyscallnames[];
  122.  
  123.     printf("HPUX %s(", hpuxsyscallnames[code]);
  124.     if (nargs)
  125.         while (nargs--)
  126.             printf("%x%c", *argp++, nargs? ',' : ')');
  127.     else
  128.         printf(")");
  129.     printf("\n");
  130.     switch (unimpresponse) {
  131.     case 0:
  132.         error = nosys(p, uap, retval);
  133.         break;
  134.     case 1:
  135.         error = EINVAL;
  136.         break;
  137.     }
  138. #else
  139.     error = nosys(p, uap, retval);
  140. #endif
  141.     uprintf("HP-UX system call %d not implemented\n", code);
  142.     return (error);
  143. }
  144.  
  145. hpuxexecv(p, uap, retval)
  146.     struct proc *p;
  147.     struct args {
  148.         char    *fname;
  149.         char    **argp;
  150.         char    **envp;
  151.     } *uap;
  152.     int *retval;
  153. {
  154.     extern int execve();
  155.  
  156.     uap->envp = NULL;
  157.     return (execve(p, uap, retval));
  158. }
  159.  
  160. /*
  161.  * HPUX versions of wait and wait3 actually pass the parameters
  162.  * (status pointer, options, rusage) into the kernel rather than
  163.  * handling it in the C library stub.  We also need to map any
  164.  * termination signal from BSD to HPUX.
  165.  */
  166. hpuxwait3(p, uap, retval)
  167.     struct proc *p;
  168.     struct args {
  169.         int    *status;
  170.         int    options;
  171.         int    rusage;
  172.     } *uap;
  173.     int *retval;
  174. {
  175.     /* rusage pointer must be zero */
  176.     if (uap->rusage)
  177.         return (EINVAL);
  178.     p->p_regs[PS] = PSL_ALLCC;
  179.     p->p_regs[R0] = uap->options;
  180.     p->p_regs[R1] = uap->rusage;
  181.     return (hpuxwait(p, uap, retval));
  182. }
  183.  
  184. hpuxwait(p, uap, retval)
  185.     struct proc *p;
  186.     struct args {
  187.         int    *status;
  188.     } *uap;
  189.     int *retval;
  190. {
  191.     int sig, *statp, error;
  192.  
  193.     statp = uap->status;    /* owait clobbers first arg */
  194.     error = owait(p, uap, retval);
  195.     /*
  196.      * HP-UX wait always returns EINTR when interrupted by a signal
  197.      * (well, unless its emulating a BSD process, but we don't bother...)
  198.      */
  199.     if (error == ERESTART)
  200.         error = EINTR;
  201.     if (error)
  202.         return (error);
  203.     sig = retval[1] & 0xFF;
  204.     if (sig == WSTOPPED) {
  205.         sig = (retval[1] >> 8) & 0xFF;
  206.         retval[1] = (bsdtohpuxsig(sig) << 8) | WSTOPPED;
  207.     } else if (sig)
  208.         retval[1] = (retval[1] & 0xFF00) |
  209.             bsdtohpuxsig(sig & 0x7F) | (sig & 0x80);
  210.     if (statp)
  211.         if (suword((caddr_t)statp, retval[1]))
  212.             error = EFAULT;
  213.     return (error);
  214. }
  215.  
  216. hpuxwaitpid(p, uap, retval)
  217.     struct proc *p;
  218.     struct args {
  219.         int    pid;
  220.         int    *status;
  221.         int    options;
  222.         struct    rusage *rusage;    /* wait4 arg */
  223.     } *uap;
  224.     int *retval;
  225. {
  226.     int sig, *statp, error;
  227.  
  228.     uap->rusage = 0;
  229.     error = wait4(p, uap, retval);
  230.     /*
  231.      * HP-UX wait always returns EINTR when interrupted by a signal
  232.      * (well, unless its emulating a BSD process, but we don't bother...)
  233.      */
  234.     if (error == ERESTART)
  235.         error = EINTR;
  236.     if (error)
  237.         return (error);
  238.     sig = retval[1] & 0xFF;
  239.     if (sig == WSTOPPED) {
  240.         sig = (retval[1] >> 8) & 0xFF;
  241.         retval[1] = (bsdtohpuxsig(sig) << 8) | WSTOPPED;
  242.     } else if (sig)
  243.         retval[1] = (retval[1] & 0xFF00) |
  244.             bsdtohpuxsig(sig & 0x7F) | (sig & 0x80);
  245.     if (statp)
  246.         if (suword((caddr_t)statp, retval[1]))
  247.             error = EFAULT;
  248.     return (error);
  249. }
  250.  
  251. /*
  252.  * Must remap some bits in the mode mask.
  253.  * O_CREAT, O_TRUNC, and O_EXCL must be remapped,
  254.  * O_SYNCIO (0100000) is removed entirely.
  255.  */
  256. hpuxopen(p, uap, retval)
  257.     struct proc *p;
  258.     register struct args {
  259.         char    *fname;
  260.         int    mode;
  261.         int    crtmode;
  262.     } *uap;
  263.     int *retval;
  264. {
  265.     int mode;
  266.  
  267.     mode = uap->mode;
  268.     uap->mode &= ~(HPUXFSYNCIO|HPUXFEXCL|HPUXFTRUNC|HPUXFCREAT);
  269.     if (mode & HPUXFCREAT) {
  270.         /*
  271.          * simulate the pre-NFS behavior that opening a
  272.          * file for READ+CREATE ignores the CREATE (unless
  273.          * EXCL is set in which case we will return the
  274.          * proper error).
  275.          */
  276.         if ((mode & HPUXFEXCL) || (FFLAGS(mode) & FWRITE))
  277.             uap->mode |= O_CREAT;
  278.     }
  279.     if (mode & HPUXFTRUNC)
  280.         uap->mode |= O_TRUNC;
  281.     if (mode & HPUXFEXCL)
  282.         uap->mode |= O_EXCL;
  283.     return (open(p, uap, retval));
  284. }
  285.  
  286. /* XXX */
  287. #define    UF_FNDELAY_ON    0x20
  288. #define    UF_FIONBIO_ON    0x40
  289. /* XXX */
  290.  
  291. hpuxfcntl(p, uap, retval)
  292.     struct proc *p;
  293.     register struct args {
  294.         int    fdes;
  295.         int    cmd;
  296.         int    arg;
  297.     } *uap;
  298.     int *retval;
  299. {
  300.     int mode, error;
  301.     char *fp;
  302.  
  303.     if (uap->cmd == F_GETFL || uap->cmd == F_SETFL) {
  304.         if ((unsigned)uap->fdes >= p->p_fd->fd_nfiles ||
  305.             p->p_fd->fd_ofiles[uap->fdes] == NULL)
  306.             return (EBADF);
  307.         fp = &p->p_fd->fd_ofileflags[uap->fdes];
  308.     }
  309.     switch (uap->cmd) {
  310.     case F_SETFL:
  311.         if (uap->arg & FNONBLOCK)
  312.             *fp |= UF_FNDELAY_ON;
  313.         else {
  314.             *fp &= ~UF_FNDELAY_ON;
  315.             if (*fp & UF_FIONBIO_ON)
  316.                 uap->arg |= FNONBLOCK;
  317.         }
  318.         uap->arg &= ~(HPUXFSYNCIO|HPUXFREMOTE|FUSECACHE);
  319.         break;
  320.     case F_GETFL:
  321.     case F_DUPFD:
  322.     case F_GETFD:
  323.     case F_SETFD:
  324.         break;
  325.     default:
  326.         return (EINVAL);
  327.     }
  328.     error = fcntl(p, uap, retval);
  329.     if (error == 0 && uap->cmd == F_GETFL) {
  330.         mode = *retval;
  331.         *retval &= ~(O_CREAT|O_TRUNC|O_EXCL|FUSECACHE);
  332.         if ((mode & FNONBLOCK) && (*fp & UF_FNDELAY_ON) == 0)
  333.             *retval &= ~FNONBLOCK;
  334.         if (mode & O_CREAT)
  335.             *retval |= HPUXFCREAT;
  336.         if (mode & O_TRUNC)
  337.             *retval |= HPUXFTRUNC;
  338.         if (mode & O_EXCL)
  339.             *retval |= HPUXFEXCL;
  340.     }
  341.     return (error);
  342. }
  343.  
  344. /*
  345.  * Read and write should return a 0 count when an operation
  346.  * on a VNODE would block, not an error.
  347.  *
  348.  * In 6.2 and 6.5 sockets appear to return EWOULDBLOCK.
  349.  * In 7.0 the behavior for sockets depends on whether FNONBLOCK is in effect.
  350.  */
  351. hpuxread(p, uap, retval)
  352.     struct proc *p;
  353.     struct args {
  354.         int    fd;
  355.     } *uap;
  356.     int *retval;
  357. {
  358.     int error;
  359.  
  360.     error = read(p, uap, retval);
  361.     if (error == EWOULDBLOCK &&
  362.         (p->p_fd->fd_ofiles[uap->fd]->f_type == DTYPE_VNODE ||
  363.          p->p_fd->fd_ofileflags[uap->fd] & UF_FNDELAY_ON)) {
  364.         error = 0;
  365.         *retval = 0;
  366.     }
  367.     return (error);
  368. }
  369.  
  370. hpuxwrite(p, uap, retval)
  371.     struct proc *p;
  372.     struct args {
  373.         int    fd;
  374.     } *uap;
  375.     int *retval;
  376. {
  377.     int error;
  378.  
  379.     error = write(p, uap, retval);
  380.     if (error == EWOULDBLOCK &&
  381.         (p->p_fd->fd_ofiles[uap->fd]->f_type == DTYPE_VNODE ||
  382.          p->p_fd->fd_ofileflags[uap->fd] & UF_FNDELAY_ON)) {
  383.         error = 0;
  384.         *retval = 0;
  385.     }
  386.     return (error);
  387. }
  388.  
  389. hpuxreadv(p, uap, retval)
  390.     struct proc *p;
  391.     struct args {
  392.         int    fd;
  393.     } *uap;
  394.     int *retval;
  395. {
  396.     int error;
  397.  
  398.     error = readv(p, uap, retval);
  399.     if (error == EWOULDBLOCK &&
  400.         (p->p_fd->fd_ofiles[uap->fd]->f_type == DTYPE_VNODE ||
  401.          p->p_fd->fd_ofileflags[uap->fd] & UF_FNDELAY_ON)) {
  402.         error = 0;
  403.         *retval = 0;
  404.     }
  405.     return (error);
  406. }
  407.  
  408. hpuxwritev(p, uap, retval)
  409.     struct proc *p;
  410.     struct args {
  411.         int    fd;
  412.     } *uap;
  413.     int *retval;
  414. {
  415.     int error;
  416.  
  417.     error = writev(p, uap, retval);
  418.     if (error == EWOULDBLOCK &&
  419.         (p->p_fd->fd_ofiles[uap->fd]->f_type == DTYPE_VNODE ||
  420.          p->p_fd->fd_ofileflags[uap->fd] & UF_FNDELAY_ON)) {
  421.         error = 0;
  422.         *retval = 0;
  423.     }
  424.     return (error);
  425. }
  426.  
  427. /*
  428.  * 4.3bsd dup allows dup2 to come in on the same syscall entry
  429.  * and hence allows two arguments.  HPUX dup has only one arg.
  430.  */
  431. hpuxdup(p, uap, retval)
  432.     struct proc *p;
  433.     register struct args {
  434.         int    i;
  435.     } *uap;
  436.     int *retval;
  437. {
  438.     register struct filedesc *fdp = p->p_fd;
  439.     struct file *fp;
  440.     int fd, error;
  441.  
  442.     if (((unsigned)uap->i) >= fdp->fd_nfiles ||
  443.         (fp = fdp->fd_ofiles[uap->i]) == NULL)
  444.         return (EBADF);
  445.     if (error = fdalloc(p, 0, &fd))
  446.         return (error);
  447.     fdp->fd_ofiles[fd] = fp;
  448.     fdp->fd_ofileflags[fd] = fdp->fd_ofileflags[uap->i] &~ UF_EXCLOSE;
  449.     fp->f_count++;
  450.     if (fd > fdp->fd_lastfile)
  451.         fdp->fd_lastfile = fd;
  452.     *retval = fd;
  453.     return (0);
  454. }
  455.  
  456. hpuxutssys(p, uap, retval)
  457.     struct proc *p;
  458.     register struct args {
  459.         struct hpuxutsname *uts;
  460.         int dev;
  461.         int request;
  462.     } *uap;
  463.     int *retval;
  464. {
  465.     register int i;
  466.     int error;
  467.  
  468.     switch (uap->request) {
  469.     /* uname */
  470.     case 0:
  471.         /* fill in machine type */
  472.         switch (machineid) {
  473.         case HP_320:
  474.             protoutsname.machine[6] = '2';
  475.             break;
  476.         /* includes 318 and 319 */
  477.         case HP_330:
  478.             protoutsname.machine[6] = '3';
  479.             break;
  480.         case HP_340:
  481.             protoutsname.machine[6] = '4';
  482.             break;
  483.         case HP_350:
  484.             protoutsname.machine[6] = '5';
  485.             break;
  486.         case HP_360:
  487.             protoutsname.machine[6] = '6';
  488.             break;
  489.         case HP_370:
  490.             protoutsname.machine[6] = '7';
  491.             break;
  492.         /* includes 345 */
  493.         case HP_375:
  494.             protoutsname.machine[6] = '7';
  495.             protoutsname.machine[7] = '5';
  496.             break;
  497.         }
  498.         /* copy hostname (sans domain) to nodename */
  499.         for (i = 0; i < 8 && hostname[i] != '.'; i++)
  500.             protoutsname.nodename[i] = hostname[i];
  501.         protoutsname.nodename[i] = '\0';
  502.         error = copyout((caddr_t)&protoutsname, (caddr_t)uap->uts,
  503.                 sizeof(struct hpuxutsname));
  504.         break;
  505.  
  506.     /* gethostname */
  507.     case 5:
  508.         /* uap->dev is length */
  509.         if (uap->dev > hostnamelen + 1)
  510.             uap->dev = hostnamelen + 1;
  511.         error = copyout((caddr_t)hostname, (caddr_t)uap->uts,
  512.                 uap->dev);
  513.         break;
  514.  
  515.     case 1:    /* ?? */
  516.     case 2:    /* ustat */
  517.     case 3:    /* ?? */
  518.     case 4:    /* sethostname */
  519.     default:
  520.         error = EINVAL;
  521.         break;
  522.     }
  523.     return (error);
  524. }
  525.  
  526. hpuxstat(p, uap, retval)
  527.     struct proc *p;
  528.     struct args {
  529.         char    *fname;
  530.         struct hpuxstat *hsb;
  531.     } *uap;
  532.     int *retval;
  533. {
  534.     return (hpuxstat1(uap->fname, uap->hsb, FOLLOW));
  535. }
  536.  
  537. hpuxlstat(p, uap, retval)
  538.     struct proc *p;
  539.     struct args {
  540.         char    *fname;
  541.         struct hpuxstat *hsb;
  542.     } *uap;
  543.     int *retval;
  544. {
  545.     return (hpuxstat1(uap->fname, uap->hsb, NOFOLLOW));
  546. }
  547.  
  548. hpuxfstat(p, uap, retval)
  549.     struct proc *p;
  550.     register struct args {
  551.         int    fdes;
  552.         struct    hpuxstat *hsb;
  553.     } *uap;
  554.     int *retval;
  555. {
  556.     register struct filedesc *fdp = p->p_fd;
  557.     register struct file *fp;
  558.     struct stat sb;
  559.     int error;
  560.  
  561.     if (((unsigned)uap->fdes) >= fdp->fd_nfiles ||
  562.         (fp = fdp->fd_ofiles[uap->fdes]) == NULL)
  563.         return (EBADF);
  564.  
  565.     switch (fp->f_type) {
  566.  
  567.     case DTYPE_VNODE:
  568.         error = vn_stat((struct vnode *)fp->f_data, &sb);
  569.         break;
  570.  
  571.     case DTYPE_SOCKET:
  572.         error = soo_stat((struct socket *)fp->f_data, &sb);
  573.         break;
  574.  
  575.     default:
  576.         panic("fstat");
  577.         /*NOTREACHED*/
  578.     }
  579.     /* is this right for sockets?? */
  580.     if (error == 0)
  581.         error = bsdtohpuxstat(&sb, uap->hsb);
  582.     return (error);
  583. }
  584.  
  585. hpuxulimit(p, uap, retval)
  586.     struct proc *p;
  587.     register struct args {
  588.         int    cmd;
  589.         long    newlimit;
  590.     } *uap;
  591.     off_t *retval;
  592. {
  593.     struct rlimit *limp;
  594.     int error = 0;
  595.  
  596.     limp = &p->p_rlimit[RLIMIT_FSIZE];
  597.     switch (uap->cmd) {
  598.     case 2:
  599.         uap->newlimit *= 512;
  600.         if (uap->newlimit > limp->rlim_max &&
  601.             (error = suser(p->p_ucred, &p->p_acflag)))
  602.             break;
  603.         limp->rlim_cur = limp->rlim_max = uap->newlimit;
  604.         /* else fall into... */
  605.  
  606.     case 1:
  607.         *retval = limp->rlim_max / 512;
  608.         break;
  609.  
  610.     case 3:
  611.         limp = &p->p_rlimit[RLIMIT_DATA];
  612.         *retval = ctob(p->p_vmspace->vm_tsize) + limp->rlim_max;
  613.         break;
  614.  
  615.     default:
  616.         error = EINVAL;
  617.         break;
  618.     }
  619.     return (error);
  620. }
  621.  
  622. /*
  623.  * Map "real time" priorities 0 (high) thru 127 (low) into nice
  624.  * values -16 (high) thru -1 (low).
  625.  */
  626. hpuxrtprio(cp, uap, retval)
  627.     struct proc *cp;
  628.     register struct args {
  629.         int pid;
  630.         int prio;
  631.     } *uap;
  632.     int *retval;
  633. {
  634.     struct proc *p;
  635.     int nice, error;
  636.  
  637.     if (uap->prio < RTPRIO_MIN && uap->prio > RTPRIO_MAX &&
  638.         uap->prio != RTPRIO_NOCHG && uap->prio != RTPRIO_RTOFF)
  639.         return (EINVAL);
  640.     if (uap->pid == 0)
  641.         p = cp;
  642.     else if ((p = pfind(uap->pid)) == 0)
  643.         return (ESRCH);
  644.     nice = p->p_nice;
  645.     if (nice < NZERO)
  646.         *retval = (nice + 16) << 3;
  647.     else
  648.         *retval = RTPRIO_RTOFF;
  649.     switch (uap->prio) {
  650.  
  651.     case RTPRIO_NOCHG:
  652.         return (0);
  653.  
  654.     case RTPRIO_RTOFF:
  655.         if (nice >= NZERO)
  656.             return (0);
  657.         nice = NZERO;
  658.         break;
  659.  
  660.     default:
  661.         nice = (uap->prio >> 3) - 16;
  662.         break;
  663.     }
  664.     error = donice(cp, p, nice);
  665.     if (error == EACCES)
  666.         error = EPERM;
  667.     return (error);
  668. }
  669.  
  670. hpuxadvise(p, uap, retval)
  671.     struct proc *p;
  672.     struct args {
  673.         int    arg;
  674.     } *uap;
  675.     int *retval;
  676. {
  677.     int error = 0;
  678.  
  679.     switch (uap->arg) {
  680.     case 0:
  681.         p->p_addr->u_pcb.pcb_flags |= PCB_HPUXMMAP;
  682.         break;
  683.     case 1:
  684.         ICIA();
  685.         break;
  686.     case 2:
  687.         DCIA();
  688.         break;
  689.     default:
  690.         error = EINVAL;
  691.         break;
  692.     }
  693.     return (error);
  694. }
  695.  
  696. hpuxptrace(p, uap, retval)
  697.     struct proc *p;
  698.     struct args {
  699.         int    req;
  700.         int    pid;
  701.         int    *addr;
  702.         int    data;
  703.     } *uap;
  704.     int *retval;
  705. {
  706.     int error;
  707.  
  708.     if (uap->req == PT_STEP || uap->req == PT_CONTINUE) {
  709.         if (uap->data) {
  710.             uap->data = hpuxtobsdsig(uap->data);
  711.             if (uap->data == 0)
  712.                 uap->data = NSIG;
  713.         }
  714.     }
  715.     error = ptrace(p, uap, retval);
  716.     return (error);
  717. }
  718.  
  719. hpuxgetdomainname(p, uap, retval)
  720.     struct proc *p;
  721.     register struct args {
  722.         char    *domainname;
  723.         u_int    len;
  724.     } *uap;
  725.     int *retval;
  726. {
  727.     if (uap->len > domainnamelen + 1)
  728.         uap->len = domainnamelen + 1;
  729.     return (copyout(domainname, uap->domainname, uap->len));
  730. }
  731.  
  732. hpuxsetdomainname(p, uap, retval)
  733.     struct proc *p;
  734.     register struct args {
  735.         char    *domainname;
  736.         u_int    len;
  737.     } *uap;
  738.     int *retval;
  739. {
  740.     int error;
  741.  
  742.     if (error = suser(p->p_ucred, &p->p_acflag))
  743.         return (error);
  744.     if (uap->len > sizeof (domainname) - 1)
  745.         return (EINVAL);
  746.     domainnamelen = uap->len;
  747.     error = copyin(uap->domainname, domainname, uap->len);
  748.     domainname[domainnamelen] = 0;
  749.     return (error);
  750. }
  751.  
  752. #ifdef SYSVSHM
  753. hpuxshmat(p, uap, retval)
  754.     struct proc *p;
  755.     int *uap, *retval;
  756. {
  757.     return (shmat(p, uap, retval));
  758. }
  759.  
  760. hpuxshmctl(p, uap, retval)
  761.     struct proc *p;
  762.     int *uap, *retval;
  763. {
  764.     return (shmctl(p, uap, retval));
  765. }
  766.  
  767. hpuxshmdt(p, uap, retval)
  768.     struct proc *p;
  769.     int *uap, *retval;
  770. {
  771.     return (shmdt(p, uap, retval));
  772. }
  773.  
  774. hpuxshmget(p, uap, retval)
  775.     struct proc *p;
  776.     int *uap, *retval;
  777. {
  778.     return (shmget(p, uap, retval));
  779. }
  780. #endif
  781.  
  782. /*
  783.  * Fake semaphore routines, just don't return an error.
  784.  * Should be adequate for starbase to run.
  785.  */
  786. hpuxsemctl(p, uap, retval)
  787.     struct proc *p;
  788.     struct args {
  789.         int semid;
  790.         u_int semnum;
  791.         int cmd;
  792.         int arg;
  793.     } *uap;
  794.     int *retval;
  795. {
  796.     /* XXX: should do something here */
  797.     return (0);
  798. }
  799.  
  800. hpuxsemget(p, uap, retval)
  801.     struct proc *p;
  802.     struct args {
  803.         key_t key;
  804.         int nsems;
  805.         int semflg;
  806.     } *uap;
  807.     int *retval;
  808. {
  809.     /* XXX: should do something here */
  810.     return (0);
  811. }
  812.  
  813. hpuxsemop(p, uap, retval)
  814.     struct proc *p;
  815.     struct args {
  816.         int semid;
  817.         struct sembuf *sops;
  818.         u_int nsops;
  819.     } *uap;
  820.     int *retval;
  821. {
  822.     /* XXX: should do something here */
  823.     return (0);
  824. }
  825.  
  826. /* convert from BSD to HPUX errno */
  827. bsdtohpuxerrno(err)
  828.     int err;
  829. {
  830.     if (err < 0 || err >= NERR)
  831.         return(BERR);
  832.     return((int)bsdtohpuxerrnomap[err]);
  833. }
  834.  
  835. hpuxstat1(fname, hsb, follow)
  836.     char *fname;
  837.     struct hpuxstat *hsb;
  838.     int follow;
  839. {
  840.     register struct nameidata *ndp;
  841.     int error;
  842.     struct stat sb;
  843.     struct nameidata nd;
  844.  
  845.     ndp = &nd;
  846.     ndp->ni_nameiop = LOOKUP | LOCKLEAF | follow;
  847.     ndp->ni_segflg = UIO_USERSPACE;
  848.     ndp->ni_dirp = fname;
  849.     if (error = namei(ndp, curproc))
  850.         return (error);
  851.     error = vn_stat(ndp->ni_vp, &sb);
  852.     vput(ndp->ni_vp);
  853.     if (error == 0)
  854.         error = bsdtohpuxstat(&sb, hsb);
  855.     return (error);
  856. }
  857.  
  858. #include "grf.h"
  859.  
  860. bsdtohpuxstat(sb, hsb)
  861.     struct stat *sb;
  862.     struct hpuxstat *hsb;
  863. {
  864.     struct hpuxstat ds;
  865.  
  866.     bzero((caddr_t)&ds, sizeof(ds));
  867.     ds.hst_dev = sb->st_dev;
  868.     ds.hst_ino = (u_long)sb->st_ino;
  869.     ds.hst_mode = sb->st_mode;
  870.     ds.hst_nlink = sb->st_nlink;
  871.     ds.hst_uid = (u_short)sb->st_uid;
  872.     ds.hst_gid = (u_short)sb->st_gid;
  873. #if NGRF > 0
  874.     /* XXX: I don't want to talk about it... */
  875.     if ((sb->st_mode & S_IFMT) == S_IFCHR && major(sb->st_rdev) == 10)
  876.         ds.hst_rdev = grfdevno(sb->st_rdev);
  877.     else
  878. #endif
  879.         ds.hst_rdev = bsdtohpuxdev(sb->st_rdev);
  880.     ds.hst_size = sb->st_size;
  881.     ds.hst_atime = sb->st_atime;
  882.     ds.hst_mtime = sb->st_mtime;
  883.     ds.hst_ctime = sb->st_ctime;
  884.     ds.hst_blksize = sb->st_blksize;
  885.     ds.hst_blocks = sb->st_blocks;
  886.     return(copyout((caddr_t)&ds, (caddr_t)hsb, sizeof(ds)));
  887. }
  888.  
  889. hpuxtobsdioctl(com)
  890.     int com;
  891. {
  892.     switch (com) {
  893.     case HPUXTIOCSLTC:
  894.         com = TIOCSLTC; break;
  895.     case HPUXTIOCGLTC:
  896.         com = TIOCGLTC; break;
  897.     case HPUXTIOCSPGRP:
  898.         com = TIOCSPGRP; break;
  899.     case HPUXTIOCGPGRP:
  900.         com = TIOCGPGRP; break;
  901.     case HPUXTIOCLBIS:
  902.         com = TIOCLBIS; break;
  903.     case HPUXTIOCLBIC:
  904.         com = TIOCLBIC; break;
  905.     case HPUXTIOCLSET:
  906.         com = TIOCLSET; break;
  907.     case HPUXTIOCLGET:
  908.         com = TIOCLGET; break;
  909.     }
  910.     return(com);
  911. }
  912.  
  913. /*
  914.  * HPUX ioctl system call.  The differences here are:
  915.  *    IOC_IN also means IOC_VOID if the size portion is zero.
  916.  *    no FIOCLEX/FIONCLEX/FIOASYNC/FIOGETOWN/FIOSETOWN
  917.  *    the sgttyb struct is 2 bytes longer
  918.  */
  919. hpuxioctl(p, uap, retval)
  920.     struct proc *p;
  921.     register struct args {
  922.         int    fdes;
  923.         int    cmd;
  924.         caddr_t    cmarg;
  925.     } *uap;
  926.     int *retval;
  927. {
  928.     register struct filedesc *fdp = p->p_fd;
  929.     register struct file *fp;
  930.     register int com, error;
  931.     register u_int size;
  932.     caddr_t memp = 0;
  933. #define STK_PARAMS    128
  934.     char stkbuf[STK_PARAMS];
  935.     caddr_t data = stkbuf;
  936.  
  937.     com = uap->cmd;
  938.  
  939.     /* XXX */
  940.     if (com == HPUXTIOCGETP || com == HPUXTIOCSETP)
  941.         return (getsettty(p, uap->fdes, com, uap->cmarg));
  942.  
  943.     if (((unsigned)uap->fdes) >= fdp->fd_nfiles ||
  944.         (fp = fdp->fd_ofiles[uap->fdes]) == NULL)
  945.         return (EBADF);
  946.     if ((fp->f_flag & (FREAD|FWRITE)) == 0)
  947.         return (EBADF);
  948.  
  949.     /*
  950.      * Interpret high order word to find
  951.      * amount of data to be copied to/from the
  952.      * user's address space.
  953.      */
  954.     size = IOCPARM_LEN(com);
  955.     if (size > IOCPARM_MAX)
  956.         return (ENOTTY);
  957.     if (size > sizeof (stkbuf)) {
  958.         memp = (caddr_t)malloc((u_long)size, M_IOCTLOPS, M_WAITOK);
  959.         data = memp;
  960.     }
  961.     if (com&IOC_IN) {
  962.         if (size) {
  963.             error = copyin(uap->cmarg, data, (u_int)size);
  964.             if (error) {
  965.                 if (memp)
  966.                     free(memp, M_IOCTLOPS);
  967.                 return (error);
  968.             }
  969.         } else
  970.             *(caddr_t *)data = uap->cmarg;
  971.     } else if ((com&IOC_OUT) && size)
  972.         /*
  973.          * Zero the buffer so the user always
  974.          * gets back something deterministic.
  975.          */
  976.         bzero(data, size);
  977.     else if (com&IOC_VOID)
  978.         *(caddr_t *)data = uap->cmarg;
  979.  
  980.     switch (com) {
  981.  
  982.     case HPUXFIOSNBIO:
  983.     {
  984.         char *ofp = &fdp->fd_ofileflags[uap->fdes];
  985.         int tmp;
  986.  
  987.         if (*(int *)data)
  988.             *ofp |= UF_FIONBIO_ON;
  989.         else
  990.             *ofp &= ~UF_FIONBIO_ON;
  991.         /*
  992.          * Only set/clear if FNONBLOCK not in effect
  993.          */
  994.         if ((*ofp & UF_FNDELAY_ON) == 0) {
  995.             tmp = fp->f_flag & FNONBLOCK;
  996.             error = (*fp->f_ops->fo_ioctl)(fp, FIONBIO,
  997.                                (caddr_t)&tmp, p);
  998.         }
  999.         break;
  1000.     }
  1001.  
  1002.     case HPUXTIOCCONS:
  1003.         *(int *)data = 1;
  1004.         error = (*fp->f_ops->fo_ioctl)(fp, TIOCCONS, data, p);
  1005.         break;
  1006.  
  1007.     /* BSD-style job control ioctls */
  1008.     case HPUXTIOCLBIS:
  1009.     case HPUXTIOCLBIC:
  1010.     case HPUXTIOCLSET:
  1011.         *(int *)data &= HPUXLTOSTOP;
  1012.         if (*(int *)data & HPUXLTOSTOP)
  1013.             *(int *)data = LTOSTOP;
  1014.         /* fall into */
  1015.     case HPUXTIOCLGET:
  1016.     case HPUXTIOCSLTC:
  1017.     case HPUXTIOCGLTC:
  1018.     case HPUXTIOCSPGRP:
  1019.     case HPUXTIOCGPGRP:
  1020.         error = (*fp->f_ops->fo_ioctl)
  1021.             (fp, hpuxtobsdioctl(com), data, p);
  1022.         if (error == 0 && com == HPUXTIOCLGET) {
  1023.             *(int *)data &= LTOSTOP;
  1024.             if (*(int *)data & LTOSTOP)
  1025.                 *(int *)data = HPUXLTOSTOP;
  1026.         }
  1027.         break;
  1028.  
  1029.     /* SYS 5 termio */
  1030.     case HPUXTCGETA:
  1031.     case HPUXTCSETA:
  1032.     case HPUXTCSETAW:
  1033.     case HPUXTCSETAF:
  1034.         error = hpuxtermio(fp, com, data, p);
  1035.         break;
  1036.  
  1037.     default:
  1038.         error = (*fp->f_ops->fo_ioctl)(fp, com, data, p);
  1039.         break;
  1040.     }
  1041.     /*
  1042.      * Copy any data to user, size was
  1043.      * already set and checked above.
  1044.      */
  1045.     if (error == 0 && (com&IOC_OUT) && size)
  1046.         error = copyout(data, uap->cmarg, (u_int)size);
  1047.     if (memp)
  1048.         free(memp, M_IOCTLOPS);
  1049.     return (error);
  1050. }
  1051.  
  1052. /*
  1053.  * Man page lies, behaviour here is based on observed behaviour.
  1054.  */
  1055. hpuxgetcontext(p, uap, retval)
  1056.     struct proc *p;
  1057.     struct args {
  1058.         char *buf;
  1059.         int len;
  1060.     } *uap;
  1061.     int *retval;
  1062. {
  1063.     int error = 0;
  1064.     register int len;
  1065.  
  1066.     len = MIN(uap->len, sizeof(hpuxcontext));
  1067.     if (len)
  1068.         error = copyout(hpuxcontext, uap->buf, (u_int)len);
  1069.     if (error == 0)
  1070.         *retval = sizeof(hpuxcontext);
  1071.     return (error);
  1072. }
  1073.  
  1074. /*
  1075.  * This is the equivalent of BSD getpgrp but with more restrictions.
  1076.  * Note we do not check the real uid or "saved" uid.
  1077.  */
  1078. hpuxgetpgrp2(cp, uap, retval)
  1079.     struct proc *cp;
  1080.     register struct args {
  1081.         int pid;
  1082.     } *uap;
  1083.     int *retval;
  1084. {
  1085.     register struct proc *p;
  1086.  
  1087.     if (uap->pid == 0)
  1088.         uap->pid = cp->p_pid;
  1089.     p = pfind(uap->pid);
  1090.     if (p == 0)
  1091.         return (ESRCH);
  1092.     if (cp->p_ucred->cr_uid && p->p_ucred->cr_uid != cp->p_ucred->cr_uid &&
  1093.         !inferior(p))
  1094.         return (EPERM);
  1095.     *retval = p->p_pgid;
  1096.     return (0);
  1097. }
  1098.  
  1099. /*
  1100.  * This is the equivalent of BSD setpgrp but with more restrictions.
  1101.  * Note we do not check the real uid or "saved" uid or pgrp.
  1102.  */
  1103. hpuxsetpgrp2(p, uap, retval)
  1104.     struct proc *p;
  1105.     struct args {
  1106.         int    pid;
  1107.         int    pgrp;
  1108.     } *uap;
  1109.     int *retval;
  1110. {
  1111.     /* empirically determined */
  1112.     if (uap->pgrp < 0 || uap->pgrp >= 30000)
  1113.         return (EINVAL);
  1114.     return (setpgid(p, uap, retval));
  1115. }
  1116.  
  1117. /*
  1118.  * XXX Same as BSD setre[ug]id right now.  Need to consider saved ids.
  1119.  */
  1120. hpuxsetresuid(p, uap, retval)
  1121.     struct proc *p;
  1122.     struct args {
  1123.         int    ruid;
  1124.         int    euid;
  1125.         int    suid;
  1126.     } *uap;
  1127.     int *retval;
  1128. {
  1129.     return (osetreuid(p, uap, retval));
  1130. }
  1131.  
  1132. hpuxsetresgid(p, uap, retval)
  1133.     struct proc *p;
  1134.     struct args {
  1135.         int    rgid;
  1136.         int    egid;
  1137.         int    sgid;
  1138.     } *uap;
  1139.     int *retval;
  1140. {
  1141.     return (osetregid(p, uap, retval));
  1142. }
  1143.  
  1144. /*
  1145.  * XXX: simple recognition hack to see if we can make grmd work.
  1146.  */
  1147. hpuxlockf(p, uap, retval)
  1148.     struct proc *p;
  1149.     struct args {
  1150.         int fd;
  1151.         int func;
  1152.         long size;
  1153.     } *uap;
  1154.     int *retval;
  1155. {
  1156. #ifdef DEBUG
  1157.     log(LOG_DEBUG, "%d: lockf(%d, %d, %d)\n",
  1158.         p->p_pid, uap->fd, uap->func, uap->size);
  1159. #endif
  1160.     return (0);
  1161. }
  1162.  
  1163. hpuxgetaccess(p, uap, retval)
  1164.     register struct proc *p;
  1165.     register struct args {
  1166.         char    *path;
  1167.         int    uid;
  1168.         int    ngroups;
  1169.         int    *gidset;
  1170.         void    *label;
  1171.         void    *privs;
  1172.     } *uap;
  1173.     int *retval;
  1174. {
  1175.     struct nameidata *ndp;
  1176.     int lgroups[NGROUPS];
  1177.     int error = 0;
  1178.     register struct ucred *cred;
  1179.     register struct vnode *vp;
  1180.  
  1181.     /*
  1182.      * Build an appropriate credential structure
  1183.      */
  1184.     cred = crdup(p->p_ucred);
  1185.     switch (uap->uid) {
  1186.     case 65502:    /* UID_EUID */
  1187.         break;
  1188.     case 65503:    /* UID_RUID */
  1189.         cred->cr_uid = p->p_cred->p_ruid;
  1190.         break;
  1191.     case 65504:    /* UID_SUID */
  1192.         error = EINVAL;
  1193.         break;
  1194.     default:
  1195.         if (uap->uid > 65504)
  1196.             error = EINVAL;
  1197.         cred->cr_uid = uap->uid;
  1198.         break;
  1199.     }
  1200.     switch (uap->ngroups) {
  1201.     case -1:    /* NGROUPS_EGID */
  1202.         cred->cr_ngroups = 1;
  1203.         break;
  1204.     case -5:    /* NGROUPS_EGID_SUPP */
  1205.         break;
  1206.     case -2:    /* NGROUPS_RGID */
  1207.         cred->cr_ngroups = 1;
  1208.         cred->cr_gid = p->p_cred->p_rgid;
  1209.         break;
  1210.     case -6:    /* NGROUPS_RGID_SUPP */
  1211.         cred->cr_gid = p->p_cred->p_rgid;
  1212.         break;
  1213.     case -3:    /* NGROUPS_SGID */
  1214.     case -7:    /* NGROUPS_SGID_SUPP */
  1215.         error = EINVAL;
  1216.         break;
  1217.     case -4:    /* NGROUPS_SUPP */
  1218.         if (cred->cr_ngroups > 1)
  1219.             cred->cr_gid = cred->cr_groups[1];
  1220.         else
  1221.             error = EINVAL;
  1222.         break;
  1223.     default:
  1224.         if (uap->ngroups > 0 && uap->ngroups <= NGROUPS)
  1225.             error = copyin((caddr_t)uap->gidset,
  1226.                        (caddr_t)&lgroups[0],
  1227.                        uap->ngroups * sizeof(lgroups[0]));
  1228.         else
  1229.             error = EINVAL;
  1230.         if (error == 0) {
  1231.             int gid;
  1232.  
  1233.             for (gid = 0; gid < uap->ngroups; gid++)
  1234.                 cred->cr_groups[gid] = lgroups[gid];
  1235.             cred->cr_ngroups = uap->ngroups;
  1236.         }
  1237.         break;
  1238.     }
  1239.     /*
  1240.      * Lookup file using caller's effective IDs.
  1241.      */
  1242.     if (error == 0) {
  1243.         ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF;
  1244.         ndp->ni_segflg = UIO_USERSPACE;
  1245.         ndp->ni_dirp = uap->path;
  1246.         error = namei(ndp, p);
  1247.     }
  1248.     if (error) {
  1249.         crfree(cred);
  1250.         return (error);
  1251.     }
  1252.     /*
  1253.      * Use the constructed credentials for access checks.
  1254.      */
  1255.     vp = ndp->ni_vp;
  1256.     *retval = 0;
  1257.     if (VOP_ACCESS(vp, VREAD, cred, p) == 0)
  1258.         *retval |= R_OK;
  1259.     if (vn_writechk(vp) == 0 && VOP_ACCESS(vp, VWRITE, cred, p) == 0)
  1260.         *retval |= W_OK;
  1261.     /* XXX we return X_OK for root on VREG even if not */
  1262.     if (VOP_ACCESS(vp, VEXEC, cred, p) == 0)
  1263.         *retval |= X_OK;
  1264.     vput(vp);
  1265.     crfree(cred);
  1266.     return (error);
  1267. }
  1268.  
  1269. /*
  1270.  * Brutal hack!  Map HPUX u-area offsets into BSD u offsets.
  1271.  * No apologies offered, if you don't like it, rewrite it!
  1272.  */
  1273.  
  1274. extern char kstack[];
  1275. #define UOFF(f)        ((int)&((struct user *)0)->f)
  1276. #define HPUOFF(f)    ((int)&((struct hpuxuser *)0)->f)
  1277.  
  1278. /* simplified FP structure */
  1279. struct bsdfp {
  1280.     int save[54];
  1281.     int reg[24];
  1282.     int ctrl[3];
  1283. };
  1284.  
  1285. hpuxtobsduoff(off)
  1286.     int *off;
  1287. {
  1288.     register int *ar0 = curproc->p_regs;
  1289.     struct hpuxfp *hp;
  1290.     struct bsdfp *bp;
  1291.     register u_int raddr;
  1292.  
  1293.     /* u_ar0 field; procxmt puts in U_ar0 */
  1294.     if ((int)off == HPUOFF(hpuxu_ar0))
  1295.         return(UOFF(U_ar0));
  1296.  
  1297. #ifdef FPCOPROC
  1298.     /* 68881 registers from PCB */
  1299.     hp = (struct hpuxfp *)HPUOFF(hpuxu_fp);
  1300.     bp = (struct bsdfp *)UOFF(u_pcb.pcb_fpregs);
  1301.     if (off >= hp->hpfp_ctrl && off < &hp->hpfp_ctrl[3])
  1302.         return((int)&bp->ctrl[off - hp->hpfp_ctrl]);
  1303.     if (off >= hp->hpfp_reg && off < &hp->hpfp_reg[24])
  1304.         return((int)&bp->reg[off - hp->hpfp_reg]);
  1305. #endif
  1306.  
  1307.     /*
  1308.      * Everything else we recognize comes from the kernel stack,
  1309.      * so we convert off to an absolute address (if not already)
  1310.      * for simplicity.
  1311.      */
  1312.     if (off < (int *)ctob(UPAGES))
  1313.         off = (int *)((u_int)off + (u_int)kstack);
  1314.  
  1315.     /*
  1316.      * 68020 registers.
  1317.      * We know that the HPUX registers are in the same order as ours.
  1318.      * The only difference is that their PS is 2 bytes instead of a
  1319.      * padded 4 like ours throwing the alignment off.
  1320.      */
  1321.     if (off >= ar0 && off < &ar0[18]) {
  1322.         /*
  1323.          * PS: return low word and high word of PC as HP-UX would
  1324.          * (e.g. &u.u_ar0[16.5]).
  1325.          */
  1326.         if (off == &ar0[PS])
  1327.             raddr = (u_int) &((short *)ar0)[PS*2+1];
  1328.         /*
  1329.          * PC: off will be &u.u_ar0[16.5]
  1330.          */
  1331.         else if (off == (int *)&(((short *)ar0)[PS*2+1]))
  1332.             raddr = (u_int) &ar0[PC];
  1333.         /*
  1334.          * D0-D7, A0-A7: easy
  1335.          */
  1336.         else
  1337.             raddr = (u_int) &ar0[(int)(off - ar0)];
  1338.         return((int)(raddr - (u_int)kstack));
  1339.     }
  1340.  
  1341.     /* everything else */
  1342.     return(-1);
  1343. }
  1344.  
  1345. /*
  1346.  * Kludge up a uarea dump so that HPUX debuggers can find out
  1347.  * what they need.  IMPORTANT NOTE: we do not EVEN attempt to
  1348.  * convert the entire user struct.
  1349.  */
  1350. hpuxdumpu(vp, cred)
  1351.     struct vnode *vp;
  1352.     struct ucred *cred;
  1353. {
  1354.     struct proc *p = curproc;
  1355.     int error;
  1356.     struct hpuxuser *faku;
  1357.     struct bsdfp *bp;
  1358.     short *foop;
  1359.  
  1360.     faku = (struct hpuxuser *)malloc((u_long)ctob(1), M_TEMP, M_WAITOK);
  1361.     /*
  1362.      * Make sure there is no mistake about this
  1363.      * being a real user structure.
  1364.      */
  1365.     bzero((caddr_t)faku, ctob(1));
  1366.     /*
  1367.      * Fill in the process sizes.
  1368.      */
  1369.     faku->hpuxu_tsize = p->p_vmspace->vm_tsize;
  1370.     faku->hpuxu_dsize = p->p_vmspace->vm_dsize;
  1371.     faku->hpuxu_ssize = p->p_vmspace->vm_ssize;
  1372.     /*
  1373.      * Fill in the exec header for CDB.
  1374.      * This was saved back in exec().  As far as I can tell CDB
  1375.      * only uses this information to verify that a particular
  1376.      * core file goes with a particular binary.
  1377.      */
  1378.     bcopy((caddr_t)p->p_addr->u_pcb.pcb_exec,
  1379.           (caddr_t)&faku->hpuxu_exdata, sizeof (struct hpux_exec));
  1380.     /*
  1381.      * Adjust user's saved registers (on kernel stack) to reflect
  1382.      * HPUX order.  Note that HPUX saves the SR as 2 bytes not 4
  1383.      * so we have to move it up.
  1384.      */
  1385.     faku->hpuxu_ar0 = p->p_regs;
  1386.     foop = (short *) p->p_regs;
  1387.     foop[32] = foop[33];
  1388.     foop[33] = foop[34];
  1389.     foop[34] = foop[35];
  1390. #ifdef FPCOPROC
  1391.     /*
  1392.      * Copy 68881 registers from our PCB format to HPUX format
  1393.      */
  1394.     bp = (struct bsdfp *) &p->p_addr->u_pcb.pcb_fpregs;
  1395.     bcopy((caddr_t)bp->save, (caddr_t)faku->hpuxu_fp.hpfp_save,
  1396.           sizeof(bp->save));
  1397.     bcopy((caddr_t)bp->ctrl, (caddr_t)faku->hpuxu_fp.hpfp_ctrl,
  1398.           sizeof(bp->ctrl));
  1399.     bcopy((caddr_t)bp->reg, (caddr_t)faku->hpuxu_fp.hpfp_reg,
  1400.           sizeof(bp->reg));
  1401. #endif
  1402.     /*
  1403.      * Slay the dragon
  1404.      */
  1405.     faku->hpuxu_dragon = -1;
  1406.     /*
  1407.      * Dump this artfully constructed page in place of the
  1408.      * user struct page.
  1409.      */
  1410.     error = vn_rdwr(UIO_WRITE, vp, (caddr_t)faku, ctob(1), (off_t)0,
  1411.             UIO_SYSSPACE, IO_NODELOCKED|IO_UNIT, cred,
  1412.             (int *)NULL, p);
  1413.     /*
  1414.      * Dump the remaining UPAGES-1 pages normally
  1415.      */
  1416.     if (!error) 
  1417.         error = vn_rdwr(UIO_WRITE, vp, kstack + ctob(1),
  1418.                 ctob(UPAGES-1), (off_t)ctob(1), UIO_SYSSPACE,
  1419.                 IO_NODELOCKED|IO_UNIT, cred, (int *)NULL, p);
  1420.     free((caddr_t)faku, M_TEMP);
  1421.     return(error);
  1422. }
  1423.  
  1424. /*
  1425.  * The remaining routines are essentially the same as those in kern_xxx.c
  1426.  * and vfs_xxx.c as defined under "#ifdef COMPAT".  We replicate them here
  1427.  * to avoid HPUXCOMPAT dependencies in those files and to make sure that
  1428.  * HP-UX compatibility still works even when COMPAT is not defined.
  1429.  */
  1430. /* #ifdef COMPAT */
  1431.  
  1432. #define HPUX_HZ    50
  1433.  
  1434. #include "sys/times.h"
  1435.  
  1436. /* from old timeb.h */
  1437. struct hpuxtimeb {
  1438.     time_t    time;
  1439.     u_short    millitm;
  1440.     short    timezone;
  1441.     short    dstflag;
  1442. };
  1443.  
  1444. /* ye ole stat structure */
  1445. struct    ohpuxstat {
  1446.     dev_t    ohst_dev;
  1447.     u_short    ohst_ino;
  1448.     u_short ohst_mode;
  1449.     short      ohst_nlink;
  1450.     short      ohst_uid;
  1451.     short      ohst_gid;
  1452.     dev_t    ohst_rdev;
  1453.     int    ohst_size;
  1454.     int    ohst_atime;
  1455.     int    ohst_mtime;
  1456.     int    ohst_ctime;
  1457. };
  1458.  
  1459. /*
  1460.  * SYS V style setpgrp()
  1461.  */
  1462. ohpuxsetpgrp(p, uap, retval)
  1463.     register struct proc *p;
  1464.     int *uap, *retval;
  1465. {
  1466.     if (p->p_pid != p->p_pgid)
  1467.         enterpgrp(p, p->p_pid, 0);
  1468.     *retval = p->p_pgid;
  1469.     return (0);
  1470. }
  1471.  
  1472. ohpuxtime(p, uap, retval)
  1473.     struct proc *p;
  1474.     register struct args {
  1475.         long    *tp;
  1476.     } *uap;
  1477.     time_t *retval;
  1478. {
  1479.     int error = 0;
  1480.  
  1481.     if (uap->tp)
  1482.         error = copyout((caddr_t)&time.tv_sec, (caddr_t)uap->tp,
  1483.                 sizeof (long));
  1484.     *retval = time.tv_sec;
  1485.     return (error);
  1486. }
  1487.  
  1488. ohpuxstime(p, uap, retval)
  1489.     struct proc *p;
  1490.     register struct args {
  1491.         int    time;
  1492.     } *uap;
  1493.     int *retval;
  1494. {
  1495.     struct timeval tv;
  1496.     int s, error;
  1497.  
  1498.     tv.tv_sec = uap->time;
  1499.     tv.tv_usec = 0;
  1500.     if (error = suser(p->p_ucred, &p->p_acflag))
  1501.         return (error);
  1502.  
  1503.     /* WHAT DO WE DO ABOUT PENDING REAL-TIME TIMEOUTS??? */
  1504.     boottime.tv_sec += tv.tv_sec - time.tv_sec;
  1505.     s = splhigh(); time = tv; splx(s);
  1506.     resettodr();
  1507.     return (0);
  1508. }
  1509.  
  1510. ohpuxftime(p, uap, retval)
  1511.     struct proc *p;
  1512.     register struct args {
  1513.         struct    hpuxtimeb *tp;
  1514.     } *uap;
  1515.     int *retval;
  1516. {
  1517.     struct hpuxtimeb tb;
  1518.     int s;
  1519.  
  1520.     s = splhigh();
  1521.     tb.time = time.tv_sec;
  1522.     tb.millitm = time.tv_usec / 1000;
  1523.     splx(s);
  1524.     tb.timezone = tz.tz_minuteswest;
  1525.     tb.dstflag = tz.tz_dsttime;
  1526.     return (copyout((caddr_t)&tb, (caddr_t)uap->tp, sizeof (tb)));
  1527. }
  1528.  
  1529. ohpuxalarm(p, uap, retval)
  1530.     register struct proc *p;
  1531.     register struct args {
  1532.         int    deltat;
  1533.     } *uap;
  1534.     int *retval;
  1535. {
  1536.     int s = splhigh();
  1537.  
  1538.     untimeout(realitexpire, (caddr_t)p);
  1539.     timerclear(&p->p_realtimer.it_interval);
  1540.     *retval = 0;
  1541.     if (timerisset(&p->p_realtimer.it_value) &&
  1542.         timercmp(&p->p_realtimer.it_value, &time, >))
  1543.         *retval = p->p_realtimer.it_value.tv_sec - time.tv_sec;
  1544.     if (uap->deltat == 0) {
  1545.         timerclear(&p->p_realtimer.it_value);
  1546.         splx(s);
  1547.         return (0);
  1548.     }
  1549.     p->p_realtimer.it_value = time;
  1550.     p->p_realtimer.it_value.tv_sec += uap->deltat;
  1551.     timeout(realitexpire, (caddr_t)p, hzto(&p->p_realtimer.it_value));
  1552.     splx(s);
  1553.     return (0);
  1554. }
  1555.  
  1556. ohpuxnice(p, uap, retval)
  1557.     register struct proc *p;
  1558.     register struct args {
  1559.         int    niceness;
  1560.     } *uap;
  1561.     int *retval;
  1562. {
  1563.     int error;
  1564.  
  1565.     error = donice(p, p, (p->p_nice-NZERO)+uap->niceness);
  1566.     if (error == 0)
  1567.         *retval = p->p_nice - NZERO;
  1568.     return (error);
  1569. }
  1570.  
  1571. ohpuxtimes(p, uap, retval)
  1572.     struct proc *p;
  1573.     register struct args {
  1574.         struct    tms *tmsb;
  1575.     } *uap;
  1576.     time_t *retval;
  1577. {
  1578.     struct tms atms;
  1579.     int error;
  1580.  
  1581.     atms.tms_utime = hpuxscale(&p->p_utime);
  1582.     atms.tms_stime = hpuxscale(&p->p_stime);
  1583.     atms.tms_cutime = hpuxscale(&p->p_stats->p_cru.ru_utime);
  1584.     atms.tms_cstime = hpuxscale(&p->p_stats->p_cru.ru_stime);
  1585.     error = copyout((caddr_t)&atms, (caddr_t)uap->tmsb, sizeof (atms));
  1586.     if (error == 0)
  1587.         *retval = hpuxscale(&time) - hpuxscale(&boottime);
  1588.     return (error);
  1589. }
  1590.  
  1591. /*
  1592.  * Doesn't exactly do what the documentation says.
  1593.  * What we really do is return 1/HPUX_HZ-th of a second since that
  1594.  * is what HP-UX returns.
  1595.  */
  1596. hpuxscale(tvp)
  1597.     register struct timeval *tvp;
  1598. {
  1599.     return (tvp->tv_sec * HPUX_HZ + tvp->tv_usec * HPUX_HZ / 1000000);
  1600. }
  1601.  
  1602. /*
  1603.  * Set IUPD and IACC times on file.
  1604.  * Can't set ICHG.
  1605.  */
  1606. ohpuxutime(p, uap, retval)
  1607.     struct proc *p;
  1608.     register struct a {
  1609.         char    *fname;
  1610.         time_t    *tptr;
  1611.     } *uap;
  1612.     int *retval;
  1613. {
  1614.     register struct vnode *vp;
  1615.     register struct nameidata *ndp;
  1616.     struct vattr vattr;
  1617.     time_t tv[2];
  1618.     int error;
  1619.     struct nameidata nd;
  1620.  
  1621.     ndp = &nd;
  1622.     if (uap->tptr) {
  1623.         error = copyin((caddr_t)uap->tptr, (caddr_t)tv, sizeof (tv));
  1624.         if (error)
  1625.             return (error);
  1626.     } else
  1627.         tv[0] = tv[1] = time.tv_sec;
  1628.     ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF;
  1629.     ndp->ni_segflg = UIO_USERSPACE;
  1630.     ndp->ni_dirp = uap->fname;
  1631.     vattr_null(&vattr);
  1632.     vattr.va_atime.tv_sec = tv[0];
  1633.     vattr.va_atime.tv_usec = 0;
  1634.     vattr.va_mtime.tv_sec = tv[1];
  1635.     vattr.va_mtime.tv_usec = 0;
  1636.     if (error = namei(ndp, p))
  1637.         return (error);
  1638.     vp = ndp->ni_vp;
  1639.     if (vp->v_mount->mnt_flag & MNT_RDONLY)
  1640.         error = EROFS;
  1641.     else
  1642.         error = VOP_SETATTR(vp, &vattr, ndp->ni_cred, p);
  1643.     vput(vp);
  1644.     return (error);
  1645. }
  1646.  
  1647. ohpuxpause(p, uap, retval)
  1648.     struct proc *p;
  1649.     int *uap, *retval;
  1650. {
  1651.     (void) tsleep(kstack, PPAUSE | PCATCH, "pause", 0);
  1652.     /* always return EINTR rather than ERESTART... */
  1653.     return (EINTR);
  1654. }
  1655.  
  1656. /*
  1657.  * The old fstat system call.
  1658.  */
  1659. ohpuxfstat(p, uap, retval)
  1660.     struct proc *p;
  1661.     register struct args {
  1662.         int    fd;
  1663.         struct ohpuxstat *sb;
  1664.     } *uap;
  1665.     int *retval;
  1666. {
  1667.     register struct filedesc *fdp = p->p_fd;
  1668.     struct file *fp;
  1669.  
  1670.     if (((unsigned)uap->fd) >= fdp->fd_nfiles ||
  1671.         (fp = fdp->fd_ofiles[uap->fd]) == NULL)
  1672.         return (EBADF);
  1673.     if (fp->f_type != DTYPE_VNODE)
  1674.         return (EINVAL);
  1675.     return (ohpuxstat1((struct vnode *)fp->f_data, uap->sb));
  1676. }
  1677.  
  1678. /*
  1679.  * Old stat system call.  This version follows links.
  1680.  */
  1681. ohpuxstat(p, uap, retval)
  1682.     struct proc *p;
  1683.     register struct args {
  1684.         char    *fname;
  1685.         struct ohpuxstat *sb;
  1686.     } *uap;
  1687.     int *retval;
  1688. {
  1689.     register struct nameidata *ndp;
  1690.     int error;
  1691.     struct nameidata nd;
  1692.  
  1693.     ndp = &nd;
  1694.     ndp->ni_nameiop = LOOKUP | LOCKLEAF | FOLLOW;
  1695.     ndp->ni_segflg = UIO_USERSPACE;
  1696.     ndp->ni_dirp = uap->fname;
  1697.     if (error = namei(ndp, p))
  1698.         return (error);
  1699.     error = ohpuxstat1(ndp->ni_vp, uap->sb);
  1700.     vput(ndp->ni_vp);
  1701.     return (error);
  1702. }
  1703.  
  1704. int
  1705. ohpuxstat1(vp, ub)
  1706.     register struct vnode *vp;
  1707.     struct ohpuxstat *ub;
  1708. {
  1709.     struct ohpuxstat ds;
  1710.     struct vattr vattr;
  1711.     register int error;
  1712.  
  1713.     error = VOP_GETATTR(vp, &vattr, curproc->p_ucred, curproc);
  1714.     if (error)
  1715.         return(error);
  1716.     /*
  1717.      * Copy from inode table
  1718.      */
  1719.     ds.ohst_dev = vattr.va_fsid;
  1720.     ds.ohst_ino = (short)vattr.va_fileid;
  1721.     ds.ohst_mode = (u_short)vattr.va_mode;
  1722.     ds.ohst_nlink = vattr.va_nlink;
  1723.     ds.ohst_uid = (short)vattr.va_uid;
  1724.     ds.ohst_gid = (short)vattr.va_gid;
  1725.     ds.ohst_rdev = (dev_t)vattr.va_rdev;
  1726.     ds.ohst_size = (int)vattr.va_size;
  1727.     ds.ohst_atime = (int)vattr.va_atime.tv_sec;
  1728.     ds.ohst_mtime = (int)vattr.va_mtime.tv_sec;
  1729.     ds.ohst_ctime = (int)vattr.va_ctime.tv_sec;
  1730.     return (copyout((caddr_t)&ds, (caddr_t)ub, sizeof(ds)));
  1731. }
  1732. /* #endif */
  1733.  
  1734. #endif
  1735.