/* $Copyright:	$
 * Copyright (c) 1984, 1985, 1986, 1987, 1988, 1989, 1990 
 * Sequent Computer Systems, Inc.   All rights reserved.
 *  
 * This software is furnished under a license and may be used
 * only in accordance with the terms of that license and with the
 * inclusion of the above copyright notice.   This software may not
 * be provided or otherwise made available to, or used by, any
 * other person.  No title to or ownership of the software is
 * hereby transferred.
*/

#ident	"$Header: kern_posix.c 1.12 90/10/29 $"

/*
 * kern_posix.c
 * 	Miscellaneous syscalls and functions for POSIX support.
 *	(currently only sysconf(), pathconf() & fpathconf() )
 */

/* $Log:	kern_posix.c,v $
 */

#include "sys/types.h"
#include "sys/unistd.h"
#include "sys/limits.h"
#include "sys/systm.h"
#include "sys/errno.h"
#include "sys/signal.h"
#include "sys/param.h"
#include "sys/user.h"
#include "sys/vnode.h"
#include "sys/file.h"
#include "sys/time.h"

extern int chown_restricted;
extern int cuserid_version;

/*
 * sysconf() system call.
 *	Provides a method for an application to determine the current value
 * of a configurable system limit or option.  It is supplied here as a
 * system call for the sake of future binary compatability. 
 */

sysconf()
{
	register struct a {
		int	name_value;
	} *uap = (struct a *)u.u_ap;

	switch( uap->name_value ) {
		case _SC_ARG_MAX:
			u.u_r.r_val1 = ARG_MAX;
			break;
		case _SC_CHILD_MAX:
			u.u_r.r_val1 = CHILD_MAX;
			break;
		case _SC_CLK_TCK:
			u.u_r.r_val1 = CLK_TCK;
			break;
		case _SC_NGROUPS_MAX:
			u.u_r.r_val1 = NGROUPS_MAX;
			break;
		case _SC_OPEN_MAX:
			u.u_r.r_val1 = OPEN_MAX;
			break;
		case _SC_JOB_CONTROL:
			u.u_r.r_val1 = _POSIX_JOB_CONTROL;
			break;
		case _SC_SAVED_IDS:
			u.u_r.r_val1 = _POSIX_SAVED_IDS;
			break;
		case _SC_VERSION:
			u.u_r.r_val1 = _POSIX_VERSION;
			break;
		case _SC_PASS_MAX:
			u.u_r.r_val1 = PASS_MAX;
			break;
		case _SC_XOPEN_VERSION:
			u.u_r.r_val1 = _XOPEN_VERSION;
			break;
		case _SC_CUSERID_VERSION:
			u.u_r.r_val1 = cuserid_version;
			break;
		default:
			u.u_r.r_val1 = -1;
			u.u_error = EINVAL;
	}
}

/* [f]pathconf() system calls.
 * 	Provide a method for an application to determine the current value
 * of a configurable limit or option that is associated with a particular
 * file or directory. 
 *
 * Currently, all values returned by [f]pathconf are invariant accross all
 * files and directories in the system.  Therefore, the path/fildes
 * arguments are ignored.  We can get away with this since the wording of
 * the POSIX 1003.1-1988 in section 5.7.1.4 specifies that an error
 * concerning the pathname/fildes will be returned only if the listed
 * conditions are DETECTED.  Since the arguments are ignored, related
 * error conditions will not be detected.
 *
 * In the future vno_pathconf() should become a vnodeop (VOP_*) to
 * return a value corresponding to the various file system types that the
 * path/fildes arguments may indicate.
 */

pathconf()
{
	register struct a {
		char	*path;
		int	name_value;
	} *uap = (struct a *)u.u_ap;
#ifdef notyet
	struct vnode *vp;

	u.u_error = lookupname( uap->path, UIOSEG_USER, FOLLOW_LINK,
			(struct vnode **)0, &vp);

	if ( u.u_error )
		return();

        u.u_error = vno_pathconf(vp, uap->name_value);
	VN_PUT(vp);
#else /* notyet */

        u.u_error = vno_pathconf((struct vnode *)0, uap->name_value);

#endif /* notyet */
}

fpathconf()
{
	register struct a {
		int	fildes;
		int	name_value;
	} *uap = (struct a *)u.u_ap;
#ifdef notyet
	register struct file *fp;

	fp = getf( uap->fildes );
	if( fp == 0 )
		return;
	VN_LOCKNODE( fp->f_vnode );

	u.u_error = vno_pathconf( fp->f_vnode, uap->name_value );

	VN_UNLOCKNODE( fp->f_vnode );
#else /* notyet */	

	u.u_error = vno_pathconf( (struct vnode *)0, uap->name_value );

#endif /* notyet */
}


vno_pathconf(vp, name_value)
register struct vnode *vp;
register int name_value;
{
	register int error;

	error = 0;
#ifndef notyet
	/* present only to keep lint quiet */
	if( vp == (struct vnode *)0)
	     error = 0;
#endif /* notyet */
	
	switch( name_value ) {
		case _PC_LINK_MAX:
			u.u_r.r_val1 = LINK_MAX;
			break;
		case _PC_MAX_CANON:
			u.u_r.r_val1 = MAX_CANON;
			break;
		case _PC_MAX_INPUT:
			u.u_r.r_val1 = MAX_INPUT;
			break;
		case _PC_NAME_MAX:
			u.u_r.r_val1 = NAME_MAX;
			break;
		case _PC_PATH_MAX:
			u.u_r.r_val1 = PATH_MAX;
			break;
		case _PC_PIPE_BUF:
			u.u_r.r_val1 = PIPE_BUF;
			break;
		case _PC_CHOWN_RESTRICTED:
			u.u_r.r_val1 = chown_restricted;
			break;
		case _PC_NO_TRUNC:
			u.u_r.r_val1 = _POSIX_NO_TRUNC;
			break;
		case _PC_VDISABLE:
			u.u_r.r_val1 = _POSIX_VDISABLE;
			break;
		default:
			u.u_r.r_val1 = -1;
			error = EINVAL;
	}
	return( error );
}
