In article <200411140421.iAE4LLlO005391 / sharui.nakada.niregi.kanuma.tochigi.jp>,
  nobu / ruby-lang.org writes:

>> * struct rlimit に対応するクラスは作らず、[cur,max] という配列を使う
>
> 細かい話ですが、
>   setrlimit(resource, [cur, max])
> でなく
>   setrlimit(resource, cur, max)
> なら、rb_ary_new3()よりもrb_assoc_new()(またはrb_values_new())
> を使うほうがいいような気がします。

たしかに。[cur,max] を使うと書いてしまいましたが、意図としては展開して
扱うと表現したほうが適切でした。ということで、配列よりも多値のほうが適
切で、rb_assoc_new のほうが適切だと思います。というわけで変更しました。

あとは、いろんな OS について RLIMIT_* な定数を調べるなどした結果、いく
つか変更しました。

* Process::RLIMIT_SBSIZE を追加 
  FreeBSD, NetBSD 用

* Process::RLIMIT_LOCKS を削除
  Early Linux 2.4 only で推奨できないため
  どうしても使いたければ、10 を指定することはできる

* rlim_t がなかった時に method を定義するようになっていなかったので定
  義するようにした

あとは 386BSD にあったらしい RLIMIT_OFILE をどうするかというのは考えた
のですが、誰かが実際に困ってからでいいかということで今はつけないことに
しました。

Index: configure.in
===================================================================
RCS file: /src/ruby/configure.in,v
retrieving revision 1.249
diff -u -p -r1.249 configure.in
--- configure.in	7 Nov 2004 15:16:06 -0000	1.249
+++ configure.in	14 Nov 2004 06:51:28 -0000
@@ -205,6 +205,12 @@ AC_CHECK_SIZEOF(float, 4)
 AC_CHECK_SIZEOF(double, 8)
 AC_CHECK_SIZEOF(time_t, 0)
 
