DataMuseum.dk

Presents historical artifacts from the history of:

DKUUG/EUUG Conference tapes

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about DKUUG/EUUG Conference tapes

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - metrics - download
Index: T u

⟦ddf923e25⟧ TextFile

    Length: 7607 (0x1db7)
    Types: TextFile
    Names: »ulimit.c«

Derivation

└─⟦a05ed705a⟧ Bits:30007078 DKUUG GNU 2/12/89
    └─⟦ca1f037a2⟧ »./bash-1.04.tar.Z« 
        └─⟦46465a4db⟧ 
            └─⟦this⟧ »bash-1.04/ulimit.c« 

TextFile

/* ulimit.c -- Setting resource usage for children of the shell. */

/* Copyright (C) 1987,1989 Free Software Foundation, Inc.

This file is part of GNU Bash, the Bourne Again SHell.

Bash is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 1, or (at your option) any later
version.

Bash is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
for more details.

You should have received a copy of the GNU General Public License along
with Bash; see the file COPYING.  If not, write to the Free Software
Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */

#include <stdio.h>
#include "shell.h"

#include <sys/types.h>
#include <sys/errno.h>
extern int errno;

#ifndef SYSV
#include <sys/time.h>
#include <sys/resource.h>
#else
#include <sys/times.h>
#endif

/* **************************************************************** */
/*								    */
/*			Ulimit builtin and Hacks.       	    */
/*								    */
/* **************************************************************** */

/* Block size for ulimit operations. */
#define ULIMIT_BLOCK_SIZE ((long)1024)

#define u_FILE_SIZE 1
#define u_MAX_BREAK_VAL 3
#define u_PIPE_SIZE 4
#define u_CORE_FILE_SIZE 6
#define u_DATA_SEG_SIZE 8
#define u_PHYS_MEM_SIZE 10
#define u_CPU_TIME_LIMIT 12
#define u_STACK_SIZE 14

#ifndef RLIM_INFINITY
#define RLIM_INFINITY  0x7fffffff
#endif

typedef struct ResourceLimit {
  struct ResourceLimit *next;
  int cmd;
  long limit;
} RESOURCE_LIMIT;

RESOURCE_LIMIT *resource_limits = (RESOURCE_LIMIT *)NULL;

/* Called after we fork.  Sets the process resource limits to the
   values saved in RESOURCE_LIMITS. */
set_process_resource_limits ()
{
  long shell_ulimit ();
  register RESOURCE_LIMIT *limits = resource_limits;

  while (limits)
    {
      shell_ulimit (limits->cmd, limits->limit, 1);
      limits = limits->next;
    }
}

/* Report or set limits associated with certain per-process resources.
   See the help documentation in builtins.c for a full description.
   Chet Ramey & Brian Fox 3/13/89 */
ulimit_builtin (list)
     register WORD_LIST *list;
{
  long shell_ulimit ();
  register char *s;
  int c, setting, cmd;
  long current_limit, real_limit, limit = -1L;
  long block_factor;

  while (list)
    {
      cmd = u_FILE_SIZE;
      setting = 0;
      block_factor = ULIMIT_BLOCK_SIZE;

      if (list)
	{
	  s = list->word->word;
	  if (s && (*s == '-'))
	    {
	      c = *++s;

	      if (!c || *++s)
		goto error_case;

	      list = list->next;

	      switch (c)
		{
		case 'f': cmd = u_FILE_SIZE;
		  break;
#ifndef SYSV
		case 'c': cmd = u_CORE_FILE_SIZE;
		  break;

		case 'd': cmd = u_DATA_SEG_SIZE;
		  break;

		case 'm': cmd = u_PHYS_MEM_SIZE;
		  break;

		case 't':
		  cmd = u_CPU_TIME_LIMIT;
		  block_factor = 1000;
		  break;

		case 's': cmd = u_STACK_SIZE;
		  break;
#endif
		default:
		error_case:
#ifdef SYSV
		  report_error("usage: ulimit [-f] [new limit]");
#else
		  report_error("usage: ulimit [-cmdstf] [new limit]");
#endif
		  return EXECUTION_FAILURE;
		}
	    }
      
	  /* If an argument was supplied for the command, then we want to
	     set the limit. */
	  if (list)
	    {
	      s = list->word->word;
	      list = list->next;
	      if (sscanf (s, "%ld", &limit) != 1)
		{
		  if (strcmp (s, "unlimited") == 0)
		    limit = RLIM_INFINITY;
		  else
		    {
		      report_error ("ulimit: bad non-numeric arg `%s'", s);
		      return (EXECUTION_FAILURE);
		    }
		}
	      setting++;
	    }
	}

      if (limit == RLIM_INFINITY)
	block_factor = 1;

      real_limit = limit * block_factor;

      current_limit = shell_ulimit (cmd, real_limit, 0);

      if (setting)
	{
	  /* If we wish to set the limit, we have to make sure that it is
	     a "legal" change. */
	  if (current_limit < (real_limit))
	    {
	      report_error("bad ulimit");
	      return (EXECUTION_FAILURE);
	    }

	  /* Since the change would be "legal", remember the new child
	     resource limit. */
	  {
	    RESOURCE_LIMIT *newlimit, *limits = resource_limits;

	    while (limits)
	      {
		if (limits->cmd == cmd)
		  {
		    limits->limit = real_limit;
		    return (EXECUTION_SUCCESS);
		  }
		limits = limits->next;
	      }
		
	    newlimit = (RESOURCE_LIMIT *)xmalloc (sizeof (RESOURCE_LIMIT));

	    newlimit->cmd = cmd;
	    newlimit->limit = real_limit;
	    newlimit->next = resource_limits;
	    resource_limits = newlimit;
	    return (EXECUTION_SUCCESS);
	  }
	}
      else
	{
	  register RESOURCE_LIMIT *limits = resource_limits;

	  /* If we aren't setting the limit, then we are getting the limit.
	     So print the results. */
	  while (limits)
	    {
	      if (limits->cmd == cmd)
		{
		  current_limit = resource_limits->limit;
		  break;
		}

	      limits = limits->next;
	    }
	  
	  if (current_limit != RLIM_INFINITY)
	    printf ("%ld\n", (current_limit / block_factor));
	  else
	    printf ("unlimited\n");
	}
    }
  return (EXECUTION_SUCCESS);
}

