141486Smckusick /* 241486Smckusick * Copyright (c) 1988 University of Utah. 363734Sbostic * Copyright (c) 1990, 1993 463734Sbostic * The Regents of the University of California. All rights reserved. 541486Smckusick * 641486Smckusick * This code is derived from software contributed to Berkeley by 741486Smckusick * the Systems Programming Group of the University of Utah Computer 841486Smckusick * Science Department. 941486Smckusick * 1041486Smckusick * %sccs.include.redist.c% 1141486Smckusick * 1264478Shibler * from: Utah $Hdr: hpux_compat.c 1.64 93/08/05$ 1341486Smckusick * 14*66074Shibler * @(#)hpux_compat.c 8.4 (Berkeley) 02/13/94 1541486Smckusick */ 1641486Smckusick 1741486Smckusick /* 1854857Shibler * Various HP-UX compatibility routines 1941486Smckusick */ 2041486Smckusick 2141486Smckusick #ifdef HPUXCOMPAT 2259982Smckusick #ifndef COMPAT_43 2359982Smckusick #define COMPAT_43 2459982Smckusick #endif 2541486Smckusick 2656506Sbostic #include <sys/param.h> 2756506Sbostic #include <sys/systm.h> 2856506Sbostic #include <sys/signalvar.h> 2956506Sbostic #include <sys/kernel.h> 3056506Sbostic #include <sys/filedesc.h> 3156506Sbostic #include <sys/proc.h> 3256506Sbostic #include <sys/buf.h> 3356506Sbostic #include <sys/wait.h> 3456506Sbostic #include <sys/file.h> 3556506Sbostic #include <sys/namei.h> 3656506Sbostic #include <sys/vnode.h> 3756506Sbostic #include <sys/ioctl.h> 3856506Sbostic #include <sys/ptrace.h> 3956506Sbostic #include <sys/stat.h> 4056506Sbostic #include <sys/syslog.h> 4156506Sbostic #include <sys/malloc.h> 4256506Sbostic #include <sys/mount.h> 4356506Sbostic #include <sys/ipc.h> 4456506Sbostic #include <sys/user.h> 4557307Shibler #include <sys/mman.h> 4641486Smckusick 4756506Sbostic #include <machine/cpu.h> 4856506Sbostic #include <machine/reg.h> 4956506Sbostic #include <machine/psl.h> 5056506Sbostic #include <machine/vmparam.h> 5156506Sbostic #include <hp/hpux/hpux.h> 5256506Sbostic #include <hp/hpux/hpux_termio.h> 5356506Sbostic 5441486Smckusick #ifdef DEBUG 5541486Smckusick int unimpresponse = 0; 5641486Smckusick #endif 5741486Smckusick 5841486Smckusick /* SYS5 style UTSNAME info */ 5941486Smckusick struct hpuxutsname protoutsname = { 6057307Shibler "4.4bsd", "", "0.5", "B", "9000/3?0", "" 6141486Smckusick }; 6241486Smckusick 6341486Smckusick /* 6.0 and later style context */ 6453922Shibler #if defined(HP380) 6553922Shibler char hpux040context[] = 6653922Shibler "standalone HP-MC68040 HP-MC68881 HP-MC68020 HP-MC68010 localroot default"; 6753922Shibler #endif 6841486Smckusick #ifdef FPCOPROC 6941486Smckusick char hpuxcontext[] = 7041486Smckusick "standalone HP-MC68881 HP-MC68020 HP-MC68010 localroot default"; 7141486Smckusick #else 7241486Smckusick char hpuxcontext[] = 7341486Smckusick "standalone HP-MC68020 HP-MC68010 localroot default"; 7441486Smckusick #endif 7541486Smckusick 7641486Smckusick /* YP domainname */ 7741486Smckusick char domainname[MAXHOSTNAMELEN] = "unknown"; 7841486Smckusick int domainnamelen = 7; 7941486Smckusick 8064478Shibler #define NERR 83 8141486Smckusick #define BERR 1000 8241486Smckusick 8341486Smckusick /* indexed by BSD errno */ 8441486Smckusick short bsdtohpuxerrnomap[NERR] = { 8541486Smckusick /*00*/ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 8641486Smckusick /*10*/ 10, 45, 12, 13, 14, 15, 16, 17, 18, 19, 8741486Smckusick /*20*/ 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 8841486Smckusick /*30*/ 30, 31, 32, 33, 34, 246, 245, 244, 216, 217, 8941486Smckusick /*40*/ 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 9041486Smckusick /*50*/ 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 9141486Smckusick /*60*/ 238, 239, 249, 248, 241, 242, 247,BERR,BERR,BERR, 9264478Shibler /*70*/ 70, 71,BERR,BERR,BERR,BERR,BERR, 46, 251,BERR, 9364478Shibler /*80*/ BERR,BERR, 11 9441486Smckusick }; 9541486Smckusick 9643452Shibler notimp(p, uap, retval, code, nargs) 9743452Shibler struct proc *p; 9843452Shibler int *uap, *retval; 9943452Shibler int code, nargs; 10041486Smckusick { 10143452Shibler int error = 0; 10241486Smckusick #ifdef DEBUG 10343452Shibler register int *argp = uap; 10441486Smckusick extern char *hpuxsyscallnames[]; 10541486Smckusick 10654857Shibler printf("HP-UX %s(", hpuxsyscallnames[code]); 10741486Smckusick if (nargs) 10841486Smckusick while (nargs--) 10941486Smckusick printf("%x%c", *argp++, nargs? ',' : ')'); 11041486Smckusick else 11141486Smckusick printf(")"); 11241486Smckusick printf("\n"); 11341486Smckusick switch (unimpresponse) { 11441486Smckusick case 0: 11543452Shibler error = nosys(p, uap, retval); 11641486Smckusick break; 11741486Smckusick case 1: 11843452Shibler error = EINVAL; 11941486Smckusick break; 12041486Smckusick } 12141486Smckusick #else 12243452Shibler error = nosys(p, uap, retval); 12341486Smckusick #endif 12443452Shibler uprintf("HP-UX system call %d not implemented\n", code); 12544421Skarels return (error); 12641486Smckusick } 12741486Smckusick 12864478Shibler /* 12964478Shibler * HP-UX fork and vfork need to map the EAGAIN return value appropriately. 13064478Shibler */ 13164478Shibler hpuxfork(p, uap, retval) 13264478Shibler struct proc *p; 13364478Shibler struct hpuxwait3_args *uap; 13464478Shibler int *retval; 13564478Shibler { 13664478Shibler int error; 13764478Shibler 13864478Shibler error = fork(p, uap, retval); 13964478Shibler if (error == EAGAIN) 14064478Shibler error = OEAGAIN; 14164478Shibler return (error); 14264478Shibler } 14364478Shibler 14464478Shibler hpuxvfork(p, uap, retval) 14564478Shibler struct proc *p; 14664478Shibler struct hpuxwait3_args *uap; 14764478Shibler int *retval; 14864478Shibler 14964478Shibler { 15064478Shibler int error; 15164478Shibler 15264478Shibler error = vfork(p, uap, retval); 15364478Shibler if (error == EAGAIN) 15464478Shibler error = OEAGAIN; 15564478Shibler return (error); 15664478Shibler } 15764478Shibler 15854917Storek struct hpuxexecv_args { 15954917Storek char *fname; 16054917Storek char **argp; 16154917Storek char **envp; 16254917Storek }; 16348478Skarels hpuxexecv(p, uap, retval) 16448478Skarels struct proc *p; 16554917Storek struct hpuxexecv_args *uap; 16648478Skarels int *retval; 16748478Skarels { 16848478Skarels extern int execve(); 16948478Skarels 17048478Skarels uap->envp = NULL; 17148478Skarels return (execve(p, uap, retval)); 17248478Skarels } 17348478Skarels 17441486Smckusick /* 17554857Shibler * HP-UX versions of wait and wait3 actually pass the parameters 17641486Smckusick * (status pointer, options, rusage) into the kernel rather than 17742352Smckusick * handling it in the C library stub. We also need to map any 17854857Shibler * termination signal from BSD to HP-UX. 17941486Smckusick */ 18054917Storek struct hpuxwait3_args { 18154917Storek int *status; 18254917Storek int options; 18354917Storek int rusage; 18454917Storek }; 18543452Shibler hpuxwait3(p, uap, retval) 18643452Shibler struct proc *p; 18754917Storek struct hpuxwait3_args *uap; 18843452Shibler int *retval; 18943452Shibler { 19041486Smckusick /* rusage pointer must be zero */ 19143452Shibler if (uap->rusage) 19244421Skarels return (EINVAL); 19352381Smckusick p->p_md.md_regs[PS] = PSL_ALLCC; 19452381Smckusick p->p_md.md_regs[R0] = uap->options; 19552381Smckusick p->p_md.md_regs[R1] = uap->rusage; 19644421Skarels return (hpuxwait(p, uap, retval)); 19741486Smckusick } 19841486Smckusick 19954917Storek struct hpuxwait_args { 20054917Storek int *status; 20154917Storek }; 20243452Shibler hpuxwait(p, uap, retval) 20343452Shibler struct proc *p; 20454917Storek struct hpuxwait_args *uap; 20543452Shibler int *retval; 20641486Smckusick { 20743452Shibler int sig, *statp, error; 20841486Smckusick 20941486Smckusick statp = uap->status; /* owait clobbers first arg */ 21043452Shibler error = owait(p, uap, retval); 21141486Smckusick /* 21241486Smckusick * HP-UX wait always returns EINTR when interrupted by a signal 21341486Smckusick * (well, unless its emulating a BSD process, but we don't bother...) 21441486Smckusick */ 21543452Shibler if (error == ERESTART) 21643452Shibler error = EINTR; 21743452Shibler if (error) 21844421Skarels return (error); 21943452Shibler sig = retval[1] & 0xFF; 22041486Smckusick if (sig == WSTOPPED) { 22143452Shibler sig = (retval[1] >> 8) & 0xFF; 22243452Shibler retval[1] = (bsdtohpuxsig(sig) << 8) | WSTOPPED; 22341486Smckusick } else if (sig) 22443452Shibler retval[1] = (retval[1] & 0xFF00) | 22541486Smckusick bsdtohpuxsig(sig & 0x7F) | (sig & 0x80); 22641486Smckusick if (statp) 22743452Shibler if (suword((caddr_t)statp, retval[1])) 22843452Shibler error = EFAULT; 22944421Skarels return (error); 23041486Smckusick } 23141486Smckusick 23254917Storek struct hpuxwaitpid_args { 23354917Storek int pid; 23454917Storek int *status; 23554917Storek int options; 23654917Storek struct rusage *rusage; /* wait4 arg */ 23754917Storek }; 23843452Shibler hpuxwaitpid(p, uap, retval) 23943452Shibler struct proc *p; 24054917Storek struct hpuxwaitpid_args *uap; 24143452Shibler int *retval; 24243452Shibler { 24355832Shibler int rv, sig, xstat, error; 24442352Smckusick 24542352Smckusick uap->rusage = 0; 24643452Shibler error = wait4(p, uap, retval); 24742352Smckusick /* 24842352Smckusick * HP-UX wait always returns EINTR when interrupted by a signal 24942352Smckusick * (well, unless its emulating a BSD process, but we don't bother...) 25042352Smckusick */ 25143452Shibler if (error == ERESTART) 25243452Shibler error = EINTR; 25343452Shibler if (error) 25444421Skarels return (error); 25555832Shibler if (uap->status) { 25655832Shibler /* 25755832Shibler * Wait4 already wrote the status out to user space, 25855832Shibler * pull it back, change the signal portion, and write 25955832Shibler * it back out. 26055832Shibler */ 26155832Shibler rv = fuword((caddr_t)uap->status); 26255832Shibler if (WIFSTOPPED(rv)) { 26355832Shibler sig = WSTOPSIG(rv); 26455832Shibler rv = W_STOPCODE(bsdtohpuxsig(sig)); 26555832Shibler } else if (WIFSIGNALED(rv)) { 26655832Shibler sig = WTERMSIG(rv); 26755832Shibler xstat = WEXITSTATUS(rv); 26855832Shibler rv = W_EXITCODE(xstat, bsdtohpuxsig(sig)) | 26955832Shibler WCOREDUMP(rv); 27055832Shibler } 27155832Shibler (void)suword((caddr_t)uap->status, rv); 27255832Shibler } 27344421Skarels return (error); 27442352Smckusick } 27542352Smckusick 27641486Smckusick /* 27763726Shibler * Old creat system call. 27863726Shibler */ 27963726Shibler struct hpuxcreat_args { 28063726Shibler char *fname; 28163726Shibler int fmode; 28263726Shibler }; 28363726Shibler hpuxcreat(p, uap, retval) 28463726Shibler struct proc *p; 28563726Shibler register struct hpuxcreat_args *uap; 28663726Shibler int *retval; 28763726Shibler { 28863726Shibler struct nargs { 28963726Shibler char *fname; 29063726Shibler int mode; 29163726Shibler int crtmode; 29263726Shibler } openuap; 29363726Shibler 29463726Shibler openuap.fname = uap->fname; 29563726Shibler openuap.crtmode = uap->fmode; 29663726Shibler openuap.mode = O_WRONLY | O_CREAT | O_TRUNC; 29763726Shibler return (open(p, &openuap, retval)); 29863726Shibler } 29963726Shibler 30063726Shibler /* 30163726Shibler * XXX extensions to the fd_ofileflags flags. 30263726Shibler * Hate to put this there, but they do need to be per-file. 30363726Shibler */ 30463726Shibler #define UF_NONBLOCK_ON 0x10 30563726Shibler #define UF_FNDELAY_ON 0x20 30663726Shibler #define UF_FIONBIO_ON 0x40 30763726Shibler 30863726Shibler /* 30941486Smckusick * Must remap some bits in the mode mask. 31041486Smckusick * O_CREAT, O_TRUNC, and O_EXCL must be remapped, 31163726Shibler * O_NONBLOCK is remapped and remembered, 31263726Shibler * O_FNDELAY is remembered, 31363726Shibler * O_SYNCIO is removed entirely. 31441486Smckusick */ 31554917Storek struct hpuxopen_args { 31654917Storek char *fname; 31754917Storek int mode; 31854917Storek int crtmode; 31954917Storek }; 32043067Skarels hpuxopen(p, uap, retval) 32143067Skarels struct proc *p; 32254917Storek register struct hpuxopen_args *uap; 32343067Skarels int *retval; 32443067Skarels { 32563726Shibler int mode, error; 32641486Smckusick 32741486Smckusick mode = uap->mode; 32863726Shibler uap->mode &= 32963726Shibler ~(HPUXNONBLOCK|HPUXFSYNCIO|HPUXFEXCL|HPUXFTRUNC|HPUXFCREAT); 33041486Smckusick if (mode & HPUXFCREAT) { 33141486Smckusick /* 33241486Smckusick * simulate the pre-NFS behavior that opening a 33341486Smckusick * file for READ+CREATE ignores the CREATE (unless 33441486Smckusick * EXCL is set in which case we will return the 33541486Smckusick * proper error). 33641486Smckusick */ 33748478Skarels if ((mode & HPUXFEXCL) || (FFLAGS(mode) & FWRITE)) 33849950Smckusick uap->mode |= O_CREAT; 33941486Smckusick } 34041486Smckusick if (mode & HPUXFTRUNC) 34149950Smckusick uap->mode |= O_TRUNC; 34241486Smckusick if (mode & HPUXFEXCL) 34349950Smckusick uap->mode |= O_EXCL; 34463726Shibler if (mode & HPUXNONBLOCK) 34563726Shibler uap->mode |= O_NDELAY; 34663726Shibler error = open(p, uap, retval); 34763726Shibler /* 34863726Shibler * Record non-blocking mode for fcntl, read, write, etc. 34963726Shibler */ 35063726Shibler if (error == 0 && (uap->mode & O_NDELAY)) 35163726Shibler p->p_fd->fd_ofileflags[*retval] |= 35263726Shibler (mode & HPUXNONBLOCK) ? UF_NONBLOCK_ON : UF_FNDELAY_ON; 35363726Shibler return (error); 35441486Smckusick } 35541486Smckusick 35654917Storek struct hpuxfcntl_args { 35754917Storek int fdes; 35854917Storek int cmd; 35954917Storek int arg; 36054917Storek }; 36143452Shibler hpuxfcntl(p, uap, retval) 36243452Shibler struct proc *p; 36354917Storek register struct hpuxfcntl_args *uap; 36443452Shibler int *retval; 36543452Shibler { 366*66074Shibler int mode, error, flg = F_POSIX; 367*66074Shibler struct file *fp; 368*66074Shibler char *pop; 369*66074Shibler struct hpuxflock hfl; 370*66074Shibler struct flock fl; 371*66074Shibler struct vnode *vp; 37241486Smckusick 373*66074Shibler if ((unsigned)uap->fdes >= p->p_fd->fd_nfiles || 374*66074Shibler (fp = p->p_fd->fd_ofiles[uap->fdes]) == NULL) 375*66074Shibler return (EBADF); 376*66074Shibler pop = &p->p_fd->fd_ofileflags[uap->fdes]; 37741486Smckusick switch (uap->cmd) { 37841486Smckusick case F_SETFL: 37963726Shibler if (uap->arg & HPUXNONBLOCK) 380*66074Shibler *pop |= UF_NONBLOCK_ON; 38163726Shibler else 382*66074Shibler *pop &= ~UF_NONBLOCK_ON; 38364478Shibler if (uap->arg & HPUXNDELAY) 384*66074Shibler *pop |= UF_FNDELAY_ON; 38563726Shibler else 386*66074Shibler *pop &= ~UF_FNDELAY_ON; 387*66074Shibler if (*pop & (UF_NONBLOCK_ON|UF_FNDELAY_ON|UF_FIONBIO_ON)) 38863726Shibler uap->arg |= FNONBLOCK; 389*66074Shibler else 390*66074Shibler uap->arg &= ~FNONBLOCK; 39163726Shibler uap->arg &= ~(HPUXNONBLOCK|HPUXFSYNCIO|HPUXFREMOTE); 39241486Smckusick break; 39341486Smckusick case F_GETFL: 39441486Smckusick case F_DUPFD: 39541486Smckusick case F_GETFD: 39641486Smckusick case F_SETFD: 39741486Smckusick break; 398*66074Shibler 399*66074Shibler case HPUXF_SETLKW: 400*66074Shibler flg |= F_WAIT; 401*66074Shibler /* Fall into F_SETLK */ 402*66074Shibler 403*66074Shibler case HPUXF_SETLK: 404*66074Shibler if (fp->f_type != DTYPE_VNODE) 405*66074Shibler return (EBADF); 406*66074Shibler vp = (struct vnode *)fp->f_data; 407*66074Shibler /* Copy in the lock structure */ 408*66074Shibler error = copyin((caddr_t)uap->arg, (caddr_t)&hfl, sizeof (hfl)); 409*66074Shibler if (error) 410*66074Shibler return (error); 411*66074Shibler fl.l_start = hfl.hl_start; 412*66074Shibler fl.l_len = hfl.hl_len; 413*66074Shibler fl.l_pid = hfl.hl_pid; 414*66074Shibler fl.l_type = hfl.hl_type; 415*66074Shibler fl.l_whence = hfl.hl_whence; 416*66074Shibler if (fl.l_whence == SEEK_CUR) 417*66074Shibler fl.l_start += fp->f_offset; 418*66074Shibler switch (fl.l_type) { 419*66074Shibler 420*66074Shibler case F_RDLCK: 421*66074Shibler if ((fp->f_flag & FREAD) == 0) 422*66074Shibler return (EBADF); 423*66074Shibler p->p_flag |= P_ADVLOCK; 424*66074Shibler return (VOP_ADVLOCK(vp, (caddr_t)p, F_SETLK, &fl, flg)); 425*66074Shibler 426*66074Shibler case F_WRLCK: 427*66074Shibler if ((fp->f_flag & FWRITE) == 0) 428*66074Shibler return (EBADF); 429*66074Shibler p->p_flag |= P_ADVLOCK; 430*66074Shibler return (VOP_ADVLOCK(vp, (caddr_t)p, F_SETLK, &fl, flg)); 431*66074Shibler 432*66074Shibler case F_UNLCK: 433*66074Shibler return (VOP_ADVLOCK(vp, (caddr_t)p, F_UNLCK, &fl, 434*66074Shibler F_POSIX)); 435*66074Shibler 436*66074Shibler default: 437*66074Shibler return (EINVAL); 438*66074Shibler } 439*66074Shibler 440*66074Shibler case F_GETLK: 441*66074Shibler if (fp->f_type != DTYPE_VNODE) 442*66074Shibler return (EBADF); 443*66074Shibler vp = (struct vnode *)fp->f_data; 444*66074Shibler /* Copy in the lock structure */ 445*66074Shibler error = copyin((caddr_t)uap->arg, (caddr_t)&hfl, sizeof (hfl)); 446*66074Shibler if (error) 447*66074Shibler return (error); 448*66074Shibler fl.l_start = hfl.hl_start; 449*66074Shibler fl.l_len = hfl.hl_len; 450*66074Shibler fl.l_pid = hfl.hl_pid; 451*66074Shibler fl.l_type = hfl.hl_type; 452*66074Shibler fl.l_whence = hfl.hl_whence; 453*66074Shibler if (fl.l_whence == SEEK_CUR) 454*66074Shibler fl.l_start += fp->f_offset; 455*66074Shibler if (error = VOP_ADVLOCK(vp, (caddr_t)p, F_GETLK, &fl, F_POSIX)) 456*66074Shibler return (error); 457*66074Shibler hfl.hl_start = fl.l_start; 458*66074Shibler hfl.hl_len = fl.l_len; 459*66074Shibler hfl.hl_pid = fl.l_pid; 460*66074Shibler hfl.hl_type = fl.l_type; 461*66074Shibler hfl.hl_whence = fl.l_whence; 462*66074Shibler return (copyout((caddr_t)&hfl, (caddr_t)uap->arg, sizeof (hfl))); 463*66074Shibler 46441486Smckusick default: 46544421Skarels return (EINVAL); 46641486Smckusick } 46743452Shibler error = fcntl(p, uap, retval); 46849329Shibler if (error == 0 && uap->cmd == F_GETFL) { 46943452Shibler mode = *retval; 47063726Shibler *retval &= ~(O_CREAT|O_TRUNC|O_EXCL); 47163726Shibler if (mode & FNONBLOCK) { 472*66074Shibler if (*pop & UF_NONBLOCK_ON) 47363726Shibler *retval |= HPUXNONBLOCK; 474*66074Shibler if ((*pop & UF_FNDELAY_ON) == 0) 47564478Shibler *retval &= ~HPUXNDELAY; 47663726Shibler } 47749950Smckusick if (mode & O_CREAT) 47843452Shibler *retval |= HPUXFCREAT; 47949950Smckusick if (mode & O_TRUNC) 48043452Shibler *retval |= HPUXFTRUNC; 48149950Smckusick if (mode & O_EXCL) 48243452Shibler *retval |= HPUXFEXCL; 48341486Smckusick } 48444421Skarels return (error); 48541486Smckusick } 48641486Smckusick 48741486Smckusick /* 48863726Shibler * Read and write calls. Same as BSD except for non-blocking behavior. 48963726Shibler * There are three types of non-blocking reads/writes in HP-UX checked 49063726Shibler * in the following order: 49149329Shibler * 49263726Shibler * O_NONBLOCK: return -1 and errno == EAGAIN 49363726Shibler * O_NDELAY: return 0 49463726Shibler * FIOSNBIO: return -1 and errno == EWOULDBLOCK 49541486Smckusick */ 49663726Shibler struct hpuxrw_args { 49763726Shibler int fd; 49854917Storek }; 49963726Shibler 50043452Shibler hpuxread(p, uap, retval) 50143452Shibler struct proc *p; 50263726Shibler struct hpuxrw_args *uap; 50343452Shibler int *retval; 50441486Smckusick { 50543452Shibler int error; 50641486Smckusick 50743452Shibler error = read(p, uap, retval); 50863726Shibler if (error == EWOULDBLOCK) { 50963726Shibler char *fp = &p->p_fd->fd_ofileflags[uap->fd]; 51063726Shibler 51163726Shibler if (*fp & UF_NONBLOCK_ON) { 51263726Shibler *retval = -1; 51364478Shibler error = OEAGAIN; 51463726Shibler } else if (*fp & UF_FNDELAY_ON) { 51563726Shibler *retval = 0; 51663726Shibler error = 0; 51763726Shibler } 51841486Smckusick } 51944421Skarels return (error); 52041486Smckusick } 52141486Smckusick 52243452Shibler hpuxwrite(p, uap, retval) 52343452Shibler struct proc *p; 52463726Shibler struct hpuxrw_args *uap; 52543452Shibler int *retval; 52641486Smckusick { 52743452Shibler int error; 52841486Smckusick 52943452Shibler error = write(p, uap, retval); 53063726Shibler if (error == EWOULDBLOCK) { 53163726Shibler char *fp = &p->p_fd->fd_ofileflags[uap->fd]; 53263726Shibler 53363726Shibler if (*fp & UF_NONBLOCK_ON) { 53463726Shibler *retval = -1; 53564478Shibler error = OEAGAIN; 53663726Shibler } else if (*fp & UF_FNDELAY_ON) { 53763726Shibler *retval = 0; 53863726Shibler error = 0; 53963726Shibler } 54041486Smckusick } 54144421Skarels return (error); 54241486Smckusick } 54341486Smckusick 54443452Shibler hpuxreadv(p, uap, retval) 54543452Shibler struct proc *p; 54663726Shibler struct hpuxrw_args *uap; 54743452Shibler int *retval; 54841486Smckusick { 54943452Shibler int error; 55041486Smckusick 55143452Shibler error = readv(p, uap, retval); 55263726Shibler if (error == EWOULDBLOCK) { 55363726Shibler char *fp = &p->p_fd->fd_ofileflags[uap->fd]; 55463726Shibler 55563726Shibler if (*fp & UF_NONBLOCK_ON) { 55663726Shibler *retval = -1; 55764478Shibler error = OEAGAIN; 55863726Shibler } else if (*fp & UF_FNDELAY_ON) { 55963726Shibler *retval = 0; 56063726Shibler error = 0; 56163726Shibler } 56241486Smckusick } 56344421Skarels return (error); 56441486Smckusick } 56541486Smckusick 56643452Shibler hpuxwritev(p, uap, retval) 56743452Shibler struct proc *p; 56863726Shibler struct hpuxrw_args *uap; 56943452Shibler int *retval; 57041486Smckusick { 57143452Shibler int error; 57241486Smckusick 57343452Shibler error = writev(p, uap, retval); 57463726Shibler if (error == EWOULDBLOCK) { 57563726Shibler char *fp = &p->p_fd->fd_ofileflags[uap->fd]; 57663726Shibler 57763726Shibler if (*fp & UF_NONBLOCK_ON) { 57863726Shibler *retval = -1; 57964478Shibler error = OEAGAIN; 58063726Shibler } else if (*fp & UF_FNDELAY_ON) { 58163726Shibler *retval = 0; 58263726Shibler error = 0; 58363726Shibler } 58441486Smckusick } 58544421Skarels return (error); 58641486Smckusick } 58741486Smckusick 58841486Smckusick /* 58941486Smckusick * 4.3bsd dup allows dup2 to come in on the same syscall entry 59054857Shibler * and hence allows two arguments. HP-UX dup has only one arg. 59141486Smckusick */ 59254917Storek struct hpuxdup_args { 59354917Storek int i; 59454917Storek }; 59543452Shibler hpuxdup(p, uap, retval) 59643452Shibler struct proc *p; 59754917Storek register struct hpuxdup_args *uap; 59843452Shibler int *retval; 59941486Smckusick { 60045923Smckusick register struct filedesc *fdp = p->p_fd; 60141486Smckusick struct file *fp; 60243452Shibler int fd, error; 60341486Smckusick 60448478Skarels if (((unsigned)uap->i) >= fdp->fd_nfiles || 60548478Skarels (fp = fdp->fd_ofiles[uap->i]) == NULL) 60644421Skarels return (EBADF); 60748478Skarels if (error = fdalloc(p, 0, &fd)) 60844421Skarels return (error); 60948478Skarels fdp->fd_ofiles[fd] = fp; 61048478Skarels fdp->fd_ofileflags[fd] = fdp->fd_ofileflags[uap->i] &~ UF_EXCLOSE; 61145923Smckusick fp->f_count++; 61245923Smckusick if (fd > fdp->fd_lastfile) 61345923Smckusick fdp->fd_lastfile = fd; 61443452Shibler *retval = fd; 61544421Skarels return (0); 61641486Smckusick } 61741486Smckusick 61854917Storek struct hpuxutssys_args { 61954917Storek struct hpuxutsname *uts; 62054917Storek int dev; 62154917Storek int request; 62254917Storek }; 62345753Smckusick hpuxutssys(p, uap, retval) 62443452Shibler struct proc *p; 62554917Storek register struct hpuxutssys_args *uap; 62643452Shibler int *retval; 62743452Shibler { 62841486Smckusick register int i; 62943452Shibler int error; 63041486Smckusick 63141486Smckusick switch (uap->request) { 63241486Smckusick /* uname */ 63341486Smckusick case 0: 63441486Smckusick /* fill in machine type */ 63541486Smckusick switch (machineid) { 63641486Smckusick case HP_320: 63741486Smckusick protoutsname.machine[6] = '2'; 63841486Smckusick break; 63941486Smckusick /* includes 318 and 319 */ 64041486Smckusick case HP_330: 64141486Smckusick protoutsname.machine[6] = '3'; 64241486Smckusick break; 64341486Smckusick case HP_340: 64441486Smckusick protoutsname.machine[6] = '4'; 64541486Smckusick break; 64641486Smckusick case HP_350: 64741486Smckusick protoutsname.machine[6] = '5'; 64841486Smckusick break; 64941486Smckusick case HP_360: 65041486Smckusick protoutsname.machine[6] = '6'; 65141486Smckusick break; 65241486Smckusick case HP_370: 65341486Smckusick protoutsname.machine[6] = '7'; 65441486Smckusick break; 65543452Shibler /* includes 345 */ 65643452Shibler case HP_375: 65743452Shibler protoutsname.machine[6] = '7'; 65843452Shibler protoutsname.machine[7] = '5'; 65943452Shibler break; 66054857Shibler /* includes 425 */ 66154857Shibler case HP_380: 66254857Shibler protoutsname.machine[6] = '8'; 66354857Shibler break; 66457307Shibler case HP_433: 66557307Shibler protoutsname.machine[5] = '4'; 66657307Shibler protoutsname.machine[6] = '3'; 66757307Shibler protoutsname.machine[7] = '3'; 66857307Shibler break; 66941486Smckusick } 67041486Smckusick /* copy hostname (sans domain) to nodename */ 67149329Shibler for (i = 0; i < 8 && hostname[i] != '.'; i++) 67241486Smckusick protoutsname.nodename[i] = hostname[i]; 67349329Shibler protoutsname.nodename[i] = '\0'; 67443452Shibler error = copyout((caddr_t)&protoutsname, (caddr_t)uap->uts, 67543452Shibler sizeof(struct hpuxutsname)); 67641486Smckusick break; 67745753Smckusick 67845753Smckusick /* gethostname */ 67945753Smckusick case 5: 68045753Smckusick /* uap->dev is length */ 68145753Smckusick if (uap->dev > hostnamelen + 1) 68245753Smckusick uap->dev = hostnamelen + 1; 68345753Smckusick error = copyout((caddr_t)hostname, (caddr_t)uap->uts, 68445753Smckusick uap->dev); 68545753Smckusick break; 68645753Smckusick 68745753Smckusick case 1: /* ?? */ 68845753Smckusick case 2: /* ustat */ 68945753Smckusick case 3: /* ?? */ 69045753Smckusick case 4: /* sethostname */ 69141486Smckusick default: 69243452Shibler error = EINVAL; 69341486Smckusick break; 69441486Smckusick } 69544421Skarels return (error); 69641486Smckusick } 69741486Smckusick 69854917Storek struct hpuxsysconf_args { 69954917Storek int name; 70054917Storek }; 70153922Shibler hpuxsysconf(p, uap, retval) 70253922Shibler struct proc *p; 70354917Storek struct hpuxsysconf_args *uap; 70453922Shibler int *retval; 70553922Shibler { 70653922Shibler switch (uap->name) { 70753922Shibler 70864905Shibler /* clock ticks per second */ 70964905Shibler case HPUX_SYSCONF_CLKTICK: 71064905Shibler *retval = hz; 71164905Shibler break; 71264905Shibler 71353922Shibler /* open files */ 71453922Shibler case HPUX_SYSCONF_OPENMAX: 71553922Shibler *retval = NOFILE; 71653922Shibler break; 71753922Shibler 71853922Shibler /* architecture */ 71953922Shibler case HPUX_SYSCONF_CPUTYPE: 72053922Shibler switch (machineid) { 72153922Shibler case HP_320: 72253922Shibler case HP_330: 72353922Shibler case HP_350: 72453922Shibler *retval = HPUX_SYSCONF_CPUM020; 72553922Shibler break; 72653922Shibler case HP_340: 72753922Shibler case HP_360: 72853922Shibler case HP_370: 72953922Shibler case HP_375: 73053922Shibler *retval = HPUX_SYSCONF_CPUM030; 73153922Shibler break; 73253922Shibler case HP_380: 73357307Shibler case HP_433: 73453922Shibler *retval = HPUX_SYSCONF_CPUM040; 73553922Shibler break; 73653922Shibler } 73753922Shibler break; 73853922Shibler default: 73954857Shibler uprintf("HP-UX sysconf(%d) not implemented\n", uap->name); 74053922Shibler return (EINVAL); 74153922Shibler } 74253922Shibler return (0); 74353922Shibler } 74453922Shibler 74554917Storek struct hpuxstat_args { 74654917Storek char *fname; 74754917Storek struct hpuxstat *hsb; 74854917Storek }; 74943452Shibler hpuxstat(p, uap, retval) 75043452Shibler struct proc *p; 75154917Storek struct hpuxstat_args *uap; 75243452Shibler int *retval; 75343452Shibler { 75455282Smckusick return (hpuxstat1(uap->fname, uap->hsb, FOLLOW, p)); 75541486Smckusick } 75641486Smckusick 75754917Storek struct hpuxlstat_args { 75854917Storek char *fname; 75954917Storek struct hpuxstat *hsb; 76054917Storek }; 76143452Shibler hpuxlstat(p, uap, retval) 76243452Shibler struct proc *p; 76354917Storek struct hpuxlstat_args *uap; 76443452Shibler int *retval; 76541486Smckusick { 76655282Smckusick return (hpuxstat1(uap->fname, uap->hsb, NOFOLLOW, p)); 76741486Smckusick } 76841486Smckusick 76954917Storek struct hpuxfstat_args { 77054917Storek int fdes; 77154917Storek struct hpuxstat *hsb; 77254917Storek }; 77343452Shibler hpuxfstat(p, uap, retval) 77443452Shibler struct proc *p; 77554917Storek register struct hpuxfstat_args *uap; 77643452Shibler int *retval; 77741486Smckusick { 77845923Smckusick register struct filedesc *fdp = p->p_fd; 77941486Smckusick register struct file *fp; 78041486Smckusick struct stat sb; 78143452Shibler int error; 78241486Smckusick 78348478Skarels if (((unsigned)uap->fdes) >= fdp->fd_nfiles || 78448478Skarels (fp = fdp->fd_ofiles[uap->fdes]) == NULL) 78544421Skarels return (EBADF); 78643452Shibler 78741486Smckusick switch (fp->f_type) { 78841486Smckusick 78941486Smckusick case DTYPE_VNODE: 79055282Smckusick error = vn_stat((struct vnode *)fp->f_data, &sb, p); 79141486Smckusick break; 79241486Smckusick 79341486Smckusick case DTYPE_SOCKET: 79455282Smckusick error = soo_stat((struct socket *)fp->f_data, &sb, p); 79541486Smckusick break; 79641486Smckusick 79741486Smckusick default: 79841486Smckusick panic("fstat"); 79941486Smckusick /*NOTREACHED*/ 80041486Smckusick } 80141486Smckusick /* is this right for sockets?? */ 80243452Shibler if (error == 0) 80343452Shibler error = bsdtohpuxstat(&sb, uap->hsb); 80444421Skarels return (error); 80541486Smckusick } 80641486Smckusick 80754917Storek struct hpuxulimit_args { 80854917Storek int cmd; 80954917Storek long newlimit; 81054917Storek }; 81143452Shibler hpuxulimit(p, uap, retval) 81243452Shibler struct proc *p; 81354917Storek register struct hpuxulimit_args *uap; 81453481Smckusick long *retval; 81543452Shibler { 81641486Smckusick struct rlimit *limp; 81743452Shibler int error = 0; 81841486Smckusick 81948478Skarels limp = &p->p_rlimit[RLIMIT_FSIZE]; 82041486Smckusick switch (uap->cmd) { 82141486Smckusick case 2: 82241486Smckusick uap->newlimit *= 512; 82341486Smckusick if (uap->newlimit > limp->rlim_max && 82448478Skarels (error = suser(p->p_ucred, &p->p_acflag))) 82541486Smckusick break; 82641486Smckusick limp->rlim_cur = limp->rlim_max = uap->newlimit; 82741486Smckusick /* else fall into... */ 82841486Smckusick 82941486Smckusick case 1: 83045753Smckusick *retval = limp->rlim_max / 512; 83141486Smckusick break; 83241486Smckusick 83341486Smckusick case 3: 83448478Skarels limp = &p->p_rlimit[RLIMIT_DATA]; 83548478Skarels *retval = ctob(p->p_vmspace->vm_tsize) + limp->rlim_max; 83641486Smckusick break; 83741486Smckusick 83841486Smckusick default: 83943452Shibler error = EINVAL; 84041486Smckusick break; 84141486Smckusick } 84244421Skarels return (error); 84341486Smckusick } 84441486Smckusick 84541486Smckusick /* 84641486Smckusick * Map "real time" priorities 0 (high) thru 127 (low) into nice 84741486Smckusick * values -16 (high) thru -1 (low). 84841486Smckusick */ 84954917Storek struct hpuxrtprio_args { 85054917Storek int pid; 85154917Storek int prio; 85254917Storek }; 85343452Shibler hpuxrtprio(cp, uap, retval) 85443452Shibler struct proc *cp; 85554917Storek register struct hpuxrtprio_args *uap; 85643452Shibler int *retval; 85743452Shibler { 85841486Smckusick struct proc *p; 85943452Shibler int nice, error; 86041486Smckusick 86141486Smckusick if (uap->prio < RTPRIO_MIN && uap->prio > RTPRIO_MAX && 86243452Shibler uap->prio != RTPRIO_NOCHG && uap->prio != RTPRIO_RTOFF) 86344421Skarels return (EINVAL); 86441486Smckusick if (uap->pid == 0) 86543452Shibler p = cp; 86643452Shibler else if ((p = pfind(uap->pid)) == 0) 86744421Skarels return (ESRCH); 86841486Smckusick nice = p->p_nice; 86941486Smckusick if (nice < NZERO) 87043452Shibler *retval = (nice + 16) << 3; 87141486Smckusick else 87243452Shibler *retval = RTPRIO_RTOFF; 87341486Smckusick switch (uap->prio) { 87441486Smckusick 87541486Smckusick case RTPRIO_NOCHG: 87644421Skarels return (0); 87741486Smckusick 87841486Smckusick case RTPRIO_RTOFF: 87941486Smckusick if (nice >= NZERO) 88044421Skarels return (0); 88141486Smckusick nice = NZERO; 88241486Smckusick break; 88341486Smckusick 88441486Smckusick default: 88541486Smckusick nice = (uap->prio >> 3) - 16; 88641486Smckusick break; 88741486Smckusick } 88843452Shibler error = donice(cp, p, nice); 88943452Shibler if (error == EACCES) 89043452Shibler error = EPERM; 89144421Skarels return (error); 89241486Smckusick } 89341486Smckusick 89454917Storek struct hpuxadvise_args { 89554917Storek int arg; 89654917Storek }; 89743452Shibler hpuxadvise(p, uap, retval) 89843452Shibler struct proc *p; 89954917Storek struct hpuxadvise_args *uap; 90043452Shibler int *retval; 90141486Smckusick { 90243452Shibler int error = 0; 90341486Smckusick 90441486Smckusick switch (uap->arg) { 90541486Smckusick case 0: 90657307Shibler p->p_md.md_flags |= MDP_HPUXMMAP; 90741486Smckusick break; 90841486Smckusick case 1: 90941486Smckusick ICIA(); 91041486Smckusick break; 91141486Smckusick case 2: 91241486Smckusick DCIA(); 91341486Smckusick break; 91441486Smckusick default: 91543452Shibler error = EINVAL; 91641486Smckusick break; 91741486Smckusick } 91844421Skarels return (error); 91941486Smckusick } 92041486Smckusick 92154917Storek struct hpuxptrace_args { 92254917Storek int req; 92354917Storek int pid; 92454917Storek int *addr; 92554917Storek int data; 92654917Storek }; 92743452Shibler hpuxptrace(p, uap, retval) 92843452Shibler struct proc *p; 92954917Storek struct hpuxptrace_args *uap; 93043452Shibler int *retval; 93143452Shibler { 93257307Shibler int error, isps = 0; 93357307Shibler struct proc *cp; 93441486Smckusick 93557307Shibler switch (uap->req) { 93657307Shibler /* map signal */ 93757307Shibler case PT_STEP: 93857307Shibler case PT_CONTINUE: 93941486Smckusick if (uap->data) { 94041486Smckusick uap->data = hpuxtobsdsig(uap->data); 94141486Smckusick if (uap->data == 0) 94241486Smckusick uap->data = NSIG; 94341486Smckusick } 94457307Shibler break; 94557307Shibler /* map u-area offset */ 94657307Shibler case PT_READ_U: 94757307Shibler case PT_WRITE_U: 94857307Shibler /* 94957307Shibler * Big, cheezy hack: hpuxtobsduoff is really intended 95057307Shibler * to be called in the child context (procxmt) but we 95157307Shibler * do it here in the parent context to avoid hacks in 95257307Shibler * the MI sys_process.c file. This works only because 95357307Shibler * we can access the child's md_regs pointer and it 95457307Shibler * has the correct value (the child has already trapped 95557307Shibler * into the kernel). 95657307Shibler */ 95757307Shibler if ((cp = pfind(uap->pid)) == 0) 95857307Shibler return (ESRCH); 95957307Shibler uap->addr = (int *) hpuxtobsduoff(uap->addr, &isps, cp); 96057307Shibler 96157307Shibler /* 96257307Shibler * Since HP-UX PS is only 16-bits in ar0, requests 96357307Shibler * to write PS actually contain the PS in the high word 96457307Shibler * and the high half of the PC (the following register) 96557307Shibler * in the low word. Move the PS value to where BSD 96657307Shibler * expects it. 96757307Shibler */ 96857307Shibler if (isps && uap->req == PT_WRITE_U) 96957307Shibler uap->data >>= 16; 97057307Shibler break; 97141486Smckusick } 97243452Shibler error = ptrace(p, uap, retval); 97357307Shibler /* 97457307Shibler * Align PS as HP-UX expects it (see WRITE_U comment above). 97557307Shibler * Note that we do not return the high part of PC like HP-UX 97657307Shibler * would, but the HP-UX debuggers don't require it. 97757307Shibler */ 97857307Shibler if (isps && error == 0 && uap->req == PT_READ_U) 97957307Shibler *retval <<= 16; 98044421Skarels return (error); 98141486Smckusick } 98241486Smckusick 98354917Storek struct hpuxgetdomainname_args { 98454917Storek char *domainname; 98554917Storek u_int len; 98654917Storek }; 98743452Shibler hpuxgetdomainname(p, uap, retval) 98843452Shibler struct proc *p; 98954917Storek register struct hpuxgetdomainname_args *uap; 99043452Shibler int *retval; 99143452Shibler { 99241486Smckusick if (uap->len > domainnamelen + 1) 99341486Smckusick uap->len = domainnamelen + 1; 99444421Skarels return (copyout(domainname, uap->domainname, uap->len)); 99541486Smckusick } 99641486Smckusick 99754917Storek struct hpuxsetdomainname_args { 99854917Storek char *domainname; 99954917Storek u_int len; 100054917Storek }; 100143452Shibler hpuxsetdomainname(p, uap, retval) 100243452Shibler struct proc *p; 100354917Storek register struct hpuxsetdomainname_args *uap; 100443452Shibler int *retval; 100543452Shibler { 100643452Shibler int error; 100741486Smckusick 100848478Skarels if (error = suser(p->p_ucred, &p->p_acflag)) 100944421Skarels return (error); 101043452Shibler if (uap->len > sizeof (domainname) - 1) 101144421Skarels return (EINVAL); 101241486Smckusick domainnamelen = uap->len; 101343452Shibler error = copyin(uap->domainname, domainname, uap->len); 101441486Smckusick domainname[domainnamelen] = 0; 101544421Skarels return (error); 101641486Smckusick } 101741486Smckusick 101841486Smckusick #ifdef SYSVSHM 101956506Sbostic #include <sys/shm.h> 102054857Shibler 102143452Shibler hpuxshmat(p, uap, retval) 102243452Shibler struct proc *p; 102343452Shibler int *uap, *retval; 102441486Smckusick { 102544421Skarels return (shmat(p, uap, retval)); 102641486Smckusick } 102741486Smckusick 102843452Shibler hpuxshmdt(p, uap, retval) 102943452Shibler struct proc *p; 103043452Shibler int *uap, *retval; 103141486Smckusick { 103244421Skarels return (shmdt(p, uap, retval)); 103341486Smckusick } 103441486Smckusick 103543452Shibler hpuxshmget(p, uap, retval) 103643452Shibler struct proc *p; 103743452Shibler int *uap, *retval; 103841486Smckusick { 103944421Skarels return (shmget(p, uap, retval)); 104041486Smckusick } 104154857Shibler 104264478Shibler hpuxshmctl(p, uap, retval) 104364478Shibler struct proc *p; 104464478Shibler int *uap, *retval; 104564478Shibler { 104664478Shibler return (hpuxshmctl1(p, uap, retval, 0)); 104764478Shibler } 104864478Shibler 104964478Shibler hpuxnshmctl(p, uap, retval) 105064478Shibler struct proc *p; 105164478Shibler int *uap, *retval; 105264478Shibler { 105364478Shibler return (hpuxshmctl1(p, uap, retval, 1)); 105464478Shibler } 105564478Shibler 105654857Shibler /* 105754857Shibler * Handle HP-UX specific commands. 105854857Shibler */ 105954917Storek struct hpuxshmctl_args { 106054917Storek int shmid; 106154917Storek int cmd; 106254917Storek caddr_t buf; 106354917Storek }; 106464478Shibler hpuxshmctl1(p, uap, retval, isnew) 106554857Shibler struct proc *p; 106654917Storek struct hpuxshmctl_args *uap; 106754857Shibler int *retval; 106864478Shibler int isnew; 106954857Shibler { 107054857Shibler register struct shmid_ds *shp; 107154857Shibler register struct ucred *cred = p->p_ucred; 107264478Shibler struct hpuxshmid_ds sbuf; 107354857Shibler int error; 107454857Shibler 107554857Shibler if (error = shmvalid(uap->shmid)) 107654857Shibler return (error); 107754857Shibler shp = &shmsegs[uap->shmid % SHMMMNI]; 107864478Shibler switch (uap->cmd) { 107964478Shibler case SHM_LOCK: 108064478Shibler case SHM_UNLOCK: 108154857Shibler /* don't really do anything, but make them think we did */ 108254857Shibler if (cred->cr_uid && cred->cr_uid != shp->shm_perm.uid && 108354857Shibler cred->cr_uid != shp->shm_perm.cuid) 108454857Shibler return (EPERM); 108554857Shibler return (0); 108664478Shibler 108764478Shibler case IPC_STAT: 108864478Shibler if (!isnew) 108964478Shibler break; 109064478Shibler error = ipcaccess(&shp->shm_perm, IPC_R, cred); 109164478Shibler if (error == 0) { 109264478Shibler sbuf.shm_perm.uid = shp->shm_perm.uid; 109364478Shibler sbuf.shm_perm.gid = shp->shm_perm.gid; 109464478Shibler sbuf.shm_perm.cuid = shp->shm_perm.cuid; 109564478Shibler sbuf.shm_perm.cgid = shp->shm_perm.cgid; 109664478Shibler sbuf.shm_perm.mode = shp->shm_perm.mode; 109764478Shibler sbuf.shm_perm.seq = shp->shm_perm.seq; 109864478Shibler sbuf.shm_perm.key = shp->shm_perm.key; 109964478Shibler sbuf.shm_segsz = shp->shm_segsz; 110064478Shibler sbuf.shm_ptbl = shp->shm_handle; /* XXX */ 110164478Shibler sbuf.shm_lpid = shp->shm_lpid; 110264478Shibler sbuf.shm_cpid = shp->shm_cpid; 110364478Shibler sbuf.shm_nattch = shp->shm_nattch; 110464478Shibler sbuf.shm_cnattch = shp->shm_nattch; /* XXX */ 110564478Shibler sbuf.shm_atime = shp->shm_atime; 110664478Shibler sbuf.shm_dtime = shp->shm_dtime; 110764478Shibler sbuf.shm_ctime = shp->shm_ctime; 110864478Shibler error = copyout((caddr_t)&sbuf, uap->buf, sizeof sbuf); 110964478Shibler } 111064478Shibler return (error); 111164478Shibler 111264478Shibler case IPC_SET: 111364478Shibler if (!isnew) 111464478Shibler break; 111564478Shibler if (cred->cr_uid && cred->cr_uid != shp->shm_perm.uid && 111664478Shibler cred->cr_uid != shp->shm_perm.cuid) { 111764478Shibler return (EPERM); 111864478Shibler } 111964478Shibler error = copyin(uap->buf, (caddr_t)&sbuf, sizeof sbuf); 112064478Shibler if (error == 0) { 112164478Shibler shp->shm_perm.uid = sbuf.shm_perm.uid; 112264478Shibler shp->shm_perm.gid = sbuf.shm_perm.gid; 112364478Shibler shp->shm_perm.mode = (shp->shm_perm.mode & ~0777) 112464478Shibler | (sbuf.shm_perm.mode & 0777); 112564478Shibler shp->shm_ctime = time.tv_sec; 112664478Shibler } 112764478Shibler return (error); 112854857Shibler } 112954857Shibler return (shmctl(p, uap, retval)); 113054857Shibler } 113141486Smckusick #endif 113241486Smckusick 113341486Smckusick /* 113441486Smckusick * Fake semaphore routines, just don't return an error. 113541486Smckusick * Should be adequate for starbase to run. 113641486Smckusick */ 113754917Storek struct hpuxsemctl_args { 113854917Storek int semid; 113954917Storek u_int semnum; 114054917Storek int cmd; 114154917Storek int arg; 114254917Storek }; 114343452Shibler hpuxsemctl(p, uap, retval) 114443452Shibler struct proc *p; 114554917Storek struct hpuxsemctl_args *uap; 114643452Shibler int *retval; 114743452Shibler { 114841486Smckusick /* XXX: should do something here */ 114944421Skarels return (0); 115041486Smckusick } 115141486Smckusick 115254917Storek struct hpuxsemget_args { 115354917Storek key_t key; 115454917Storek int nsems; 115554917Storek int semflg; 115654917Storek }; 115743452Shibler hpuxsemget(p, uap, retval) 115843452Shibler struct proc *p; 115954917Storek struct hpuxsemget_args *uap; 116043452Shibler int *retval; 116143452Shibler { 116241486Smckusick /* XXX: should do something here */ 116344421Skarels return (0); 116441486Smckusick } 116541486Smckusick 116654917Storek struct hpuxsemop_args { 116754917Storek int semid; 116854917Storek struct sembuf *sops; 116954917Storek u_int nsops; 117054917Storek }; 117143452Shibler hpuxsemop(p, uap, retval) 117243452Shibler struct proc *p; 117354917Storek struct hpuxsemop_args *uap; 117443452Shibler int *retval; 117543452Shibler { 117641486Smckusick /* XXX: should do something here */ 117744421Skarels return (0); 117841486Smckusick } 117941486Smckusick 118057307Shibler /* 118157307Shibler * HP-UX mmap() emulation (mainly for shared library support). 118257307Shibler */ 118357307Shibler struct hpuxmmap_args { 118457307Shibler caddr_t addr; 118557307Shibler int len; 118657307Shibler int prot; 118757307Shibler int flags; 118857307Shibler int fd; 118957307Shibler long pos; 119057307Shibler }; 119157307Shibler hpuxmmap(p, uap, retval) 119257307Shibler struct proc *p; 119357307Shibler struct hpuxmmap_args *uap; 119457307Shibler int *retval; 119557307Shibler { 119657307Shibler struct mmap_args { 119757307Shibler caddr_t addr; 119857307Shibler int len; 119957307Shibler int prot; 120057307Shibler int flags; 120157307Shibler int fd; 120257307Shibler long pad; 120357307Shibler off_t pos; 120457307Shibler } nargs; 120557307Shibler 120657307Shibler nargs.addr = uap->addr; 120757307Shibler nargs.len = uap->len; 120857307Shibler nargs.prot = uap->prot; 120957307Shibler nargs.flags = uap->flags & 121057307Shibler ~(HPUXMAP_FIXED|HPUXMAP_REPLACE|HPUXMAP_ANON); 121157307Shibler if (uap->flags & HPUXMAP_FIXED) 121257307Shibler nargs.flags |= MAP_FIXED; 121357307Shibler if (uap->flags & HPUXMAP_ANON) 121457307Shibler nargs.flags |= MAP_ANON; 121557307Shibler nargs.fd = (nargs.flags & MAP_ANON) ? -1 : uap->fd; 121657307Shibler nargs.pos = uap->pos; 121763440Sbostic return (mmap(p, &nargs, retval)); 121857307Shibler } 121957307Shibler 122054857Shibler /* convert from BSD to HP-UX errno */ 122141486Smckusick bsdtohpuxerrno(err) 122241486Smckusick int err; 122341486Smckusick { 122441486Smckusick if (err < 0 || err >= NERR) 122541486Smckusick return(BERR); 122641486Smckusick return((int)bsdtohpuxerrnomap[err]); 122741486Smckusick } 122841486Smckusick 122955282Smckusick hpuxstat1(fname, hsb, follow, p) 123041486Smckusick char *fname; 123141486Smckusick struct hpuxstat *hsb; 123241486Smckusick int follow; 123355282Smckusick struct proc *p; 123441486Smckusick { 123548478Skarels int error; 123641486Smckusick struct stat sb; 123748478Skarels struct nameidata nd; 123841486Smckusick 123955282Smckusick NDINIT(&nd, LOOKUP, follow | LOCKLEAF, UIO_USERSPACE, fname, p); 124052330Smckusick if (error = namei(&nd)) 124141486Smckusick return (error); 124255282Smckusick error = vn_stat(nd.ni_vp, &sb, p); 124352330Smckusick vput(nd.ni_vp); 124441486Smckusick if (error == 0) 124541486Smckusick error = bsdtohpuxstat(&sb, hsb); 124641486Smckusick return (error); 124741486Smckusick } 124841486Smckusick 124941486Smckusick #include "grf.h" 125053922Shibler #if NGRF > 0 125153922Shibler #ifdef __STDC__ 125253922Shibler extern int grfopen(dev_t dev, int oflags, int devtype, struct proc *p); 125353922Shibler #else 125453922Shibler extern int grfopen(); 125553922Shibler #endif 125653922Shibler #endif 125741486Smckusick 125853922Shibler #define NHIL 1 /* XXX */ 125953922Shibler #if NHIL > 0 126053922Shibler #ifdef __STDC__ 126153922Shibler extern int hilopen(dev_t dev, int oflags, int devtype, struct proc *p); 126253922Shibler #else 126353922Shibler extern int hilopen(); 126453922Shibler #endif 126553922Shibler #endif 126653922Shibler 126756506Sbostic #include <sys/conf.h> 126853922Shibler 126941486Smckusick bsdtohpuxstat(sb, hsb) 127041486Smckusick struct stat *sb; 127141486Smckusick struct hpuxstat *hsb; 127241486Smckusick { 127341486Smckusick struct hpuxstat ds; 127441486Smckusick 127541486Smckusick bzero((caddr_t)&ds, sizeof(ds)); 127653481Smckusick ds.hst_dev = (u_short)sb->st_dev; 127741486Smckusick ds.hst_ino = (u_long)sb->st_ino; 127841486Smckusick ds.hst_mode = sb->st_mode; 127941486Smckusick ds.hst_nlink = sb->st_nlink; 128041486Smckusick ds.hst_uid = (u_short)sb->st_uid; 128141486Smckusick ds.hst_gid = (u_short)sb->st_gid; 128257307Shibler ds.hst_rdev = bsdtohpuxdev(sb->st_rdev); 128357307Shibler 128453922Shibler /* XXX: I don't want to talk about it... */ 128553922Shibler if ((sb->st_mode & S_IFMT) == S_IFCHR) { 128641486Smckusick #if NGRF > 0 128753922Shibler if (cdevsw[major(sb->st_rdev)].d_open == grfopen) 128853922Shibler ds.hst_rdev = grfdevno(sb->st_rdev); 128941486Smckusick #endif 129053922Shibler #if NHIL > 0 129153922Shibler if (cdevsw[major(sb->st_rdev)].d_open == hilopen) 129253922Shibler ds.hst_rdev = hildevno(sb->st_rdev); 129353922Shibler #endif 129453922Shibler ; 129557307Shibler } 129653481Smckusick if (sb->st_size < (quad_t)1 << 32) 129753481Smckusick ds.hst_size = (long)sb->st_size; 129853481Smckusick else 129953481Smckusick ds.hst_size = -2; 130041486Smckusick ds.hst_atime = sb->st_atime; 130141486Smckusick ds.hst_mtime = sb->st_mtime; 130241486Smckusick ds.hst_ctime = sb->st_ctime; 130341486Smckusick ds.hst_blksize = sb->st_blksize; 130441486Smckusick ds.hst_blocks = sb->st_blocks; 130541486Smckusick return(copyout((caddr_t)&ds, (caddr_t)hsb, sizeof(ds))); 130641486Smckusick } 130741486Smckusick 130841486Smckusick hpuxtobsdioctl(com) 130941486Smckusick int com; 131041486Smckusick { 131141486Smckusick switch (com) { 131241486Smckusick case HPUXTIOCSLTC: 131341486Smckusick com = TIOCSLTC; break; 131441486Smckusick case HPUXTIOCGLTC: 131541486Smckusick com = TIOCGLTC; break; 131641486Smckusick case HPUXTIOCSPGRP: 131741486Smckusick com = TIOCSPGRP; break; 131841486Smckusick case HPUXTIOCGPGRP: 131941486Smckusick com = TIOCGPGRP; break; 132041486Smckusick case HPUXTIOCLBIS: 132141486Smckusick com = TIOCLBIS; break; 132241486Smckusick case HPUXTIOCLBIC: 132341486Smckusick com = TIOCLBIC; break; 132441486Smckusick case HPUXTIOCLSET: 132541486Smckusick com = TIOCLSET; break; 132641486Smckusick case HPUXTIOCLGET: 132741486Smckusick com = TIOCLGET; break; 132864478Shibler case HPUXTIOCGWINSZ: 132964478Shibler com = TIOCGWINSZ; break; 133064478Shibler case HPUXTIOCSWINSZ: 133164478Shibler com = TIOCSWINSZ; break; 133241486Smckusick } 133341486Smckusick return(com); 133441486Smckusick } 133541486Smckusick 133641486Smckusick /* 133754857Shibler * HP-UX ioctl system call. The differences here are: 133841486Smckusick * IOC_IN also means IOC_VOID if the size portion is zero. 133949329Shibler * no FIOCLEX/FIONCLEX/FIOASYNC/FIOGETOWN/FIOSETOWN 134041486Smckusick * the sgttyb struct is 2 bytes longer 134141486Smckusick */ 134254917Storek struct hpuxioctl_args { 134354917Storek int fdes; 134454917Storek int cmd; 134554917Storek caddr_t cmarg; 134654917Storek }; 134743452Shibler hpuxioctl(p, uap, retval) 134843452Shibler struct proc *p; 134954917Storek register struct hpuxioctl_args *uap; 135043452Shibler int *retval; 135143452Shibler { 135245923Smckusick register struct filedesc *fdp = p->p_fd; 135343452Shibler register struct file *fp; 135443452Shibler register int com, error; 135541486Smckusick register u_int size; 135641486Smckusick caddr_t memp = 0; 135741486Smckusick #define STK_PARAMS 128 135841486Smckusick char stkbuf[STK_PARAMS]; 135941486Smckusick caddr_t data = stkbuf; 136041486Smckusick 136141486Smckusick com = uap->cmd; 136241486Smckusick 136341486Smckusick /* XXX */ 136443452Shibler if (com == HPUXTIOCGETP || com == HPUXTIOCSETP) 136545923Smckusick return (getsettty(p, uap->fdes, com, uap->cmarg)); 136641486Smckusick 136748478Skarels if (((unsigned)uap->fdes) >= fdp->fd_nfiles || 136848478Skarels (fp = fdp->fd_ofiles[uap->fdes]) == NULL) 136944421Skarels return (EBADF); 137043452Shibler if ((fp->f_flag & (FREAD|FWRITE)) == 0) 137144421Skarels return (EBADF); 137241486Smckusick 137341486Smckusick /* 137441486Smckusick * Interpret high order word to find 137541486Smckusick * amount of data to be copied to/from the 137641486Smckusick * user's address space. 137741486Smckusick */ 137841486Smckusick size = IOCPARM_LEN(com); 137943452Shibler if (size > IOCPARM_MAX) 138044421Skarels return (ENOTTY); 138141486Smckusick if (size > sizeof (stkbuf)) { 138243452Shibler memp = (caddr_t)malloc((u_long)size, M_IOCTLOPS, M_WAITOK); 138341486Smckusick data = memp; 138441486Smckusick } 138541486Smckusick if (com&IOC_IN) { 138641486Smckusick if (size) { 138743452Shibler error = copyin(uap->cmarg, data, (u_int)size); 138843452Shibler if (error) { 138941486Smckusick if (memp) 139041486Smckusick free(memp, M_IOCTLOPS); 139144421Skarels return (error); 139241486Smckusick } 139341486Smckusick } else 139441486Smckusick *(caddr_t *)data = uap->cmarg; 139541486Smckusick } else if ((com&IOC_OUT) && size) 139641486Smckusick /* 139743452Shibler * Zero the buffer so the user always 139843452Shibler * gets back something deterministic. 139941486Smckusick */ 140041486Smckusick bzero(data, size); 140141486Smckusick else if (com&IOC_VOID) 140241486Smckusick *(caddr_t *)data = uap->cmarg; 140341486Smckusick 140441486Smckusick switch (com) { 140541486Smckusick 140649329Shibler case HPUXFIOSNBIO: 140749329Shibler { 140849329Shibler char *ofp = &fdp->fd_ofileflags[uap->fdes]; 140949329Shibler int tmp; 141049329Shibler 141149329Shibler if (*(int *)data) 141249329Shibler *ofp |= UF_FIONBIO_ON; 141349329Shibler else 141449329Shibler *ofp &= ~UF_FIONBIO_ON; 141549329Shibler /* 141663726Shibler * Only set/clear if O_NONBLOCK/FNDELAY not in effect 141749329Shibler */ 141863726Shibler if ((*ofp & (UF_NONBLOCK_ON|UF_FNDELAY_ON)) == 0) { 141963726Shibler tmp = *ofp & UF_FIONBIO_ON; 142049329Shibler error = (*fp->f_ops->fo_ioctl)(fp, FIONBIO, 142149329Shibler (caddr_t)&tmp, p); 142249329Shibler } 142349329Shibler break; 142449329Shibler } 142549329Shibler 142641486Smckusick case HPUXTIOCCONS: 142741486Smckusick *(int *)data = 1; 142848478Skarels error = (*fp->f_ops->fo_ioctl)(fp, TIOCCONS, data, p); 142941486Smckusick break; 143041486Smckusick 143141486Smckusick /* BSD-style job control ioctls */ 143241486Smckusick case HPUXTIOCLBIS: 143341486Smckusick case HPUXTIOCLBIC: 143441486Smckusick case HPUXTIOCLSET: 143541486Smckusick *(int *)data &= HPUXLTOSTOP; 143641486Smckusick if (*(int *)data & HPUXLTOSTOP) 143741486Smckusick *(int *)data = LTOSTOP; 143841486Smckusick /* fall into */ 143964478Shibler 144064478Shibler /* simple mapping cases */ 144141486Smckusick case HPUXTIOCLGET: 144241486Smckusick case HPUXTIOCSLTC: 144341486Smckusick case HPUXTIOCGLTC: 144441486Smckusick case HPUXTIOCSPGRP: 144541486Smckusick case HPUXTIOCGPGRP: 144664478Shibler case HPUXTIOCGWINSZ: 144764478Shibler case HPUXTIOCSWINSZ: 144848478Skarels error = (*fp->f_ops->fo_ioctl) 144948478Skarels (fp, hpuxtobsdioctl(com), data, p); 145043452Shibler if (error == 0 && com == HPUXTIOCLGET) { 145141486Smckusick *(int *)data &= LTOSTOP; 145241486Smckusick if (*(int *)data & LTOSTOP) 145341486Smckusick *(int *)data = HPUXLTOSTOP; 145441486Smckusick } 145541486Smckusick break; 145641486Smckusick 145755832Shibler /* SYS 5 termio and POSIX termios */ 145841486Smckusick case HPUXTCGETA: 145941486Smckusick case HPUXTCSETA: 146041486Smckusick case HPUXTCSETAW: 146141486Smckusick case HPUXTCSETAF: 146255832Shibler case HPUXTCGETATTR: 146355832Shibler case HPUXTCSETATTR: 146455832Shibler case HPUXTCSETATTRD: 146555832Shibler case HPUXTCSETATTRF: 146664478Shibler error = hpuxtermio(uap->fdes, com, data, p); 146741486Smckusick break; 146841486Smckusick 146941486Smckusick default: 147048478Skarels error = (*fp->f_ops->fo_ioctl)(fp, com, data, p); 147141486Smckusick break; 147241486Smckusick } 147341486Smckusick /* 147441486Smckusick * Copy any data to user, size was 147541486Smckusick * already set and checked above. 147641486Smckusick */ 147743452Shibler if (error == 0 && (com&IOC_OUT) && size) 147843452Shibler error = copyout(data, uap->cmarg, (u_int)size); 147941486Smckusick if (memp) 148041486Smckusick free(memp, M_IOCTLOPS); 148144421Skarels return (error); 148241486Smckusick } 148341486Smckusick 148441486Smckusick /* 148541486Smckusick * Man page lies, behaviour here is based on observed behaviour. 148641486Smckusick */ 148754917Storek struct hpuxgetcontext_args { 148854917Storek char *buf; 148954917Storek int len; 149054917Storek }; 149143452Shibler hpuxgetcontext(p, uap, retval) 149243452Shibler struct proc *p; 149354917Storek struct hpuxgetcontext_args *uap; 149443452Shibler int *retval; 149543452Shibler { 149641486Smckusick int error = 0; 149741486Smckusick register int len; 149841486Smckusick 149953922Shibler #if defined(HP380) 150053922Shibler if (machineid == HP_380) { 150155072Spendry len = min(uap->len, sizeof(hpux040context)); 150253922Shibler if (len) 150353922Shibler error = copyout(hpux040context, uap->buf, len); 150453922Shibler if (error == 0) 150553922Shibler *retval = sizeof(hpux040context); 150653922Shibler return (error); 150753922Shibler } 150853922Shibler #endif 150955072Spendry len = min(uap->len, sizeof(hpuxcontext)); 151041486Smckusick if (len) 151141486Smckusick error = copyout(hpuxcontext, uap->buf, (u_int)len); 151243452Shibler if (error == 0) 151343452Shibler *retval = sizeof(hpuxcontext); 151444421Skarels return (error); 151541486Smckusick } 151641486Smckusick 151741486Smckusick /* 151841486Smckusick * This is the equivalent of BSD getpgrp but with more restrictions. 151941486Smckusick * Note we do not check the real uid or "saved" uid. 152041486Smckusick */ 152154917Storek struct hpuxgetpgrp2_args { 152254917Storek int pid; 152354917Storek }; 152443452Shibler hpuxgetpgrp2(cp, uap, retval) 152543452Shibler struct proc *cp; 152654917Storek register struct hpuxgetpgrp2_args *uap; 152743452Shibler int *retval; 152841486Smckusick { 152941486Smckusick register struct proc *p; 153041486Smckusick 153141486Smckusick if (uap->pid == 0) 153243452Shibler uap->pid = cp->p_pid; 153341486Smckusick p = pfind(uap->pid); 153443452Shibler if (p == 0) 153544421Skarels return (ESRCH); 153648478Skarels if (cp->p_ucred->cr_uid && p->p_ucred->cr_uid != cp->p_ucred->cr_uid && 153748478Skarels !inferior(p)) 153844421Skarels return (EPERM); 153943452Shibler *retval = p->p_pgid; 154044421Skarels return (0); 154141486Smckusick } 154241486Smckusick 154341486Smckusick /* 154441486Smckusick * This is the equivalent of BSD setpgrp but with more restrictions. 154541486Smckusick * Note we do not check the real uid or "saved" uid or pgrp. 154641486Smckusick */ 154754917Storek struct hpuxsetpgrp2_args { 154854917Storek int pid; 154954917Storek int pgrp; 155054917Storek }; 155143452Shibler hpuxsetpgrp2(p, uap, retval) 155243452Shibler struct proc *p; 155354917Storek struct hpuxsetpgrp2_args *uap; 155443452Shibler int *retval; 155543452Shibler { 155641486Smckusick /* empirically determined */ 155743452Shibler if (uap->pgrp < 0 || uap->pgrp >= 30000) 155844421Skarels return (EINVAL); 155948478Skarels return (setpgid(p, uap, retval)); 156041486Smckusick } 156141486Smckusick 156241486Smckusick /* 156355165Smckusick * XXX Same as BSD setre[ug]id right now. Need to consider saved ids. 156445753Smckusick */ 156554917Storek struct hpuxsetresuid_args { 156654917Storek int ruid; 156754917Storek int euid; 156854917Storek int suid; 156954917Storek }; 157045753Smckusick hpuxsetresuid(p, uap, retval) 157155165Smckusick struct proc *p; 157254917Storek struct hpuxsetresuid_args *uap; 157345753Smckusick int *retval; 157445753Smckusick { 157555165Smckusick return (osetreuid(p, uap, retval)); 157645753Smckusick } 157745753Smckusick 157854917Storek struct hpuxsetresgid_args { 157954917Storek int rgid; 158054917Storek int egid; 158154917Storek int sgid; 158254917Storek }; 158345753Smckusick hpuxsetresgid(p, uap, retval) 158455165Smckusick struct proc *p; 158554917Storek struct hpuxsetresgid_args *uap; 158645753Smckusick int *retval; 158745753Smckusick { 158855165Smckusick return (osetregid(p, uap, retval)); 158945753Smckusick } 159045753Smckusick 159157307Shibler struct hpuxrlimit_args { 159257307Shibler u_int which; 159357307Shibler struct orlimit *rlp; 159457307Shibler }; 159557307Shibler hpuxgetrlimit(p, uap, retval) 159657307Shibler struct proc *p; 159757307Shibler struct hpuxrlimit_args *uap; 159857307Shibler int *retval; 159957307Shibler { 160057307Shibler if (uap->which > HPUXRLIMIT_NOFILE) 160157307Shibler return (EINVAL); 160257307Shibler if (uap->which == HPUXRLIMIT_NOFILE) 160357307Shibler uap->which = RLIMIT_NOFILE; 160460110Smckusick return (ogetrlimit(p, uap, retval)); 160557307Shibler } 160657307Shibler 160757307Shibler hpuxsetrlimit(p, uap, retval) 160857307Shibler struct proc *p; 160957307Shibler struct hpuxrlimit_args *uap; 161057307Shibler int *retval; 161157307Shibler { 161257307Shibler if (uap->which > HPUXRLIMIT_NOFILE) 161357307Shibler return (EINVAL); 161457307Shibler if (uap->which == HPUXRLIMIT_NOFILE) 161557307Shibler uap->which = RLIMIT_NOFILE; 161660110Smckusick return (osetrlimit(p, uap, retval)); 161757307Shibler } 161857307Shibler 161945753Smckusick /* 162045753Smckusick * XXX: simple recognition hack to see if we can make grmd work. 162145753Smckusick */ 162254917Storek struct hpuxlockf_args { 162354917Storek int fd; 162454917Storek int func; 162554917Storek long size; 162654917Storek }; 162745753Smckusick hpuxlockf(p, uap, retval) 162845753Smckusick struct proc *p; 162954917Storek struct hpuxlockf_args *uap; 163045753Smckusick int *retval; 163145753Smckusick { 163245753Smckusick return (0); 163345753Smckusick } 163445753Smckusick 163554917Storek struct hpuxgetaccess_args { 163654917Storek char *path; 163754917Storek int uid; 163854917Storek int ngroups; 163954917Storek int *gidset; 164054917Storek void *label; 164154917Storek void *privs; 164254917Storek }; 164345753Smckusick hpuxgetaccess(p, uap, retval) 164445753Smckusick register struct proc *p; 164554917Storek register struct hpuxgetaccess_args *uap; 164645753Smckusick int *retval; 164745753Smckusick { 164845753Smckusick int lgroups[NGROUPS]; 164945753Smckusick int error = 0; 165045753Smckusick register struct ucred *cred; 165145753Smckusick register struct vnode *vp; 165252330Smckusick struct nameidata nd; 165345753Smckusick 165445753Smckusick /* 165545753Smckusick * Build an appropriate credential structure 165645753Smckusick */ 165748478Skarels cred = crdup(p->p_ucred); 165845753Smckusick switch (uap->uid) { 165945753Smckusick case 65502: /* UID_EUID */ 166045753Smckusick break; 166145753Smckusick case 65503: /* UID_RUID */ 166248478Skarels cred->cr_uid = p->p_cred->p_ruid; 166345753Smckusick break; 166445753Smckusick case 65504: /* UID_SUID */ 166545753Smckusick error = EINVAL; 166645753Smckusick break; 166745753Smckusick default: 166845753Smckusick if (uap->uid > 65504) 166945753Smckusick error = EINVAL; 167045753Smckusick cred->cr_uid = uap->uid; 167145753Smckusick break; 167245753Smckusick } 167345753Smckusick switch (uap->ngroups) { 167445753Smckusick case -1: /* NGROUPS_EGID */ 167545753Smckusick cred->cr_ngroups = 1; 167645753Smckusick break; 167745753Smckusick case -5: /* NGROUPS_EGID_SUPP */ 167845753Smckusick break; 167945753Smckusick case -2: /* NGROUPS_RGID */ 168045753Smckusick cred->cr_ngroups = 1; 168148478Skarels cred->cr_gid = p->p_cred->p_rgid; 168245753Smckusick break; 168345753Smckusick case -6: /* NGROUPS_RGID_SUPP */ 168448478Skarels cred->cr_gid = p->p_cred->p_rgid; 168545753Smckusick break; 168645753Smckusick case -3: /* NGROUPS_SGID */ 168745753Smckusick case -7: /* NGROUPS_SGID_SUPP */ 168845753Smckusick error = EINVAL; 168945753Smckusick break; 169045753Smckusick case -4: /* NGROUPS_SUPP */ 169145753Smckusick if (cred->cr_ngroups > 1) 169245753Smckusick cred->cr_gid = cred->cr_groups[1]; 169345753Smckusick else 169445753Smckusick error = EINVAL; 169545753Smckusick break; 169645753Smckusick default: 169745753Smckusick if (uap->ngroups > 0 && uap->ngroups <= NGROUPS) 169845753Smckusick error = copyin((caddr_t)uap->gidset, 169945753Smckusick (caddr_t)&lgroups[0], 170045753Smckusick uap->ngroups * sizeof(lgroups[0])); 170145753Smckusick else 170245753Smckusick error = EINVAL; 170345753Smckusick if (error == 0) { 170445753Smckusick int gid; 170545753Smckusick 170645753Smckusick for (gid = 0; gid < uap->ngroups; gid++) 170745753Smckusick cred->cr_groups[gid] = lgroups[gid]; 170845753Smckusick cred->cr_ngroups = uap->ngroups; 170945753Smckusick } 171045753Smckusick break; 171145753Smckusick } 171245753Smckusick /* 171345753Smckusick * Lookup file using caller's effective IDs. 171445753Smckusick */ 171545753Smckusick if (error == 0) { 171652330Smckusick NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, 171752330Smckusick uap->path, p); 171852330Smckusick error = namei(&nd); 171945753Smckusick } 172045753Smckusick if (error) { 172145753Smckusick crfree(cred); 172245753Smckusick return (error); 172345753Smckusick } 172445753Smckusick /* 172545753Smckusick * Use the constructed credentials for access checks. 172645753Smckusick */ 172752330Smckusick vp = nd.ni_vp; 172845753Smckusick *retval = 0; 172948478Skarels if (VOP_ACCESS(vp, VREAD, cred, p) == 0) 173045753Smckusick *retval |= R_OK; 173148478Skarels if (vn_writechk(vp) == 0 && VOP_ACCESS(vp, VWRITE, cred, p) == 0) 173245753Smckusick *retval |= W_OK; 173345753Smckusick /* XXX we return X_OK for root on VREG even if not */ 173448478Skarels if (VOP_ACCESS(vp, VEXEC, cred, p) == 0) 173545753Smckusick *retval |= X_OK; 173645753Smckusick vput(vp); 173745753Smckusick crfree(cred); 173845753Smckusick return (error); 173945753Smckusick } 174045753Smckusick 174149134Skarels extern char kstack[]; 174241486Smckusick #define UOFF(f) ((int)&((struct user *)0)->f) 174341486Smckusick #define HPUOFF(f) ((int)&((struct hpuxuser *)0)->f) 174441486Smckusick 174541486Smckusick /* simplified FP structure */ 174641486Smckusick struct bsdfp { 174741486Smckusick int save[54]; 174841486Smckusick int reg[24]; 174941486Smckusick int ctrl[3]; 175041486Smckusick }; 175141486Smckusick 175257307Shibler /* 175357307Shibler * Brutal hack! Map HP-UX u-area offsets into BSD k-stack offsets. 175457307Shibler */ 175557307Shibler hpuxtobsduoff(off, isps, p) 175657307Shibler int *off, *isps; 175757307Shibler struct proc *p; 175841486Smckusick { 175957307Shibler register int *ar0 = p->p_md.md_regs; 176041486Smckusick struct hpuxfp *hp; 176141486Smckusick struct bsdfp *bp; 176241486Smckusick register u_int raddr; 176341486Smckusick 176457307Shibler *isps = 0; 176557307Shibler 176648478Skarels /* u_ar0 field; procxmt puts in U_ar0 */ 176741486Smckusick if ((int)off == HPUOFF(hpuxu_ar0)) 176848478Skarels return(UOFF(U_ar0)); 176941486Smckusick 177041486Smckusick #ifdef FPCOPROC 177157307Shibler /* FP registers from PCB */ 177241486Smckusick hp = (struct hpuxfp *)HPUOFF(hpuxu_fp); 177341486Smckusick bp = (struct bsdfp *)UOFF(u_pcb.pcb_fpregs); 177441486Smckusick if (off >= hp->hpfp_ctrl && off < &hp->hpfp_ctrl[3]) 177541486Smckusick return((int)&bp->ctrl[off - hp->hpfp_ctrl]); 177641486Smckusick if (off >= hp->hpfp_reg && off < &hp->hpfp_reg[24]) 177741486Smckusick return((int)&bp->reg[off - hp->hpfp_reg]); 177841486Smckusick #endif 177941486Smckusick 178041486Smckusick /* 178141486Smckusick * Everything else we recognize comes from the kernel stack, 178241486Smckusick * so we convert off to an absolute address (if not already) 178341486Smckusick * for simplicity. 178441486Smckusick */ 178541486Smckusick if (off < (int *)ctob(UPAGES)) 178649134Skarels off = (int *)((u_int)off + (u_int)kstack); 178741486Smckusick 178841486Smckusick /* 178957307Shibler * General registers. 179054857Shibler * We know that the HP-UX registers are in the same order as ours. 179141486Smckusick * The only difference is that their PS is 2 bytes instead of a 179241486Smckusick * padded 4 like ours throwing the alignment off. 179341486Smckusick */ 179448478Skarels if (off >= ar0 && off < &ar0[18]) { 179541486Smckusick /* 179641486Smckusick * PS: return low word and high word of PC as HP-UX would 179741486Smckusick * (e.g. &u.u_ar0[16.5]). 179857307Shibler * 179957307Shibler * XXX we don't do this since HP-UX adb doesn't rely on 180057307Shibler * it and passing such an offset to procxmt will cause 180157307Shibler * it to fail anyway. Instead, we just set the offset 180257307Shibler * to PS and let hpuxptrace() shift up the value returned. 180341486Smckusick */ 180457307Shibler if (off == &ar0[PS]) { 180557307Shibler #if 0 180648478Skarels raddr = (u_int) &((short *)ar0)[PS*2+1]; 180757307Shibler #else 180857307Shibler raddr = (u_int) &ar0[(int)(off - ar0)]; 180957307Shibler #endif 181057307Shibler *isps = 1; 181157307Shibler } 181241486Smckusick /* 181357307Shibler * PC: off will be &u.u_ar0[16.5] since HP-UX saved PS 181457307Shibler * is only 16 bits. 181541486Smckusick */ 181648478Skarels else if (off == (int *)&(((short *)ar0)[PS*2+1])) 181748478Skarels raddr = (u_int) &ar0[PC]; 181841486Smckusick /* 181941486Smckusick * D0-D7, A0-A7: easy 182041486Smckusick */ 182141486Smckusick else 182248478Skarels raddr = (u_int) &ar0[(int)(off - ar0)]; 182349134Skarels return((int)(raddr - (u_int)kstack)); 182441486Smckusick } 182541486Smckusick 182641486Smckusick /* everything else */ 182741486Smckusick return(-1); 182841486Smckusick } 182941486Smckusick 183041486Smckusick /* 183154857Shibler * Kludge up a uarea dump so that HP-UX debuggers can find out 183241486Smckusick * what they need. IMPORTANT NOTE: we do not EVEN attempt to 183341486Smckusick * convert the entire user struct. 183441486Smckusick */ 183541486Smckusick hpuxdumpu(vp, cred) 183641486Smckusick struct vnode *vp; 183741486Smckusick struct ucred *cred; 183841486Smckusick { 183948478Skarels struct proc *p = curproc; 184041486Smckusick int error; 184141486Smckusick struct hpuxuser *faku; 184241486Smckusick struct bsdfp *bp; 184341486Smckusick short *foop; 184441486Smckusick 184541486Smckusick faku = (struct hpuxuser *)malloc((u_long)ctob(1), M_TEMP, M_WAITOK); 184641486Smckusick /* 184741486Smckusick * Make sure there is no mistake about this 184841486Smckusick * being a real user structure. 184941486Smckusick */ 185041486Smckusick bzero((caddr_t)faku, ctob(1)); 185141486Smckusick /* 185241486Smckusick * Fill in the process sizes. 185341486Smckusick */ 185448478Skarels faku->hpuxu_tsize = p->p_vmspace->vm_tsize; 185548478Skarels faku->hpuxu_dsize = p->p_vmspace->vm_dsize; 185648478Skarels faku->hpuxu_ssize = p->p_vmspace->vm_ssize; 185741486Smckusick /* 185841486Smckusick * Fill in the exec header for CDB. 185941486Smckusick * This was saved back in exec(). As far as I can tell CDB 186041486Smckusick * only uses this information to verify that a particular 186141486Smckusick * core file goes with a particular binary. 186241486Smckusick */ 186357307Shibler bcopy((caddr_t)p->p_addr->u_md.md_exec, 186441486Smckusick (caddr_t)&faku->hpuxu_exdata, sizeof (struct hpux_exec)); 186541486Smckusick /* 186641486Smckusick * Adjust user's saved registers (on kernel stack) to reflect 186754857Shibler * HP-UX order. Note that HP-UX saves the SR as 2 bytes not 4 186841486Smckusick * so we have to move it up. 186941486Smckusick */ 187052381Smckusick faku->hpuxu_ar0 = p->p_md.md_regs; 187152381Smckusick foop = (short *) p->p_md.md_regs; 187241486Smckusick foop[32] = foop[33]; 187341486Smckusick foop[33] = foop[34]; 187441486Smckusick foop[34] = foop[35]; 187541486Smckusick #ifdef FPCOPROC 187641486Smckusick /* 187754857Shibler * Copy 68881 registers from our PCB format to HP-UX format 187841486Smckusick */ 187949134Skarels bp = (struct bsdfp *) &p->p_addr->u_pcb.pcb_fpregs; 188041486Smckusick bcopy((caddr_t)bp->save, (caddr_t)faku->hpuxu_fp.hpfp_save, 188141486Smckusick sizeof(bp->save)); 188241486Smckusick bcopy((caddr_t)bp->ctrl, (caddr_t)faku->hpuxu_fp.hpfp_ctrl, 188341486Smckusick sizeof(bp->ctrl)); 188441486Smckusick bcopy((caddr_t)bp->reg, (caddr_t)faku->hpuxu_fp.hpfp_reg, 188541486Smckusick sizeof(bp->reg)); 188641486Smckusick #endif 188741486Smckusick /* 188841486Smckusick * Slay the dragon 188941486Smckusick */ 189041486Smckusick faku->hpuxu_dragon = -1; 189141486Smckusick /* 189241486Smckusick * Dump this artfully constructed page in place of the 189341486Smckusick * user struct page. 189441486Smckusick */ 189548478Skarels error = vn_rdwr(UIO_WRITE, vp, (caddr_t)faku, ctob(1), (off_t)0, 189648478Skarels UIO_SYSSPACE, IO_NODELOCKED|IO_UNIT, cred, 189749134Skarels (int *)NULL, p); 189841486Smckusick /* 189941486Smckusick * Dump the remaining UPAGES-1 pages normally 190041486Smckusick */ 190141486Smckusick if (!error) 190249134Skarels error = vn_rdwr(UIO_WRITE, vp, kstack + ctob(1), 190341486Smckusick ctob(UPAGES-1), (off_t)ctob(1), UIO_SYSSPACE, 190449134Skarels IO_NODELOCKED|IO_UNIT, cred, (int *)NULL, p); 190541486Smckusick free((caddr_t)faku, M_TEMP); 190641486Smckusick return(error); 190741486Smckusick } 190841486Smckusick 190941486Smckusick /* 191041486Smckusick * The remaining routines are essentially the same as those in kern_xxx.c 191141486Smckusick * and vfs_xxx.c as defined under "#ifdef COMPAT". We replicate them here 191241486Smckusick * to avoid HPUXCOMPAT dependencies in those files and to make sure that 191341486Smckusick * HP-UX compatibility still works even when COMPAT is not defined. 191457307Shibler * 191557307Shibler * These are still needed as of HP-UX 7.05. 191641486Smckusick */ 191755832Shibler #ifdef COMPAT_OHPUX 191855832Shibler 191945753Smckusick #define HPUX_HZ 50 192045753Smckusick 192157307Shibler #include "sys/times.h" 192241486Smckusick 192341486Smckusick /* from old timeb.h */ 192441486Smckusick struct hpuxtimeb { 192541486Smckusick time_t time; 192641486Smckusick u_short millitm; 192741486Smckusick short timezone; 192841486Smckusick short dstflag; 192941486Smckusick }; 193041486Smckusick 193141486Smckusick /* ye ole stat structure */ 193241486Smckusick struct ohpuxstat { 193353481Smckusick u_short ohst_dev; 193441486Smckusick u_short ohst_ino; 193541486Smckusick u_short ohst_mode; 193641486Smckusick short ohst_nlink; 193741486Smckusick short ohst_uid; 193841486Smckusick short ohst_gid; 193953481Smckusick u_short ohst_rdev; 194041486Smckusick int ohst_size; 194141486Smckusick int ohst_atime; 194241486Smckusick int ohst_mtime; 194341486Smckusick int ohst_ctime; 194441486Smckusick }; 194541486Smckusick 194641486Smckusick /* 194741486Smckusick * SYS V style setpgrp() 194841486Smckusick */ 194943452Shibler ohpuxsetpgrp(p, uap, retval) 195043452Shibler register struct proc *p; 195143452Shibler int *uap, *retval; 195241486Smckusick { 195341486Smckusick if (p->p_pid != p->p_pgid) 195448478Skarels enterpgrp(p, p->p_pid, 0); 195543452Shibler *retval = p->p_pgid; 195645753Smckusick return (0); 195741486Smckusick } 195841486Smckusick 195954917Storek struct ohpuxtime_args { 196054917Storek long *tp; 196154917Storek }; 196243452Shibler ohpuxtime(p, uap, retval) 196343452Shibler struct proc *p; 196454917Storek register struct ohpuxtime_args *uap; 196554917Storek int *retval; 196641486Smckusick { 196745753Smckusick int error = 0; 196841486Smckusick 196941486Smckusick if (uap->tp) 197043452Shibler error = copyout((caddr_t)&time.tv_sec, (caddr_t)uap->tp, 197143452Shibler sizeof (long)); 197254917Storek *(time_t *)retval = time.tv_sec; 197344421Skarels return (error); 197441486Smckusick } 197541486Smckusick 197654917Storek struct ohpuxstime_args { 197754917Storek int time; 197854917Storek }; 197943452Shibler ohpuxstime(p, uap, retval) 198043452Shibler struct proc *p; 198154917Storek register struct ohpuxstime_args *uap; 198243452Shibler int *retval; 198341486Smckusick { 198441486Smckusick struct timeval tv; 198543452Shibler int s, error; 198641486Smckusick 198741486Smckusick tv.tv_sec = uap->time; 198841486Smckusick tv.tv_usec = 0; 198948478Skarels if (error = suser(p->p_ucred, &p->p_acflag)) 199044421Skarels return (error); 199141486Smckusick 199241486Smckusick /* WHAT DO WE DO ABOUT PENDING REAL-TIME TIMEOUTS??? */ 199341486Smckusick boottime.tv_sec += tv.tv_sec - time.tv_sec; 199441486Smckusick s = splhigh(); time = tv; splx(s); 199541486Smckusick resettodr(); 199644421Skarels return (0); 199741486Smckusick } 199841486Smckusick 199954917Storek struct ohpuxftime_args { 200054917Storek struct hpuxtimeb *tp; 200154917Storek }; 200243452Shibler ohpuxftime(p, uap, retval) 200343452Shibler struct proc *p; 200454917Storek register struct ohpuxftime_args *uap; 200543452Shibler int *retval; 200643452Shibler { 200741486Smckusick struct hpuxtimeb tb; 200841486Smckusick int s; 200941486Smckusick 201041486Smckusick s = splhigh(); 201141486Smckusick tb.time = time.tv_sec; 201241486Smckusick tb.millitm = time.tv_usec / 1000; 201341486Smckusick splx(s); 201441486Smckusick tb.timezone = tz.tz_minuteswest; 201541486Smckusick tb.dstflag = tz.tz_dsttime; 201644421Skarels return (copyout((caddr_t)&tb, (caddr_t)uap->tp, sizeof (tb))); 201741486Smckusick } 201841486Smckusick 201954917Storek struct ohpuxalarm_args { 202054917Storek int deltat; 202154917Storek }; 202243452Shibler ohpuxalarm(p, uap, retval) 202343452Shibler register struct proc *p; 202454917Storek register struct ohpuxalarm_args *uap; 202543452Shibler int *retval; 202641486Smckusick { 202741486Smckusick int s = splhigh(); 202841486Smckusick 202941486Smckusick untimeout(realitexpire, (caddr_t)p); 203041486Smckusick timerclear(&p->p_realtimer.it_interval); 203143452Shibler *retval = 0; 203241486Smckusick if (timerisset(&p->p_realtimer.it_value) && 203341486Smckusick timercmp(&p->p_realtimer.it_value, &time, >)) 203443452Shibler *retval = p->p_realtimer.it_value.tv_sec - time.tv_sec; 203541486Smckusick if (uap->deltat == 0) { 203641486Smckusick timerclear(&p->p_realtimer.it_value); 203741486Smckusick splx(s); 203844421Skarels return (0); 203941486Smckusick } 204041486Smckusick p->p_realtimer.it_value = time; 204141486Smckusick p->p_realtimer.it_value.tv_sec += uap->deltat; 204241486Smckusick timeout(realitexpire, (caddr_t)p, hzto(&p->p_realtimer.it_value)); 204341486Smckusick splx(s); 204444421Skarels return (0); 204541486Smckusick } 204641486Smckusick 204754917Storek struct ohpuxnice_args { 204854917Storek int niceness; 204954917Storek }; 205043452Shibler ohpuxnice(p, uap, retval) 205143452Shibler register struct proc *p; 205254917Storek register struct ohpuxnice_args *uap; 205343452Shibler int *retval; 205441486Smckusick { 205543452Shibler int error; 205641486Smckusick 205743452Shibler error = donice(p, p, (p->p_nice-NZERO)+uap->niceness); 205843452Shibler if (error == 0) 205943452Shibler *retval = p->p_nice - NZERO; 206044421Skarels return (error); 206141486Smckusick } 206241486Smckusick 206354917Storek struct ohpuxtimes_args { 206454917Storek struct tms *tmsb; 206554917Storek }; 206643452Shibler ohpuxtimes(p, uap, retval) 206743452Shibler struct proc *p; 206854917Storek register struct ohpuxtimes_args *uap; 206954917Storek int *retval; 207041486Smckusick { 207154771Storek struct timeval ru, rs; 207241486Smckusick struct tms atms; 207343452Shibler int error; 207441486Smckusick 207554771Storek calcru(p, &ru, &rs, NULL); 207654771Storek atms.tms_utime = hpuxscale(&ru); 207754771Storek atms.tms_stime = hpuxscale(&rs); 207848478Skarels atms.tms_cutime = hpuxscale(&p->p_stats->p_cru.ru_utime); 207948478Skarels atms.tms_cstime = hpuxscale(&p->p_stats->p_cru.ru_stime); 208043452Shibler error = copyout((caddr_t)&atms, (caddr_t)uap->tmsb, sizeof (atms)); 208143452Shibler if (error == 0) 208254917Storek *(time_t *)retval = hpuxscale(&time) - hpuxscale(&boottime); 208344421Skarels return (error); 208441486Smckusick } 208541486Smckusick 208645753Smckusick /* 208745753Smckusick * Doesn't exactly do what the documentation says. 208845753Smckusick * What we really do is return 1/HPUX_HZ-th of a second since that 208945753Smckusick * is what HP-UX returns. 209045753Smckusick */ 209145753Smckusick hpuxscale(tvp) 209241486Smckusick register struct timeval *tvp; 209341486Smckusick { 209445753Smckusick return (tvp->tv_sec * HPUX_HZ + tvp->tv_usec * HPUX_HZ / 1000000); 209541486Smckusick } 209641486Smckusick 209741486Smckusick /* 209841486Smckusick * Set IUPD and IACC times on file. 209941486Smckusick * Can't set ICHG. 210041486Smckusick */ 210154917Storek struct ohpuxutime_args { 210254917Storek char *fname; 210354917Storek time_t *tptr; 210454917Storek }; 210543452Shibler ohpuxutime(p, uap, retval) 210643452Shibler struct proc *p; 210754917Storek register struct ohpuxutime_args *uap; 210843452Shibler int *retval; 210943452Shibler { 211048478Skarels register struct vnode *vp; 211141486Smckusick struct vattr vattr; 211241486Smckusick time_t tv[2]; 211343452Shibler int error; 211448478Skarels struct nameidata nd; 211541486Smckusick 211641486Smckusick if (uap->tptr) { 211743452Shibler error = copyin((caddr_t)uap->tptr, (caddr_t)tv, sizeof (tv)); 211843452Shibler if (error) 211944421Skarels return (error); 212041486Smckusick } else 212141486Smckusick tv[0] = tv[1] = time.tv_sec; 212241486Smckusick vattr_null(&vattr); 212354107Smckusick vattr.va_atime.ts_sec = tv[0]; 212454107Smckusick vattr.va_atime.ts_nsec = 0; 212554107Smckusick vattr.va_mtime.ts_sec = tv[1]; 212654107Smckusick vattr.va_mtime.ts_nsec = 0; 212752330Smckusick NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->fname, p); 212852330Smckusick if (error = namei(&nd)) 212944421Skarels return (error); 213052330Smckusick vp = nd.ni_vp; 213142154Smckusick if (vp->v_mount->mnt_flag & MNT_RDONLY) 213243452Shibler error = EROFS; 213341486Smckusick else 213452330Smckusick error = VOP_SETATTR(vp, &vattr, nd.ni_cnd.cn_cred, p); 213541486Smckusick vput(vp); 213644421Skarels return (error); 213741486Smckusick } 213841486Smckusick 213943452Shibler ohpuxpause(p, uap, retval) 214043452Shibler struct proc *p; 214143452Shibler int *uap, *retval; 214241486Smckusick { 214349134Skarels (void) tsleep(kstack, PPAUSE | PCATCH, "pause", 0); 214442155Skarels /* always return EINTR rather than ERESTART... */ 214544421Skarels return (EINTR); 214641486Smckusick } 214741486Smckusick 214841486Smckusick /* 214941486Smckusick * The old fstat system call. 215041486Smckusick */ 215154917Storek struct ohpuxfstat_args { 215254917Storek int fd; 215354917Storek struct ohpuxstat *sb; 215454917Storek }; 215543452Shibler ohpuxfstat(p, uap, retval) 215643452Shibler struct proc *p; 215754917Storek register struct ohpuxfstat_args *uap; 215843452Shibler int *retval; 215943452Shibler { 216045923Smckusick register struct filedesc *fdp = p->p_fd; 216141486Smckusick struct file *fp; 216241486Smckusick 216348478Skarels if (((unsigned)uap->fd) >= fdp->fd_nfiles || 216448478Skarels (fp = fdp->fd_ofiles[uap->fd]) == NULL) 216544421Skarels return (EBADF); 216643452Shibler if (fp->f_type != DTYPE_VNODE) 216744421Skarels return (EINVAL); 216855282Smckusick return (ohpuxstat1((struct vnode *)fp->f_data, uap->sb, p)); 216941486Smckusick } 217041486Smckusick 217141486Smckusick /* 217241486Smckusick * Old stat system call. This version follows links. 217341486Smckusick */ 217454917Storek struct ohpuxstat_args { 217554917Storek char *fname; 217654917Storek struct ohpuxstat *sb; 217754917Storek }; 217843452Shibler ohpuxstat(p, uap, retval) 217943452Shibler struct proc *p; 218054917Storek register struct ohpuxstat_args *uap; 218143452Shibler int *retval; 218243452Shibler { 218343452Shibler int error; 218448478Skarels struct nameidata nd; 218541486Smckusick 218652330Smckusick NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->fname, p); 218752330Smckusick if (error = namei(&nd)) 218844421Skarels return (error); 218955282Smckusick error = ohpuxstat1(nd.ni_vp, uap->sb, p); 219052330Smckusick vput(nd.ni_vp); 219144421Skarels return (error); 219241486Smckusick } 219341486Smckusick 219441486Smckusick int 219555282Smckusick ohpuxstat1(vp, ub, p) 219657307Shibler struct vnode *vp; 219741486Smckusick struct ohpuxstat *ub; 219855282Smckusick struct proc *p; 219941486Smckusick { 220057307Shibler struct ohpuxstat ohsb; 220157307Shibler struct stat sb; 220257307Shibler int error; 220341486Smckusick 220457307Shibler error = vn_stat(vp, &sb, p); 220541486Smckusick if (error) 220657307Shibler return (error); 220757307Shibler 220857307Shibler ohsb.ohst_dev = sb.st_dev; 220957307Shibler ohsb.ohst_ino = sb.st_ino; 221057307Shibler ohsb.ohst_mode = sb.st_mode; 221157307Shibler ohsb.ohst_nlink = sb.st_nlink; 221257307Shibler ohsb.ohst_uid = sb.st_uid; 221357307Shibler ohsb.ohst_gid = sb.st_gid; 221457307Shibler ohsb.ohst_rdev = sb.st_rdev; 221557307Shibler if (sb.st_size < (quad_t)1 << 32) 221657307Shibler ohsb.ohst_size = sb.st_size; 221757307Shibler else 221857307Shibler ohsb.ohst_size = -2; 221957307Shibler ohsb.ohst_atime = sb.st_atime; 222057307Shibler ohsb.ohst_mtime = sb.st_mtime; 222157307Shibler ohsb.ohst_ctime = sb.st_ctime; 222257307Shibler return (copyout((caddr_t)&ohsb, (caddr_t)ub, sizeof(ohsb))); 222341486Smckusick } 222441486Smckusick #endif 222555832Shibler #endif 2226