/*
 * nqsd/nqs_enf.c
 * Enforce kernel-based resource limits
 * 
 * DESCRIPTION:
 *
 *	This module enforces batch request resource limits.
 *
 *	Original Author:
 *	-------
 *	Robert W. Sandstrom, Sterling Software Incorporated.
 *	February 17, 1986.
 */

#include <libnqs/license.h>
#include <libnqs/proto.h>

#include <errno.h>
#include <libnqs/informcc.h>		/* NQS information completion */
					/* codes and masks */
#include <libnqs/requestcc.h>		/* NQS request completion codes */
#include <unistd.h>

#include <libsal/license.h>
#include <libsal/proto.h>
#include <libsal/defines.h>

/*** enf_bsdcpu
 *
 *
 *	void enf_bsdcpu():
 *
 *	Enforce within BSD4.2 a per process or per request
 *	cpu time limit.
 */
void enf_cpu_limit (
	struct cpulimit *cpulimitp,	/* Pointer to what is to be set */
	short infinite,			/* Boolean */
	long limit_type)		/* Per_process or Per_request */
{
  	sal_syslimit stSyslimit;

  	sal_dprintf(SAL_DEBUG_INFO, SAL_DEBUG_MSG_DEBUGHIGH, "Entering enf_cpu_limit()\n");
  
	if (limit_type == LIM_PPCPUT)
    	  stSyslimit.stLimitInfo.iName = SAL_LIMIT_CPU;
        else if (limit_type == LIM_PRCPUT)
          stSyslimit.stLimitInfo.iName = SAL_LIMIT_RCPU;
        else
    	  NEVER;
  
  	if (sal_syslimit_find(&stSyslimit) && (sal_syslimit_supported(&stSyslimit)))
	{
          if (infinite)
    	    stSyslimit.stLimitValue.boUnlimited = TRUE;
  	  else
            stSyslimit.stLimitValue.boUnlimited = FALSE;
  
  	  stSyslimit.stLimitValue.iValue = cpulimitp->max_seconds;
	  sal_dprintf(SAL_DEBUG_INFO, SAL_DEBUG_MSG_DEBUGHIGH, "Attempting to set %s limit of %lu\n", stSyslimit.stLimitInfo.szName, (unsigned long) stSyslimit.stLimitValue.iValue);
	  if (sal_syslimit_setlimit(&stSyslimit) == FALSE)
	    serexit(RCM_UNABLETOEXE | TCI_PP_CTLEXC, asciierrno());
	}
  
  	sal_dprintf(SAL_DEBUG_INFO, SAL_DEBUG_MSG_DEBUGHIGH, "Leaving enf_cpu_limit()\n");
}

void enf_nic_limit (int nice_value)
{
  sal_syslimit stSyslimit;

  sal_dprintf(SAL_DEBUG_INFO, SAL_DEBUG_MSG_DEBUGHIGH, "Entering enf_nic_limit() with value %d\n", nice_value);
  stSyslimit.stLimitInfo.iName = SAL_LIMIT_NICE;
  
  if (sal_syslimit_find(&stSyslimit))
  {
#if 0
    /* Generic NQS 3.50.1-pre1
     * 
     * This code is removed to ensure that nice values are set to absolutes
     * rather than as relative to NQS daemon priority.
     */
    sal_syslimit_getlimit(&stSyslimit);
    
    sal_dprintf(SAL_DEBUG_INFO, SAL_DEBUG_MSG_DEBUGLOW, "Results of getlimit:");
    sal_syslimit_dump(&stSyslimit);
    
    stSyslimit.stLimitValue.iValue += nice_value;
#endif
    
    stSyslimit.stLimitValue.iValue = nice_value;
    
    if (sal_syslimit_setlimit(&stSyslimit) == FALSE)
      serexit (RCM_UNABLETOEXE | TCI_PP_NELEXC, asciierrno());
  }
  else
    sal_dprintf(SAL_DEBUG_INFO, SAL_DEBUG_MSG_WARNING, "Nice limit not supported on this operating system!!\n");
  sal_dprintf(SAL_DEBUG_INFO, SAL_DEBUG_MSG_DEBUGHIGH, "Exiting enf_nic_limit() with value %d\n", nice_value);
}

void enf_quo_limit 
(
  struct quotalimit *quotalimitp,	/* Pointer to what is to be set */
  short infinite,			/* Boolean */
  long limit_type
)					/* One of LIM_??? */
{
  sal_syslimit stSyslimit;

  if (nqs_getsyslimit(limit_type, &stSyslimit))
  {
    if (sal_syslimit_find(&stSyslimit))
    {
      if (infinite)
        stSyslimit.stLimitValue.boUnlimited = TRUE;
      else
      {
        stSyslimit.stLimitValue.iValue = quotalimitp->max_quota;
	stSyslimit.stLimitValue.boUnlimited = FALSE;
	
        switch (quotalimitp->max_units)
        {
         case QLM_BYTES:
          break;
         case QLM_KBYTES:
          stSyslimit.stLimitValue.iValue *= 1024;
          break;
         case QLM_MBYTES:
          stSyslimit.stLimitValue.iValue *= 1024 * 1024;
          break;
         case QLM_GBYTES:
          stSyslimit.stLimitValue.iValue *= 1024 * 1024 * 1024;
          break;
         default:
          /* we should never see limits we do not support */
          stSyslimit.stLimitValue.boUnlimited = TRUE;
        }
      }
      sal_syslimit_setlimit(&stSyslimit);
    }
    else
      sal_dprintf(SAL_DEBUG_INFO, SAL_DEBUG_MSG_DEBUGMEDIUM, "NQS limit %u is not supported on this host\n", limit_type);
  }
  else
    sal_dprintf(SAL_DEBUG_INFO, SAL_DEBUG_MSG_DEBUGMEDIUM, "Unable to translate NQS limit %u into SAL limit\n", limit_type);
}