+AC_CHECK_TYPE(rlim_t, [AC_DEFINE(HAVE_RLIM_T)], [], [#include <sys/resource.h>])
+AC_CHECK_SIZEOF(rlim_t, 0, [
+  #include <stdio.h>
+  #include <sys/resource.h>
+])
+
 AC_CACHE_CHECK(for prototypes, rb_cv_have_prototypes,
   [AC_TRY_COMPILE([int foo(int x) { return 0; }], [return foo(10);],
 	rb_cv_have_prototypes=yes,
@@ -416,7 +422,8 @@ AC_CHECK_FUNCS(fmod killpg wait4 waitpid
 	      setitimer setruid seteuid setreuid setresuid setproctitle\
 	      setrgid setegid setregid setresgid issetugid pause lchown lchmod\
 	      getpgrp setpgrp getpgid setpgid initgroups getgroups setgroups\
-	      getpriority getrlimit dlopen sigprocmask sigaction _setjmp\
+	      getpriority getrlimit setrlimit\
+	      dlopen sigprocmask sigaction _setjmp\
 	      setsid telldir seekdir fchmod mktime timegm cosh sinh tanh\
 	      setuid setgid daemon)
 AC_ARG_ENABLE(setreuid,
Index: process.c
===================================================================
RCS file: /src/ruby/process.c,v
retrieving revision 1.118
diff -u -p -r1.118 process.c
--- process.c	1 Nov 2004 02:49:06 -0000	1.118
+++ process.c	14 Nov 2004 06:51:28 -0000
@@ -45,7 +45,7 @@ struct timeval rb_time_interval _((VALUE
 #ifdef HAVE_SYS_WAIT_H
 # include <sys/wait.h>
 #endif
-#ifdef HAVE_GETPRIORITY
+#ifdef HAVE_SYS_RESOURCE_H
 # include <sys/resource.h>
 #endif
 #include "st.h"
@@ -1931,6 +1931,109 @@ proc_setpriority(obj, which, who, prio)
 #endif
 }
 
+#ifdef HAVE_RLIM_T
+#if SIZEOF_RLIM_T == SIZEOF_INT
+# define RLIM2NUM(v) UINT2NUM(v)
+# define NUM2RLIM(v) NUM2UINT(v)
+#elif SIZEOF_RLIM_T == SIZEOF_LONG
+# define RLIM2NUM(v) ULONG2NUM(v)
+# define NUM2RLIM(v) NUM2ULONG(v)
+#elif SIZEOF_RLIM_T == SIZEOF_LONG_LONG
+# define RLIM2NUM(v) ULL2NUM(v)
+# define NUM2RLIM(v) NUM2ULL(v)
+#else
+# error cannot find an integer type which size is same as rlim_t.
+#endif
+#endif
+
+/*
+ *  call-seq:
+ *     Process.getrlimit(resource)   => [cur_limit, max_limit]
+ *
+ *  Gets the resource limit of the process.
+ *  _cur_limit_ means current (soft) limit and
+ *  _max_limit_ means maximum (hard) limit.
+ *
+ *  _resource_ indicates the kind of resource to limit:
+ *  such as <code>Process::RLIMIT_CORE</code>,
+ *  <code>Process::RLIMIT_CPU</code>, etc.
+ *  See Process.setrlimit for details.
+ *
+ *  _cur_limit_ and _max_limit_ may be <code>Process::RLIM_INFINITY</code>,
+ *  <code>Process::RLIM_SAVED_MAX</code> or
+ *  <code>Process::RLIM_SAVED_CUR</code>.
+ *  See Process.setrlimit and the system getrlimit(2) manual for details.
+ */
+
+static VALUE
+proc_getrlimit(
+    VALUE obj,
+    VALUE resource)
+{
+#ifdef HAVE_GETRLIMIT
+    struct rlimit rlim;
+
+    if (getrlimit(NUM2INT(resource), &rlim) < 0) {
+       rb_sys_fail("getrlimit");
+    }
+    return rb_assoc_new(RLIM2NUM(rlim.rlim_cur), RLIM2NUM(rlim.rlim_max));
+#else
+    rb_notimplement();
+#endif
+}
+
+/*
+ *  call-seq:
+ *     Process.setrlimit(resource, cur_limit, max_limit)        => nil
+ *
+ *  Sets the resource limit of the process.
+ *  _cur_limit_ means current (soft) limit and
+ *  _max_limit_ means maximum (hard) limit.
+ *
+ *  _resource_ indicates the kind of resource to limit.
+ *  Although the list of resources are OS dependent,
+ *  SUSv3 defines following resources.
+ *
+ *  [Process::RLIMIT_CORE] core size (bytes)
+ *  [Process::RLIMIT_CPU] CPU time (seconds)
+ *  [Process::RLIMIT_DATA] data segment (bytes)
+ *  [Process::RLIMIT_FSIZE] file size (bytes)
+ *  [Process::RLIMIT_NOFILE] file descriptors (number)
+ *  [Process::RLIMIT_STACK] stack size (bytes)
+ *  [Process::RLIMIT_AS] total available memory (bytes)
+ *
+ *  Other <code>Process::RLIMIT_???</code> constants may be defined.
+ *
+ *  _cur_limit_ and _max_limit_ may be <code>Process::RLIM_INFINITY</code>,
+ *  which means that the resource is not limited.
+ *  They may be <code>Process::RLIM_SAVED_MAX</code> or
+ *  <code>Process::RLIM_SAVED_CUR</code> too.
+ *  See system setrlimit(2) manual for details.
+ *
+ */
+
+static VALUE
+proc_setrlimit(
+    VALUE obj,
+    VALUE resource,
+    VALUE rlim_cur,
+    VALUE rlim_max)
+{
+#ifdef HAVE_SETRLIMIT
+    struct rlimit rlim;
+
+    rlim.rlim_cur = NUM2RLIM(rlim_cur);
+    rlim.rlim_max = NUM2RLIM(rlim_max);
+
+    if (setrlimit(NUM2INT(resource), &rlim) < 0) {
+       rb_sys_fail("setrlimit");
+    }
+    return Qnil;
+#else
+    rb_notimplement();
+#endif
+}
+
 static int under_uid_switch = 0;
 static void
 check_uid_switch()
@@ -3608,6 +3711,57 @@ Init_process()
     rb_define_const(rb_mProcess, "PRIO_PROCESS", INT2FIX(PRIO_PROCESS));
     rb_define_const(rb_mProcess, "PRIO_PGRP", INT2FIX(PRIO_PGRP));
     rb_define_const(rb_mProcess, "PRIO_USER", INT2FIX(PRIO_USER));
+#endif
+
+#ifdef HAVE_GETRLIMIT
+    rb_define_module_function(rb_mProcess, "getrlimit", proc_getrlimit, 1);
+#endif
+#ifdef HAVE_SETRLIMIT
+    rb_define_module_function(rb_mProcess, "setrlimit", proc_setrlimit, 3);
+#endif
+#ifdef HAVE_RLIM_T
+#ifdef RLIM_INFINITY
+    rb_define_const(rb_mProcess, "RLIM_INFINITY", RLIM2NUM(RLIM_INFINITY));
+#endif
+#ifdef RLIM_SAVED_MAX
+    rb_define_const(rb_mProcess, "RLIM_SAVED_MAX", RLIM2NUM(RLIM_SAVED_MAX));
+#endif
+#ifdef RLIM_SAVED_CUR
+    rb_define_const(rb_mProcess, "RLIM_SAVED_CUR", RLIM2NUM(RLIM_SAVED_CUR));
+#endif
+#ifdef RLIMIT_CORE
+    rb_define_const(rb_mProcess, "RLIMIT_CORE", INT2FIX(RLIMIT_CORE));
+#endif
+#ifdef RLIMIT_CPU
+    rb_define_const(rb_mProcess, "RLIMIT_CPU", INT2FIX(RLIMIT_CPU));
+#endif
+#ifdef RLIMIT_DATA
+    rb_define_const(rb_mProcess, "RLIMIT_DATA", INT2FIX(RLIMIT_DATA));
+#endif
+#ifdef RLIMIT_FSIZE
+    rb_define_const(rb_mProcess, "RLIMIT_FSIZE", INT2FIX(RLIMIT_FSIZE));
+#endif
+#ifdef RLIMIT_NOFILE
+    rb_define_const(rb_mProcess, "RLIMIT_NOFILE", INT2FIX(RLIMIT_NOFILE));
+#endif
+#ifdef RLIMIT_STACK
+    rb_define_const(rb_mProcess, "RLIMIT_STACK", INT2FIX(RLIMIT_STACK));
+#endif
+#ifdef RLIMIT_AS
+    rb_define_const(rb_mProcess, "RLIMIT_AS", INT2FIX(RLIMIT_AS));
+#endif
+#ifdef RLIMIT_MEMLOCK
+    rb_define_const(rb_mProcess, "RLIMIT_MEMLOCK", INT2FIX(RLIMIT_MEMLOCK));
+#endif
+#ifdef RLIMIT_NPROC
+    rb_define_const(rb_mProcess, "RLIMIT_NPROC", INT2FIX(RLIMIT_NPROC));
+#endif
+#ifdef RLIMIT_RSS
+    rb_define_const(rb_mProcess, "RLIMIT_RSS", INT2FIX(RLIMIT_RSS));
+#endif
+#ifdef RLIMIT_SBSIZE
+    rb_define_const(rb_mProcess, "RLIMIT_SBSIZE", INT2FIX(RLIMIT_SBSIZE));
+#endif
 #endif
 
     rb_define_module_function(rb_mProcess, "uid", proc_getuid, 0);
Index: ruby.h
===================================================================
RCS file: /src/ruby/ruby.h,v
retrieving revision 1.107
diff -u -p -r1.107 ruby.h
--- ruby.h	27 Oct 2004 09:29:25 -0000	1.107
+++ ruby.h	14 Nov 2004 06:51:28 -0000
@@ -265,6 +265,7 @@ unsigned long rb_fix2uint _((VALUE));
 LONG_LONG rb_num2ll _((VALUE));
 unsigned LONG_LONG rb_num2ull _((VALUE));
 # define NUM2LL(x) (FIXNUM_P(x)?FIX2LONG(x):rb_num2ll((VALUE)x))
+# define NUM2ULL(x) rb_num2ull((VALUE)x)
 #endif
 
 #if HAVE_LONG_LONG && SIZEOF_OFF_T > SIZEOF_LONG
-- 
[田中 哲][たなか あきら][Tanaka Akira]