/* The ulimit that we call from within Bash.  Extended to handle
   more resources by Chet Ramey (chet@cwjcc.cwru.edu).
   WHICH says which limit to twiddle; SETTING is non-zero if NEWLIM
   contains the desired new limit.  Otherwise, the existing limit is
   returned. */
long
shell_ulimit (which, newlim, setting)
     int which, setting;
     long newlim;
{
#ifndef SYSV
  struct rlimit limit;
#endif

  switch (which)
    {

    case u_FILE_SIZE:
      if (!setting)
	{
#ifdef SYSV
	  return (ulimit (1, 0l));
#else
	  if (getrlimit (RLIMIT_FSIZE, &limit) != 0 )
	    return ((long) -1);
	  return (limit.rlim_max);
#endif
	}
      else
	{
#ifdef SYSV
	  return (ulimit (2, newlim));
#else
	  limit.rlim_cur = limit.rlim_max = newlim;
	  return (setrlimit (RLIMIT_FSIZE, &limit));
#endif
	}

#ifndef SYSV
    case u_MAX_BREAK_VAL:
      if (setting || (getrlimit (RLIMIT_DATA, &limit) != 0))
	return ((long) -1);
      return (limit.rlim_max);

      /* You can't get or set the pipe size with getrlimit. */
    case u_PIPE_SIZE:
      errno = EINVAL;
      return ((long) -1);

    case u_CORE_FILE_SIZE:
      if (!setting)
	{
	  if (getrlimit (RLIMIT_CORE, &limit) != 0)
	    return ((long) -1);
	  return (limit.rlim_max);
	}
      else
	{
	  limit.rlim_cur = limit.rlim_max = newlim;
	  return (setrlimit (RLIMIT_CORE, &limit));
	}

    case u_DATA_SEG_SIZE:
      if (!setting)
	{
	  if (getrlimit (RLIMIT_DATA, &limit) != 0)
	    return (long) -1;
	  return (limit.rlim_max);
	}
      else
	{
	  limit.rlim_cur = limit.rlim_max = newlim;
	  return (setrlimit (RLIMIT_DATA, &limit));
	}

    case u_PHYS_MEM_SIZE:
      if (!setting)
	{
	  if (getrlimit (RLIMIT_RSS, &limit) != 0)
	    return ((long) -1);
	  return (limit.rlim_max);
	}
      else
	{
	  limit.rlim_cur = newlim;
	  return (setrlimit (RLIMIT_RSS, &limit));
	}

    case u_CPU_TIME_LIMIT:
      if (!setting)
	{
	  if (getrlimit (RLIMIT_CPU, &limit) != 0)
	    return ((long) -1);
	  return (limit.rlim_max);
	}
      else
	{
	  limit.rlim_cur = limit.rlim_max = newlim;
	  return (setrlimit (RLIMIT_CPU, &limit));
	}

    case u_STACK_SIZE:
      if (!setting)
	{
	  if (getrlimit (RLIMIT_STACK, &limit) != 0)
	    return ((long) -1);
	  return (limit.rlim_max);
	}
      else
	{
	  limit.rlim_cur = limit.rlim_max = newlim;
	  return (setrlimit(RLIMIT_STACK, &limit));
	}
#endif

    default:
      errno = EINVAL;
      return ((long) -1);
    }
}